Why is this ancestor code not working - Prolog - prolog

parent(jill, john).
parent(john, pam).
parent(pam, bob).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
parent(pat, jim).
female(jill).
female(pam).
female(liz).
female(ann).
female(pat).
male(jim).
male(john).
male(tom).
male(bob).
mother(X,Y) :- female(X) , parent(X,Y).
father(X,Y) :- male(X), parent(X,Y).
offspring(X,Y) :- parent(Y,X).
sister(X,Y) :- female(X), female(Y), parent(Z,X), parent(Z,Y), not(X=Y).
ancestor(X, Y) :- parent(X,Z), ancestor(Z,Y).
This is the whole code plus some other stuff not related to the ancestor part. When I try to test it in swipl, the ancestor code gives me false. I am trying ancestor(pat,jim). and ancestor(X,jim). If I use ; instead of , in the ancestor code, it kind of works but repeats names when a person has both parents in the list.

In cases like this, trace is your friend:
?- trace.
true.
[trace] ?- ancestor(pat, jim).
Call: (8) ancestor(pat, jim) ? creep
Call: (9) parent(pat, _3162) ? creep
Exit: (9) parent(pat, jim) ? creep
Call: (9) ancestor(jim, jim) ? creep
Call: (10) parent(jim, _3162) ? creep
Fail: (10) parent(jim, _3162) ? creep
Fail: (9) ancestor(jim, jim) ? creep
Fail: (8) ancestor(pat, jim) ? creep
false.
See what happens? You defined ancestor(X,Y) as having two requirements: First, X must be the parent of some middleman Z, and then Z also needs to be an ancestor of Y. Since pat is the parent of jim, this requires jim to be his own ancestor, which he isn't.
One possible solution is to define an ancestor as either a direct parent or the parent of another ancestor:
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
Let's test:
[trace] ?- ancestor(pat, jim).
Call: (8) ancestor(pat, jim) ? creep
Call: (9) parent(pat, jim) ? creep
Exit: (9) parent(pat, jim) ? creep
Exit: (8) ancestor(pat, jim) ? creep
So, we're good with pat and jim, because they are in a direct parent relation. What about the recursive case?
[trace] ?- ancestor(tom,pat).
Call: (8) ancestor(tom, pat) ? creep
Call: (9) parent(tom, pat) ? creep
Fail: (9) parent(tom, pat) ? creep
Redo: (8) ancestor(tom, pat) ? creep
Call: (9) parent(tom, _3168) ? creep
Exit: (9) parent(tom, bob) ? creep
Call: (9) ancestor(bob, pat) ? creep
Call: (10) parent(bob, pat) ? creep
Exit: (10) parent(bob, pat) ? creep
Exit: (9) ancestor(bob, pat) ? creep
Exit: (8) ancestor(tom, pat) ? creep
true .

Related

prolog questions.. fails to invoke predicate

I am trying to understand why duck2 is not called.. Should I cover all cases of the two list being empty, non empty.
duck([H|T], something ) :-
write("*"),
write("?"),
duck2([H|T], T, something_else),
write("Over").
duck2([], [], something_else) :- write("AllDone").
duck2([H|T], [H1,T1], something_else) :-
write("I am here").
trace gives this..
Call: (16) duck([dog, eats], [eats], something) ? creep
Call: (17) write("*") ? creep
*
Exit: (17) write("*") ? creep
Call: (17) write("?") ? creep
?
Exit: (17) write("?") ? creep
Call: (17) duck2([dog, eats], [eats], something_else) ? creep
Fail: (17) duck2([dog, eats], [eats], something_else) ? creep
Fail: (16) duck([dog, eats], [eats], something) ? creep
duck2([H|T], [H1,T1], something_else) :-
% spaced out to line up with the below trace
duck2([H|T], [H1,T1], something_else) :-
Call: (17) `duck2([dog, eats], [eats], something_else)` ? creep
[H1, T1] is a list of two items and [eats] is a list of one item; if you try and unify them, they don't unify:
?- [H1, T1] = [eats].
false
so the call fails.
Should I cover all cases
Well, at least cover enough cases to make the code work. All cases is up to you.

Fibonacci numbers - Out of global stack error

