I am studying Prolog using Ivan Bratko book: Programming for Artificial Intelligence and I am finding some difficulties to implement the final part of an exercise proposed
The exercise is a program that use graphs to decide how to move blocks and to arrange them in an order.
This is an image related to what the program have to do:
As you can see in the previous immage the blocks A,B,C can be moved using a number of admissible moves that are:
A block can be moved only if it is at the top of the stack
A block can be moved on the ground (on a void stack)
A block can be moved over another block (at the top of another stack that contains some others blocks)
So these admissible moves induce a graph of the possible transitions between one state and another state in the graph, something like this:
So, as you can se in the previous graph I can rappresent a situation using a list of 3 sublist.
Each sublist rappresent a stack where I can put the blocks according to the previous constraints
So for example the situation of the central node of the previous graph can be represented by:
[[A], [B], [C]]
Because each stack contains a single block.
The situation represented by the node at the top left where I stacked one below the other blocks C,A,B can be represented by:
[[C,A,B], [], []]
Ok, so my program is the following one:
del(X, [X|Tail], Tail).
del(X, [Y|Tail], [Y|Tail1]) :- del(X, Tail, Tail1).
/* s(CurrentState, SuccessorState): Predicate that calculate a legal move from
the CurrentState to the SuccessorState:
*/
s(Stacks, [Stack1, [Top1|Stack2] | OtherStacks]) :-
del( [Top1|Stack1], Stacks, Stacks1),
del( Stack2, Stacks1, OtherStacks).
goal(Situation) :- member([a,b,c], Situation).
In these last days I have deeply studied it and I understand how it works.
Substantially the s/3 predicate is my successor function s(CurrentState, SuccessorState)
that calculates a legal move from the CurrentState
to the SuccessorState
.
This predicate works well, in fact if I launch the following query:
[debug] ?- s([[a,b,c],[],[]],R).
R = [[b, c], [a], []]
I obtain that [[b,c],[a],[]] is a successor state for the state [[a,b,c],[],[]] and this is good because I have moved the a
block from the top of the first stack on the top of the second stack (that was void) and this is a perfectly legal move.
Ok, going on I have the goal/1
predicate that says when I have reached a final state (when the computation have to stop):
goal(Situation) :- member([a,b,c], Situation).
It says that a situation (a specific stacks list configuration) is a goal situation if in the related stacks list there is a stack that is the [a,b,c] list.
So the following situations are goal situations:
[[a,b,c],[],[]]
[[], [a,b,c],[]]
[[],[], [a,b,c]]
Ok now my problem is the following one: I have to implement the solve/2
predicate like this:
solve([[c,a,b],[],[]], Situation)
that starts from a passed situation (in this case the list of stacks that have all the blocks in the first stack with c
on the ground, b
in the middle and a
on the top) and arrives to a goal situation.
I don't know exactly what I have to do and how I have to solve it (unfortunately I have no teacher)
I was trying to inspire myself looking at this version of 8 queen problem that uses a similar programming technique (in which I have a goal to satisfy and the solve predicate):
s(Queens, [Queen|Queens]) :- member(Queen, [1,2,3,4,5,6,7,8]),
noattack(Queen, Queens, 1).
goal([_,_,_,_,_,_,_,_]).
noattack(_,[],_) :- !.
noattack(Y,[Y1|Ylist],Xdist) :- Y =\= Y1,
Y1-Y =\= Xdist,
Y-Y1 =\= Xdist,
Dist1 is Xdist + 1,
noattack(Y,Ylist,Dist1).
solve(N,[N]) :- goal(N). % sample call: solve([], X).
solve(N, [N|Sol1]) :- s(N,N1),
solve(N1,Sol1).