Пример #1
0
 def setUp(self):
     self.firstState   = State("First")
     self.secondState  = State("Second")
     self.thirdState   = State("Third")
     self.fourthState  = State("Fourth")
     self.fifthState   = State("Fifth")
     self.sixthState   = State("Sixth")
     self.seventhState = State("Seventh")
     self.firstAction  = Action("<Action One>")
     self.secondAction = Action("<Action Two>")
     self.thirdAction  = Action("<Action Three>")
     self.fourthAction = Action("<Action Four>")
     
     self.successorFunction = SuccessorFunction()
     self.successorFunction.addMapping(self.firstState, self.firstAction,\
                                       self.firstState)
     
     self.successorFunction.addMapping(self.firstState, self.secondAction,\
                                       self.secondState)
     
     self.successorFunction.addMapping(self.firstState, self.thirdAction,\
                                       self.firstState)
     
     self.searchProblem = SearchProblem(self.firstState,\
                                        self.successorFunction,\
                                        self.secondState)
Пример #2
0
    def testSuccessorFunctionDefinition(self):
        simpleFunction = SuccessorFunction()
        simpleFunction.addMapping(self.firstState, self.firstAction, self.secondState)
        simpleFunctionString = str(simpleFunction)
        #Verbose output:
#        print(simpleFunctionString)
        
 
#        print("--------------------------------------------\n")
#        print("Trying to execute:\naddMapping((State First with conditions: \
#        (None)) ->\n\t(Action <Action One>, State Second with conditions: (None)))\n")
#        print("This is a duplicate of the first mapping in a Successor Function \
#        and should not be reflected at all.\n")
        simpleFunction.addMapping(self.firstState, self.firstAction, self.secondState)
        simpleFunctionDupString = str(simpleFunction)
#        print(simpleFunctionDupString)
        self.assertEqual(simpleFunctionString, simpleFunctionDupString, \
                         "Duplicate mappings in a Successor Function should not \
                          be reflected at all.")
                
#        print("--------------------------------------------\n")
#        print("Trying to execute:\naddMapping((State First with conditions: \
#        (None)) ->\n\t(Action <Action One>, State Third with conditions: (None)))\n")
#        print("Applying the same action in the same state should not be allowed to\
#        result in two different states.\n")
#        print("Adding this mapping should replace the original mapping.\n")
        simpleFunction.addMapping(self.firstState, self.firstAction, self.thirdState)
        simpleFunctionReplaceString = str(simpleFunction)
        #print(simpleFunctionReplaceString)
        self.assertNotEqual(simpleFunctionString, simpleFunctionReplaceString, \
                            "Mapping one State to one Action with multiple \
                            resulting States keeps only the last-most State.")
