Changing order of arguments in predicate changes result - prolog

Hello I'm new to Prolog and some things about it just confuse me.
So I have this list of Facts and a predecate:
parent(gerlinde,mark).
parent(gerlinde,lena).
.
.
(and so on)
female(gerlinde).
.
.
(and so on)
male(mark).
sister(S,X) :- parent(F,S),parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S),S\==X.
So if I do ?-sister(S,X). I get the answers correclty without the answer that S is the sister of herself (S=X). However, if I Change the order like that:
sister(S,X) :- S\==X,parent(F,S),parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S).
or like that:
sister(S,X) :- parent(F,S),S\==X,parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S).
then I suddenly get the answer S=X too. So why is that happening? In my understanding there should be no difference between both predicates.

This is because X\==S is the same as \+X == S, and \+T means 'T cannot be proven'. So, in your second predicate:
sister(S,X) :- S\==X,parent(F,S),parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S).
When S\==X is called, both S and X are variables. Thus, it 'cannot be proven' that S == X and this goal succeeds.
Then, as the predicate continues to be evaluated, parent(F,S) will ground S - in your case, to mark.
Then, parent(F,X) will ground X - to mark again! And it is never required again that S be different from X. Of course, with S = X = mark the predicate fails, as mark is not a female (female(S) fails). But not with lena; she will indeed be her own sister.

Related

Prolog: Assign value to Variable in Predicate

