Not equal and not unify in Prolog - prolog

What is the difference between A \= B and not(A==B) in Prolog?
I found this http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse5
and this wiki page
http://en.wikibooks.org/wiki/Prolog/Built-in_predicates
but it didn't help me since there is no clarification to the difference, nor short meaning for \=.
Thanks.

A \= B is equivalent to not (A = B)
So lets compare =/2 and ==/2 first; from the swi-prolog manual:
?Term1 = ?Term2
Unify Term1 with Term2. True if the unification succeeds
#Term1 == #Term2
True if Term1 is equivalent to Term2.
Notice that =/2 tries to unify the terms and if it succeeds it's true while ==/2 just performs a check:
?- X = 1.
X = 1.
(implicit true.)
while
?- X == 1.
false.
and also:
?- X = Y.
X = Y.
?- X == Y.
false.
now, not/1 will invert the result and be true if =/2 or ==/2 was false.
for==/2 there is nothing complicated; if the terms were equivalent now it will return false otherwise true.
for =/2 you should remember that all unifications will be temporary:
?- \+ (\+ X = 1), print(X).
_G399
true.
(_G399 indicates that X is non-instantiated)

Related

Why `X=1,X=1.` prints `X=1` instead of `true`

I'm learning the basics of Prolog and I was wondering why the following line prints X = 1 instead of true?
?- X=1,1=X.
X = 1.
--
The first X=1 in my command is an assignment, and the second one will be a check of equality.
There are no assignments or equality tests in your query, only unification of terms. The query succeeds by unifying the variable X with 1 and that's what the top-level reports: it tells which variable bindings makes the query true.
After the first goal in the conjunction, X = 1, succeeds, the second goal is the unification 1 = 1, which trivially succeeds.
P.S. Also note that Prolog systems differ in the way they report successful queries. Some print true, others print yes (the traditional way that successful queries are reported).
When the answer is true and a value is bound to variable at the top level, the value of the variable is displayed, which implies the result was true.
Here are some examples.
test_01 :-
X = 1,
X = 1.
test_02 :-
X = 1,
X = 2.
test_03(X) :-
X = 1,
X = 1.
test_04(X) :-
X = 1,
X = 2.
and when the examples are run from the top level using SWI-Prolog
?- test_01.
true.
?- test_02.
false.
?- test_03(X).
X = 1.
?- test_04(X).
false.
Here are some examples that are done only in the top level
?- X=1.
X = 1.
?- 1=1.
true.
?- 1=0.
false.
?- 1==0.
false.
The first X=1 in my command is an assignment, and the second one will be a check of equality.
X=1 is not an assignment it is a unification of the integer 1 to the variable X. The second X=1 is not a check of the equality, it is another unification of X to 1, but since X is bound to 1 by this time, it is really a different unification.
To do equality checking in Prolog use ==, e.g.
?- 1 == 1.
true.
?- 1 == 2.
false.
Also , is the logical and, so if
?- X = 1.
X = 1.
then 1 is bound to X and is true and similar for the second line in your question.
However the code has to be also viewed as
?- true,true.
true.
as opposed to
?- true,false.
false.
While ; is logical or
?- true;true.
true ;
true.
?- true;false.
true ;
false.
?- true;false;true.
true ;
true.
?- false;true.
true.
?- false;false.
false.
Notice that the first 3 answers have 2 results, but the last two answers have 1 result.

Prolog only check variable is instantiated

In Prolog, is it possible to check if the variable is certain value only if the variable is instantiated.
? - my_rule(X).
my_rule(X):-
X = 4,
write('continue').
Here I am trying to check if the X is 4, if the X is 4 then we continue, but I also want the rule to continue if the X is _, but when it is called with something else, like X is 3 then it should not continue.
So the results would look like this:
?- my_rule(X).
continue
true.
?- my_rule(4).
continue
true.
?- my_rule(3).
false.
Have a look at var/1, atom/1 and ground/1:
var(X) is true if and only if X is a variable.
?- var(X), X= 1.
X = 1.
?- X=1, var(X).
false.
?- X=f(Y), var(X).
false.
atom(X) is true if X is an atom.
?- atom(a).
true.
?- atom(f(a)).
false.
?- atom(X).
false.
ground(X) is true if X is ground (does not contain variables).
?- ground(f(a)).
true.
?- ground(f(X)).
false.
The three predicates are deterministic (i.e. do not backtrack) and you can safely negate them.
Your code become something like this:
my_rule(4) :-
% handle the 4 case
my_rule(X) :-
var(X),
% general case
I'm just not sure if this is, what you want. In most programs, there should be no necessity to handle the variable only case separately. Also be aware that such meta-logical tests are outside the scope of classical logic. If compare the queries X = 1, var(X) and var(X), X = 1, you can see that the conjunction is not commutative anymore but in logic A ∧ B = B ∧ A holds.
You can use double negation ( \+(\+(...)) ):
In your example:
my_rule(X):-
\+(\+(X = 4)),
write('continue').
my_rule(X):-
check(X),
write('continue').
% A fact used to check a value.
check(4).
% A predicate that checks if X is unbound, e.g. a variable.
check(X) :-
var(X).
Verification of desired results.
?- my_rule(X).
continue
X = 4 ;
continue
true.
?- my_rule(4).
continue
true ;
false.
?- my_rule(3).
false.