def main():
    
    move_one_missionary   = Action("Move One Missionary")
    move_two_missionaries = Action("Move Two Missionaries")
    move_one_cannibal     = Action("Move One Cannibal")
    move_two_cannibals    = Action("Move Two Cannibals")
    move_one_and_one      = Action("Move One Missionary + One Cannibal") 
    
    initial_state = State("Init", {'L':{'3m','3c','b'}, 'R':{'0m','0c'}})
    goal_state = State("Goal", {'L':{'0m','0c'}, 'R':{'3m','3c','b'}})
    
    # Any state where cannibals outnumber missionaries is not a valid state
    one_and_one_over = State("1m1c Over", {'L':{'2m','2c'}, 'R':{'1m','1c','b'}})
    one_and_one_over_without_boat = State("1m1c Over w/o Boat", {'L':{'2m','2c','b'}, 'R':{'1m','1c'}})

    two_cannibals_over = State("2c Over", {'L':{'3m','1c'}, 'R':{'0m','2c','b'}})
    two_cannibals_over_without_boat = State("2c Over w/o Boat", {'L':{'3m','1c', 'b'}, 'R':{'0m','2c'}})

    one_cannibal_over = State("1c Over", {'L':{'3m','2c'}, 'R':{'0m','1c','b'}})
    one_cannibal_over_without_boat = State("1c Over w/o Boat", {'L':{'3m','2c','b'}, 'R':{'0m','1c'}})
    
    two_and_two_over = State("2m2c Over", {'L':{'1m','1c'}, 'R':{'2m','2c','b'}})
    two_and_two_over_without_boat = State("2m2c Over", {'L':{'1m','1c','b'}, 'R':{'2m','2c'}})
    
    three_cannibals_over = State("3c Over", {'L':{'3m','0c'}, 'R':{'0m','3c','b'}})
    three_missionaries_over_without_boat = State("3m Over w/o Boat", {'L':{'0m','3c', 'b'}, 'R':{'3m','0c'}})
    
    three_missionaries_one_cannibal_over = State("3m3c Over", {'L':{'0m','1c'}, 'R':{'3m','1c','b'}})
    three_missionaries_one_cannibal_over_without_boat = State("3m1c Over w/o Boat", {'L':{'0m','2c', 'b'}, 'R':{'3m','1c'}})
    
    three_missionaries_two_cannibals_over = State("3m2c Over", {'L':{'0m','1c'}, 'R':{'3m','2c','b'}})
    
    
    #Example invalid states:
    #two_cannibals_over_without_boat = State("2c Over w/o Boat", {'L':{'3m','1c', 'b'}, 'R':{'0m','2c'}})
    #one_missionary_two_cannibals_over = State("1m2c Over", {'L':{'2m','1c'}, 'R':{'1m','2c','b'}})
    
    #Successor Function
    successor_fn = SuccessorFunction()
    successor_fn.addMapping(initial_state, move_two_cannibals, two_cannibals_over)
    successor_fn.addMapping(initial_state, move_one_and_one, one_and_one_over)
    successor_fn.addMapping(initial_state, move_one_cannibal, one_cannibal_over)
    
    #be careful w/mappings that result in the initial_state
    #you could descend in an infinte loop...
    
    #Beginning in (two_cannibals_over)
    successor_fn.addMapping(two_cannibals_over, move_two_cannibals, initial_state)
    successor_fn.addMapping(two_cannibals_over, move_one_cannibal, one_cannibal_over_without_boat)
    
    #Beginning in (one_and_one_over)
    successor_fn.addMapping(one_and_one_over, move_one_and_one, initial_state)
    successor_fn.addMapping(one_and_one_over, move_one_missionary, one_cannibal_over_without_boat)
    
    #Beginning in (one_cannibal_over)
    successor_fn.addMapping(one_cannibal_over, move_one_cannibal, initial_state)
    
    #Beginning in (one_cannibal_over_without_boat)
    successor_fn.addMapping(one_cannibal_over_without_boat, move_one_cannibal, two_cannibals_over)
    successor_fn.addMapping(one_cannibal_over_without_boat, move_one_missionary, one_and_one_over)
    successor_fn.addMapping(one_cannibal_over_without_boat, move_two_cannibals, three_cannibals_over)
    
    #Beginning in (three_cannibals_over)
    successor_fn.addMapping(three_cannibals_over, move_one_cannibal, two_cannibals_over_without_boat)
    successor_fn.addMapping(three_cannibals_over, move_two_cannibals, one_cannibal_over_without_boat)
    
    #Beginning in (two_cannibals_over_without_boat)
    successor_fn.addMapping(two_cannibals_over_without_boat, move_two_missionaries, two_and_two_over)
    successor_fn.addMapping(two_cannibals_over_without_boat, move_one_cannibal, three_cannibals_over)
    
    #Beginning in (two_and_two_over)
    successor_fn.addMapping(two_and_two_over, move_two_missionaries, two_cannibals_over_without_boat)
    successor_fn.addMapping(two_and_two_over, move_one_and_one, one_and_one_over_without_boat)
    
    #Beginning in (one_and_one_over_without_boat)
    successor_fn.addMapping(one_and_one_over_without_boat, move_one_and_one, two_and_two_over)
    successor_fn.addMapping(one_and_one_over_without_boat, move_two_missionaries, three_missionaries_one_cannibal_over)
    
    #Beginning in (three_missionaries_one_cannibal_over)
    successor_fn.addMapping(three_missionaries_one_cannibal_over, move_two_missionaries, one_and_one_over_without_boat)
    successor_fn.addMapping(three_missionaries_one_cannibal_over, move_one_cannibal, three_missionaries_over_without_boat)
    
    #Beginning in (three_missionaries_over_without_boat)
    successor_fn.addMapping(three_missionaries_over_without_boat, move_one_cannibal, three_missionaries_one_cannibal_over)
    successor_fn.addMapping(three_missionaries_over_without_boat, move_two_cannibals, three_missionaries_two_cannibals_over)
    
    #Beginning in (three_missionaries_two_cannibals_over)
    successor_fn.addMapping(three_missionaries_two_cannibals_over, move_two_cannibals, three_missionaries_over_without_boat)
    successor_fn.addMapping(three_missionaries_two_cannibals_over, move_one_cannibal, three_missionaries_one_cannibal_over_without_boat)
    successor_fn.addMapping(three_missionaries_two_cannibals_over, move_one_missionary, two_and_two_over_without_boat)
    
    #Beginning in (two_and_two_over_without_boat)
    successor_fn.addMapping(two_and_two_over_without_boat, move_one_missionary, three_missionaries_one_cannibal_over)
    successor_fn.addMapping(two_and_two_over_without_boat, move_one_and_one, goal_state)
    
    #Beginning in (three_missionaries_one_cannibal_over_without_boat)
    successor_fn.addMapping(three_missionaries_one_cannibal_over_without_boat, move_one_cannibal, three_missionaries_two_cannibals_over)
    successor_fn.addMapping(three_missionaries_one_cannibal_over_without_boat, move_two_cannibals, goal_state)
    
    
    #Define the Search Problem
    missionaries_and_cannibals = SearchProblem(initial_state, successor_fn, goal_state)
    plan = tree_search(missionaries_and_cannibals)
    
    print(missionaries_and_cannibals)
    print("\nSolution: \n")
    for plan_step in plan:
        if plan_step.action is None:
            print ("<start>")
        
        else:
            print ("\t"),
            print (plan_step.action)
    
    print("<end>")
    
   
    print("\nExpanded Nodes: \n")
    for plan_step in plan:
        print(plan_step)
