Information Technology Reference
In-Depth Information
Figure 7.3.
The blocks-world program redone
blocks2.pl
% This is a list-based version of the blocks-world program.
% X appears before Y in list L.
before(X,Y,L) :- append(Z,[Y|_],L), append(_,[X|_],Z).
% The given blocks-world scene: three stacks of blocks
scene([[b1,b2],[b3,b4,b5,b6],[b7]]).
% above(X,Y) means that block X is somewhere above block Y.
above(X,Y) :- scene(L), member(Stack,L), before(X,Y,Stack).
% left(X,Y) means that block X is somewhere left of block Y.
left(X,Y) :- scene(L), before(Stack1,Stack2,L),
member(X,Stack1), member(Y,Stack2).
right(Y,X) :- left(X,Y).
This says that
X
appears before
Y
in list
L
if there is a list
Z
such that
X
appears
somewhere in
Z
, and joining
Z
to a list whose head is
Y
results in
L
.
This almost does the right thing:
?- before(2,4,[1,2,3,4,5]).
Yes
?- before(8,4,[1,2,3,4,5]).
ERROR: Out of global stack
The problem is the first atom in the body,
append(_,[X|_],Z)
. There are infinitely
many lists
Z
that contain
X
, and it may turn out that none of them satisfy the second
query. The solution is to change the order of the queries so that
Z
is generated as a
sublist of
L
:
% A better version
before(X,Y,L) :- append(Z,[Y|_],L), append(_,[X|_],Z).
This results in the desired behavior:
?- before(2,4,[1,2,3,4,5]).
Yes
?- before(8,4,[1,2,3,4,5]).
No