Consider this simple Prolog program:
nat(0).
nat(s(X)) :- nat(X).
plus(X, 0, X) :- nat(X).
plus(X, s(Y), s(Z)) :- nat(X), nat(Y), nat(Z), plus(X, Y, Z).
fib(0, 0).
fib(s(0), s(0)).
fib(s(s(K)), Z) :- fib(s(K), Y), fib(K, X), plus(X, Y, Z).
I already tested plus and it seems to be working. Let's see if fib works okay as well...
?- fib(0, 0).
true.
?- fib(s(0), s(0)).
true ;
false.
?- fib(s(s(0)), s(0)).
true ;
false.
?- fib(s(s(s(0))), s(s(0))).
true ;
ERROR: Out of global stack
Everything works splendidly until I want to print out the 3rd number, which happens to be 2!
I understand that simulating the Peano arithmetic this way is far from effective, and also that an exponential algorithm that is being used here is suboptimal, nonetheless I refuse to believe that performance issues kick in that early, when I'm only computing the third number. Therefore my program surely loops and therefore it is wrong.
... why does it loop? and what does it take to make it stop looping?
Short answer: It loops because plus(0, s(0), X). will produce true, and then loop.
If we take a look at the trace, we see:
[trace] ?- fib(s(s(s(0))), s(s(0))).
Call: (8) fib(s(s(s(0))), s(s(0))) ? creep
Call: (9) fib(s(s(0)), _902) ? creep
Call: (10) fib(s(0), _906) ? creep
Exit: (10) fib(s(0), s(0)) ? creep
Call: (10) fib(0, _910) ? creep
Exit: (10) fib(0, 0) ? creep
Call: (10) plus(0, s(0), _912) ? creep
...
Exit: (9) plus(s(0), s(0), s(s(0))) ? creep
Exit: (8) fib(s(s(s(0))), s(s(0))) ? creep
true .
But the interpreter backtracks in that predicate and aims to find more solutions. This is due to the fact that your nat(Z) each time comes up with a next value, and then the interpreter calls plus(X, Y, Z) to check if that matches, but each time it fails.
We can see that when we trace plus(0, s(0), X):
[trace] ?- plus(0, s(0), X).
Call: (8) plus(0, s(0), _676) ? creep
Call: (9) nat(0) ? creep
Exit: (9) nat(0) ? creep
Call: (9) nat(0) ? creep
Exit: (9) nat(0) ? creep
Call: (9) nat(_884) ? creep
Exit: (9) nat(0) ? creep
Call: (9) plus(0, 0, 0) ? creep
Call: (10) nat(0) ? creep
Exit: (10) nat(0) ? creep
Exit: (9) plus(0, 0, 0) ? creep
Exit: (8) plus(0, s(0), s(0)) ? creep
X = s(0) ;
Redo: (9) plus(0, 0, 0) ? creep
Fail: (9) plus(0, 0, 0) ? creep
Redo: (9) nat(_884) ? creep
Call: (10) nat(_888) ? creep
Exit: (10) nat(0) ? creep
Exit: (9) nat(s(0)) ? creep
Call: (9) plus(0, 0, s(0)) ? creep
Fail: (9) plus(0, 0, s(0)) ? creep
Redo: (10) nat(_888) ? creep
Of course none of the answers nat(Z) will propose will succeed once plus(0, s(0), X) has succeeded.
There is however no reason to call nat(Z) anyway, since eventually the recursive call will land in the basecase that will validate nat(X), so we can implement it like:
plus(X, 0, X) :- nat(X).
plus(X, s(Y), s(Z)) :- plus(X, Y, Z).
It is also typically more efficient to use different patterns on the first parameter:
plus(0, X, X) :- nat(X).
plus(s(X), Y, s(Z)) :- plus(X, Y, Z).

How come this Prolog rule doesn't go into a infinity loop?