Пример #4
0
class Test(unittest.TestCase):

    def setUp(self):
        self.firstState   = State("First")
        self.secondState  = State("Second")
        self.thirdState   = State("Third")
        self.fourthState  = State("Fourth")
        self.fifthState   = State("Fifth")
        self.sixthState   = State("Sixth")
        self.seventhState = State("Seventh")
        self.firstAction  = Action("<Action One>")
        self.secondAction = Action("<Action Two>")
        self.thirdAction  = Action("<Action Three>")
        self.fourthAction = Action("<Action Four>")
        
        self.successorFunction = SuccessorFunction()
        self.successorFunction.addMapping(self.firstState, self.firstAction,\
                                          self.firstState)
        
        self.successorFunction.addMapping(self.firstState, self.secondAction,\
                                          self.secondState)
        
        self.successorFunction.addMapping(self.firstState, self.thirdAction,\
                                          self.firstState)
        
        self.searchProblem = SearchProblem(self.firstState,\
                                           self.successorFunction,\
                                           self.secondState)
        

    def tearDown(self):
        pass

    def testStateNameEquality(self):
        left    = State("Left")
        leftToo = State("Left")
        right   = State("Right")
        
        self.assertEqual(left, leftToo, "States should be equal")
        self.assertNotEqual(left, right, "States should not be equal")
    
    def testStateConditionsEquality(self):
        allLeft    = State("AllLeft", {'L':{'3m','3c','b'}, 'R':{'0m','0c'}})
        allLeftToo = State("AllLeft", {'L':{'3m','3c','b'}, 'R':{'0m','0c'}})
        allRight   = State("AllRight", {'L':{'0m','0c'}, 'R':{'3m','3c','b'}})
        
        self.assertEqual(allLeft, allLeftToo, "These two States have identical\
         names and conditions")
        self.assertNotEqual(allLeft, allRight, "These two States have different\
         names and conditions")
        
    def testSuccessorFunctionDefinition(self):
        simpleFunction = SuccessorFunction()
        simpleFunction.addMapping(self.firstState, self.firstAction, self.secondState)
        simpleFunctionString = str(simpleFunction)
        #Verbose output:
#        print(simpleFunctionString)
        
 
#        print("--------------------------------------------\n")
#        print("Trying to execute:\naddMapping((State First with conditions: \
#        (None)) ->\n\t(Action <Action One>, State Second with conditions: (None)))\n")
#        print("This is a duplicate of the first mapping in a Successor Function \
#        and should not be reflected at all.\n")
        simpleFunction.addMapping(self.firstState, self.firstAction, self.secondState)
        simpleFunctionDupString = str(simpleFunction)
