Prolog: why is true == not(not(true)) -> false? - prolog

Obviously true = not(not(true)) has to be false, because = tries to unify the atom true with the term not(not(true)) (without evaluating the term), which is false, since the terms are not identical.
However, I thought == really compares whatever is evaluated. Thus, I thought true == not(not(true)) should evaluate to true == true, just like (for arithmetic operators) 4 =:= 2 + 2 would evaluate to 4 =:= 4 and return true.
...but this is what I get in SWI-Prolog:
?- true == not(not(true)).
false.
What am I getting wrong?

(==)/2 does not compare whatever is evaluated. It does not evaluate its arguments. It only succeeds if the arguments are already instantiated to matching terms.
In prolog, not(not(true)) is a compound term, which is the term not/1 with a single argument, not(true), itself being a term not/1 of one argument consisting of the term true/0 which has no arguments. It doesn't have a value. It doesn't even get "executed" except in certain contexts. In Prolog, the predicate not/1 succeeds if it's argument fails, and it fails if its argument succeeds. This isn't the value or functional result, but a behavior. This is assuming that it appears in a context such as the following:
not(not(true)),
write('This will be written out because not(not(true)) succeeded'), nl.
The expression true == not(not(true)) in Prolog is a compound term, equivalent to:
'=='(true, not(not(true)))
In this context, not(not(true)) is not evaluated. Prolog will first exercise the (==)/2 equivalence operator, which succeeds if its arguments are instantiated to the same term. Are the terms true and not(not(true)) in Prolog the same (or equivalent)? No they are not. One is simple term with no arguments (true/0). The other is a compound term: a term with one argument that is itself a term with one argument. Thus the (==)/2 fails here.
Note that (=:=)/2 is quite different. It is an operator that compares results of arithmetic expressions. The arguments must be evaluable arithmetic expressions and (=:=)/2 will succeed if they evaluate to the same result, and it will fail if they do not.

Related

What's the difference between functor, a fact, a predicate and a rule in Prolog?

