Arithmetic term doesn't fail but its negation does - prolog

given the query ?- p == 'p'., prolog outputs true.
But given the query p =\= 'p'., prolog outputs
ERROR: Arithmetic: `p' is not a function
ERROR: In:
Why is that? whats the difference between == and =/= so p is somehow evaluated differently?

The negation of == is not =\=, but \==.
From comparision operators:
T1 == T2 succeeds if terms T1 and T2 are identical
T1 \== T2 succeeds if terms T1 and T2 are not identical
E1 =:= E2 succeeds if values of expressions E1 and E2 are equal
E1 =\= E2 succeeds if values of expressions E1 and E2 are not equal
=\= expects p and 'p' to be expressions and attempts to evaluate, but they are not.

Related

Prolog equality check fails on simple task

Im trying to achieve this:
sum(bookmark(num)),
bookmark(bookmark(bum)),
bookmark(bookmark(bookmark(num))).
sum(bookmark(num), bookmark(bookmark(num)), A).
to return А = bookmark(bookmark(bookmark(num)))
Im not close yet, since i fail at the bookmark function as stated below.
bookmark(e1, e2) :-
e1 \= 0,
e2 \= 0.
/*#e1 = element-one, e2 = element-two*/
sum(e1, e2, result) :-
bookmark(e1, e2),
e1 is (1+1),
e2 is (1+1),
result = (e1 + e2).
Im checking if the bookmark function returns true, then the simple addition will follow. Problem is: if the input for the bookmark function is any two numbers, it returns false.
Example with bookmark(1, 2) - false.
Example with bookmark(0, 0) - false.
Any help why this doesn't work will be greatly appreciated.
In Prolog variables start with an uppercase. So e1 is not a variable, but a costant, E1 is a variable.
bookmark(E1, E2) :-
E1 \= 0,
E2 \= 0.
sum(E1, E2, Result) :-
bookmark(E1, E2),
E1 is (1+1),
E2 is (1+1),
Result = E1 + E2.
The above will however only succeed if E1 and E2 are both 2, and then Result will be 2 + 2 (not 4, just 2 + 2, or in canonical form +(2, 2)).

; (or) operator in Prolog not returning true unless the left side is true, even if the right side of the operator returns true by itself

I'm trying to return true if either of the two rules on opposite sides of an or operator succeed in Prolog. It only works if what's on the left side of the or operator is found to be true.
It seems like my code should work according to http://www.cse.unsw.edu.au/~billw/dictionaries/prolog/or.html.
Case2 works when case1 is commented out, so it should be returning true, but because it is on the right side of the operator, it isn't. (?)
For clarity, the parameters mean Person1, Person2, TypeOfCousinsTheyAre, DegreesRemovedTheyAre. I am trying to write rules that determine whether two people are first-cousins-once-removed.
Here is the line that uses the or operator which won't return true if the right side is true:
cousins(A, B, 1, 1) :- ( cousinsCase1(A, B, 1, 1) ; cousinsCase2(A, B, 1, 1) ).
Other things I have tried:
(1) Omitting the or operator and writing two identical functions, but whenever they are called and the top one fails, my program crashes.
cousins(A, B, 1, 1) :- var(FirstCousin),
cousin(A, FirstCousin, 1, 0),
parent(FirstCousin, B),
A \= B.
cousins(A, B, 1, 1) :- var(P1),
parent(P1, A),
cousin(P1, B, 1, 0),
A \= B,
A \= P1,
B \= P1.
(2) I have also tried an if-statement to call the other function if the first one fails, but it crashes if the first case fails again.
cousins(A, B, 1, 1) :- cousinsCase1(A, B, 1, 1) -> true ; cousinsCase2(A, B, 1, 1)).
Is there a different way to call the other rule if the first one fails?
EDIT
To take the advice given, here is more of the code:
Facts:
parent(gggm, ggm).
parent(ggm, gm).
parent(gm, m).
parent(m, self).
parent(self, d).
parent(d, gd).
parent(gggm, gga).
parent(gga, c12a).
parent(c12a, c21a).
parent(c21a, c3).
parent(ggm, ga)
parent(ga, c11a).
parent(c11a, c2).
parent(gm, a).
parent(a, c1).
parent(m, s).
parent(s, n).
parent(n, gn).
parent(c1, c11b).
parent(c11b, c12b).
parent(c2, c21b).
parent(c21b, c22).
parent(c3, c31).
parent(c31, c32).
Other rules I have written in order to get the above ones to work:
% Sibling Rule
sibling(A, B) :- parent(P, A), parent(P, B), A \= B.
% First-cousin Rule:
cousin(A, B, 1, 0) :- sibling(P1, P2), parent(P1, A), parent(P2, B).
% Second-cousin Rule:
cousin(A, B, 2, 0) :- parent(P1, A),
parent(P2, B),
parent(PP1, P1), % your grandparent
parent(PP2, P2), % your grand-aunt/uncle
sibling(PP1, PP2). % they're siblings
% 3rd-cousin and more Rule
cousin(A, B, M, 0) :- ReducedM = M - 1,
cousin(A, B, ReducedM, 0).
Calls to the above rules: Sidenote: Both calls do work but the problem is getting them both to work without commenting out the other rule:
cousins(self, c11b, 1, 1).
This call corresponds to the first "1st-cousin, once-removed" case and the case returns the correct answer of true if the other case is commented out.
cousins(self, c11a, 1, 1).
This call corresponds to the second "1st-cousin, once-removed" case and the case returns the correct answer of true if the other case is commented out.
This is a comment in an answer because it will not format correctly in a comment.
What most beginners to Prolog don't realize early enough is that Prolog is based on logic (that they realize) and the three basics operators of logic and, or and not are operators in Prolog, namely (, ; \+). It is not realizing those operators for what they really are.
Starting with not which in Prolog use to be not/1 but is now commonly (\+)/1.
?- \+ false.
true.
?- \+ true.
false.
or using the older not/1 which you can use but is like speaking in a Shakespearean play because it is no longer done this way. I am including this here because many older examples still have it in the examples this way.
?- not(true).
false.
?- not(false).
true.
Next is and which in Prolog is ,/2.
The reason many new Prolog users don't see this as logical and is that a , in many other programming languages is seen as a statement separator (Ref) and acting much like a , in an English sentence. The entire problem with understating , in programming is that it is really an operator and is used for so many things that programmers don't even realize that it should almost always be thought of as an operator but with many different meanings, (operator overloading). Also because , is used as a statement separator, the statements are typically put on separate lines and some programmers even think that a comma (,) is just a statement end like a period (.) is a line end in a sentence; that is not the way to think of these single character operators. They are operators and need to be seen and comprehended as such.
So now that you know where and how your ideas that cause you problems are coming from, the next time you see a comma , or a period . in a programming language really take time to think about what it means.
?- true,true.
true.
?- true,false.
false.
?- false,true.
false.
?- false,false.
false.
Finally logical or which in Prolog is ;/2 or in DCGs will appear as |/2. The use of |/2 in DCGs is the same as | in BNF.
?- true;true.
true ;
true.
?- true;false.
true ;
false.
?- false;true.
true.
?- false;false.
false.
The interesting thing to note about the results of using or (;) in Prolog is that it will they will return when true as many times as one of the propositions is true and false only when all of the propositions are false. (Not sure if proposition is the correct word to use here). e.g.
?- false;false;false.
false.
?- false;false;true.
true.
?- true;false;true.
true ;
true.
?- true;true;true.
true ;
true ;
true.
In case you didn't heed my warning about thinking about the operators when you see them, how many of you looked at
?- true,true.
true.
and did not think that would commonly be written in source code as
true,
true.
with the , looking like a statement end. , is not a statement end, it is the logical and operator. So do yourself a favor and be very critical of even a single , as it has a specific meaning in programming.
A reverse way to get this idea across is to use the addition operator (+) like a statement end operator which it is not but to someone new to math could be mistakenly taken to be that as seen in this reformatting of a simple math expression.
A =
1 +
2 +
3
That is not how one is use to seeing a simple math expression, but in the same way how some programmers are looking at the use of the , operator.
Over the years one thing I have seen that divides programmers who easily get this from the programmers who struggle with this all their careers are those that do well in a parsing class easily get this because they have to parse the syntax down to the tokens such as ,, then convert that into the semantics of the language.
For more details see section 1.2. Control on page 23 of this paper.
EDIT
You really need to use test cases. Here are two to get you started.
This is done using SWI-Prolog
:- begin_tests(family_relationship).
sibling_test_case_generator(ggm ,gga ).
sibling_test_case_generator(gga ,ggm ).
sibling_test_case_generator(gm ,ga ).
sibling_test_case_generator(ga ,gm ).
sibling_test_case_generator(m ,a ).
sibling_test_case_generator(a ,m ).
sibling_test_case_generator(self,s ).
sibling_test_case_generator(s ,self).
test(01,[forall(sibling_test_case_generator(Person,Sibling))]) :-
sibling(Person,Sibling).
cousin_1_0_test_case_generator(gm ,c12a).
cousin_1_0_test_case_generator(ga ,c12a).
cousin_1_0_test_case_generator(m ,c11a).
cousin_1_0_test_case_generator(a ,c11a).
cousin_1_0_test_case_generator(self,c1 ).
cousin_1_0_test_case_generator(s ,c1 ).
cousin_1_0_test_case_generator(d ,n ).
cousin_1_0_test_case_generator(c12a,gm ).
cousin_1_0_test_case_generator(c12a,ga ).
cousin_1_0_test_case_generator(c11a,m ).
cousin_1_0_test_case_generator(c11a,a ).
cousin_1_0_test_case_generator(c1 ,self).
cousin_1_0_test_case_generator(c1 ,s ).
cousin_1_0_test_case_generator(n ,d ).
test(02,[nondet,forall(cousin_1_0_test_case_generator(Person,Cousin))]) :-
cousin(Person, Cousin, 1, 0).
:- end_tests(family_relationship).
EDIT
By !Original:J DiVector: Matt Leidholm (LinkTiger) - Own work based on: Cousin tree.png, Public Domain, Link
This is an answer.
Using this code based on what you gave in the question and a few changes as noted below this code works. Since you did not give test cases I am not sure if the answers are what you expect or need.
parent(gggm, ggm).
parent(ggm, gm).
parent(gm, m).
parent(m, self).
parent(self, d).
parent(d, gd).
parent(gggm, gga).
parent(gga, c12a).
parent(c12a, c21a).
parent(c21a, c3).
parent(ggm, ga).
parent(ga, c11a).
parent(c11a, c2).
parent(gm, a).
parent(a, c1).
parent(m, s).
parent(s, n).
parent(n, gn).
parent(c1, c11b).
parent(c11b, c12b).
parent(c2, c21b).
parent(c21b, c22).
parent(c3, c31).
parent(c31, c32).
% Sibling Rule
sibling(A, B) :-
parent(P, A),
parent(P, B),
A \= B.
% First-cousin Rule:
cousin(A, B, 1, 0) :-
sibling(P1, P2),
parent(P1, A),
parent(P2, B).
% Second-cousin Rule:
cousin(A, B, 2, 0) :-
parent(P1, A),
parent(P2, B),
parent(PP1, P1), % your grandparent
parent(PP2, P2), % your grand-aunt/uncle
sibling(PP1, PP2). % they're siblings
% 3rd-cousin and more Rule
cousin(A, B, M, 0) :-
% ReducedM = M - 1,
ReducedM is M - 1,
ReducedM > 0,
cousin(A, B, ReducedM, 0).
cousinsCase1(A, B, 1, 1) :-
% var(FirstCousin),
cousin(A, FirstCousin, 1, 0),
parent(FirstCousin, B),
A \= B.
cousinsCase2(A, B, 1, 1) :-
% var(P1),
parent(P1, A),
cousin(P1, B, 1, 0),
A \= B,
A \= P1,
B \= P1.
cousins(A, B, 1, 1) :-
(
cousinsCase1(A, B, 1, 1)
;
cousinsCase2(A, B, 1, 1)
).
The first change was as Paulo noted and the checks for var/2 were commented out.
The next change was to change = to is.
The third change to stop infinite looping was to add ReducedM > 0,.
This query now runs.
?- cousins(Person,Cousin,1,1).
Person = gm,
Cousin = c21a ;
Person = ga,
Cousin = c21a ;
Person = m,
Cousin = c2 ;
Person = a,
Cousin = c2 ;
Person = self,
Cousin = c11b ;
Person = s,
Cousin = c11b ;
Person = d,
Cousin = gn ;
Person = c12a,
Cousin = m ;
Person = c12a,
Cousin = a ;
Person = c12a,
Cousin = c11a ;
Person = c11a,
Cousin = self ;
Person = c11a,
Cousin = s ;
Person = c11a,
Cousin = c1 ;
Person = c1,
Cousin = d ;
Person = c1,
Cousin = n ;
Person = n,
Cousin = gd ;
Person = m,
Cousin = c12a ;
Person = self,
Cousin = c11a ;
Person = d,
Cousin = c1 ;
Person = gd,
Cousin = n ;
Person = c21a,
Cousin = gm ;
Person = c21a,
Cousin = ga ;
Person = c11a,
Cousin = c12a ;
Person = c2,
Cousin = m ;
Person = c2,
Cousin = a ;
Person = a,
Cousin = c12a ;
Person = c1,
Cousin = c11a ;
Person = s,
Cousin = c11a ;
Person = n,
Cousin = c1 ;
Person = gn,
Cousin = d ;
Person = c11b,
Cousin = self ;
Person = c11b,
Cousin = s ;
false.

Why does p =\= 'p' return an error in SWI-prolog?

I have question with single quote atom.
While p == 'p' returns true, why is p =\= 'p' not returning false? it gives me an error saying 'p' is not a function.
Because == checks term equality, while =\= checks arithmetical inequality. Being as p is not a number, Prolog treats it as an arithmetic expression, trying to find out its arithmetic value:
1 ?- p == 'p'.
true.
2 ?- p =/= 'p'.
ERROR: Syntax error: Operator expected
ERROR: p
ERROR: ** here **
ERROR: =/= 'p' .
2 ?- p =\= 'p'.
ERROR: =\=/2: Arithmetic: `p/0' is not a function
3 ?-