#        print(simpleFunctionDupString)
        self.assertEqual(simpleFunctionString, simpleFunctionDupString, \
                         "Duplicate mappings in a Successor Function should not \
                          be reflected at all.")
                
#        print("--------------------------------------------\n")
#        print("Trying to execute:\naddMapping((State First with conditions: \
#        (None)) ->\n\t(Action <Action One>, State Third with conditions: (None)))\n")
#        print("Applying the same action in the same state should not be allowed to\
#        result in two different states.\n")
#        print("Adding this mapping should replace the original mapping.\n")
        simpleFunction.addMapping(self.firstState, self.firstAction, self.thirdState)
        simpleFunctionReplaceString = str(simpleFunction)
        #print(simpleFunctionReplaceString)
        self.assertNotEqual(simpleFunctionString, simpleFunctionReplaceString, \
                            "Mapping one State to one Action with multiple \
                            resulting States keeps only the last-most State.")
        
    def testGettingApplicableActionsForStates(self):
        applicable_actions = \
        self.successorFunction.getApplicableActionsInState(self.firstState)
        
        self.assertTrue(type(applicable_actions)==type(set()), \
                        "The returned value should be a Set")
        
        for action in applicable_actions:
            self.assertTrue(type(action)==Action, \
                             "Each element of the Set should be an Action")
        
        self.assertIn(self.firstAction, applicable_actions, \
                      "<Action One> should be in the returned Set")
        self.assertNotIn(self.fourthAction, applicable_actions, \
                         "<Action Four> should not be in the returned Set")
        
    def testResolveActionInState(self):
        resulting_state = \
        self.successorFunction.resolveActionInState(self.firstState, self.firstAction)
        
        self.assertTrue(type(resulting_state)==State, \
                        "Resulting state should be a State")
        
        self.assertEqual(resulting_state, self.firstState, \
                         "Correct State is returned for applying corresponding Action")
        
        self.assertIsNone(self.successorFunction.resolveActionInState(self.thirdState, \
                                                                      self.firstAction), \
                          "If State is not mapped, resulting State is None")
        
        self.assertIsNone(self.successorFunction.resolveActionInState(self.firstState, \
                                                                      self.fourthAction), \
                          "If State is not mapped to given Action, resulting State is None")
        
    def testGoalTest(self):
        secondStateNode = SearchNode(self.secondState)
        self.assertTrue(self.searchProblem.goalTest(secondStateNode), \
                        "The SearchNode for the second State is the goal of this toy Search Problem")
        
        self.assertFalse(self.searchProblem.goalTest(self.secondState), \
                         "The Second State should be the goal of this toy Search Problem, \
                         but we're passing in a State, not a Node")
        
        self.assertFalse(self.searchProblem.goalTest(self.firstState), \
                         "The First State should not be the goal of this toy Search Problem")
        
        self.assertFalse(self.searchProblem.goalTest(1), "A number is not a State!  This should be False")
    
    def testPathTo(self):
        root  = SearchNode(self.firstState)
        child = SearchNode(self.secondState, root)
        grandchild = SearchNode(self.thirdState, child)
        
        true_path = [root, child, grandchild]
        test_path = path_to(grandchild)
        
        self.assertEqual(test_path, true_path, "Test and True Paths should be equal")
        
    def testExpand(self):
        #the expand function can actually have repeated nodes, so this is normal.
        true_expanded_nodes = [SearchNode(self.firstState,SearchNode(self.firstState),self.firstAction,0,1),
                               SearchNode(self.firstState,SearchNode(self.firstState),self.thirdAction,0,1),
                               SearchNode(self.secondState,SearchNode(self.firstState),self.secondAction,0,1)
                               ]
        test_expanded_nodes = expand(self.searchProblem, SearchNode(self.firstState))
        
    
        self.assertEqual(len(test_expanded_nodes), 3, "There should be three nodes in the Test Expansion")
        self.assertEqual(test_expanded_nodes[0], true_expanded_nodes[0], "Test and True Expansions should be the same")
        self.assertEqual(test_expanded_nodes[1], true_expanded_nodes[1], "Test and True Expansions should be the same")
        self.assertEqual(test_expanded_nodes[2], true_expanded_nodes[2], "Test and True Expansions should be the same")