Пример #1
0
    def result(self, state, action):
        """
        Return the state that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).

        The action can be a drop or rotation.        
        """
        # Here a workbench state is a frozenset of parts

        #raise NotImplementedError

        part_list = list(state)

        pa, pu, offset = action

        if pu == None:
            part_list.remove(pa)

            rotated_part = TetrisPart(pa)
            rotated_part.rotate90()

            part_list.append(rotated_part.get_frozen())

            return make_state_canonical(part_list)
        else:
            part_list.remove(pa)
            part_list.remove(pu)

            new_part = TetrisPart(pa, pu, offset)

            part_list.append(new_part.get_frozen())

            return make_state_canonical(part_list)
Пример #2
0
    def result(self, state, action):
        """
        Return the state that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).

        The action can be a drop or rotation.        
        """

        # Here a workbench state is a frozenset of parts
        #Extract the values from action
        pa,pu,offset=action
        # Make a new TetrisPart Object with the given action
        new_part = TetrisPart(pa, pu, offset)
        # Make a copy of the state as a list type
        state_list=list(state)
        # Dequeue pa,pu from the list
        state_list.remove(pa)
        state_list.remove(pu)
        # Queue the new_part into the list
        #get forzen, new part
        new_part = new_part.get_frozen()
        state_list.append(new_part)
        #state_list.append(tuple(new_part))
        # This effectively "stacks" the pa & pu together at the specified offset
        # Make the state_list canonical to make sure it is in the correct order
        state_list = make_state_canonical(state_list)
        # Return a tuple of tuples
        return tuple(state_list)
Пример #3
0
    def result(self, state, action):
        """
        Return the state (as a tuple of parts in canonical order)
        that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).
        
        @return
          a state in canonical order
        
        """
        # Here a workbench state is a frozenset of parts

        #raise NotImplementedError

        # pa, pu, offset = action # HINT

        part_list = list(state)

        pa, pu, offset = action

        part_list.remove(pa)
        part_list.remove(pu)

        new_part = TetrisPart(pa, pu, offset)

        part_list.append(new_part.get_frozen())

        return make_state_canonical(part_list)
Пример #4
0
    def result(self, state, action):
        """
        Return the state (as a tuple of parts in canonical order)
        that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).
        
        @return
          a state in canonical order
        
        """

        # Store action[0] - [2] in corresponding part and offset variables (pa = part above, pu = part under).
        pa, pu, offset = action

        # Resulting array of combined state.
        state_to_make_canonical = []

        # Create TetrisPart object and return tuple of object.
        make_object = TetrisPart(pa, pu, offset)
        returned_state = make_object.get_frozen()

        # Loop parts in state and avoid existing parts (pa & pu), then append current part to
        # results array (state_make_canonical).
        for index in state:
            if index != pa and index != pu:
                state_to_make_canonical.append(index)

        # Add new Tetris part to resulting array as well and make state canonical with call to
        # respective function and return canonical final_state array.
        state_to_make_canonical.append(returned_state)
        final_state = make_state_canonical(state_to_make_canonical)
        return final_state
Пример #5
0
    def result(self, state, action):
        """
        Return the state that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).

        The action can be a drop or rotation.        
        """
        currentState = list(state)

        if (action[0] == "rotate"):  #Check if the action is a rotation action
            piece = TetrisPart(action[1])
            piece.rotate90()
            currentState.append(
                piece.get_frozen())  #Add new rotated piece to the state
            currentState.remove(action[1])  #remove old piece
        else:
            newPiece = TetrisPart(action[0], action[1], action[2])
            currentState.append(
                newPiece.get_frozen())  #Add the new piece to the state
            currentState.remove(action[0])
            currentState.remove(action[1])  #Remove old pieces

        currentState = make_state_canonical(currentState)

        return currentState
Пример #6
0
    def result(self, state, action):                                    #DONE
        """
        Return the state (as a tuple of parts in canonical order)
        that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).

        Actions are just drops.
        
        @return
          a state in canonical order
        """
        # USE THE ACTION GIVEN TO MAKE A NEW PART FROM PU AND PA
        # REMOVE PA AND PU FROM STATE, REPLACE WITH NEW PART
        # COMPUTE AND RETURN NEW STATE
        assert(action in self.actions(state)) #defense 
        
        pa, pu, offset = action # HINT
        new_part = TetrisPart(pa,pu,offset) #was checked as valid before
        new_part_tuple = new_part.get_frozen()
        part_list = list(state)
        part_list.remove(pu)
        part_list.remove(pa)
        part_list.append(new_part_tuple)
        
        return make_state_canonical(part_list) #tuple, in canonical order
