What is the difference between this:
X \= Y
and this piece of code:
dif(X, Y)
I thought that they should behave the same, but they do not. Here's the example:
n_puta(L, N, X) :- nputa(L, N, 0, X).
nputa([], N, C, _) :- N = C.
nputa([G|R], N, C, X) :- G = X, nputa(R, N, Y, X), C is Y - 1.
nputa([G|R], N, C, X) :- dif(G,X), nputa(R, N, C, X).
And here are some calls:
?- n_puta([a,a,b,b,b], 2, X).
X = a ;
false.
?- n_puta([a,a,b,a,b,b], 3, X).
X = a ;
X = b ;
false.
X should be the atom that occurs exactly N times in the list L. If I replace dif(G, X) with G \= X, I don't get the expected result. Can someone tell me what is the difference between these two operators? Can I use anything else except dif(G, X)?
This example works prefectly in SWI-Prolog, but doesn't work in Amzi! Prolog.
dif/2 and (\=)/2 are the same as long as their arguments are ground. But only dif/2 is a pure relation that works correctly also with variables and can be used in all directions. Your example clearly shows that you should use dif/2 in this case, because you use your predicate not only to test, but also to generate solutions. The most widely used Prolog systems all provide dif/2.
Related
I'm trying to program the unification algorithm in Prolog to verify if two expressions can unify by returning boolean True/False:
EDIT.
I found this implementation usefull:
from: http://kti.mff.cuni.cz/~bartak/prolog/data_struct.html
unify(A,B):-
atomic(A),atomic(B),A=B.
unify(A,B):-
var(A),A=B. % without occurs check
unify(A,B):-
nonvar(A),var(B),A=B. % without occurs check
unify(A,B):-
compound(A),compound(B),
A=..[F|ArgsA],B=..[F|ArgsB],
unify_args(ArgsA,ArgsB).
unify_args([A|TA],[B|TB]):-
unify(A,B),
unify_args(TA,TB).
unify_args([],[]).```
Here is a partial implementation of something like the Martelli and Montanari unification algorithm described at https://en.wikipedia.org/wiki/Unification_(computer_science)#A_unification_algorithm. The comments for each part refer to the corresponding rewrite rule from the algorithm. Note that there is no need for an explicit conflict rule, we can just fail if no other rule applies.
% assuming a universe with function symbols g/2, p/2, q/2
% identical terms unify (delete rule)
unify(X, Y) :-
X == Y,
!.
% a variable unifies with anything (eliminate rule)
unify(X, Y) :-
var(X),
!,
X = Y.
% an equation Term = Variable can be solved as Variable = Term (swap rule)
unify(X, Y) :-
var(Y),
!,
unify(Y, X).
% given equal function symbols, unify the arguments (decompose rule)
unify(g(A, B), g(X, Y)) :-
unify(A, X),
unify(B, Y).
unify(p(A, B), p(X, Y)) :-
unify(A, X),
unify(B, Y).
unify(q(A, B), q(X, Y)) :-
unify(A, X),
unify(B, Y).
Examples:
?- unify(q(Y,g(a,b)), p(g(X,X),Y)).
false.
?- unify(q(Y,g(a,b)), q(g(X,X),Y)).
false.
?- unify(q(Y,g(a,a)), q(g(X,X),Y)).
Y = g(a, a),
X = a.
One or two things remain for you to do:
Generalize the decompose rule to deal with arbitrary terms. You might find the =.. operator useful. For example:
?- Term = r(a, b, c), Term =.. FunctorAndArgs, [Functor | Args] = FunctorAndArgs.
Term = r(a, b, c),
FunctorAndArgs = [r, a, b, c],
Functor = r,
Args = [a, b, c].
You will need to check if two terms have the same functor and the same number of arguments, and whether all corresponding pairs of arguments unify.
Find out if your professor would like you to implement the occurs check, and if yes, implement it.
I have two, slightly different, implementations of a predicate, unique_element/2, in Prolog. The predicate succeeds when given an element X and a list L, the element X appears only once in the list. Below are the implementations and the results:
Implementation 1:
%%% unique_element/2
unique_element(Elem, [Elem|T]) :-
not(member(Elem, T)).
unique_element(Elem, [H|T]) :-
member(Elem, T),
H\==Elem,
unique_element(Elem, T),
!.
Results:
?- unique_element(X, [a, a, b, c, c, b]).
false.
?- unique_element(X, [a, b, c, c, b, d]).
X = a ;
X = d.
Implementation 2:
%%% unique_element/2
unique_element(Elem, [Elem|T]) :-
not(member(Elem, T)).
unique_element(Elem, [H|T]) :-
H\==Elem,
member(Elem, T),
unique_element(Elem, T),
!.
In case you didn't notice at first sight: H\==Elem and member(Elem, T) are flipped on the 2nd impl, rule 2.
Results:
?- unique_element(X, [a, a, b, c, c, b]).
X = a.
?- unique_element(X, [a, b, c, c, b, d]).
X = a ;
X = d.
Question: How does the order, in this case, affect the result? I realize that the order of the rules/facts/etc matters. The two specific rules that are flipped though, don't seem to be "connected" or affect each other somehow (e.g. a cut in the wrong place/order).
Note: We are talking about SWI-Prolog here.
Note 2: I am aware of, probably different and better implementations. My question here is about the order of sub-goals being changed.
H\==Elem is testing for syntactic inequality at the point in time when the goal is executed. But later unification might make variables identical:
?- H\==Elem, H = Elem.
H = Elem.
?- H\==Elem, H = Elem, H\==Elem.
false.
So here we test if they are (syntactically) different, and then they are unified nevertheless and thus are no longer different. It is thus just a temporary test.
The goal member(Elem, T) on the other hand is true if that Elem is actually an element of T. Consider:
?- member(Elem, [X]).
Elem = X.
Which can be read as
(When) does it hold that Elem is an element of the list [X]?
and the answer is
It holds under certain circumstances, namely when Elem = X.
If you now mix those different kinds of goals in your programs you get odd results that can only explained by inspecting your program in detail.
As a beginner, it is best to stick to the pure parts of Prolog only. In your case:
use dif/2 in place of \==
do not use cuts - in your case it limits the number of answers to two. As in
unique_element(X, [a,b,c])
do not use not/1 nor (\+)/1. It produces even more incorrectness. Consider unique_element(a,[a,X]),X=b. which incorrectly fails while X=b,unique_element(a,[a,X]) correctly succeeds.
Here is a directly purified version of your program. There is still room for improvement!
non_member(_X, []).
non_member(X, [E|Es]) :-
dif(X, E),
non_member(X, Es).
unique_element(Elem, [Elem|T]) :-
non_member(Elem, T).
unique_element(Elem, [H|T]) :-
dif(H,Elem),
% member(Elem, T), % makes unique_element(a,[b,a,a|Xs]) loop
unique_element(Elem, T).
?- unique_element(a,[a,X]).
dif(X, a)
; false. % superfluous
?- unique_element(X,[E1,E2,E3]).
X = E1, dif(E1, E3), dif(E1, E2)
; X = E2, dif(E2, E3), dif(E1, E2)
; X = E3, dif(E2, E3), dif(E1, E3)
; false.
Note how the last query reads?
When is X a unique element of (any) list [E1,E2,E3]?
The answer is threefold. Considering one element after the other:
X is E1 but only if it is different to E2 and E3
etc.
TL;DR: Read the documentation and figure out why:
?- X = a, X \== a.
false.
?- X \== a, X = a.
X = a.
I wonder why you stop so close from figuring it out yourself ;-)
There are too many ways to compare things in Prolog. At the very least, you have unification, which sometimes can compare, and sometimes does more; than you have equvalence, and its negation, the one you are using. So what does it do:
?- a \== b. % two different ground terms
true.
?- a \== a. % the same ground term
false.
Now it gets interesting:
?- X \== a. % a free variable and a ground term
true.
?- X \== X. % the same free variable
false.
?- X \== Y. % two different free variables
true.
I would suggest that you do the following: figure out how member/2 does its thing (does it use unification? equivalence? something else?) then replace whatever member/2 is using in all the examples above and see if the results are any different.
And since you are trying to make sure that things are different, try out what dif/2 does. As in:
?- dif(a, b).
or
?- dif(X, X).
or
?- dif(X, a).
and so on.
See also this question and answers: I think the answers are relevant to your question.
Hope that helps.
Here is another possibility do define unique_element/2 using if_/3 and maplist/2:
:- use_module(library(apply)).
unique_element(Y,[X|Xs]) :-
if_(Y=X,maplist(dif(Y),Xs),unique_element(Y,Xs)).
In contrast to #user27815's very elegant solution (+s(0)) this version does not build on clpfd (used by tcount/3). The example queries given by the OP work as expected:
?- unique_element(a,[a, a, b, c, c, b]).
no
?- unique_element(X,[a, b, c, c, b, d]).
X = a ? ;
X = d ? ;
no
The example provided by #false now succeeds without leaving a superfluous choicepoint:
?- unique_element(a,[a,X]).
dif(a,X)
The other more general query yields the same results:
?- unique_element(X,[E1,E2,E3]).
E1 = X,
dif(X,E3),
dif(X,E2) ? ;
E2 = X,
dif(X,E3),
dif(X,E1) ? ;
E3 = X,
dif(X,E2),
dif(X,E1) ? ;
no
Can you not define unique_element like tcount Prolog - count repetitions in list
unique_element(X, List):- tcount(=(X),List,1).
This question already has answers here:
Prolog, X before Y in a List
(4 answers)
Closed 6 years ago.
I am going to write predicate which is true iff only and only when element X occurs before Y on list L
before(L, X, Y) :-
nth1(PX, L, X),
nth1(PY, L, Y),
PX < PY.
Above, you can see my solution. What do you think about it ?
When it comes to my specific question:
My predicate returns true when there is exists at least one pair that Y followed X. How to define predicate such that it is true for each pair ?
The solution you show works for the "if one exists" case, but is somewhat imperative in nature. That is, it's a little bit like a C program translated to Prolog. Imperative means you are telling the computer, using the programming language, what steps to execute in order to achieve your results.
To be more declarative or relational, your "exists" solution could be expressed nicely as a DCG:
... --> [].
... --> [_], ... .
before(X, Y) --> ... , [X], ... , [Y], ... .
(NOTE: You can in Prolog have a predicate named ..., which is shown here.) This describes the relationship of X and Y in the list. It does not describe steps to execute, but instead describes the relationship of X and Y in a sequence. This solution has been shown before on SO.
Following this approach (where we describe the relationship of X and Y), one way (not necessarily the only way) to express that all the X precede all the Y would be:
before_all(X, Y) -->
{ dif(X,Y) },
any_sequence_but(Y), [X], any_sequence_but(Y), [Y], any_sequence_but(X).
any_sequence_but(_) --> [].
any_sequence_but(Y) --> [X], { dif(X,Y) }, any_sequence_but(Y).
Which yields a solution like this:
?- phrase(before_all(X,Y), [b,a,b,c,a,b,d]).
X = b,
Y = d ;
X = a,
Y = d ;
X = b,
Y = d ;
X = c,
Y = d ;
X = a,
Y = d ;
X = b,
Y = d ;
false.
?-
If the condition should hold for all pairs, the condition should hold for at least one pair, while its converse shouldn't be true for any pair.
I took the liberty of renaming your before/3 to beforeSome/3.
beforeSome(L, X, Y) :-
nth1(PX, L, X),
nth1(PY, L, Y),
PX < PY.
beforeAll(L, X, Y) :-
beforeSome(X,Y),
not(beforeSome(L, Y, X)).
Which yields the desired results:
?- beforeAll([1,2,3,1,4,5], 1, 4).
true.
?- beforeAll([1,2,3,1,4,5], 1, 2).
false.
Please note that your use of nth1/3 precludes it being used with uninstantiated variables. In other words, beforeAll([1,2,3,1,4,5], X, Y). is false.
A better implementation of beforeSome/3 would be something like
beforeSome([X|T], X, Y) :-
member(Y, T).
beforeSome([_|T], X, Y) :-
beforeSome(T, X, Y).
% no change needed, but repeated here for completeness' sake
beforeAll(L, X, Y) :-
beforeSome(X,Y),
not(beforeSome(L, Y, X)).
How can i define that two variables are not equal in Prolog? For example :
z is X and Y parent
X is male and Y is female
Now i want find sisters or brothers. But Prolog result is:
Y sister Y when parent have one child and not have X
Now i want define:
different(X,y).
I think old or other version of Visual Prolog have "different" in library but i dont find this in new Visual Prolog. What can i do?
define two variables are not equal in Prolog:
X \= Y
not(X = Y)
\+ (X = Y)
Equivalence in Prolog is ==/2. This is also defined between variables. It specifically does not unify two different variables as =/2 would.
Some simple examples:
?- X = Y.
X = Y.
?- X == Y.
false.
And:
?- X = X.
true.
?- X == X.
true.
Since you specifically ask for equality between variables, I am wondering whether you are asking for something more than equivalence. Equality is sometimes defined as equivalence under substitution. So that a = b implies f(..., a, ...) = f(..., b, ...).
In Prolog this seems to be the case as well:
?- f(a, B1, c) = f(a, B2, c).
B1 = B2.
?- f(a, B1, c) == f(a, B2, c).
false.
And:
?- f(a, B, c) = f(a, B, c).
true.
?- f(a, B, c) == f(a, B, c).
true.
Hope this helps!
I'm very new to Prolog so please bear with me.
Lets say I have the following:
foo(bar(a,b)).
foo(bar(b,a)).
Then I enter foo(X) as a query:
?- foo(X).
X = bar(a, b) ;
X = bar(b, a).
Prolog returns two instantiations of X to satisfy the query: bar(a, b) and bar(b,a).
Is there away I can make these two instantiations equivalent? Once Prolog instantiates X to bar(a,b), it won't instantiate it to bar(b,a).
So when I enter foo(X) as a query:
?- foo(X).
X = bar(a, b).
X was no instantiated as bar(b,a), because it's equivalent to bar(a,b). Is this possible to do with Prolog, or does it go against the fundamental principals of Prolog?
The first clause of symmetry/2 deals with cases in which both foo(bar(a,b)) and foo(bar(b,a)) occur. I use the standard order of terms in order to return only the former. Notice that the use of #< would have falsely excluded results like foo(bar(e,e)).
The second clause treats cases in which either foo(bar(c,d)) or foo(bar(d,c)) occur.
foo(bar(a, b)).
foo(bar(b, a)).
foo(bar(c, d)).
foo(bar(e, e)).
symmetry(X, Y):-
foo(bar(X, Y)),
foo(bar(Y, X)),
X #=< Y.
symmetry(X, Y):-
foo(bar(X, Y)),
\+ foo(bar(Y, X)).
Example of usage:
?- symmetry(X, Y).
X = a,
Y = b ;
X = Y, Y = e ;
X = c,
Y = d ;
false
Hope this helps!
Identity of literals it's the core of unification - the fundamental operation of Prolog algorithm - and then the answer to your question it's no, it's not possible to handle bar(a,b) as bar(b,a).