Can prolog be used to determine invalid inference?

If I have two premises as follows:
a -> c (a implies c)
b -> c (b implies c)
and a derived conclusion:
a -> b (a therefore implies b),
then the conclusion can be shown to be invalid because:
a -> c is valid for statement #1 when a is true and c is true, and
b -> c is valid for statement #2 when b is false and c is true. This leads to a -> b when a is true and b is false, a direct contradiction of statement #3.
Or, per proof with a truth table that contains a line for where the premises are true but the conclusion is false:
Truth Table with true premises and false conclusion
My question is: "Is there a way to use prolog to show that the assertions of statements #1 and #2 contradict the conclusion of statement #3? If so, what is a clear and concise way to do so?"
#coder has already given a very good answer, using clpb constraints.
I would like to show a slightly different way to show that the conclusion does not follow from the premises, also using CLP(B).
The main difference is that I post individual sat/1 constraints for each of the premises, and then use taut/2 to see whether the conclusion follows from the premises.
The first premise is:
a → c
In CLP(B), you can express this as:
sat(A =< C)
The second premise, i.e., b &rightarrow; c, becomes:
sat(B =< C)
If the a &rightarrow; b followed from these premises, then taut/2 would succeed with T = 1 in:
?- sat(A =< C), sat(B =< C), taut(A =< B, T).
false.
Since it doesn't, we know that the conclusion does not follow from the premises.
We can ask CLP(B) to show a counterexample, i.e., an assignment of truth values to variables where a &rightarrow; c and b &rightarrow; c both hold, and a &rightarrow; b does not hold:
?- sat(A =< C), sat(B =< C), sat(~(A =< B)).
A = C, C = 1,
B = 0.
Simply posting the constraints suffices to show the unique counterexample that exists in this case. If the counterexample were not unique, we could use labeling/1 to produce ground instances, for example: labeling([A,B,C]).
For comparison, consider for example:
?- sat(A =< B), sat(B =< C), taut(A =< C, T).
T = 1,
sat(A=:=A*B),
sat(B=:=B*C).
This shows that a &rightarrow; c follows from a &rightarrow; b ∧ b &rightarrow; c.
You could use library(clpb):
Firstly assign to a variable Expr your expression:
Expr = ((A + ~C)*(B + ~C)+(~(A + ~B)).
Note that:
'+' stands for logical OR
'*' for logical AND
'~' for logical NOT
Also A->B is equivalent with A+(~B). So the above expression is equivalent with ((A->C),(B->C))-> (A->C) where we wrote '->' using +,~ and ',' with *.
Now if we query:
?- use_module(library(clpb)).
true.
?- Expr=((A + ~C)*(B + ~C))+(~(A + ~B)),taut(Expr,T).
false.
Predicate taut/2 takes as input an clpb Expression and returns T=1 if it tautology, T=0 if expression cannot be satisfied and fails in any other case. So the fact that the above query failed means that Expr was nor a tautology neither could not be satisfied, it meant that it could be satisfied.
Also by querying:
?- Expr=((A + ~C)*(B + ~C))+(~(A + ~B)),sat(Expr).
Expr = (A+ ~C)* (B+ ~C)+ ~ (A+ ~B),
sat(1#C#C*B),
sat(A=:=A).
Predicate sat/1 returns True iff the Boolean expression is satisfiable and gives the answer that the above Expression is satisfiable when:
sat(1#C#C*B),
sat(A=:=A).
where '#' is the exclusive OR which means that your expression (we know from taut/2 that is satisfiable) is satisfied when 1#C#C*B is satisfied.
Another solution without using libraries could be:
truth(X):-member(X,[true,false]).
test_truth(A,B,C):-
truth(A),
truth(B),
truth(C),
((A->C),(B->C)->(A->C)).
Example:
?- test_truth(A,B,C).
A = B, B = C, C = true ;
false.
Also if I understood correctly from your comment, to collect all possible solutions you could write:
?- findall([A,B,C],test_truth(A,B,C),L).
L = [[true, true, true]].
Which gives a list of lists, where the inner lists have the form [true,true,true] in the above example which means a solution is A=true,B=true,C=true and in the above case it has only one solution.
To find all contradictions you could write:
truth(X):-member(X,[true,false]).
test_truth(A,B,C):-
truth(A),
truth(B),
truth(C),
not( (\+ ((\+A; C),(\+B ; C)) ; (\+A ; B)) ).
last line could also been written as:
not( ( (A->C;true),(B->C;true) ) -> (A->B;true) ;true ).
Example:
?- findall([A,B,C],test_truth(A,B,C),L).
L = [[true, false, true]].

Please i am new in prolog can some body help me in this exercice

Write a predicate less/2, such that if t1 represents n1 and t2 represents n2, then
less(t1, t2) succeeds iff n1 < n2. For example, less(s(z), s(s(s(z)))) should
succeed, and less(s(z), s(z)) should fail. If t1 is an uninstantiated logic variable,
while t2 is a proper representation of a natural number n2, then the predicate
should enumerate all numbers less than n2. For example, the query
?- less(X, s(s(z))).
should succeed with X = z and X = s(z) (not necessarily in that order).
You might try the following:
ls(0,s(_)).
ls(s(X),s(Y)) :- ls(X,Y).
Here are some example runs:
?- ls(s(0),s(s(s(0)))).
Yes
?- ls(s(s(0)),s(0)).
No
Bye

Resources