Prolog ... define predicate that checks if both arguments are/point to the same atom

I have a prolog predicate that takes two parameters (both labelled X here since they should be the same) and compares them to see if they evaluate to the same atom. That is the intent. However, the predicate unexpectedly returns false when both arguments are variables.
I'm trying to define a notion of an expression in sentential logic / propositional calculus being in "implication normal form" in Prolog. Implication normal form here meaning that all connectives are replaced with -> and falsum.
As a base case, I want to say that an expression consisting entirely of an atom is already in normal form with itself.
Here's how I'm attempting to express that. I'm repeating a parameter name instead of doing some type of check of sameness between the parameters.
% foo.P
implication_normal(X, X) :- atom(X).
This incomplete-but-still-useful definition is intended to capture the fact that implication_normal(x, x) is true but implication_normal(x, y) is false.
In some ways it seems to work:
$ swipl -s foo.P
?- implication_normal(x, x).
true.
?- implication_normal(x, y).
false.
?- implication_normal(1, 1).
false.
It does the wrong thing with variables (It should be enumerating pairs of "binding contexts" where X and Z happen to point to the same atom).
?- implication_normal(X, Z).
false.
It also just returns false if you give it the same variable twice.
?- implication_normal(X, X).
false.
for some strange reason, the behavior is correct if you give it a variable and a single atom (and you get failure with an integer).
?- implication_normal(X, z).
X = z.
?- implication_normal(X, 1).
false.
and similarly if the variable is second.
?- implication_normal(z, X).
X = z.
?- implication_normal(1, X).
false.
How do I change the definition of implication_normal so that it enumerates in all the cases where variables are supplied?
The standard atom/1 predicate is a type-checking predicate. It doesn't enumerate atoms. It just deterministically checks if its argument is an atom. Moreover, your definition of the implication_normal /2 predicate attempts to unify its two arguments and, if the unification is successful, calls atom/1 with the resulting term. That's why a call such as implication_normal(X, z) succeeds: X is unified with z and atom(z) is true.
Note that some Prolog systems provide a current_atom/1 that does enumerate atoms. On those systems, you could write instead:
implication_normal(X, X) :- current_atom(X).
Some sample calls using SWI-Prolog:
?- implication_normal(X, Z).
X = Z, Z = '' ;
X = Z, Z = abort ;
X = Z, Z = '$aborted'
...
?- implication_normal(X, X).
X = '' ;
X = abort ;
X = '$aborted' ;
...
?- implication_normal(X, z).
X = z.
?- implication_normal(X, 1).
false.

Prolog: comparing predicate value with constant