Пример #7
0
 def actions(self, state):                                           #DONE
     """Return the actions that can be executed in the given
     state. The result would typically be a list, but if there are
     many actions, consider yielding them one at a time in an
     iterator, rather than building them all at once.
     
     Rotations are allowed, but no filtering out the actions that 
     lead to doomed states.
     
     """
     # EACH COMBINATION OF 2 PARTS AND AN OFFSET, OR 
         # A PART AND A ROTATION IS AN ACTION
     # EACH DROP CAN EXIST WITH OFFSETS IN ALLOWABLE RANGE
     # RETURN LIST OF TUPLES: (pa, pu, offset) or (part, rotation)
     actions = []
     part_list = list(make_state_canonical(state))  #    HINT
     for u in range(0, len(part_list)): #under
         for a in range(0, len(part_list)): #above
             if u == a: # APPEND A ROTATION
                 p = part_list[u]
                 for rot in range(1,4):
                     actions.append((p, rot))
             else: # APPEND A DROP
                 pa = part_list[a]
                 pu = part_list[u]
                 offsets = offset_range(pa, pu)
                 for o in range(offsets[0], offsets[1]):
                     new_part = TetrisPart(pa,pu,o)
                     # No pruning, but check valid offset value
                     if new_part.offset is not None:
                         actions.append((pa, pu, o)) #tuple
                 
     return actions
Пример #8
0
    def actions(self, state):                                           #DONE
        """
        Return the actions that can be executed in the given
        state. The result would typically be a list, but if there are
        many actions, consider yielding them one at a time in an
        iterator, rather than building them all at once.
        
        A candidate action is eliminated if and only if the new part 
        it creates does not appear in the goal state.

        Actions are just drops
        """
        # EACH COMBINATOIN OF 2 PARTS IS AN ACTION
        # EACH COMBINATION CAN EXIST IN ONE OF TWO ORDERS 
        # EACH COMBINATION CAN EXIST WITH OFFSETS IN ALLOWABLE RANGE
        # RETURN ACTIONS AS A TUPLE: (pa, pu, offset)
        actions = []
        part_list = list(make_state_canonical(state))  #    HINT
        
        '''
        # SLOWER -> didnt use
        for part1, part2 in itertools.combinations(part_list, 2):
            for pa, pu in itertools.permutations((part1, part2)):
                offsets = offset_range(pa, pu)
                for o in range(offsets[0], offsets[1]):
                    new_part = TetrisPart(pa,pu,o)
                    # Check valid offset and not a duplicate
                    if (new_part.offset is not None and (pa, pu, o) not in actions):
                        # P R U N I N G
                        # Check new part exists in goal, and action is unique
                        for part in self.goal:
                            if appear_as_subpart(new_part.get_frozen(), part):
                                actions.append((pa, pu, o)) #tuple
                                break #do not keep checking and appending
                    
        '''
        for u in range(0, len(part_list)): #under
            for a in range(0, len(part_list)): #above
                if u != a: # check index isnt the same, because actual part can be
                    pa = part_list[a]
                    pu = part_list[u]
                    offsets = offset_range(pa, pu)
                    for o in range(offsets[0], offsets[1]):
                        new_part = TetrisPart(pa,pu,o)
                        # Check valid offset and not a duplicate
                        if (new_part.offset is not None and (pa, pu, o) not in actions):
                            # P R U N I N G
                            # Check new part exists in goal, and action is unique
                            for part in self.goal:
                                if appear_as_subpart(new_part.get_frozen(), part):
                                    actions.append((pa, pu, o)) #tuple
                                    break #do not keep checking and appending
               
        
        return actions
Пример #9
0
 def actions(self, state):                                       #DONE
     """Return the actions that can be executed in the given
     state. The result would typically be a list, but if there are
     many actions, consider yielding them one at a time in an
     iterator, rather than building them all at once.
     
     Filter out actions (drops and rotations) that are doomed to fail 
     using the function 'cost_rotated_subpart'.
     A candidate action is eliminated if and only if the new part 
     it creates does not appear in the goal state.
     This should  be checked with the function "cost_rotated_subpart()'.
             
     """
     # EACH COMBINATION OF 2 PARTS AND AN OFFSET, OR 
         # A PART AND A ROTATION IS AN ACTION
     # EACH DROP CAN EXIST WITH OFFSETS IN ALLOWABLE RANGE
     # EACH ROTATION CAN EXIST WITH ROTATIONS 1, 2, OR 3 
     # RETURN LIST OF TUPLES: (pa, pu, offset) or (part, rotation)
     actions = []
     part_list = list(make_state_canonical(state))  #    HINT
     for u in range(0, len(part_list)): #under
         for a in range(0, len(part_list)): #above
             if u == a:                  # APPEND A ROTATION
                 p = part_list[u]
                 #Do not want to prune rotations, otherwise it will fail
                     #to detect parts (especially if the goal is rotated after
                         # it has been completely assembled)
                 for r in range(1,4):
                     if (p,r) not in actions:
                         actions.append((p,r))                       
                     
                     
             else:                       # APPEND A DROP
                 pa = part_list[a] # u!= a
                 pu = part_list[u]
                 offsets = offset_range(pa, pu)
                 for o in range(offsets[0], offsets[1]):
                     # P R U N I N G
                     # COMPUTE NEW PART
                     # IF NEW PART EXISTS IN GOAL, APPEND THE ACTION
                     # ROTATION IS ALLOWED (COST != INF)
                     new_part = TetrisPart(pa,pu,o)
                     if (new_part.offset is not None and (pa, pu, o) not in actions):
                         # P R U N I N G
                         # NEW PART EXISTS IN GOAL (C_R_S != INF)
                         for part in self.goal:
                             if (cost_rotated_subpart(new_part.get_frozen(), part) < 5):
                                 actions.append((pa, pu, o)) #tuple
                                 break #do not keep checking and appending
     
     return actions
