Exercise 3.17 “ Prolog Programming for Artificial Intelligence” by
Ivan Btrako
I understand the max predicate, but I’m having trouble tracing the maxList one. I’m trying to write the logic in pseudocode to help me out
- Take first and second elements and compare them and get the
maximum - Take that maximum and compare it with third element in
list and if it’s bigger overwrite the maximum and repeat again till
list is empty.
I don’t understand the solution given however, and I tried tracing it and failed. I’m having trouble mapping the MaxRest to the Max & with the base case. Also, I don’t understand why prolog doesn’t give an error when unifying [X,Y|Rest] with [Y|T]. Example [1,3,[7,2]] with [3|[7,2]].
max(X,Y,X):-
X>=Y.
max(X,Y,Y):-
X<Y.
maxlist( [X], X). %what does this line do?
maxlist( [X,Y|Rest], Max):-
maxlist( [Y|Rest], MaxRest),
max(X, MaxRest,Max).
Any help tracing would be greatly appreciated.
2
Answers
Since you understand
max/3
this won’t explain it.This is a classic recursive list pattern that does the recursion before processing the item. The normal recursive list pattern with a tail-call is
but here it is
where the item is processed after recursing through the list.
Also this processes two items at a time, i.e.
because the compare needs two items.
This
is just taking the values off of the list and pushing them onto the stack so that when it backtracks it will have one value for the comparison, i.e.
MaxRest
which is the max of all the values that were inRest
and the current value which isX
. You might think it should beY
, but when there is just one item in the list, the list is actually[Y|[]]
which is really[Y]
with matches with the pattern in this clausemaxlist( [X], X).
.So what does
maxlist( [X], X).
do? A common base case for a list is justpredicate([],R).
for returning a list, but in this case the last value alone needs to be returned as a value, so this takesX
out of the list in the first parameter and returns it as a value in the second parameter so that it becomesMaxRest
which is the max value when there is only one item in the list. Whenmax(X, MaxRest,Max)
is executed it has a value forMaxRest
return from backtracking, andX
on the stack when deconstructing the list. The result isMax
which is returned as the third parameter inmaxlist( [X,Y|Rest], Max)
which becomes the value forMaxRest
upon backtracking again.Ask questions if that doesn’t make sense.
Actually
so while your example does give an error, it is not what is being done with
Start with the list
[1,2,3,4]
and unify it with[X,Y|Rest]
Notice that
[Y|Rest]
would then be[2|[3,4]]
.Don’t try an unify
[X,Y|Rest]
with[Y|Rest]
but instead unifyRest
withRest
andY
withY
,X
is stored on the stack but not passed to next level of the stackframe.If you really want to understand list then use this to see them
If you have Version 4 of the book see Figure 3.1 on page 61.
Prolog predicates define relations in terms of logic that says that the head of the clause is true if (
:-
) the body is true. This helps you properly read a predicate:This says that:
You can similarly read the clause for
max(X,Y,Y)
.Now look at:
Here, we’re defining
maxlist
to mean the maximum value of a list. This particular clause says that:There are no if conditions (
:-
) in this case since no other conditions are necessary to establish this rule.Then there is the recursive clause:
This says that:
This recursive clause and the prior base case clause completely define
maxlist
. If you read through that carefully, it should seem completely logical.I don’t understand this comment. Nowhere in your code does Prolog attempt to unify these two terms. Your example terms of
[1,3,[7,2]]
and[3|[7,2]]
would not unify because the first is a list of three elements: 1, 3, and [7,2], whereas the other is a list of 3 elements: 3, 7, and 2. For two lists to be unifiable, it not only needs to be the same length, but each corresponding term in the list must be unifiable.What would then make
[X,Y|Rest]
and[Y|T]
unifiable? You can write[X,Y|Rest]
as[X|[Y|Rest]]
, which makes it easy to see that these are unifiable if the following are true:In other words, the lists have to have (a) at least two elements, and (b) the first two elements are the same.