Solving the Monkey and Banana Using Basic STRIPS Algorithm
NickName:Syzorr Ask DateTime:2015-10-10T06:59:52

Solving the Monkey and Banana Using Basic STRIPS Algorithm

We have been asked (for homework) to create solutions to a couple of AI problems using Python and making modifications to a basic STRIPS algorithm. At the moment I am trying to tackle the Monkey and Banana problem using it and have had some success but a lot of problems regarding behavior of the algorithm and I'm not sure what I'm missing here. This code has been trimmed down as I try to get the monkey to just push a chair somewhere and climb it.

from string import *


class Stripper:
    # A STRIPS-style planner for the blocks world

# Initialization code
def __init__(self):
    """
    Initialize the global variables, and function dictionaries
    """
    self.worldStack = []
    self.goalStack = []
    self.plan = []

    # token to function mappings
    self.formulas = {"height": self.height, "at": self.at}
    self.Operators = {"GO": self.go, "PUSH": self.push,
                      "CLIMB": self.climb}

    # safety net tests are denoted by the following as the first list item.
    self.SafetyTag = "SAFETYTAG"

@staticmethod
def populate(strng, statestack):
    """
    Helper function that parses strng according to expectations
    and adds to the sateStack passed in.
    """
    for x in (strng.lower().replace('(', '').replace(')', '').split(',')):
        ls = x.strip().split(' ')
        statestack.append(ls)
    statestack.reverse()

def populategoal(self, strng):
    """
    Populate the goal stack with data in strng.
    """
    self.populate(strng, self.goalStack)
    # add original safety check
    goalcheck = [self.SafetyTag]
    for g in self.goalStack:
        goalcheck.append(g)
    self.goalStack.insert(0, goalcheck)

def populateworld(self, strng):
    """
    Populate the world state stack with data in strng.
    """
    self.populate(strng, self.worldStack)

# ----------------------------------------------------
# Solver
#   Attempts to solve the problem using the setup
#   goal and world states
# ----------------------------------------------------

def solve(self):
    """
    Attempts to solve the problem using STRIPS Algorithm
    Note: You need to setup the problem prior to running this
          by using populateWorld and populateGoal using a well
          formatted string.
    """
    if (not len(self.worldStack) > 0) or (not len(self.goalStack) > 0):
        print "\nNothing to do.\nMake sure you populate the problem using\n" \
              "populateWorld and populateGoal before calling this function."
        return
    while len(self.goalStack) > 0:
        # if the subgoal is in world state
        if self.top(self.goalStack) in self.worldStack:
            # pop it from the stack
            self.goalStack.pop()
        # if that item is an operator,
        elif self.top(self.goalStack)[0].upper() in self.Operators:
            subgoal = self.goalStack.pop()
            # store it in a "plan"
            self.plan.append(subgoal)
            # and modify the world state as specified
            self.Operators[(subgoal[0])](subgoal)
        # if the item is a safety check
        elif self.SafetyTag == self.top(self.goalStack)[0].upper():
            safetycheck = self.goalStack.pop()
            for check in safetycheck[1:]:
                if not (check in self.worldStack):
                    print " Safety net ripped.n Couldn't contruct a plan. Exiting...", check
                    return
        else:
            # find an operator that will cause the
            # top subgoal to result
            if self.top(self.goalStack)[0] in self.formulas:
                self.formulas[self.top(self.goalStack)[0]]()
            else:
                raise Exception(self.top(self.goalStack)[0] + " not valid formula/subgoal")
                # or add to goal stack and try, but not doing that for now.
    print "\nFinal Plan:\n",
    for step in self.plan:
        print "  ", join(step, " ").upper()

# ----------------------------------------------------
# Predicate logic
# ----------------------------------------------------
def at(self):
    topg = self.top(self.goalStack)
    assert(topg[0] == "at"), "expected at"
    assert(len(topg) == 3), "expected 3 arguments"
    print topg
    x = self.getloc(topg[1])
    if topg[1] == "monkey":
        self.goalStack.append(["GO", x, topg[2]])
        self.goalStack.append([self.SafetyTag, ["at", "monkey", x], ["height", "monkey", "low"]])
        self.goalStack.append(["at", "monkey", x])
        self.goalStack.append(["height", "monkey", "low"])
    else:
        self.goalStack.append(["PUSH", topg[1], x, topg[2]])
        self.goalStack.append([self.SafetyTag, ["at", topg[1], x], ["at", "monkey", x], ["height", "monkey", "low"],
                               ["height", topg[1], "low"], ["handempty"]])
        self.goalStack.append(["at", topg[1], x])
        self.goalStack.append(["at", "monkey", x])
        self.goalStack.append(["height", "monkey", "low"])
        self.goalStack.append(["height", topg[1], "low"])
        self.goalStack.append(["handempty"])

def height(self):
    topg = self.top(self.goalStack)
    print topg
    assert(topg[0] == "height"), "expected height"
    assert(len(topg) == 3), "expected 3 arguments"
    if topg[1] == "monkey":
        x = self.getloc("monkey")
        y = "low" if (self.getheight("monkey") == "low") else "high"
        self.goalStack.append(["CLIMB"])
        self.goalStack.append([self.SafetyTag, ["at", "monkey", x], ["at", "chair", x], ["height", "monkey", y],
                               ["height", "chair", "low"]])
        self.goalStack.append(["at", "chair", x])
        self.goalStack.append(["height", "monkey", y])
        self.goalStack.append(["height", "chair", "low"])
        self.goalStack.append(["at", "monkey", x])

# ----------------------------------------------------
# Operators
# ----------------------------------------------------