Пример #10
0
    def h(self, n):                                             #DONE
        '''
        This heuristic computes the following cost; 
        
           Let 'k_n' be the number of parts of the state associated to node 'n'
           and 'k_g' be the number of parts of the goal state. (self.goal)
          
        The cost function h(n) must return 
            k_n - k_g + max ("cost of the rotations")  
        where the list of cost of the rotations is computed over the parts in 
        the state 'n.state' according to 'cost_rotated_subpart'.
        
        
        @param
          n : node of a search tree
          
        '''
        # Save current state and goal state as lists
        state_list = list(make_state_canonical(n.state))
        #state_list = n
        goal_list = list(make_state_canonical(self.goal))
        
        # Num parts is the length of the state lists
        k_n = len(state_list)
        k_g = len(goal_list)

                 
        # For all the parts in current state, get the cost_rotated_subpart
        r_costs = [] #make it a list, and append as we calculate
        for i in range(0, k_g): # for all the goal parts
            for j in range(0, k_n): # check all the current parts
                r_costs.append(cost_rotated_subpart(state_list[j], goal_list[i]))

        print(k_n,",",k_g,",",max(r_costs))
        
        return k_n - k_g + max(r_costs)
Пример #11
0
 def actions(self, state):                                           #DONE
     """
     Return the actions that can be executed in the given
     state. The result would typically be a list, but if there are
     many actions, consider yielding them one at a time in an
     iterator, rather than building them all at once.
     
     @param
       state : a state of an assembly problem.
     
     @return i
        the list of all legal drop actions available in the 
         state passed as argument.   
        the individual actions are tuples, contained in a list. 
     """
     # EACH COMBINATOIN OF 2 PARTS IS AN ACTION
     # EACH COMBINATION CAN EXIST IN ONE OF TWO ORDERS 
     # EACH COMBINATION CAN EXIST WITH OFFSETS IN ALLOWABLE RANGE
     # RETURN AS A LIST OF TUPLES: (pa, pu, offset)
     actions = []
     part_list = list(make_state_canonical(state))  #    HINT
     
     #cemetary:
     for u in range(0, len(part_list)): #under
         for a in range(0, len(part_list)): #above
             if u != a: # check index isnt the same, because actual part can be
                 pa = part_list[a]
                 pu = part_list[u]
                 offsets = offset_range(pa, pu)
                 for o in range(offsets[0], offsets[1]):
                     new_part = TetrisPart(pa,pu,o)
                     # No pruning, but check for valid offset value
                     if new_part.offset is not None:
                         actions.append((pa, pu, o)) #tuple
     '''
                         
     # using itertools -> SLOWER, didnt use. 
     for part1, part2 in itertools.combinations(part_list, 2):
         for pa, pu in itertools.permutations((part1, part2)):
             offsets = offset_range(pa, pu)
             for o in range(offsets[0], offsets[1]):
                 new_part = TetrisPart(pa,pu,o)
                 # Ensure valid offset value
                 if new_part.offset is not None:
                     actions.append((pa,pu,o)) #tuple
     '''
     return actions
def test_action_result_deep():   #USER ADDED
    '''
    Load some parts, and keep building randomly until only one part exists.
    '''
    
    initial_state = load_state('workbenches/wb_08_i.txt')        
    ap = AssemblyProblem_3(initial_state)
    
    state = initial_state
    display_state(state, "INITIAL: ")
    assert(state == initial_state)
    i = 1
    
    while len(make_state_canonical(state)) is not 1:
        
        actions = ap.actions(state)
        action = random.choice(actions)
        
        if len(action)==3:
            pa, pu, offset = action
            pa_ = TetrisPart(pa)
            pu_ = TetrisPart(pu)
            print("\n\nACTION #", i, ", DROP")
            print("Part Above:")
            pa_.display()
            print("Part Under:")
            pu_.display()
            print("Offset: ", offset)
        elif len(action)==2:
            p, r = action
            part = TetrisPart(p)
            print("\n\nACTION #",i, ", ROTATION")
            print("Part:")
            part.display()
            print("Rotate: ", r*90)
        
        new_state = ap.result(state, action)
        assert(new_state != state)
        display_state(new_state, "Result: ")
        state = new_state
        i +=1
        
    print("\n\nFully Built.")
    test_passed = len(state) == 1
    print("Test Action and Result Passed: ", test_passed)