I have some problems with prolog, specifically I can't compare a value of a predicate with a constant.
predicate(9).
compare(X,Y) :- X<Y.
Running the program:
?-compare(predicate(X),10).
Why doesn't it work? Thank you for your answers.
Predicates don't return values in the way that a function does.
This is C:
int nine() { return 9; }
int main() {
int x = nine(); /* x is now 9 */
}
This is Prolog:
% source
nine(9).
% from the top level
?- nine(X).
X = 9.
?- nine(X), X < 10.
X = 9.
?- nine(X), compare(C1, X, 10), compare(C2, 10, X).
X = 9,
C1 = (<),
C2 = (>).
Few things (trying not to use too much Prolog lingo):
What your predicate/1 and my nine/1 does is to unify its only argument with the integer 9. If the unification succeeds, the predicate succeeds, and now the argument is bound to 9. If the unification fails, the predicate fails.
?- nine(9).
true.
?- nine(nine).
false.
?- nine(X), nine(Y).
X = Y, Y = 9.
You will also notice that there is a standard predicate compare/3 that can be used for comparison of Prolog terms. Because predicates don't have a return value in the way that functions do, it uses an extra argument to report the result of the comparison. You could have instead tried something along the lines of:
% greater_than(X, Y) : true if X is greater than Y according
% to the standard order of terms
greater_than(X, Y) :- X #> Y.
But this is just defining an alias for #>/2, which is a predicate itself (but has been declared as an operator so that you can use it in infix notation).
?- #>(a, b).
false.
?- #>(b, a).
true.
Same goes for </2, which is a predicate for comparison of arithmetic expressions:
?- 2 + 4 =< 6.
true.
?- nine(X), X > 10 - X.
X = 9.
?- nine(X), X > 10.
false.
Like #Boris said before "Predicates don't return values in the way that a function does." Here you must try to instantiate the variables in the head of your rule.
If you are trying with you predicate compare/2 to find a number X greater than Y, and at the same time this number X should be a fact predicate/1, then add both conditions to the body of your rule or predicate compare/2
predicate(9).
compare(X,Y) :- predicate(X), X<Y.
Now if you consult:
?- compare(X,10).
The answer will be
X = 9
As you can see, 9 is smaller than 10, and at the same time 9 is a fact predicate/1. And that is the return value you are looking for.
Caution
Note that the operator >/2, requires that both sides are instantiated, so in this case you won't be able ask for the value Y in your predicate
?- compare(9, Y)
</2: Arguments are not sufficiently instantiated
Maybe and if it make sense, you can try to instantiate this variable to a fact predicate/1 too.
predicate(9).
predicate(10).
compare(X,Y) :- predicate(X), predicate(Y), X<Y.
?- compare(9,Y).
Y = 10

Implement a Prolog predicate that say if an element belong to a list. Problems with not numerical lists

I am studying Prolog for an university exam and I have problems with this exercise:
Implement the predicate not_member(X,L) that is TRUE if the element X does not belong to the list L.
If my reasoning is correct, I have found a solution:
% FACT (BASE CASE): It is TRUE that X is not in the list if the list is empty.
not_member(_,[]).
% RULE (GENERAL CASE): If the list is non-empty, I can divide it in its Head
% element and the sublist Tail. X does not belong to the list if it is different
% from the current Head element and if it does not belong to the sublist Tail.
not_member(X,[Head|Tail]) :-
X =\= Head,
not_member(X,Tail).
This code works well with lists of numbers, as the following queries show:
2 ?- not_member(4, [1,2,3]).
true.
3 ?- not_member(1, [1,2,3]).
false.
With lists having some non-numerical elements, however,
it does not work and reports an error:
4 ?- not_member(a, [a,b,c]).
ERROR: =\=/2: Arithmetic: `a/0' is not a function
Why?
Let's check the documentation!
(=\=)/2 is an arithmetic operator.
+Expr1 =\= +Expr2
True if expression Expr1 evaluates to a number non-equal to Expr2.
You have to use (\=)/2 to compare two generic terms:
not_member(_, []) :- !.
not_member(X, [Head|Tail]) :-
X \= Head,
not_member(X, Tail).
and:
?- not_member(d, [a,b,c]).
true.
Use prolog-dif to get logically sound answers—for both ground and non-ground cases!
Just like in this answer, we define non_member(E,Xs) as maplist(dif(E),Xs).
Let's put maplist(dif(E),Xs) and not_member(E,Xs) by #Haile to the test!
?- not_member(E,[1,2,3]).
false. % wrong! What about `E=4`?
?- maplist(dif(E),[1,2,3]).
dif(E,1), dif(E,2), dif(E,3). % success with pending goals
Is it steadfast? (For more info on this important issue, read
this, this, this, and this answer.)
?- E=d, not_member(E,[a,b,c]).
E = d.
?- not_member(E,[a,b,c]), E=d.
false. % not steadfast
?- E=d, maplist(dif(E),[a,b,c]).
E = d.
?- maplist(dif(E),[a,b,c]), E=d. % steadfast
E = d.
Let's not forget about the most general use!
?- not_member(E,Xs).
Xs = []. % a lot of solutions are missing!
?- maplist(dif(E),Xs).
Xs = []
; Xs = [_A] , dif(E,_A)
; Xs = [_A,_B] , dif(E,_A), dif(E,_B)
; Xs = [_A,_B,_C], dif(E,_A), dif(E,_B), dif(E,_C)
...

Resources