With the following rules:
test('John', ebola).
test('John', covid).
test('Maria', covid).
How can I create a predicate that would tell me if John or Maria took (both) the Ebola and Covid tests?
I want to do something similar to this (I know it's wrong, just the idea):
tests(Persona, Ebola, Covid) :-
Ebola = test(Persona, ebola),
Covid = test(Persona, covid).
Prolog is relational not functional. test(X, Y) either holds or fails and doesn't return a value like what you thought. Here's what you should have written:
tests(Persona) :-
test(Persona, ebola),
test(Persona, covid).
You can query tests('John') which is true since both test/2 calls succeeds. The query tests('Maria') fails because test('Maria', ebola) fails.
Does it answer your question ?

Prolog (Sicstus) - nonmember and setof issues

Given following facts:
route(TubeLine, ListOfStations).
route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...
I am required to find all the pairs of tube Lines that do not have any stations in common, producing the following:
| ?- disjointed_lines(Ls).
Ls = [(yellow,blue),(yellow,green),(yellow,red),(yellow,silver)] ? ;
no
I came up with the below answer, however it does not only give me incorrect answer, but it also does not apply my X^ condition - i.e. it still prints results per member of Stations lists separately:
disjointed_lines(Ls) :-
route(W, Stations1),
route(Z, Stations2),
setof(
(W,Z),X^
(member(X, Stations1),nonmember(X, Stations2)),
Ls).
This is the output that the definition produces:
| ?- disjointed_lines(L).
L = [(green,green)] ? ;
L = [(green,blue)] ? ;
L = [(green,silver)] ? ;
...
I believe that my logic relating to membership is incorrect, however I cannot figure out what is wrong. Can anyone see where am I failing?
I also read Learn Prolog Now chapter 11 on results gathering as suggested here, however it seems that I am still unable to use the ^ operator correctly. Any help would be appreciated!
UPDATE:
As suggested by user CapelliC, I changed the code into the following:
disjointed_lines(Ls) :-
setof(
(W,Z),(Stations1, Stations2)^
((route(W, Stations1),
route(Z, Stations2),notMembers(Stations1,Stations2))),
Ls).
notMembers([],_).
notMembers([H|T],L):- notMembers(T,L), nonmember(H,L).
The following, however, gives me duplicates of (X,Y) and (Y,X), but the next step will be to remove those in a separate rule. Thank you for the help!
I think you should put route/2 calls inside setof' goal, and express disjointness more clearly, so you can test it separately. About the ^ operator, it requests a variable to be universally quantified in goal scope. Maybe a concise explanation like that found at bagof/3 manual page will help...
disjointed_lines(Ls) :-
setof((W,Z), Stations1^Stations2^(
route(W, Stations1),
route(Z, Stations2),
disjoint(Stations1, Stations2)
), Ls).
disjoint(Stations1, Stations2) :-
... % could be easy as intersection(Stations1, Stations2, [])
% or something more efficient: early fail at first shared 'station'
setof/3 is easier to use if you create an auxiliary predicate that expresses the relationship you are interested in:
disjoint_routes(W, Z) :-
route(W, Stations1),
route(Z, Stations2),
disjoint(Stations1, Stations2).
With this, the definition of disjointed_lines/1 becomes shorter and simpler and no longer needs any ^ operators:
disjointed_lines(Ls) :-
setof((W, Z), disjoint_routes(W, Z), Ls).
The variables you don't want in the result of setof/3 are automatically hidden inside the auxiliary predicate definition.

What is the explanation of this code (Prolog)?

I am trying to learn Prolog. I have a problem and the solution for that in Prolog. Though I am unable to understand the code completely.
The call of the code goes like this-
conc(Before,[c|After],[a,b,c,d]) .
This code will return
Before = [a,b]
After = [d]
I have the solution -
conc([],L,L).
conc([X|L1],L2,[X|L3]) :- conc(L1,L2,L3) .
I am not able to understand the flow of the program completely. Let me start with a dry run. I added some write command in order understand the code flow. The code now looks like this -
conc([],L,L):- write("Line1: "), write(L).
conc([X|L1],L2,[X|L3]) :-
write("Line-2: "), write(L1), write(" "),
write(L2), write(" "), write(L3), conc(L1,L2,L3) .
Initial call is -
conc(Before,[c|After],[a,b,c,d]) .
At this moment, the call goes to line 2 (because, Before is unknown term which is not empty)which is :
conc([X|L1],L2,[X|L3]) :-
write("Line-2: "), write(L1), write(" "),
write(L2), write(" "), write(L3), conc(L1,L2,L3) .
At this point, X=[a], l1= unknown, L2=[c|After] and L3=[b,c,d]. This prints -
Line2: _G481 [c|_G368] [b,c,d]
This will again call the recursion(code line 2) with the following value:
cons(L1, [c|After], [b,c,d]). (L1 is unknown still now)
And, prints -
Line2: _G494 [c|_G368] [c,d]
Now the next call will be :
cons(L1, [c|After], [c,d]).
But , I can see while printing the customized comments in the code, that, at this point the code control goes to #line 1 which I am not able to understand. Because, now,
L1= unknown(just as all the previous calls).
L(parameter 2)= [c|After]
L(parameter 3) = [c,d].
But, the control goes to the #line 1, and it prints :
Line1: [c,d]
I thought prolog executes the code from left to right. So, as per my understanding, while executing the value of L should be [c,d].
My question is:
1. After the second call, L1 is undefined as all the calls as before. And, second and third parameters , both are L. So, why, after second call the control goes to the #line1.?
2. Is my understanding correct in this matter ? "I thought prolog executes the code from left to right. So, as per my understanding, while executing the value of L should be [c,d]."
Thanks in advance...
Please help me out!!
You cannot expect to understand everything that is happening here if you look at it procedurally, because there is too much going on at the same time. This is especially true if you are just beginning to learn the language.
A good approach for learning Prolog is to think declaratively, and ask: What are the conditions that make this hold?
In addition, you are currently writing atoms when you actually mean to write variables. Please correct your post to say for example:
cons(L1, [c|After], [c,d])
Note that After is a variable, and after is an atom.
Now, leaving everything else aside, just consider this single goal in isolation. Try it with:
?- cons(L1, [c|After], [c,d]).
In complete accordance with our expectation, we get the solution:
L1 = [],
After = [d]
Thus, it suffices to understand that this goal can be derived in isolation. Also notice the difference between X = [a] and X = a, which you are currently intermingling.

Prolog error in loop

I would need help about Prolog.
I posted my code, the problem is that i do not obtain the expected result.
I want planning actions for moving on table all blocks until is possible. To do this I prompt :
?- do(while(some(x, block(x) & -onTable(x)),pi(x,putOnTable(x))),s0,S).
I expect to see a response like :
S = do(putOnTable(e), do(putOnTable(b), do(putOnTable(c), s0)))
but Prolog returns "false" only. Someone can help me??
% Golog interpreter
%:- [golog_swi].
:- discontiguous clear/2, on/3, onTable/2.
:- op(800,xfy,[&]).
do(E,S,do(E,S)):- primitive_action(E),poss(a,S).
% Primitive Action Declarations.
primitive_action(putOn(_,_)).
primitive_action(putOnTable(_)).
poss(putOn(X,Y),S) :- clear(X,S), clear(Y,S), \+ on(X,Y,S), \+ X=Y.
poss(putOnTable(X),S):- clear(X,S), \+(onTable(X,S)).
% Successor State Axioms.
on(X,Y,do(A,S)):- A = putOn(X,Y); on(X,Y,S), \+ (A = putOnTable(X); A = putOn(X,_)).
onTable(X,do(A,S)) :- A = putOnTable(X); onTable(X,S), \+ A= putOn(X,_).
clear(X,do(A,S)) :- on(Y,X,S), (A = putOn(Y,_) ; A = putOnTable(Y)); clear(X,S), \+ A = putOn(_,X).
% Restore suppressed situation arguments
restoreSitArg(onTable(X),S,onTable(X,S)).
restoreSitArg(on(X,Y),S,on(X,Y,S)).
restoreSitArg(clear(X),S,clear(X,S)).
block(X):- member(X,[a,b,c,d,e]).
% iniTial COndition
onTable(a,s0).
on(b,a,s0).
on(c,b,s0).
clear(c,s0).
onTable(d,s0).
on(e,d,s0).
clear(3,s0).
thank you!!!
Your predicate do/3 cannot succeed because the goal primitive_action/1 will fail with your query.
Currently, while/2 is not described in primitive_action/1 and it seems it is missing also from your program. So you need to extend primitive_action/1 by further facts, or add a new rule to do/3. And in addition to that you need to describe what while/2 means.
This question is actually about Golog. Your mistake is pretty mundane: you didn't copy the Golog interpreter code into your source file/directory.
Golog defines a number of high-level programming constructs, including while-loops and non-deterministic picks (pi), used here. I'm sure you don't want to reinvent Golog, so just go and get it. I'm assuming that your question is part of an assignment of sorts, and your teacher probably pointed you to the Golog interpreter. Otherwise, you can always find it on the pages of the cognitive robotics group at the Univ. of Toronto: http://www.cs.toronto.edu/cogrobo/main/systems/index.html

Prolog, how to show multiple output in write()

go :- match(Mn,Fn),
write('--Matching Result--'),
nl,
write(Mn),
write(' match with '),
write(Fn),
match(Mn1,Fn1).
person(may,female,25,blue).
person(rose,female,20,blue).
person(hock,male,30,blue).
person(ali,male,24,blue).
match(Mn,Fn):-person(Fn,'female',Fage,Fatt),
person(Mn,'male',Mage,Matt),
Mage>=Fage,
Fatt=Matt.
Hi,this is my code...but it's only can show the 1 output...but there are 3 pair of matching in match(X,Y).how to show them all in my go function.
Thank you
You get all your matches if you force backtracking, usually by entering ; (e.g. in SWI Prolog). But you also see that you are getting unnecessary outputs true. This is because the last clause in go is match(Mn1,Fn1). This clause succeeds three times and binds the variables Mn1,Fn1 but then only true is output, because you do not write() after that clause. The fourth time match(Mn1,Fn1) fails and by backtracking you come back to the first clause match(Mn,Fn) that matches, the match is output, etc.
You surely do not want to have this behavior. You should remove the last clause match(Mn1,Fn1) in go. Now by pressing ; you get the 3 matches without any output true in between.
But what you likely want is that the program does the backtracking. To achieve this, you just need to force backtracking by adding false as the last clause. To get proper formatting of the output, use the following program. The last clause go2. is added to get true at the very end.
go2 :- write('--Matching Result--'), nl,
match(Mn,Fn),
write(Mn), write(' match with '), write(Fn), nl,
fail.
go2.
This technique is called failure driven loop.
If you have any predicate that has multiple results and want to to find all of them, you should use findall/3
For example, in your case, you could do something like:
findall([X,Y], match(X,Y),L).
L will be a list that will contain all the X,Y that satisfy match(X,Y) in the format [X,Y].
for example, assuming that:
match(m1,f1).
match(m2,f2).
the result will be L = [ [m1,f1], [m2,f2] ]
note that you can define the format as you wish, for example you could write:
findall(pair(X,Y), match(X,Y), L).
L = [ pair(m1,f1), pair(m2,f2) ]
findall( X, match(X,Y), L).
L = [ m1, m2]
findall( 42, match(X,Y), L).
L = [42, 42]
then you have to recurse on the list to print them.
However, if you wish to find one result, run some code and then continue you could use forall/2:
forall(match(X,Y), my_print(X,Y).
Prolog is a lazy language. Which means that it will stop once it has found a condition that made your problem true. This will be the very first match alone.
IF your code is working (I haven't tried it), then you should try and run the match-statement like this in your prolog inspector: match(X,Y)
The prolog inspector will return all states and print them for you.

Resources