def go(self, subgoal):
    # deletion
    self.worldstateremove(["at", "monkey", subgoal[1]])
    # addition
    self.worldstateadd(["at", "monkey", subgoal[2]])

def push(self, subgoal):
    # deletion
    self.worldstateremove(["at", "monkey", subgoal[2]])
    self.worldstateremove(["at", subgoal[1], subgoal[2]])
    # addition
    self.worldstateadd(["at", subgoal[1], subgoal[3]])
    self.worldstateadd(["at", "monkey", subgoal[3]])

def climb(self, subgoal):
    # deletion
    self.worldstateremove(["height", "monkey", "low"])
    # addition
    self.worldstateadd(["height", "monkey", "high"])

# ----------------------------------------------------
# Utility functions
# ----------------------------------------------------

#  Returns the item that is being held in the world state, 0 if not
def getholdingitem(self):
    for x in self.worldStack:
        if x[0] == "holding":
            return x[1]
    return 0

# Return height of object
def getheight(self, item):
    for x in self.worldStack:
        if x[0] == "height" and x[1] == item:
            return x[2]
    raise Exception("Object " + item + " is on nothing!")

# Return location of object
def getloc(self, item):
    for x in self.worldStack:
        if x[0] == "at" and x[1] == item:
            return x[2]
    raise Exception("Object " + item + " has no location!")

# Adds a state to world state if the state isn't already true
def worldstateadd(self, toadd):
    if toadd not in self.worldStack:
        self.worldStack.append(toadd)

# Tries to remove the toRem state from the world state stack.
def worldstateremove(self, torem):
    while torem in self.worldStack:
        self.worldStack.remove(torem)

@staticmethod
def top(lst):
    """
    Returns the item at the end of the given list
    We don't catch an error because that's the error we want it to throw.
    """
    return lst[len(lst) - 1]

I've got some basic tests set up:

from monkey2 import Stripper


def runtests():

print "\n\nRunning Monkey-Banana Problem - Part 1\n"
ws = "((height chair low), (height monkey low), (handempty), (at monkey a), (at chair b))"
gs = "((at monkey d))"
s = Stripper()
s.populateworld(ws)
s.populategoal(gs)
s.solve()

print "\n\nRunning Monkey-Banana Problem - Part 2\n"
ws = "((height chair low), (height monkey low), (handempty), (at monkey a), (at chair b))"
gs = "((at monkey d), (height monkey high))"
s = Stripper()
s.populateworld(ws)
s.populategoal(gs)
s.solve()

print "\n\nRunning Monkey-Banana Problem - Part 2 Rearranged\n"
ws = "((height chair low), (height monkey low), (handempty), (at monkey a), (at chair b))"
gs = "((height monkey high), (at monkey d))"
s = Stripper()
s.populateworld(ws)
s.populategoal(gs)
s.solve()

if __name__ == "__main__":
    runtests()

For the test Part 2 it works but for when it is rearranged, the monkey gets stuck and I'm aware it is probably something simple but I can't quite figure out why my algorithm isn't robust enough to handle this. Can anyone see what I am missing? Or point me in the right direction?

I get the feeling that the problem lies in the base solve() method because it isn't designed to allow backtracking.

Copyright Notice:Content Author:「Syzorr」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/33048330/solving-the-monkey-and-banana-using-basic-strips-algorithm

More about “Solving the Monkey and Banana Using Basic STRIPS Algorithm” related questions

Solving the Monkey and Banana Using Basic STRIPS Algorithm

We have been asked (for homework) to create solutions to a couple of AI problems using Python and making modifications to a basic STRIPS algorithm. At the moment I am trying to tackle the Monkey and

Show Detail

Solving monkey and banana with BFS algorithm

I try to solve the monkey and banana problem with the BFS algorithm with java. Here is my code so far public class Program { static final int[][] states={ { 1, 1, 0, 0, 0, 0 }, //...

Show Detail

STRIPS representation of monkey in the lab

I have been reviewing some material on the representation of an AI plan given the STRIPS format, and found that different people seem to formulate the same problem in different ways. For instance,

Show Detail

Monkey & Banana in prolog

I have this prolog code for solving monkey and banana problem but my compiler give an error This is my code: move(state(middle, onbox, middle, hasnot), grasp, state(middle, onbox, middle, ...

Show Detail

Prolog: Monkey and Banana, Two Boxes

Instructions: Modify the attached program so that in order for the monkey to reach the bananas, he has to stand on a smaller box, which he has placed on top of a bigger one. At the beginning of the

Show Detail

Monkey and banana in Thinking as Computation

I am reading the book Thinking as Computation and wrote the code as chapter 9.4: plan(L) :- initial_state(I), goal_state(G), reachable(I, L, G). initial_state([]). legal_move(S, A, [A |...

Show Detail

Monkey and banana solution doesn't stop after grabbing the banana (Prolog)

I have this code to represent the famous monkey and banana problem in Prolog detailed here : init(state(atdoor,onfloor,atwindow,hasnot)). goal(state(_,_,_,has)). move(state(middle,onbox,middle,has...

Show Detail

Tetravex solving algorithm

Well, i was thinking of making a Tetravex solving program in order to practice my code writing skills (language will propably be Visual Basic) and I need help finding an algorithm for solving it. For

Show Detail

Android Monkey: "No activities found to run, monkey aborted"

My package is named com.mywebsite.banana. I want to have a seed, so the test is repeatable: -s 13 I want to have a fairly low-level of verbosity: -v I want to run 500 psuedo-random commands: 500 ...

Show Detail

Improving my Minesweeper solving algorithm

I have implemented in Python an algorithm for solving the game 'Minesweeper'. The program works as follows: Say that the solver clicks a square named 'a'. For sake of example let the number thus

Show Detail