This popular puzzle is a nice example of finding trajectories in the state space: A farmer is standing on the west side of the river and with him are a wolf, a goat and a cabbage. In the river there is a small boat. The farmer wants to cross the river with all the three items that are with him. There are no bridges and in the boat there is only room for the farmer and one item. However, the crossings are danger-ridden:
• If the farmer leaves the goat with the cabbages alone on the same side of the river, the goat will eat the cabbages.
• If the farmer leaves the wolf and the goat on the same side of the river, the wolf will eat the goat.
Only the farmer can separate the wolf from the goat and the goat from the cabbage. How can the farmer cross the river with all three items, without one eating the other27?
The first thing needed is to define astate that accumulates all data needed to properly determine the next move. The state of the systemfarmer-wolf-goat- cabbageis given by declaring their whereabouts, see Figure 2.12. While crossing the river no state may appear twice.
Figure 2.12: State of the systemfarmer-wolf-goat-cabbage
The solution is given by program2_18_fwgc.pl:
/*1*/ top:- /*2*/ cross_the_river(state(w,w,w,w),state(e,e,e,e)). /*3*/ cross_the_river(Initial_state,Final_state):- /*4*/ feasible_crossing(Initial_state,Final_state, [Initial_state],Final_sequence),nl, /*5*/ reverse(Final_sequence,Final_sequence_r), /*6*/ write_feasible_crossing(Final_sequence_r), /*7*/ fail.
/*8*/ cross_the_river(_,_):- nl, write("Those are all solutions!"). /*9*/ feasible_crossing(Current_state,Final_state,
Final_sequence_accu,Final_sequence):- /*10*/ crossing(Current_state,Next_state), /*11*/ not(unsafe(Next_state)),
ecclesiastic, poet, mathematician and teacher from York, Northumbria. He wrote a textbook Propositiones ad Acuendos Juvenes(in English: Problems to Sharpen the Young) containing 53 puzzles, some of them of the ”river crossing” type.
/*12*/ not(member(Next_state,Final_sequence_accu)), /*13*/ feasible_crossing(Next_state,Final_state,
[Next_state|Final_sequence_accu],Final_sequence). /*14*/ feasible_crossing(Final_state,Final_state,
Final_sequence,Final_sequence):- !. % Farmer and wolf change river bank,
% goat and cabbage stay put in their places: /*15*/ crossing(state(X,X,Go,Ca),state(Y,Y,Go,Ca)):- /*16*/ opposite_banks(X,Y).
% Farmer and goat change river bank,
% wolf and cabbage stay put in their places: /*17*/ crossing(state(X,W,X,Ca),state(Y,W,Y,Ca)):- /*18*/ opposite_banks(X,Y).
% Farmer and cabbage change river bank, % wolf and goat stay put in their places: /*19*/ crossing(state(X,W,Go,X),state(Y,W,Go,Y)):- /*20*/ opposite_banks(X,Y).
% Farmer only changes river bank,
% wolf, goat and cabbage stay put in their places: /*21*/ crossing(state(X,W,Go,Ca),state(Y,W,Go,Ca)):- /*22*/ opposite_banks(X,Y).
% Wolf and goat cannot be left with no farmers supervision: /*23*/ unsafe( state(Y,X,X,_) ):-
/*24*/ opposite_banks(Y,X).
% Goat and cabbage cannot be left with no farmers supervision: /*25*/ unsafe( state(Y,_,X,X) ):- /*26*/ opposite_banks(Y,X). /*27*/ opposite_banks(w,e). /*28*/ opposite_banks(e,w). /*29*/ write_feasible_crossing([H1,H2|T]) :- /*30*/ write_crossing(H1,H2), /*31*/ write_feasible_crossing([H2|T]). /*32*/ write_feasible_crossing([_|[]]):-
/*33*/ writeln("All safely crossed the river."). /*34*/ write_crossing(state(X,W,G,C), state(Y,W,G,C)):- /*35*/ translate(X,X_translated),
/*36*/ translate(Y,Y_translated),
write(Y_translated),write("."),nl. /*38*/ write_crossing(state(X,X,G,C), state(Y,Y,G,C)):- /*39*/ translate(X,X_translated),
/*40*/ translate(Y,Y_translated),
/*41*/ write("Farmer moves with wolf from "),write(X_translated), write(" to "),write(Y_translated),write("."),nl. /*42*/ write_crossing(state(X,W,X,C), state(Y,W,Y,C)) :-
/*43*/ translate(X,X_translated), /*44*/ translate(Y,Y_translated),
/*45*/ write("Farmer moves with goat from "),write(X_translated), write(" to "),write(Y_translated),write("."),nl. /*46*/ write_crossing(state(X,W,G,X), state(Y,W,G,Y)) :-
/*47*/ translate(X,X_translated), /*48*/ translate(Y,Y_translated),
/*49*/ write("Farmer moves with cabbage from "),write(X_translated), write(" to "),write(Y_translated),write("."),nl.
/*50*/ translate(w,"west bank"). /*51*/ translate(e,"east bank").
There are two solutions to this problem. The first one is:
Farmer moves with goat from west bank to east bank. Farmer moves from east bank to west bank.
Farmer moves with wolf from west bank to east bank. Farmer moves with goat from east bank to west bank. Farmer moves with cabbage from west bank to east bank. Farmer moves from east bank to west bank.
Farmer moves with goat from west bank to east bank. All safely crossed the river,
depicted on Figure 2.13.
As can be seen, the farmer must first take the goat across the river. He then returns and picks up the wolf. He leaves the wolf off and takes the goat back across the river with him. Then he leaves the goat at the starting point and takes the cabbage over to where the wolf is. He returns and picks up the goat, and then lands where the wolf and the cabbage are.
Figure 2.13: First solution river crossings for farmer, wolf, goat and cabbage
Farmer moves with goat from west bank to east bank. Farmer moves from east bank to west bank.
Farmer moves with cabbage from west bank to east bank. Farmer moves with goat from east bank to west bank. Farmer moves with wolf from west bank to east bank. Farmer moves from east bank to west bank.
Farmer moves with goat from west bank to east bank. All safely crossed the river,
Those are all solutions!
It is depicted on Figure 2.14.
This time the farmer also starts with taking the goat across the river. He then returns and picks up the cabbage. He leaves the cabbage off and takes the goat back across the river with him. Then he leaves the goat at the starting point and takes the wolf over to where the cabbage is. He returns and picks up the goat, and then lands where the wolf and the cabbage are.
The program contains an interesting feature: the number of crossings is implicitly minimized by demanding that no state ever appears twice. This is
Figure 2.14: Second solution river crossings for farmer, wolf, goat and cabbage
done in line /*12*/: any new state Next_State may not belong to the list Final_sequence_accuof states already accumulated. Unfortunately, this fea- ture is only a fortuitous heuristics that just works for the example discussed, but is not of general nature and does not work for all conceivable optimum state trajectory problems.