I have following facts and rules:
one(s).
one(t).
two(X,Y) :- one(X), one(Y), three(X), \+three(Y), \+two(Y,X).
three(s).
For the query two(Y,X). I get this result:
?- two(Y,X).
Y = s,
X = t ;
false.
I don't understand why the results are Y=s and X=t. Why does Prolog don't go infinitely many times into \+two(Y,X)? Does Prolog remember which predicates have already been processed?
This succeeds because Prolog uses negation as finite failure.
If we evaluate the Prolog predicate, we see that:
[trace] ?- two(X, Y).
Call: (8) two(_660, _662) ? creep
Call: (9) one(_660) ? creep
Exit: (9) one(s) ? creep
Call: (9) one(_662) ? creep
Exit: (9) one(s) ? creep
Call: (9) three(s) ? creep
Exit: (9) three(s) ? creep
Call: (9) three(s) ? creep
Exit: (9) three(s) ? creep
Redo: (9) one(_662) ? creep
Exit: (9) one(t) ? creep
Call: (9) three(s) ? creep
Exit: (9) three(s) ? creep
Call: (9) three(t) ? creep
Fail: (9) three(t) ? creep
Redo: (8) two(s, t) ? creep
Call: (9) two(t, s) ? creep
Call: (10) one(t) ? creep
Exit: (10) one(t) ? creep
Call: (10) one(s) ? creep
Exit: (10) one(s) ? creep
Call: (10) three(t) ? creep
Fail: (10) three(t) ? creep
Fail: (9) two(t, s) ? creep
Redo: (8) two(s, t) ? creep
Exit: (8) two(s, t) ? creep
X = s,
Y = t .
So in a first "path" that fails X and Y are both set to s:
two(X,Y) :-
one(X), %% X = s
one(Y), %% Y = s
three(X), %% X = s
\+three(Y), %% Y = s, fail
\+two(Y,X).
But then we backtrack over the one(Y) call, and we obtain:
two(X,Y) :-
one(X), %% X = s
one(Y), %% Y = t
three(X), %% X = s
\+three(Y), %% Y = t
\+two(Y,X) %% call two(t, s).
Now \+ p(X, Y) is considered true, given p(X, Y) can not be satisfied, and gets stuck in an infinite loop. We thus call two(t, s), and this fails, since:
two(t,s) :-
one(t), %% succeeds
one(s), %% succeeds
three(t), %% fails
\+three(s), %%
\+two(s,t) %%
So three(t) fails, and since there are no backtracking opportunities here, two(t, s) thus ends. So that means that two(t, s) has finite failure, hence \+ two(t, s) succeeds, and thus two(X, Y) succeeds with X = s, Y = t.
You have the following predicates defined:
one(s).
one(t).
two(X,Y) :- one(X), one(Y), three(X), \+three(Y), \+two(Y,X).
three(s).
The predicate two(X,Y) is equivalent to
two(X,Y) :- (X=s ; X=t), (Y=s ; Y=t), (X=s), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- (X=s, (Y=s ; Y=t), X=s ; X=t, (Y=s ; Y=t), X=s), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- (X=s, (Y=s ; Y=t), s=s ; X=t, (Y=s ; Y=t), t=s), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- (X=s, (Y=s ; Y=t) ; false), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- ((X=s, Y=s ; false), \+(Y=s) ; (X=s, Y=t ; false), \+(Y=s)), \+two(Y,X).
=
two(X,Y) :- ((X=s, Y=s ; false), \+(s=s) ; (X=s, Y=t ; false), \+(t=s)), \+two(Y,X).
=
two(X,Y) :- (X=s, Y=t ; false), true, \+two(Y,X).
=
two(X,Y) :- (X=s, Y=t, \+two(Y,X) ; false).
=
two(s,t) :- (true, \+two(t,s) ; false).
=
two(s,t) :- (true ; false).
and that's what you're getting.

Brother in law predicate for Prolog not working