I would like to know the difference between those terms :
facts
functor
predicate.
rule
in Prolog.
if I write: brother(john, jack).
is that a fact? or a predicate?
To address your given example:
brother(john, jack).
^ ^ ^
functor | |
argument |
argument
\________ ________/
\/
fact/predicate
brother/2 is a predicate AND a fact as well (see 3.72 fact in #GuyCoder's quote from the standard) since you can write it as a clause with a body that consists of the single goal true:
brother(john, jack) :- % <- head of the clause
true. % <- body of the clause
The predicate brother in your example has two arguments, therefore the arity 2 and is referred to as brother/2 (see 3.129 predicate in #GuyCoder's post). The name or identifier of the predicate brother/2 is also called the functor of the predicate (see 3.77 functor; note that 3.77 and 3.129 use the same definition). You can think of a fact as a special kind of predicate that you can define without rules.
If you had some facts parent_of/2 and male/2 and defined a predicate brother_of/2 based on those, e.g...
brother_of(X,Y) :- % X is brother of Y if
dif(X,Y), % X and Y are different AND
male(X), % X is male AND
parent_of(P,X), % X has a parent P AND
parent_of(P,Y). % Y has the same parent P
... then the above definition constitutes a rule because the body of the clause is not the goal true (see 3.154 rule). The rule above consists of the following parts:
brother_of(X,Y) :- % head of the rule
dif(X,Y), % goal \
male(X), % goal \ body of
parent_of(P,X), % goal / the rule
parent_of(P,Y). % goal /
The head of the rule is followed by :- which is an implication arrow pointing towards the head of the rule and the goals are separated by , which is a logical AND (conjunction). So the body of a rule consists of a single goal or a conjunction of goals and the body of a rule implies the head of the rule. Hence you can read the above definition of brother_of/2 as a logic formula:
brother_of(X,Y) ← dif(X,Y) ∧ male(X) ∧ parent_of(P,X) ∧ parent_of(P,Y)
If you come from mathematical logic you might find it helpful to recall that a predicate is defined as a boolean-valued function, that is, a function that maps its arguments to true or false. So a predicate is the characteristic function of a relation (see Predicate (mathematical logic). Since you can query facts and get true/false as an answer, they constitute predicates. You can observe this when you query your definition of brother/2:
?- brother(john,jack).
true. % <- maps to true
?- brother(john,jason).
false. % <- maps to false
If you issue queries with variables, you get substitutions for said variables that make the predicate true instead of the answer true, e.g.:
?- brother(X,Y).
X = john, % these substitutions for X and Y
Y = jack. % map to true
A final remark: When talking about Prolog the terms predicate and relation are often used interchangeably and it is quite helpful to think about writing predicates as describing relations (see the comments in the definition of brother_of/2 above). Hence, for the above queries it is also appropriate to say: The relation brother(john,jack) holds. The relation brother(john,jason) does not hold. The relation brother(X,Y) holds for the substitutions X=john and Y=jack.
From
ISO/IEC 13211-1 First edition 1995-06-01
Information technology - Programming languages - Prolog -
Part 1:
General Core
3.9 arity: The number of arguments of a compound term. Syntactically, a non-negative integer associated with a functor or predicate.
3.19 body: A goal, distinguished by its context as part
of a rule (see 3.154).
3.32 clause: A fact or a rule. It has two parts: a head,
and a body.
3.37 compound term: A functor of arity N, N positive, together with a sequence of N arguments.
3.72 fact: A clause whose body is the goal true.
NOTE - A fact can be represented in Prolog text by a term
whose principal functor is neither (:-)/1 nor (:-)/2.
3.77 functor: An identifier together with an arity.
3.81 goal: A predication which is to be executed (see
body, query, and 7.7.3).
3.84 head (of a rule): A predication, distinguished by its context.
3.88 identifier: A basic unstructured object used to denote an atom, functor name or predicate name.
3.129 predicate: An identifier together with an arity.
3.133 predication: A predicate with arity N and a
sequence of N arguments.
3.143 query: A goal given as interactive input to the
top level.
3.154 rule: A clause whose body is not the goal true.
During execution, if the body is true for some substitution,
then the head is also true for that substitution. A rule
is represented in Prolog text by a term whose principal
functor is (:-)/2 where the first argument is converted
to the head, and the second argument is converted to the
body.
So brother(john, jack). is a fact.
The difference between a term and a predicate (or goal) can be subtle. They look the same and are distinguished by context. For example:
foo(1).
foo(2).
foo_results(Results) :- setof(X, foo(X), Results).
?- foo_results(Results).
Results = [1, 2].
The predicate foo/1 has two clauses. The predicate foo_results/1 calls this, but indirectly ... the setof/3 meta-predicate takes a term as its second argument, which it interprets as a predicate. In other words, a functor (name/arity) is the skeleton of a kind of term; some meta-predicates (e.g., call/1, setof/3, etc.) can interpret a term (functor/arity) as a predicate.
A fact is a predicate expression that makes a declarative statement about the problem domain.
likes(john, mary).
A rule is a predicate expression that uses logical implication (:-) to describe a relationship among facts. A rule could be
left :- right.
friends(X,Y) :- likes(X,Y),likes(Y,X).
Both facts and rules are predicates.
So for your question, brother(john, jack) is a fact.

Is nonexistence queriable in Datalog?

Suppose I've defined a few values for a function:
+(value[1] == "cats")
+(value[2] == "mice")
Is it possible to define a function like the following?
(undefined[X] == False) <= (value[X] == Y)
(undefined[X] == True) <= (value[X] does not exist)
My guess is that it can't, for two reasons:
(1) Queries are guaranteed to terminate in Datalog, and you could query for undefined[X] == True.
(2) According to Wikipedia, one of the ways Datalog differs from Prolog is that Datalog "requires that every variable appearing in a negative literal in the body of a clause also appears in some positive literal in the body of the clause".
But I'm not sure, because the terms involved ("terminate", "literal", "negative") have so many uses. (For instance: Does negative literal mean f[X] == not Y or does it mean not (f[X] == Y)? Does termination mean that it can evaluate a single expression like undefined[3] == True, or does it mean it would have found all X for which undefined[X] == True?)
Here another definition of "safe".
A safety condition says that every variable in the body of a rule must occur in at least one positive (i.e., not negated)
atom.
Source: Datalog and Recursive Query Processing
And an atom (or goal) is a predicate symbol (function) along with a list of terms as arguments. (Note that “term” and “atom” are used differently here than they are in Prolog.)
The safety problem is to decide whether the result of a given Datalog program can be guaranteed to be finite even when some source relations are infinite.
For example, the following rule is not safe because the Y variable appears only in a negative atom (i.e. not predicate2(Z,Y)).
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y) .
To meet the condition of safety the Y variable should appear in a positive predicate too:
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y), predicate3(Y) .

Prolog converting text to number and doing arithmatic operations

I working in prolog for first time.
I am trying to convert operations in text.
Such as,
THREE + THREE = SIX
should return true.
I tried this.
I am getting error on last line and when I try add(ONE,ONE,TWO) it returns false instead of true.
numericValue(ONE, 1).
numericValue(TWO, 2).
numericValue(THREE, 3).
numericValue(FOUR, 4).
numericValue(FIVE, 5).
numericValue(SIX, 6).
numericValue(SEVEN, 7).
numericValue(EIGHT, 8).
numericValue(ZERO, 0).
numericValue(NINE, 9).
add(num1,num2,num3):-
numericValue(num1,a),
numericValue(num2,b),
numericValue(num3,c),
(c =:= a+b -> true ; false).
istBiggerThen(XinEng,YinEng) :-
numericValue(XinEng, X),
numericValue(YinEng, Y),
( X < Y -> true ; false).
A + B = C :- add(A,B,C).
Error on last line is
ERROR: /home/name/prolog_examples/crypt.pl:24:
No permission to modify static procedure `(=)/2'
literals (lower-case) vs. Variabls (upper-case):
as #lurker pointed out, you have your atoms and variables mixed up. So your facts should look something like this:
text_to_number(one, 1).
text_to_number(two, 2).
text_to_number(three, 3).
%% etc...
while your rules will need to use variables, like so:
add(A_Text, B_Text, C_Text) :-
text_to_number(A_Text, A_Num),
text_to_number(B_Text, B_Num),
C_Num is A_Num + B_Num,
text_to_number(C_Text, C_Num).
bigger_than(A_Text, B_Text) :-
text_to_number(A_Text, A_Num),
text_to_number(B_Text, B_Num),
A_Num > B_Num.
The reason reason why add(ONE, ONE, TWO) turns out false is because your original rule for add/3 only defines relationships between the atoms num1, num2, num3, a, b, c. When you query add(ONE, ONE, TWO) Prolog tries to unify the variables with the atoms in the head of your rule, which is add(num1, num2, num3). Because you have ONE as the first and second argument of your query, this unification is impossible, since ONE = ONE but num1 \= num2. As there are no further rules or facts for add/3, the query simply returns false.
Using the pattern (|Condition| -> true ; false):
Statements in the body of a clause (i.e., to the right of the :- operator) is evaluated to be either true or false, so you will almost never need to use the pattern (|Condition| -> true ; false). E.g. C_Num is A_Num + B_Num is true iff C_Num can be unified with the sum of A_Num and B_Num, or else it is false, in which case Prolog will start back tracking.
Using =:=/2 vs. is/2:
=:=/2 checks for the equality of its first argument with the value of its second argument, which can be an arithmetical expression that can be evaluated using is/2. Query ?- X =:= 2 + 2 and you'll get an instantiation error, because =:=/2 cannot compare a free variable to a mathematical expression. is/2, on the other hand, unifies the variable on the left with the value of the expression on the right: ?- X is 2 + 2. X = 4.
Your use of =:=/2 would work (provided you straightened out the variable-atom thing), but your rule describes an inefficient and roundabout solution for the following reason: since numericValue(Num3,C) precedes evaluation of the arithmetic, Prolog will first unify numericValue(Num3,C) with the first fitting fact, viz. numericValue(one, 1) then test if 1 =:= A + B. When this fails, Prolog will unify with the next fact numericValue(two, 2) then test if 2 =:= A + B, then the next... until it finally happens upon the right value. Compare with my suggested rule: the numeric values A_Num and B_Num are summed with C_Num is A_Num + B_Num, unifying C_Num with the sum. Then Prolog unifies text_to_number(C_Text, C_Num) with the single fitting fact that has the appropriate value for C_Num.
Defining operators:
When a term appears on the right of a :-, or on the top level of the program, is being defined. However, you cannot simply redefine predicates (it can be done, but requires some bookkeeping and special declarations. Cf., dynamic/1). Moreover, you wouldn't want to redefine core terms like +/2 and =/2. But you can define your own predicates with relative ease. In fact, going crazy with predicate definitions is one of my favorite idle things to do with Prolog (though I've read cautions against using unnecessary operators in practice, since it makes your code recondite).
Operators are declared using op/3 in a directive. It has the signature op(+Precedence, +Type, :Name) (Cf., the SWI-Prolog documentation):
:- op(200, xfx, user:(++)).
:- op(300, yfx, user:(=::=)).
A ++ B =::= C :- add(A, B, C).
In action:
?- one ++ two =::= X.
X = three.

Negation and testing for a unique set in Prolog

I've just started experimenting with Prolog, and I was trying to write a rule to find out whether a list contained only unique elements. I got it working in the second variation (by negating a positive test), but I've completely failed to understand why the first variation doesn't work.
Given this file:
uniqueElements([X|Y]) :-
notmember(X, Y),
uniqueElements(Y).
notmember(X, Y) :-
\+ member(X, Y).
hasRepeatedElements([X|Y]) :-
(
member(X, Y) ->
true
; hasRepeatedElements(Y)
).
uniqueElements_2(X) :-
\+ hasRepeatedElements(X).
The GNU Prolog interpreter gives these responses:
| ?- uniqueElements([1,2,3]).
no
| ?- uniqueElements([1,2,3,2,3]).
no
| ?- uniqueElements_2([1,2,3]).
yes
| ?- uniqueElements_2([1,2,3,2,3]).
no
Why is the first response 'no'? (I would have expected member to return false, be negated to true, and thus have notmemeber return true on each iteration of uniqueElements). I guess I'm expecting '\+' to behave like '!' does in a C if clause, or the 'not' keyword in Python. Is this a misunderstanding?
In uniqueElements, you haven't provided the base case for the recursion:
uniqueElements([]).
Without that clause, when a particular call chain gets to the empty list case, it doesn't find any applicable clauses, which means fail in Prolog. Meaning, "unprovable". So, your call uniqueElements([1,2,3]) has produced an equivalent of true && true && true && false.
Now it should work.
hasRepeatedElements doesn't have a clause defined for the base case either, but its failure in finding whether there were repeated elements in an empty list [] is consistent with its semantics - it should have found that there are no repeated elements in empty list, in the first place.
In Prolog, "not" means "can't prove that ...".

Boolean assignment in Prolog

all.
I want to assign a boolean value to a variable.
I've tried stuff like.
Diagonal is (XPiece = XFinal)
Diagonal is (XPiece =:= XFinal)
Diagonal is (XPiece is XFinal)
None work...
Any solutions?
Prolog's built-in predicate is/2 evaluates the right-hand side of the expression as an arithmetic expression and unifies the result with the left-hand side.
Also, prolog doesn't have a boolean type. Prolog's built-in types are
integer
float
atom
unbound variable
compound term
You could elect to represent a boolean value as the atoms true/false (useful for readability), or you could represent a boolean value as the integer values 1/0 (useful for computation). The way most procedural languages, like C, evaluate arithmetic values as booleans is broken WRT formal logic, though: falsity is single-valued (0) and truth multi-valued (non-zero), meaning that which is not false. In formal logic, truth is single-valued and falsity is defined as that which is not true.
So you might want to consider the semantics of your representation and build some predicates to manipulate your booleans, possibly adding some operators to "extend" prolog a bit.
Use an if-then-else:
(XPiece = XFinal ->
Diagonal = true
;
Diagonal = false
)
or use 1/0, or whatever you want. Alternatively, use CLP(FD), that supports the idiom you want:
use_module(library(clpfd)).
diag(XPiece, XFinal, Diagonal) :-
Diagonal #= (XPiece #= XFinal).
What about
diagonal(XPiece, XFinal) :- XPiece = XFinal.

Resources