Пример #13
0
    def result(self, state, action):
        """
        Return the state that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).

        The action can be a drop or rotation.        
        """

        # Store action[0] - [2] in corresponding part and offset variables (pa = part above, pu = part under).
        pa, pu, offset = action

        # Resulting list of combined state. Currently lists all parts in state.
        state_to_make_canonical = list(state)
        final_state = ""

        # Conditional statement to check if there is a part to drop onto or not.
        if pu is not None:

            # Make new part with pa and pu.
            make_object = TetrisPart(pa, pu, offset)

            # Get tuple of tetris part.
            returned_state = make_object.get_frozen()

            # Remove existing parts from list
            state_to_make_canonical.remove(pa)
            state_to_make_canonical.remove(pu)
        else:

            # Make new part with pa, rotate and get tuple of new part.
            make_object = TetrisPart(pa)
            make_object.rotate90()
            returned_state = make_object.get_frozen()

            # Remove old part above from state list.
            state_to_make_canonical.remove(pa)

        # Append new state to resulting list, make canonical and return.
        state_to_make_canonical.append(returned_state)
        final_state = make_state_canonical(state_to_make_canonical)

        return final_state
Пример #14
0
 def result(self, state, action):
     """
     Return the state (as a tuple of parts in canonical order)
     that results from executing the given
     action in the given state. The action must be one of
     self.actions(state).
     
     @return
       a state in canonical order
     """
     assert action in self.actions(state)
     pa, pu, offset = action
     # Rename variables with meaningful names
     tetris = TetrisPart(part_above=pa, part_under=pu, offset=offset)
     new_part = tetris.get_frozen()
     tetris.frozen = None
     updated_state = [a for a in state if a not in [pa, pu]]
     updated_state.append(new_part)
     return make_state_canonical(tuple(updated_state))
Пример #15
0
    def result(self, state, action):
        """
        Return the state that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).

        The action can be a drop or rotation.        
        """
        # Here a workbench state is a frozenset of parts
        assert action in self.actions(state)
        if self.magic_num in action:
            rotated_piece = action[0]
            idx_rot = action[1]  # Index of rotated piece
            updated_state = [
                state[i] if i != idx_rot else rotated_piece
                for i in range(0, len(state))
            ]
            return make_state_canonical(updated_state)
        else:
            return AssemblyProblem_2.result(self, state, action)
Пример #16
0
    def result(self, state, action):                                    #DONE
        """
        Return the state that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).

        The action can be a drop or rotation.        
        """
        # Here a workbench state is a frozenset of parts        
        assert(action in self.actions(state)) #defense 

        part_list = list(state)
        
        if len(action)==2: #THIS IS A ROTATION
            part, rot = action
            assert (rot in range(1,4)) #defense
            
            # ROTATE PART NUM_ROT TIMES 90 DEGREES 
            # REMOVE PART FROM PART LIST 
            # APPEND ROTATED PART TO PART LIST
            new_part = TetrisPart(part)
            for i in range(0, rot):
                new_part.rotate90()
    
            new_part_tuple = new_part.get_frozen() 
            part_list.remove(part)
            part_list.append(new_part_tuple)
            
            
        elif len(action) == 3: # THIS IS A DROP
            # USE THE ACTION GIVEN TO MAKE A NEW PART FROM PU AND PA
            # REMOVE PA AND PU FROM STATE, REPLACE WITH NEW PART
            # COMPUTE AND RETURN NEW STATE
            pa, pu, offset = action
            new_part = TetrisPart(pa,pu,offset)
            new_part_tuple = new_part.get_frozen()
            part_list.remove(pu)
            part_list.remove(pa)
            part_list.append(new_part_tuple)
            
        return make_state_canonical(part_list)
Пример #17
0
    def result(self, state, action):
        """
        Return the state (as a tuple of parts in canonical order)
        that results from executing the given
        action in the given state. The action must be one of
        self.actions(state).
        
        @return
          a state in canonical order
        
        """
        currentState = list(state)

        newPiece = TetrisPart(action[0], action[1], action[2])
        currentState.append(
            newPiece.get_frozen())  #Add the new piece to the state
        currentState.remove(action[0])
        currentState.remove(action[1])  #Remove the old pieces

        currentState = make_state_canonical(currentState)
        return currentState