Here's the relevant code:
married(X,Y) :- wife(X,Y);husband(X,Y).
parent(X,Y) :- father(X,Y) ;mother(X,Y).
brother(X,Y) :-
man(X),
parent(Z,X),
parent(Z,Y),
X \= Y.
brother_in_law(X,Y) :-
brother(X,Z),married(Z,Y).
I've googled and it seems other have been using the exact code for the brother in law predicate so it should be fine? I checked the other predicates and they seem good too.. not sure what is happening.
Also, by not working I mean that it's not acknowledging the relevant relation when I check.
Look at the trace and you will see the problem:
?- trace, brother_in_law(prins-daniel, Y).
Call: (9) brother_in_law(prins-daniel, _11346) ? creep
Call: (10) brother(prins-daniel, _11680) ? creep
Call: (11) man(prins-daniel) ? creep
Exit: (11) man(prins-daniel) ? creep
Call: (11) parent(_11678, prins-daniel) ? creep
Call: (12) father(_11678, prins-daniel) ? creep
Fail: (12) father(_11678, prins-daniel) ? creep
Redo: (11) parent(_11678, prins-daniel) ? creep
Call: (12) mother(_11678, prins-daniel) ? creep
Fail: (12) mother(_11678, prins-daniel) ? creep
Fail: (11) parent(_11678, prins-daniel) ? creep
Redo: (11) man(prins-daniel) ? creep
Fail: (11) man(prins-daniel) ? creep
Fail: (10) brother(prins-daniel, _11680) ? creep
Fail: (9) brother_in_law(prins-daniel, _11346) ? creep
false.
Who is prins-daniel's father? You don't have a fact for that. Who is prins-daniel's mother? You don't have a fact for that either. As a result, you can't find any brothers, so the query fails.
Does this mean you are missing facts or missing code? The code says X and Y are brothers-in-law if X has a brother Z who is married to Y. Is this the only way to have a brother-in-law?
Side note: prins-daniel is not an atom in Prolog as it would be in Lisp. This is a term:
?- write_canonical(prins-daniel).
-(prins,daniel)
The situation is compounded by longer terms:
?- write_canonical(johann-georg-av-hohenzollern).
-(-(-(johann,georg),av),hohenzollern)
Just something to be aware of.

When is the Redo-port called with new variables in Trace/0 and when not?

