Prolog - Monkey and Banana Problem



In this prolog example, we will see one very interesting and famous problem, The Monkey and Banana Problem.

Problem Statement

Suppose the problem is as given below −

  • A hungry monkey is in a room, and he is near the door.

  • The monkey is on the floor.

  • Bananas have been hung from the center of the ceiling of the room.

  • There is a block (or chair) present in the room near the window.

  • The monkey wants the banana, but cannot reach it.

Monkey and Banana Problem

So how can the monkey get the bananas?

So if the monkey is clever enough, he can come to the block, drag the block to the center, climb on it, and get the banana. Below are few observations in this case −

  • Monkey can reach the block, if both of them are at the same level. From the above image, we can see that both the monkey and the block are on the floor.

  • If the block position is not at the center, then monkey can drag it to the center.

  • If monkey and the block both are on the floor, and block is at the center, then the monkey can climb up on the block. So the vertical position of the monkey will be changed.

  • When the monkey is on the block, and block is at the center, then the monkey can get the bananas.

Now, let us see how we can solve this using Prolog. We will create some predicates as follows −

We have some predicates that will move from one state to another state, by performing action.

  • When the block is at the middle, and monkey is on top of the block, and monkey does not have the banana (i.e. has not state), then using the grasp action, it will change from has not state to have state.

  • From the floor, it can move to the top of the block (i.e. on top state), by performing the action climb.

  • The push or drag operation moves the block from one place to another.

  • Monkey can move from one place to another using walk or move clauses.

Another predicate will be canget(). Here we pass a state, so this will perform move predicate from one state to another using different actions, then perform canget() on state 2. When we have reached to the state ‘has>’, this indicates ‘has banana’. We will stop the execution.

Program

move(state(middle,onbox,middle,hasnot),
   grasp,
   state(middle,onbox,middle,has)).
move(state(P,onfloor,P,H),
   climb,
   state(P,onbox,P,H)).
move(state(P1,onfloor,P1,H),
   drag(P1,P2),
   state(P2,onfloor,P2,H)).
move(state(P1,onfloor,B,H),
   walk(P1,P2),
   state(P2,onfloor,B,H)).
canget(state(_,_,_,has)).
canget(State1) :-
   move(State1,_,State2),
   canget(State2).

Output

| ?- [monkey_banana].
compiling D:/TP Prolog/Sample_Codes/monkey_banana.pl for byte code...
D:/TP Prolog/Sample_Codes/monkey_banana.pl compiled, 17 lines read - 2167 bytes written, 19 ms

(31 ms) yes
| ?- canget(state(atdoor, onfloor, atwindow, hasnot)).

true ?

yes
| ?- trace
.
The debugger will first creep -- showing everything (trace)

yes
{trace}
| ?- canget(state(atdoor, onfloor, atwindow, hasnot)).
      1 1 Call: canget(state(atdoor,onfloor,atwindow,hasnot)) ?
      2 2 Call: move(state(atdoor,onfloor,atwindow,hasnot),_52,_92) ?
      2 2 Exit:move(state(atdoor,onfloor,atwindow,hasnot),walk(atdoor,_80),state(_80,onfloor,atwindow,hasnot)) ?
      3 2 Call: canget(state(_80,onfloor,atwindow,hasnot)) ?
      4 3 Call: move(state(_80,onfloor,atwindow,hasnot),_110,_150) ?
      4 3 Exit: move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwindow,onbox,atwindow,hasnot)) ?
      5 3 Call: canget(state(atwindow,onbox,atwindow,hasnot)) ?
      6 4 Call: move(state(atwindow,onbox,atwindow,hasnot),_165,_205) ?
      6 4 Fail: move(state(atwindow,onbox,atwindow,hasnot),_165,_193) ?
      5 3 Fail: canget(state(atwindow,onbox,atwindow,hasnot)) ?
      4 3 Redo: move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwindow,onbox,atwindow,hasnot)) ?
      4 3 Exit: move(state(atwindow,onfloor,atwindow,hasnot),drag(atwindow,_138),state(_138,onfloor,_138,hasnot)) ?
      5 3 Call: canget(state(_138,onfloor,_138,hasnot)) ?
      6 4 Call: move(state(_138,onfloor,_138,hasnot),_168,_208) ?
      6 4 Exit: move(state(_138,onfloor,_138,hasnot),climb,state(_138,onbox,_138,hasnot)) ?
      7 4 Call: canget(state(_138,onbox,_138,hasnot)) ?
      8 5 Call:   move(state(_138,onbox,_138,hasnot),_223,_263) ?
      8 5 Exit: move(state(middle,onbox,middle,hasnot),grasp,state(middle,onbox,middle,has)) ?
      9 5 Call: canget(state(middle,onbox,middle,has)) ?
      9 5 Exit: canget(state(middle,onbox,middle,has)) ?
      7 4 Exit: canget(state(middle,onbox,middle,hasnot)) ?
      5 3 Exit: canget(state(middle,onfloor,middle,hasnot)) ?
      3 2 Exit: canget(state(atwindow,onfloor,atwindow,hasnot)) ?
      1 1 Exit: canget(state(atdoor,onfloor,atwindow,hasnot)) ?
      
true ?

(78 ms) yes
Advertisements