Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prolog - formulas in propositional logic

I am trying to make a predicate in order to validate if a given input represents a formula.

I am allowed to use only to propositional atoms like p, q, r, s, t, etc. The formulas which I have to test are the following:

neg(X) - represents the negation of X  
and(X, Y) - represents X and Y  
or(X, Y) - represents X or Y  
imp(X, Y) - represents X implies Y  

I have made the predicate wff which returns true if a given structure is a formula and false the otherwise. Also, I don't have to use variables inside the formula, only propositional atoms as mentioned bellow.

logical_atom( A ) :-
    atom( A ),     
    atom_codes( A, [AH|_] ),
    AH >= 97,
    AH =< 122.

wff(A):-
    \+ ground(A),
    !,
    fail.

wff(and(A, B)):-
    wff(A),
    wff(B).

wff(neg(A)):-
    wff(A).

wff(or(A, B)):-
    wff(A),
    wff(B).

wff(imp(A, B)):-
    wff(A),
    wff(B).

wff(A):-
    ground(A),
    logical_atom(A),
    !.

When i introduce a test like this one, wff(and(q, imp(or(p, q), neg(p))))., the call returns both the true and false values. Can you please tell me why it happens like this?

like image 219
Simon Avatar asked Oct 16 '10 07:10

Simon


People also ask

Is Prolog propositional logic?

Since Prolog is based heavily on formal logic, it's useful to have some experience with it before starting to learn the language. This is a short introduction to logic for people who want to learn Prolog. It will discuss two logical languages: propositional logic and first-order logic.

What is Proposition in Prolog?

A Prolog program consists of a set of premises, the database. A user interacts with the database by submitting queries (goals to be proved). The Prolog interpreter uses predicate logic to prove or to refute the queries. The simplest form of premise is a primitive proposition, like these two: expensive(car).

Is Prolog first-order logic?

Prolog has its roots in first-order logic, a formal logic, and unlike many other programming languages, Prolog is intended primarily as a declarative programming language: the program logic is expressed in terms of relations, represented as facts and rules.

How do you represent in Prolog?

In Prolog, predicate names and bound variables are expressed as a sequence of alphanumeric characters beginning with an alphabetic. Variables are represented as a string of alphanumeric characters beginning (the first character, at least) with an uppercase alphabetic. Thus: likes(X, susie).


1 Answers

The data structure you chose to represent formulae is called "defaulty", because you need a "default" case to test for atomic identifiers: Everything that is not something of the above (and, or, neg, imp) and satisfies logical_atom/1 is a logical atom (in your representation). The interpreter cannot distinguish these cases by their functor to apply first-argument indexing. It is much cleaner to, in analogy to and/or/etc., also equip atomic variables with their dedicated functor, say "atom(...)". wff/1 could then read:

wff(atom(_)).
wff(and(A, B))    :- wff(A), wff(B).
wff(neg(A))       :- wff(A).
wff(or(A, B))     :- wff(A), wff(B).
wff(imp(A, B))    :- wff(A), wff(B).

Your query is now deterministic as desired:

?- wff(and(atom(q), imp(or(atom(p), atom(q)), neg(atom(p))))).
true.

If your formulae are initially not represented in this way, it is still better to first convert them to such a form, and then to use such a representation which is not defaulty for further processing.

An additional advantage is that you can now easily not only test but also enumerate well-formed formulae with code like:

wff(atom(_))  --> [].
wff(and(A,B)) --> [_,_], wff(A), wff(B).
wff(neg(A))   --> [_], wff(A).
wff(or(A,B))  --> [_,_], wff(A), wff(B).
wff(imp(A,B)) --> [_,_], wff(A), wff(B).

And a query like:

?- length(Ls, _), phrase(wff(W), Ls), writeln(W), false.

Yielding:

atom(_G490)
neg(atom(_G495))
and(atom(_G499),atom(_G501))
neg(neg(atom(_G500)))
or(atom(_G499),atom(_G501))
imp(atom(_G499),atom(_G501))
and(atom(_G502),neg(atom(_G506)))
and(neg(atom(_G504)),atom(_G506))
neg(and(atom(_G504),atom(_G506)))
neg(neg(neg(atom(_G505))))
neg(or(atom(_G504),atom(_G506)))
neg(imp(atom(_G504),atom(_G506)))
etc.

as its output.

like image 59
mat Avatar answered Sep 23 '22 06:09

mat