To start off this is a homework question poised to me.
I am supposed to write a predicate btree_height\2 that takes a Binary tree and (for now) just returns the height of the tree.
A binary tree is represented as:
node(node(leaf, x, leaf), x, node(leaf, x, leaf))
where the x's are integer values of the node. (This is just an example tree).
My code is as follows:
btree_height(leaf, 0).
btree_height(node(leaf,_,leaf), 1).
btree_height(node(LT,_,RT), D):-
btree_height(LT, DL),
btree_height(RT, DR),
D is max(DL,DR)+1.
The problem that I am having is that when I call btree_height(BT, D) and supply it with a BT if the depth is 4 then it recurses 4 times and "returns" the number 4 four times. According to my professor this is an incorrect behavior as it should only return the number 4 once. (Using the example above it returns the number 2 twice)
This is my first time coding in Prolog and I have no idea where I should start looking.
This is technically SWI-Prolog if it makes a difference...
Since this is homework, I won't give you the full solution.
When your predicate hits a node that matches node(leaf, _, leaf), it first executes the second clause. That returns one. Then, when you ask it to backtrack, it will also execute the third clause, because that also matches the input with LT=leaf and RT=leaf, so it will recurse twice and hit the leaf case both times.
Next time, if you have to debug this kind of problem yourself, trace/1 is a good tool:
2 ?- trace.
true.
[trace] 2 ?- btree_height(node(node(leaf, x, leaf), x, node(leaf, x, leaf)), H).
Call: (6) btree_height(node(node(leaf, x, leaf), x, node(leaf, x, leaf)), _G821) ? creep
Call: (7) btree_height(node(leaf, x, leaf), _G903) ? creep
Exit: (7) btree_height(node(leaf, x, leaf), 1) ? creep
Call: (7) btree_height(node(leaf, x, leaf), _G903) ? creep
Exit: (7) btree_height(node(leaf, x, leaf), 1) ? creep
Call: (7) _G821 is max(1, 1)+1 ? creep
Exit: (7) 2 is max(1, 1)+1 ? creep
Exit: (6) btree_height(node(node(leaf, x, leaf), x, node(leaf, x, leaf)), 2) ? creep
H = 2 ;
Redo: (7) btree_height(node(leaf, x, leaf), _G903) ? creep
Call: (8) btree_height(leaf, _G903) ? creep
Exit: (8) btree_height(leaf, 0) ? creep
Call: (8) btree_height(leaf, _G903) ? creep
Exit: (8) btree_height(leaf, 0) ? creep
Call: (8) _G911 is max(0, 0)+1 ? creep
Exit: (8) 1 is max(0, 0)+1 ? creep
Exit: (7) btree_height(node(leaf, x, leaf), 1) ? creep
Call: (7) _G821 is max(1, 1)+1 ? creep
Exit: (7) 2 is max(1, 1)+1 ? creep
Exit: (6) btree_height(node(node(leaf, x, leaf), x, node(leaf, x, leaf)), 2) ? creep
H = 2
(Where it says creep, I pressed Enter.)
Related
door_between(bed_room, hidden_chamber).
door_between(hidden_chamber, basement).
rev(L,R) :- my_reverse(L,[],R).
my_reverse([H|T],A,R) :- my_reverse(T,[H|A],R).
my_reverse([],A,A).
path_from(Src,Dest,Path) :-
path_from(Src,Dest,[],Path),
rev(Path,Z),
append(Src,Z,Z).
path_from(S,S,P,P).
path_from(S,D,P,NV) :-
(door_between(S,A) ; door_between(A,S)),
\+ member(A,P),
path_from(A, D, [A|P], NV).
This is my code to find a path in an un-directed graph of rooms. It seems to get to the correct result during recursion but calls *Redo at a point and I do not understand why, here is the trace.
path_from(bed_room,basement,X).
* Call: (8) path_from(bed_room, basement, _12282) ? creep
* Call: (9) path_from(bed_room, basement, [], _12282) ? creep
Call: (10) door_between(bed_room, _12624) ? creep
Exit: (10) door_between(bed_room, hidden_chamber) ? creep
Call: (10) lists:member(hidden_chamber, []) ? creep
Fail: (10) lists:member(hidden_chamber, []) ? creep
* Redo: (9) path_from(bed_room, basement, [], _12282) ? creep
* Call: (10) path_from(hidden_chamber, basement, [hidden_chamber], _12282) ? creep
Call: (11) door_between(hidden_chamber, _12630) ? creep
Exit: (11) door_between(hidden_chamber, basement) ? creep
Call: (11) lists:member(basement, [hidden_chamber]) ? creep
Fail: (11) lists:member(basement, [hidden_chamber]) ? creep
* Redo: (10) path_from(hidden_chamber, basement, [hidden_chamber], _12282) ? creep
* Call: (11) path_from(basement, basement, [basement, hidden_chamber], _12282) ? creep
* Exit: (11) path_from(basement, basement, [basement, hidden_chamber], [basement, hidden_chamber]) ? creep
* Exit: (10) path_from(hidden_chamber, basement, [hidden_chamber], [basement, hidden_chamber]) ? creep
* Exit: (9) path_from(bed_room, basement, [], [basement, hidden_chamber]) ? creep
Call: (9) rev([basement, hidden_chamber], _12636) ? creep
Call: (10) my_reverse([basement, hidden_chamber], [], _12638) ? creep
Call: (11) my_reverse([hidden_chamber], [basement], _12644) ? creep
Call: (12) my_reverse([], [hidden_chamber, basement], _12650) ? creep
Exit: (12) my_reverse([], [hidden_chamber, basement], [hidden_chamber, basement]) ? creep
Exit: (11) my_reverse([hidden_chamber], [basement], [hidden_chamber, basement]) ? creep
Exit: (10) my_reverse([basement, hidden_chamber], [], [hidden_chamber, basement]) ? creep
Exit: (9) rev([basement, hidden_chamber], [hidden_chamber, basement]) ? creep
Call: (9) lists:append(bed_room, [hidden_chamber, basement], [hidden_chamber, basement]) ? creep
* Redo: (11) path_from(basement, basement, [basement, hidden_chamber], _12282) ? creep
Call: (12) door_between(basement, _12636) ?
(The bolded line that breaks the code block is the line I'm concerned about, and it's triggered by append(Src,Z,Z) in path_from/3.) At the Call: (9) to append, that resulting list is the answer that I want for this particular test case, I'm assuming append would return [bed_room, hidden_chamber, basement], but the next thing is a *Redo and I'm really confused as to why, am I just confused on the concept of recursion? I think I just need a tiny nudge and I can wrap my head around it.
I'm learning Prolog and I'm having a hard time with recursion. The simple cases with a database I can understand, but I can't follow this exercise, where redu/2 is implemented, which will remove the duplicates of a given list and give the new list as second argument:
redu([],[]).
redu([H|T], Result):-
member(H,T),
redu(T,Result).
redu([H|T], [H|Result]):-
redu(T, Result).
A trace gives me this:
[trace] ?- redu([a,b,b,c,a], X).
Call: (8) redu([a, b, b, c, a], _35630) ? creep
Call: (9) lists:member(a, [b, b, c, a]) ? creep
Exit: (9) lists:member(a, [b, b, c, a]) ? creep
Call: (9) redu([b, b, c, a], _35630) ? creep
Call: (10) lists:member(b, [b, c, a]) ? creep
Exit: (10) lists:member(b, [b, c, a]) ? creep
Call: (10) redu([b, c, a], _35630) ? creep
Call: (11) lists:member(b, [c, a]) ? creep
Fail: (11) lists:member(b, [c, a]) ? creep
Redo: (10) redu([b, c, a], _35630) ? creep
Call: (11) redu([c, a], _35900) ? creep
Call: (12) lists:member(c, [a]) ? creep
Fail: (12) lists:member(c, [a]) ? creep
Redo: (11) redu([c, a], _35900) ? creep
Call: (12) redu([a], _35906) ? creep
Call: (13) lists:member(a, []) ? creep
Fail: (13) lists:member(a, []) ? creep
Redo: (12) redu([a], _35906) ? creep
Call: (13) redu([], _35912) ? creep
Exit: (13) redu([], []) ? creep
Exit: (12) redu([a], [a]) ? creep
Exit: (11) redu([c, a], [c, a]) ? creep
Exit: (10) redu([b, c, a], [b, c, a]) ? creep
Exit: (9) redu([b, b, c, a], [b, c, a]) ? creep
Exit: (8) redu([a, b, b, c, a], [b, c, a]) ? creep
X = [b, c, a]
I would really appreciate it if somebody could explain to me in natural language what recursion does and how to read the clauses. Like with the second clause, is it right that it reads as "remove duplicates from list H|T and output Result if the head of that list is a member of the tail and remove the duplicates from the tail and output the result? But how can the two Results be the same? And I also don't get which rule is activated when. When does it go forward in my list of clauses? When does it go back?
Sorry for all the questions. I really want to understand everything.
So you have
redu([], []).
redu([H|T], R ):- member(H, T), redu(T, R).
redu([H|T], [H|R]):- redu(T, R).
==
redu([], []).
redu([H|T], X ):- member(H, T), X = R , redu(T, R).
redu([H|T], X):- X = [H|R], redu(T, R).
==
redu([], []).
redu([H|T], X ):- ( member(H, T), X = R
; X = [H|R]), redu(T, R).
==
redu([], []).
redu([H|T], X ):- disj(H, T, X, R), redu(T, R).
disj(H, T, R, R):- member(H, T).
disj(H,_T, [H|R], R).
These two new redu/2 clauses are mutually exclusive, so the code can be easier to understand in this form. Whether disj/4 includes H into the list X being built (in the top-down manner) or not - and however many times it succeeds (*) - after disj/4 does its thing, the recursive call to redu/2 is simply made.
So we read redu(L,X) as "for the head element H in L=[H|T], if there are some more Hs in T, either don't include H in the 'output' list X, or do; and for a unique H - such that does not occur in T - include it in X always; and then, having dealt with this head element H of L, proceed to deal with the rest of the elements in the list in the same manner." In other words, do this for each element in the list L.
This recursive definition follows naturally the inductive definitions of lists as [H|T] or [] structures.
(*) (do take note that A. member may succeed more than once, and B. the two clauses of disj/4 are not mutually exclusive).
With your example,
redu([a,b,b,c,a], X)
==
disj( a, [b,b,c,a], X,R), % AND redu([b,b,c,a], R) i.e.
disj( b, [b,c,a], R,R2), % AND redu([b,c,a], R2) i.e.
disj( b, [c,a], R2,R3), % AND redu([c,a], R3) i.e.
disj( c, [a], R3,R4), % AND redu([a], R4) i.e.
disj( a, [], R4,R5), % AND the final clause,
redu( [], R5).
Now you can try each disj/4 invocation and see what is happening there, like
33 ?- disj(a,[b,b,c,a], X,R).
X = R ;
X = [a|R].
34 ?- disj(b,[c,a], R2,R3).
R2 = [b|R3].
Thus the whole example becomes
(X = R ; X = [a|R]), % [ a
(R = R2 ; R = [b|R2]), % b
R2 = [b|R3], % b
R3 = [c|R4], % c
R4 = [a|R5], % a
R5 = []. % ]
or
ex(X):-
(X = R ; X = [a|R]),
(R = R2 ; R = [b|R2]),
R2 = [b,c,a].
which is
42 ?- ex(X).
X = [b, c, a] ;
X = [b, b, c, a] ;
X = [a, b, c, a] ;
X = [a, b, b, c, a].
Any recursive implementation has at least two clauses - base clauses, and oone or more recursive clauses.
Base clauses deal with degenerate cases: empty lists, zeros, and so on. They give simple answers - for example, in your case the base clause states that the answer for an empty list is an empty list.
The recursive clauses deal separately with a situation when the item is on the list (second clause), and when the item is not on the list (third clause). The second clause says that when an item is found on the tail portion of the list (member of T) then it should not be added to the result now; it will be added later. If, on the other hand, this is the last item, third clause adds it to the output list.
But then, eventually, the member check will fail (b is not a member of [c,a]), but how does it work then?
Once member check fails, Prolog goes to the third clause, which adds H to the output list with [H|Result], and proceeds to computing the rest of the Result from the tail part T of the list with redu(T, Result).
Note 1: There is one mistake in the program, though: the last clause needs to be conditioned on the item not being on the tail portion of the list:
redu([H|T], [H|Result]):-
\+ member(H,T),
redu(T, Result).
This should prevent Prolog from going into the clause if the second clause has executed.
Note 2: The other option is to use cut in the second clause, but this option is highly discouraged.
I'm trying to implement the recursive version of the Fibonacci sequence in Prolog. Below is the code:
fib(0,F) :- F is 0.
fib(1,F) :- F is 1.
fib(N,F) :- N > 1,
AA is (N - 1),
BB is (N - 2),
fib(AA,CC),
fib(BB,DD),
RR is (CC + DD),
F == RR,
F is RR.
The problem is that it's not behaving as I logically expect it to. When I use trace to call fib(3,2), I get the following lines:
Call: (7) fib(3, 2) ? creep
Call: (8) 3>1 ? creep
Exit: (8) 3>1 ? creep
Call: (8) _G2569 is 3+ -1 ? creep
Exit: (8) 2 is 3+ -1 ? creep
Call: (8) _G2572 is 3+ -2 ? creep
Exit: (8) 1 is 3+ -2 ? creep
Call: (8) fib(2, _G2573) ? creep
Call: (9) 2>1 ? creep
Exit: (9) 2>1 ? creep
Call: (9) _G2575 is 2+ -1 ? creep
Exit: (9) 1 is 2+ -1 ? creep
Call: (9) _G2578 is 2+ -2 ? creep
Exit: (9) 0 is 2+ -2 ? creep
Call: (9) fib(1, _G2579) ? creep
Call: (10) _G2578 is 1 ? creep
Exit: (10) 1 is 1 ? creep
What catches my attention is the last call, Call: (10), which says "_G2578 is 1 ?", even though I'm calling fib(1, _G2579). My expectation is that it's _G2579 that's going to be changed, but that does not appear to be the case. I need to find out why because I highly suspect that this is why fib(3,2) is returning false instead of true.
The problem, if I'm not wrong, is in
F == R
that check if F (a newly introduced term without a value) is equal to R.
If you change it in
F = R
so unifing F with R (an in redundant following F is R), your fib/2 should work.
But I propose you some semplification.
(1) the terminale case fib(0,F) :- F is 0. is good but you can write it as
fib(0,0).
(2) same semplification for the other terminal case: you can write it as
fib(1,1).
(3) in the general clause, you don't need two different variables F and RR with the same (unified) value; you can use only F in the following way
fib(N,F) :-
N > 1,
AA is (N - 1),
BB is (N - 2),
fib(AA,CC),
fib(BB,DD),
F is (CC + DD).
I'm trying to understand this sum predicate
sum([], 0).
sum([H|T], Sum) :-
sum(T, Temp),
Sum is Temp + H.
It works however I don't understand why. From my understanding with a query such as sum([1,2,3], Sum) it will match on the second clause instantiating H as 1 and T as [2,3] and Sum is still Sum. Then it will attempt to satisfy the first sub goal calling sum again but in the second goal where Sum is Temp + H when is Temp given a value?
Temp is given a value first in the base case, sum([],0). That causes Temp=0 in the recursive call above. The call above that adds H to give 0+H, etc.
To convince yourself of this, trace the execution of your query:
?- trace.
true.
[trace] ?- sum([1,2,3], Sum).
Call: (6) sum([1, 2, 3], _G376) ? creep
Call: (7) sum([2, 3], _G455) ? creep
Call: (8) sum([3], _G455) ? creep
Call: (9) sum([], _G455) ? creep
Exit: (9) sum([], 0) ? creep
^ Call: (9) _G460 is 0+3 ? creep
^ Exit: (9) 3 is 0+3 ? creep
Exit: (8) sum([3], 3) ? creep
^ Call: (8) _G463 is 3+2 ? creep
^ Exit: (8) 5 is 3+2 ? creep
Exit: (7) sum([2, 3], 5) ? creep
^ Call: (7) _G376 is 5+1 ? creep
^ Exit: (7) 6 is 5+1 ? creep
Exit: (6) sum([1, 2, 3], 6) ? creep
Sum = 6.
(The creep is me hitting Enter; this is SWI-Prolog.)
I dont think I understand how recursion works in prolog
The following code (a power function)
pow(_,0,1).
pow(X,Y,Z) :-
Y1 is Y - 1 ,
pow(X,Y1,Z1) ,
Z is Z1*X
.
Creates the following trace:
[trace] ?- pow(2,2,X).
Call: (6) pow(2, 2, _G368) ? creep
Call: (7) _G444 is 2+ -1 ? creep
Exit: (7) 1 is 2+ -1 ? creep
Call: (7) pow(2, 1, _G443) ? creep
Call: (8) _G447 is 1+ -1 ? creep
Exit: (8) 0 is 1+ -1 ? creep
Call: (8) pow(2, 0, _G446) ? creep
Exit: (8) pow(2, 0, 1) ? creep
Call: (8) _G450 is 1*2 ? creep
Exit: (8) 2 is 1*2 ? creep
Exit: (7) pow(2, 1, 2) ? creep
Call: (7) _G368 is 2*2 ? creep
Exit: (7) 4 is 2*2 ? creep
Exit: (6) pow(2, 2, 4) ? creep
I dont understand how the last state : 'Z is Z1*X' works. When is this function called? When the base case is reached?
How does the base case ever get called?
Thanks
The main point is that pow is not a function. It's a predicate. Prolog doesn't really evaluate pow, it tries satisfy its conditions.
And when is the first clause reached? It's tried every time. But unless the second argument is 0 and the third one is 1 (or they are variables that can be unified with those values), it fails. And when the first clause fails, the second one is tried.
You can think of pow as a function that is split in two clauses that deal with different parameter values. The function is recursive, which is triggered by the recursive call in the second clause. But after this call, there is still something to do, the Z is Z1*1 goal. These "dangling" computations are done when the recursion has terminated and control "bubbles" upward again, on the way back so to speak. (There is a name for this kind of recursion which I can't remember).
Look at this commented trace:
[trace] ?- pow(2,2,X).
% initial call
Call: (6) pow(2, 2, _G368) ? creep
% the second clause is picked for this call,
% the third argument is an uninstantiated variable, represented by _G368
Call: (7) _G444 is 2+ -1 ? creep
% the first goal in this claus is "Y1 is Y -1", which is here
% translated with its bindings
Exit: (7) 1 is 2+ -1 ? creep
% the is/2 goal has been called, and has provided a binding for "Y1"
Call: (7) pow(2, 1, _G443) ? creep
% this is the first recursive call, with the new arguments 2, 1 and an
% undefined Z1
Call: (8) _G447 is 1+ -1 ? creep
% again the second clause is used, this is the first goal in it,
% calling is/2
Exit: (8) 0 is 1+ -1 ? creep
% is/2 delivers a binding for the current Y1, 0
Call: (8) pow(2, 0, _G446) ? creep
% the next (second) recursive call; see how at this point non of the
% "Z is Z1*X" "statements" have been reached
Exit: (8) pow(2, 0, 1) ? creep
% the second recursive call matches the first clause; this is where
% the base case is used! it can immediately "Exit" as with the match
% to the clause all bindings have been established already; the third
% argument is instantiated to 1
Call: (8) _G450 is 1*2 ? creep
% now the recursion has terminated, and control is passed back to that
% more recent calling clause (this was the one where Y1 has been bound
% to 0); now the "Z is Z1*X" can be tried for the first time, and Z
% can be instantiated ("unified")
Exit: (8) 2 is 1*2 ? creep
% this is the result of this unification, Z is bound to 2;
% with this, this level in the stack of recursive calls has been completed...
Exit: (7) pow(2, 1, 2) ? creep
% ... and this is the result ("Exit") of this call, showing all
% instantiated parameters
Call: (7) _G368 is 2*2 ? creep
% but this just brings us back one more level in the call stack, to a
% pending execution (this was the one where Y1 has been bound to 1),
% now the pending execution can be performed
Exit: (7) 4 is 2*2 ? creep
% here you see the result of the execution of is/2, binding Z to 4
Exit: (6) pow(2, 2, 4) ? creep
% and this finishes the initial call of the predicate, delivering a
% binding for the X in the query, 4; you can tell that the recursive
% call stack as been processed completely by looking at the "stack
% depth indicator", (6), which matches the initial (6) when the trace
% started (they don't necessarily start with 0 or 1).
Every line in the trace with the asterisk (*) is using the "Z is Z1 * X" rule.
This code works by providing the following recursive definition of the power function:
X^0 = 1 for all X.
X^Y = X^(Y-1) * X
The Z, Z1 and Y1 variables are artifacts of the fact that Prolog needs a way to refer to intermediate results; you call Y-1 Y1 and you call X^(Y-1) Z1.
This gets to the base case by decreasing the exponent (Y) by one (yielding Y1) at each level of the recursion until Y = 0 and the first case of the definition applies.