Fibonacci numbers - Out of global stack error - prolog

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).

Related

Prolog: Why doesn't this predicate fail with an empty list passed as an argument

I made a pretty basic predicate to explain my problem, so don't mind it's uselessness. I want the predicate to fail if an empty list is passed as the B argument,
predicate(_,[],_) :- fail.
predicate(A,B,C) :-
write(A),
writeln(B),
C = true.
But when I enter this query:
?- predicate(test,[],X).
Instead of returning false(since it's supposed to fail), it execute the predicate and the output is:
test[]
X = true.
Why won't the predicate fail even if B is an empty list?
In fact, the first clause fails for the query ?- predicate(test,[],X).. However, when the first clause fails, the second clause is trigged and produces the observed output. To check that, you can use predicate trace/0:
?- trace, predicate(test,[],X).
Call: (11) predicate(test, [], _26304) ? creep % <= try first clause
Call: (12) fail ? creep
Fail: (12) fail ? creep
Redo: (11) predicate(test, [], _26304) ? creep % <= try second clause
Call: (12) write(test) ? creep
test
Exit: (12) write(test) ? creep
Call: (12) writeln([]) ? creep
[]
Exit: (12) writeln([]) ? creep
Call: (12) _26304=true ? creep
Exit: (12) true=true ? creep
Exit: (11) predicate(test, [], true) ? creep
X = true.
If you want that predicate/3 fails when called with []as second argument, then you can define that predicate as follows:
predicate(A, B, C) :-
B \= [], % this condition forces failure when B is the empty list
write(A),
writeln(B),
C = true.
Examples:
[trace] ?- predicate(test,[],X).
Call: (10) predicate(test, [], _28066) ? creep
Call: (11) []\=[] ? creep
Fail: (11) []\=[] ? creep
Fail: (10) predicate(test, [], _28066) ? creep
false.
[trace] ?- nodebug.
true.
?- predicate(test,[],X).
false.
?- predicate(test,[a],X).
test[a]
X = true.

Why is this ancestor code not working - 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 .

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.

Infinite loop in Prolog. How do I prevent this?

I am writing a program in Prolog that represents the rules of a card game. However, I am running into an infinite loop with the following code.
succ(seven_of_hearts,eight_of_hearts).
succ(eight_of_hearts,nine_of_hearts).
succ(nine_of_hearts,ten_of_hearts).
succ(ten_of_hearts,jack_of_hearts).
succ(jack_of_hearts,queen_of_hearts).
succ(queen_of_hearts,king_of_hearts).
succ(king_of_hearts,ace_of_hearts).
succ(X,Y) :-
succ(X,Z),
succ(Z,Y),
!.
beats(X,Y) :-
succ(Y,X).
Basically, my attempt with these few lines is to set up a system for determining if one card beats another according to the succ (or succession) relationships I have established. So the query I am running is beats(X,Y), where X and Y and atoms corresponding to cards. This query terminates successfully if it is true. For example, if I query beats(jack_of_hearts,seven_of_hearts), it returns true and terminates.
However, the query enters an infinite loop if it is false. For example, when I query beats(seven_of_hearts,jack_of_hearts). I traced the query and found that due to the recursive nature of the last succ statement, the query follows the chain of succ statements all the way down to the seven_of_hearts, or all the way up to the ace_of_hearts, and then continuously tries to evaluate succ(seven_of_hearts,X) or succ(ace_of_hearts,X) instead of returning false.
I have two questions: using this current structure, how could I prevent this? Or, if that's not possible, what is an alternative structure I could use to accomplish my goal?
EDIT:
Here is a screenshot of my trace for one of the failing queries:
Call: (267) beats(seven_of_hearts, jack_of_hearts) ? creep
Call: (268) succ(jack_of_hearts, seven_of_hearts) ? creep
Call: (269) succ(jack_of_hearts, _G7104) ? creep
Exit: (269) succ(jack_of_hearts, queen_of_hearts) ? creep
Call: (269) succ(queen_of_hearts, seven_of_hearts) ? creep
Call: (270) succ(queen_of_hearts, _G7104) ? creep
Exit: (270) succ(queen_of_hearts, king_of_hearts) ? creep
Call: (270) succ(king_of_hearts, seven_of_hearts) ? creep
Call: (271) succ(king_of_hearts, _G7104) ? creep
Exit: (271) succ(king_of_hearts, ace_of_hearts) ? creep
Call: (271) succ(ace_of_hearts, seven_of_hearts) ? creep
Call: (272) false ? creep
Fail: (272) false ? creep
Redo: (271) succ(ace_of_hearts, seven_of_hearts) ? creep
Call: (272) succ(ace_of_hearts, _G7104) ? creep
Call: (273) false ? creep
Fail: (273) false ? creep
Redo: (272) succ(ace_of_hearts, _G7104) ? creep
Call: (273) succ(ace_of_hearts, _G7104) ? creep
Call: (274) false ? creep
Fail: (274) false ? creep
Redo: (273) succ(ace_of_hearts, _G7104) ? creep
Call: (274) succ(ace_of_hearts, _G7104) ? creep
Call: (275) false ? creep
Your predicate obviously keeps calling itself: succ(X, Y) :- succ(Y, X), .... A simple solution is not to use the same name for your predicate as you do your facts. Get rid of your succ/2 predicate (leaving the facts) in favor of:
successor(X, Y) :- succ(X, Y).
successor(X, Y) :- succ(X, Z), succ(Z, Y).
beats(X, Y) :- successor(Y, X).

Resources