During my implementation of the Adventure game in Prolog I was wondering when the redo-port is called with new variables during backtracking and when it is called with the same ones?
For example, I have the following knowledge base:
location(desk,office).
location(apple,kitchen).
location(flashlight,desk).
location('washing machine',cellar).
location(nani,'washing machine').
location(broccoli,kitchen).
location(crackers,kitchen).
location(computer,office).
door(office,hall).
door(kitchen,office).
door(hall,'dining room').
door(kitchen,cellar).
door('dining room',kitchen).
When tracing the query ?-(location(X,Y),door(kitchen,Y)). I get this:
Call: (9) location(_7998, _8000) ? creep
Exit: (9) location(desk, office) ? creep
Call: (9) door(kitchen, office) ? creep
Exit: (9) door(kitchen, office) ? creep
X = desk,
Y = office ;
Redo: (9) door(kitchen, office) ? creep <==== 1
Fail: (9) door(kitchen, office) ? creep
Redo: (9) location(_7998, _8000) ? creep
Exit: (9) location(apple, kitchen) ? creep
Call: (9) door(kitchen, kitchen) ? creep
Fail: (9) door(kitchen, kitchen) ? creep
Redo: (9) location(_7998, _8000) ? creep
Exit: (9) location(flashlight, desk) ? creep
Call: (9) door(kitchen, desk) ? creep
Fail: (9) door(kitchen, desk) ? creep
Redo: (9) location(_7998, _8000) ? creep
Exit: (9) location('washing machine', cellar) ? creep
Call: (9) door(kitchen, cellar) ? creep
Exit: (9) door(kitchen, cellar) ? creep
X = 'washing machine',
Y = cellar ;
Redo: (9) location(_7998, _8000) ? creep <==== 2
Exit: (9) location(nani, 'washing machine') ? creep
Call: (9) door(kitchen, 'washing machine') ? creep
Fail: (9) door(kitchen, 'washing machine') ? creep
Redo: (9) location(_7998, _8000) ? creep
Exit: (9) location(broccoli, kitchen) ? creep
Call: (9) door(kitchen, kitchen) ? creep
Fail: (9) door(kitchen, kitchen) ? creep
Redo: (9) location(_7998, _8000) ? creep
Exit: (9) location(crackers, kitchen) ? creep
Call: (9) door(kitchen, kitchen) ? creep
Fail: (9) door(kitchen, kitchen) ? creep
Redo: (9) location(_7998, _8000) ? creep
Exit: (9) location(computer, office) ? creep
Call: (9) door(kitchen, office) ? creep
Exit: (9) door(kitchen, office) ? creep
X = computer,
Y = office ;
Redo: (9) door(kitchen, office) ? creep <==== 3
Fail: (9) door(kitchen, office) ? creep
false.
I understand how the binding of the variables works, but I do not understand why Prolog returns
Redo: (9) door(kitchen, office) ? creep <==== 1
Redo: (9) door(kitchen, office) ? creep <==== 3
after finding the first solution (and the same for the last solution),
while it immediately looks for a new binding of X and Y after the second solution
Redo: (9) location(_7998, _8000) ? creep <==== 2
Why does it not immediately continue to look for a new binding of X and Y after the first and last solution, instead of resorting to
Redo: (9) door(kitchen, office) ? creep <==== 3
(which fails anyway)?
(I found a similar question here, but unfortunately my reputation does not allow me to comment over there and I think this particular issue does not have to do with my Prolog version (as I tried it with SWI-Prolog and GNUProlog))
Thanks in advance for offering any clarity.
This answer makes use of SWI-Prolog.
The first thing that can help when using trace for the first time is to make all of the ports visible. By default the unify port is not visible but can be made visible with
?- visible(+unify).
Now since this is such a short running query, instead of having to press the space bar for each port, we can disable the leashing of the leashed ports with
?- leash(-call).
?- leash(-exit).
?- leash(-redo).
?- leash(-fail).
Now if you turn on trace and run the query
?- trace.
[trace] ?- (location(X,Y),door(kitchen,Y)).
you will not have to press the space bar expect for answers.
Doing so will return
Call: (9) location(_9632, _9634)
Unify: (9) location(desk, office)
Exit: (9) location(desk, office)
Call: (9) door(kitchen, office)
Unify: (9) door(kitchen, office)
Exit: (9) door(kitchen, office)
X = desk,
Y = office ;
Redo: (9) door(kitchen, office)
Fail: (9) door(kitchen, office)
Redo: (9) location(_9632, _9634)
Unify: (9) location(apple, kitchen)
Exit: (9) location(apple, kitchen)
Call: (9) door(kitchen, kitchen)
Fail: (9) door(kitchen, kitchen)
Redo: (9) location(_9632, _9634)
Unify: (9) location(flashlight, desk)
Exit: (9) location(flashlight, desk)
Call: (9) door(kitchen, desk)
Fail: (9) door(kitchen, desk)
Redo: (9) location(_9632, _9634)
Unify: (9) location('washing machine', cellar)
Exit: (9) location('washing machine', cellar)
Call: (9) door(kitchen, cellar)
Unify: (9) door(kitchen, cellar)
Exit: (9) door(kitchen, cellar)
X = 'washing machine',
Y = cellar ;
Redo: (9) location(_9632, _9634)
Unify: (9) location(nani, 'washing machine')
Exit: (9) location(nani, 'washing machine')
Call: (9) door(kitchen, 'washing machine')
Fail: (9) door(kitchen, 'washing machine')
Redo: (9) location(_9632, _9634)
Unify: (9) location(broccoli, kitchen)
Exit: (9) location(broccoli, kitchen)
Call: (9) door(kitchen, kitchen)
Fail: (9) door(kitchen, kitchen)
Redo: (9) location(_9632, _9634)
Unify: (9) location(crackers, kitchen)
Exit: (9) location(crackers, kitchen)
Call: (9) door(kitchen, kitchen)
Fail: (9) door(kitchen, kitchen)
Redo: (9) location(_9632, _9634)
Unify: (9) location(computer, office)
Exit: (9) location(computer, office)
Call: (9) door(kitchen, office)
Unify: (9) door(kitchen, office)
Exit: (9) door(kitchen, office)
X = computer,
Y = office ;
Redo: (9) door(kitchen, office)
Fail: (9) door(kitchen, office)
false.
which now has the Unify ports visible.
Since this is such a short query I will comment the significant lines of the trace and that in turn should answer your questions.
% location fact 1: location(desk, office) -------------------------
% First predicate of query - location(X,Y)
% The location facts are matched in the order of the source code
% Since the code is looking for location(X,Y)
% it matches location fact 1: location(desk, office)
% Since there are more location facts like location(X, Y),
% e.g.
% location(apple,kitchen).
% location(flashlight,desk).
% location('washing machine',cellar).
% location(nani,'washing machine').
% location(broccoli,kitchen).
% location(crackers,kitchen).
% location(computer,office).
% a choice point is generated
% choice point: location 1
Call: (9) location(_9632, _9634)
% Unifies with first location fact.
% X binds with desk
% Y binds with office
Unify: (9) location(desk, office)
Exit: (9) location(desk, office)
% Second predicate of query - door(kitchen,Y)).
% Y is bound with office
% The door facts are matched in the order of the source code
% Since the code is only looking for door(kitchen,office)
% it matches door fact 2: door(kitchen,office)
% Since there are more door facts like door(kitchen,Y),
% e.g.
% door(kitchen,cellar).
% a choice point is generated
% choice point: door 1
Call: (9) door(kitchen, office)
% Since there is a door(kitchen, office) fact
% unify with second predicate
Unify: (9) door(kitchen, office)
Exit: (9) door(kitchen, office)
% No more predicates in the query so return result.
X = desk,
Y = office ;
% Remember choice point: door 1
% Use the second predicate
% on the remaining door facts like door(kitchen,Y)
% e.g.
% door(kitchen,cellar).
Redo: (9) door(kitchen, office)
% There are no more door facts that unify with door(kitchen, office)
% so fail.
Fail: (9) door(kitchen, office)
% Since the second predicate failed,
% go back to the first predicate location(X,Y)
% location fact 2: location(apple, kitchen) -----------------------
% Remember choice point: location 1
% Use the first predicate
% on the remaining location facts like location(X,Y)
% e.g.
% location(apple,kitchen).
% location(flashlight,desk).
% location('washing machine',cellar).
% location(nani,'washing machine').
% location(broccoli,kitchen).
% location(crackers,kitchen).
% location(computer,office).
Redo: (9) location(_9632, _9634)
% The second fact unifies with the first predicate location(X,Y)
% X binds with apple
% Y binds with kitchen
Unify: (9) location(apple, kitchen)
Exit: (9) location(apple, kitchen)
% Second predicate of query - door(kitchen,Y)).
% Y is bound with kitchen
% The door facts are matched in the order of the source code
% Since the code is only looking for door(kitchen,kitchen)
% it matches none of the door facts
% and since it checked all of the door facts
% no choice point was generated.
Call: (9) door(kitchen, kitchen)
% There is no door(kitchen, kitchen) fact so fail.
Fail: (9) door(kitchen, kitchen)
% location fact 3: location(flashlight, desk) ---------------------
% Remember choice point: location 1
% Use the first predicate
% on the remaining location facts like location(X,Y)
% e.g.
% location(flashlight,desk).
% location('washing machine',cellar).
% location(nani,'washing machine').
% location(broccoli,kitchen).
% location(crackers,kitchen).
% location(computer,office).
Redo: (9) location(_9632, _9634)
Unify: (9) location(flashlight, desk)
Exit: (9) location(flashlight, desk)
Call: (9) door(kitchen, desk)
Fail: (9) door(kitchen, desk)
% Since the second predicate failed,
% go back to the first predicate location(X,Y)
% location fact 4: location('washing machine', cellar) -----------
% Remember choice point: location 1
% Use the first predicate
% on the remaining location facts like location(X,Y)
% e.g.
% location('washing machine',cellar).
% location(nani,'washing machine').
% location(broccoli,kitchen).
% location(crackers,kitchen).
% location(computer,office).
Redo: (9) location(_9632, _9634)
% The forth fact unifies with the first predicate location(X,Y)
% X binds with 'washing machine'
% Y binds with cellar
Unify: (9) location('washing machine', cellar)
Exit: (9) location('washing machine', cellar)
% Second predicate of query - door(kitchen,Y)).
% Y is bound with cellar
% The door facts are matched in the order of the source code
% Since the code is only looking for door(kitchen,cellar)
% it matches door fact 4: door(kitchen,cellar)
% Since there are NO more door facts like door(kitchen,Y),
% NO choice point is generated
Call: (9) door(kitchen, cellar)
% There is a door(kitchen, cellar) fact so unify.
Unify: (9) door(kitchen, cellar)
Exit: (9) door(kitchen, cellar)
% No more predicates in the query so return result.
X = 'washing machine',
Y = cellar ;
% location fact 5: location(nani, 'washing machine') --------------
% Remember choice point: location 1
% Use the first predicate
% on the remaining location facts like location(X,Y)
% e.g.
% location(nani,'washing machine').
% location(broccoli,kitchen).
% location(crackers,kitchen).
% location(computer,office).
Redo: (9) location(_9632, _9634)
Unify: (9) location(nani, 'washing machine')
Exit: (9) location(nani, 'washing machine')
Call: (9) door(kitchen, 'washing machine')
Fail: (9) door(kitchen, 'washing machine')
% location fact 6: location(broccoli, kitchen) --------------------
% Remember choice point: location 1
% Use the first predicate
% on the remaining location facts like location(X,Y)
% e.g.
% location(broccoli,kitchen).
% location(crackers,kitchen).
% location(computer,office).
Redo: (9) location(_9632, _9634)
Unify: (9) location(broccoli, kitchen)
Exit: (9) location(broccoli, kitchen)
Call: (9) door(kitchen, kitchen)
Fail: (9) door(kitchen, kitchen)
% location fact 7: location(crackers, kitchen) --------------------
% Remember choice point: location 1
% Use the first predicate
% on the remaining location facts like location(X,Y)
% e.g.
% location(crackers,kitchen).
% location(computer,office).
Redo: (9) location(_9632, _9634)
Unify: (9) location(crackers, kitchen)
Exit: (9) location(crackers, kitchen)
Call: (9) door(kitchen, kitchen)
Fail: (9) door(kitchen, kitchen)
% Since the second predicate failed,
% go back to the first predicate location(X,Y)
% location fact 8: location(computer, office) ---------------------
% Remember choice point: location 1
% Use the first predicate
% on the remaining location facts like location(X,Y)
% e.g.
% location(computer,office).
Redo: (9) location(_9632, _9634)
% The last fact unifies with the first predicate location(X,Y)
% X binds with computer
% Y binds with office
Unify: (9) location(computer, office)
Exit: (9) location(computer, office)
% Second predicate of query - door(kitchen,Y)).
% Y is bound with office
% The door facts are matched in the order of the source code
% Since the code is only looking for door(kitchen,office)
% it matches door fact 2: door(kitchen,office)
% Since there are more door facts like door(kitchen,Y),
% e.g.
% door(kitchen,cellar).
% a choice point is generated
% choice point: door 2
Call: (9) door(kitchen, office)
% Since there is a door(kitchen, office) fact
% unify with second predicate
Unify: (9) door(kitchen, office)
Exit: (9) door(kitchen, office)
% No more predicates in the query so return result.
X = computer,
Y = office ;
% Remember choice point: door 2
% Use the second predicate
% on the remaining door facts like door(kitchen,Y)
% e.g.
% door(kitchen,cellar).
Redo: (9) door(kitchen, office)
% There are no more door facts that unify with door(kitchen, office)
% so fail.
Fail: (9) door(kitchen, office)
% There are no more location facts so end the query.
false.
Supplement
When I created the answer it was in a text editor that can do syntax highlight for Prolog code, and to help me keep things straight I had three panes open for comparing. One pane had the location and door rules. One pane had a comment, and the third pane had a similar comment. As I moved down the code I kept updating the comments in the third pane to match similar comment in the second pane while checking against the facts in the first pane. I note this because it is probably a better way to understand the comments than reading them from this answer as posted.
The editor is Visual Studio Code and for highlighting Prolog the Prolog extension is installed.
This is just a comment posted as a answer because it has a picture.
If you use the graphical debugger you can see when choice points are created.
?- gtrace.
true.
[trace] ?- (location(X,Y),door(kitchen,Y)).
In the following image of the debugger I highlighted the choice point with a green rectangle.
To exit out of trace mode in top-level enter nodebug.
[trace] ?- nodebug.
true.
?-
Note: It is the choice points that lead to using the redo port.
Note: Another way to debug prolog is via use of failure slice. Also read questions tagged with failure slice

Resources