예제 #1
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
예제 #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 cost_rotated_subpart(some_part, goal_part):
    '''    
    Determine whether the part 'some_part' appears in another part 'goal_part'
    as a rotated subpart. If yes, return the number of 'rotate90' needed, if 
    no return 'np.inf'
    
    The definition of appearance is the same as in the function 
    'appear_as_subpart'.
                   
    @param
        some_part: a tuple representation of a tetris part
        goal_part: a tuple representation of another tetris part
    
    @return
        the number of rotation needed to see 'some_part' appear in 'goal_part'
        np.inf  if no rotated version of 'some_part' appear in 'goal_part'
    
    '''
    # Create TetrisPart object of some_part tuple, to access TetrisPart functions.
    make_object_part = TetrisPart(some_part)

    # Rotate above tetris part 90 degrees clockwise, 4 times.
    for rot in list(range(1, 5)):
        make_object_part.rotate90()

        # Get tuple of tetris part
        matrix_part_rotated = make_object_part.get_frozen()

        # Call appear_as_subpart and If rotated some_part appears in goal_part,
        # return current iteration value as it is the number of rotations.
        if appear_as_subpart(matrix_part_rotated, goal_part):
            return rot

    # Return np.inf if no solution found.
    return np.inf
예제 #4
0
    def actions(self, state):
        """
        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.
        """
        #

        #raise NotImplementedError

        part_list = list(state)

        filtered_actions = []

        for pa, pu in itertools.product(part_list, repeat=2):
            if pa != pu:
                start, end = offset_range(pa, pu)
                for offset in range(start, end):
                    new_part = TetrisPart(pa, pu, offset)
                    if new_part.offset != None:
                        for goal in self.goal:
                            if appear_as_subpart(new_part.get_frozen(), goal):
                                filtered_actions.append((pa, pu, offset))

        return filtered_actions
예제 #5
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)
예제 #6
0
    def actions(self, state):
        """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.

        The actions that lead to rotation are defined as a tuple of the form:
        action = (rotated(piece),index(piece),magic_num)
        """
        # First the drop of one piece into other
        valid_moves1 = AssemblyProblem_2.actions(self, state)
        # Rotation of one of the pieces of state
        valid_moves2 = []
        # Check if all elements are equal. If all pieces are the same it does not matter which one we rotate
        are_equal = False
        if state[1:] == state[:-1]:
            are_equal = True
        for i in range(0, len(state)):
            tetris_piece = TetrisPart(state[i])
            tetris_piece.rotate90()
            piece = tetris_piece.get_frozen()
            valid_moves2.append((piece, i, self.magic_num))
            if are_equal:
                break
        valid_moves = valid_moves1 + valid_moves2

        return valid_moves
예제 #7
0
    def actions(self, state):
        """
        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.
        """
        actionList = []
        partList = list(state)
        goals = np.array(self.goal)

        possibleCombinations = it.permutations(
            partList, 2)  #Get all possible combinations
        for combination in possibleCombinations:
            start, end = offset_range(
                combination[0], combination[1])  #Get all possible offsets
            for offset in range(start, end):
                resultPiece = TetrisPart(combination[0], combination[1],
                                         offset)
                for goal in goals:  #Loop through each goal piece
                    if (
                            appear_as_subpart(resultPiece.get_frozen(), goal)
                    ):  #Check if the combination is in the current goal piece
                        actionList.append(
                            (combination[0], combination[1], offset)
                        )  #Add part above, part below and offset to action list

        return actionList
예제 #8
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
예제 #9
0
 def actions(self, state):
     """
     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.
     """
     #Make an empty list to append pruned actions
     action_list=[]
     # Make a copy of the state as a list
     state_list=list(state)
     
     # Make a similar nested for loop as AssemblyProblem_1
     for pa,pu in itertools.permutations(state_list,2):
       
       start, end = offset_range(pa, pu)
       # Returns start, end
       for offset in range(start, end):
         # Make a TetrisPart of the pa,pu and offset to get a value for TetrisPart.offset
         temp_piece=TetrisPart(pa,pu,offset)
         
         # Pruning
         # If valid piece, append the action
         # Does it appear in the goal state?
         # self.goal is NOT a part -> how to convert state to part?
         if temp_piece.offset!=None and appear_as_subpart(temp_piece,TetrisPart(self.goal)):
           action_list.append((pa, pu, offset))
     
     return action_list
예제 #10
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
예제 #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.
     
     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
예제 #12
0
def cost_rotated_subpart(some_part, goal_part):                         #DONE
    '''    
    Determine whether the part 'some_part' appears in another part 'goal_part'
    as a rotated subpart. If yes, return the number of 'rotate90' needed, if 
    no return 'np.inf'
    
    The definition of appearance is the same as in the function 
    'appear_as_subpart'. -> call this function for all rotations of some_part
                   
    @param
        some_part: a tuple representation of a tetris part
        goal_part: a tuple representation of another tetris part
    
    @return
        the number of rotation needed to see 'some_part' appear in 'goal_part'
            0, 1, 2, 3 or infinity (np.inf)
        np.inf  if no rotated version of 'some_part' appear in 'goal_part'
    
    '''
    
    #USING HIS METHOD
    # Make a tetris part of all parts, rotate some part n times, test 
    # appear_as_subpart for each rotation, if true return n. If all rotations 
    # tested and returned false, return inf because no solution. 
    sp = TetrisPart(some_part)
    gp = TetrisPart(goal_part)
    
    
    for num_rot in range(0,4):
        if appear_as_subpart(sp.get_frozen(), gp.get_frozen()):
            return num_rot
        sp.rotate90()
    
    return np.inf
예제 #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.        
        """
        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
예제 #14
0
def appear_as_subpart(some_part, goal_part):
    '''    
    Determine whether the part 'some_part' appears in another part 'goal_part'.
    
    Formally, we say that 'some_part' appears in another part 'goal_part',
    when the matrix representation 'S' of 'some_part' is a a submatrix 'M' of
    the matrix representation 'G' of 'goal_part' and the following constraints
    are satisfied:
        for all indices i,j
            S[i,j] == 0 or S[i,j] == M[i,j]
            
    During an assembly sequence that does not use rotations, any part present 
    on the workbench has to appear somewhere in a goal part!
    
    @param
        some_part: a tuple representation of a tetris part
        goal_part: a tuple representation of another tetris part
        
    @return
        True if 'some_part' appears in 'goal_part'
        False otherwise    
    '''
    
    #raise NotImplementedError
    #return TetrisPart.get_height
    #return TetrisPart.get_width

    ps = np.array(some_part)  #
    pg = np.array(goal_part)
    
    psT = TetrisPart(ps)
    pgT = TetrisPart(pg)
    
    ps_h = psT.get_height()
    ps_w = psT.get_width()
    #get rows and cols from some_part
        
    pg_h = pgT.get_height()
    pg_w = pgT.get_width()
    #get rows and cols from goal_part
        
    #for each col of each row in goal_part
    for i in range(pg_h-ps_h+1):
        for j in range(pg_w-ps_w+1):
        #if the first index of some part matches a index of goal part  
            if ps[0][0] == pg[i][j]:
                #numpy function of extracting a matrix from a large matrix.
                def submatrix ( matrix, startRow, startCol, size1, size2):
                    return pg[startRow:startRow+size1,startCol:startCol+size2]
                    #form matrix for comparison 
                pm = submatrix (pg, i, j, ps_h,ps_w)
                #
                ps_nonzero_index = np.nonzero(ps)
                #
                ps_nonzero=ps[ps_nonzero_index]
                pm_nonzero=pm[ps_nonzero_index]
                #comparing if the selected matrix from goal part is equal to some part.
                if np.array_equal(ps_nonzero,pm_nonzero):
                    return True# return true if appears
    return False
예제 #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

        #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)
예제 #16
0
    def actions(self, state):
        """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()'.
                
        """

        # Declare results array to store legal actions.
        actionsToTake = []

        # Continue if there is a state.
        if state is not None:

            # Store separate parts of state in hold_state_parts array by
            # looping through state.
            hold_state_parts = []
            for part in state:
                hold_state_parts.append(part)
                actionsToTake.append((part, None, 0))

            # Store all combinations of both parts (all actions).
            permutations_hold = itertools.permutations(hold_state_parts, 2)

            # Loop through all combinations, find offset and store each part with offset
            # range in actionsToTake array.
            for part in permutations_hold:
                range_of_offset = offset_range(part[0], part[1])
                range_offset = list(
                    range(range_of_offset[0], range_of_offset[1]))

                for offset_number in range_offset:
                    make_object_part = TetrisPart(part[0],
                                                  part_under=part[1],
                                                  offset=offset_number)
                    part_object = make_object_part.get_frozen()

                    # Check if part exists in final goal part with consideration of all rotations.
                    if cost_rotated_subpart(part_object, self.goal) != np.inf:
                        actionsToTake.append((part[0], part[1], offset_number))

        # Return results array.
        return actionsToTake
예제 #17
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
예제 #18
0
    def actions(self, state):
        """
        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.
        """

        # Declare results array to store legal drop actions.
        actionsToTake = []

        # Continue if there is a state.
        if state != None:

            # Store separate parts of state in hold_state_parts array by
            # looping through state.
            hold_state_parts = []
            for i in state:
                hold_state_parts.append(i)

            # Store all combinations of both parts (all actions).
            permutations_hold = itertools.permutations(
                hold_state_parts, 2)  # Permutations of state parts

            # Loop through all combinations, find offset and store each part with offset
            # range in actionsToTake array.
            for part in permutations_hold:
                range_of_offset = offset_range(part[0],
                                               part[1])  # Get offset range
                range_offset = list(
                    range(range_of_offset[0], range_of_offset[1]))
                for offset_number in range_offset:
                    make_object_part = TetrisPart(part[0],
                                                  part_under=part[1],
                                                  offset=offset_number)
                    part_object = make_object_part.get_frozen()

                    # Perform search tree pruning by checking if current part appears in final
                    # goal part by calling appear_as_subpart function.
                    if appear_as_subpart(part_object, self.finalGoal):
                        actionsToTake.append((part[0], part[1], offset_number))

        # Return resulting array
        return actionsToTake
예제 #19
0
def cost_rotated_subpart(some_part, goal_part):
    '''    
    Determine whether the part 'some_part' appears in another part 'goal_part'
    as a rotated subpart. If yes, return the number of 'rotate90' needed, if 
    no return 'np.inf'
    
    The definition of appearance is the same as in the function 
    'appear_as_subpart'.
                   
    @param
        some_part: a tuple representation of a tetris part
        goal_part: a tuple representation of another tetris part
    
    @return
        the number of rotation needed to see 'some_part' appear in 'goal_part'
        np.inf  if no rotated version of 'some_part' appear in 'goal_part'
    
    '''
    '''
    compare subpart to goal_part
    do you need to rotate?
    no? -> sub_part == goal part
    rotate_counter=np.inf
    yes-> rotate-> (assignment_one) -> assignment_one.rotate90()
    rotate_counter=rotate_counter+1
    loop until sub_part == goal_part OR rotate_counter == 4 (360deg)
    '''
#    raise NotImplementedError
    rotate_counter = 0
    
    while rotate_counter < 4:
        ps = np.array(some_part)  #
        pg = np.array(goal_part)
    
        psT = TetrisPart(ps)
        pgT = TetrisPart(pg)
        
        if appear_as_subpart(ps,pg) == False:
            psT.rotate90()
            rotate_counter += 1
        #do rotation
        #return rotate_counter
    
    # if counter exits loop, there is no match; set value to infinity and exit
    rotate_counter=np.inf
    return rotate_counter
예제 #20
0
    def actions(self, state):
        """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()'.
                
        """
        actionList = []
        partList = list(state)
        goals = np.array(self.goal)

        possibleCombinations = it.permutations(
            partList, 2)  #Get all possible combinations
        for combination in possibleCombinations:
            start, end = offset_range(combination[0],
                                      combination[1])  #Get all possible offset
            for offset in range(start, end):
                resultPiece = TetrisPart(combination[0], combination[1],
                                         offset)
                for goal in goals:  #Loop through each goal piece
                    cost = cost_rotated_subpart(
                        resultPiece.get_frozen(), goal
                    )  #Check if the cost of rotations of any goal for the piece is not np.inf
                    if (cost != np.inf):
                        actionList.append(
                            (combination[0], combination[1], offset)
                        )  #Add part above, part below and offset to action list

        for part in partList:  #Loop through each part
            for goal in goals:  #Loop through each goal piece
                numberOfRotations = cost_rotated_subpart(part, goal)
                if (
                        numberOfRotations != np.inf
                ):  #Check if the piece needs to be rotated to be part of a goal piece
                    actionList.append(
                        ("rotate", part)
                    )  #add rotation action for the part to the action list

        return actionList
예제 #21
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))
예제 #22
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
예제 #23
0
    def actions(self, state):
        """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()'.
                
        """

        #raise NotImplementedError

        part_list = list(state)

        filtered_actions = []

        for pa_index in range(len(part_list)):
            filtered_actions.append((part_list[pa_index], None, None))
            for pu_index in range(len(part_list)):
                if pa_index != pu_index:
                    start, end = offset_range(part_list[pa_index],
                                              part_list[pu_index])
                    for offset in range(start, end):
                        new_part = TetrisPart(part_list[pa_index],
                                              part_list[pu_index], offset)
                        if new_part.offset != None:
                            if appear_as_subpart(new_part.get_frozen(),
                                                 self.goal[0]):
                                filtered_actions.append(
                                    (part_list[pa_index], part_list[pu_index],
                                     offset))

        return filtered_actions
예제 #24
0
def cost_rotated_subpart(some_part, goal_part):
    '''    
    Determine whether the part 'some_part' appears in another part 'goal_part'
    as a rotated subpart. If yes, return the number of 'rotate90' needed, if 
    no return 'np.inf'
    
    The definition of appearance is the same as in the function 
    'appear_as_subpart'.
                   
    @param
        some_part: a tuple representation of a tetris part
        goal_part: a tuple representation of another tetris part
    
    @return
        the number of rotation needed to see 'some_part' appear in 'goal_part'
        np.inf  if no rotated version of 'some_part' appear in 'goal_part'
    
    '''
    piece = TetrisPart(some_part)
    for rotation in range(0, 4):
        if (appear_as_subpart(piece.get_frozen(), goal_part)):
            return rotation  # return the first number of rotation needed to appear in a goal part
        piece.rotate90()
    return np.inf  # return np.inf if part can't be found in a goal piece
예제 #25
0
def test3():

    initial_state = load_state('workbenches/wb_09_i.txt')
    c = initial_state[0]
    print(initial_state)
    print(c)
    d = TetrisPart(c)
    d.rotate90()
    print(d.get_frozen())
    display_state((d.get_frozen(), c))
예제 #26
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
예제 #27
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
예제 #28
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)
예제 #29
0
    def actions(self, state):
        """
        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.
        """

        valid_moves = [
            (a, b, c) for a, b in itertools.permutations(state, 2)
            for c in range((offset_range(a, b)[0]), (offset_range(a, b)[1]))
            if c is not None and appear_as_subpart(
                TetrisPart(part_under=b, part_above=a, offset=c).get_frozen(),
                self.goal[0])
        ]
        return valid_moves
예제 #30
0
def cost_rotated_subpart(some_part, goal_part):
    '''    
    Determine whether the part 'some_part' appears in another part 'goal_part'
    as a rotated subpart. If yes, return the number of 'rotate90' needed, if 
    no return 'np.inf'
    
    The definition of appearance is the same as in the function 
    'appear_as_subpart'.
                   
    @param
        some_part: a tuple representation of a tetris part
        goal_part: a tuple representation of another tetris part
    
    @return
        the number of rotation needed to see 'some_part' appear in 'goal_part'
        np.inf  if no rotated version of 'some_part' appear in 'goal_part'
    
    '''
    # Create a TetrisPart to rotate some_part
    some_part_tetris = TetrisPart(some_part)
    # Check if the array has just a single element.
    if np.array(some_part).size == 1:
        # Check if the element is in goal.
        if some_part[0] in goal_part:
            return 0
        else:
            return np.inf
    # Check the four possible rotations
    possible_rotations = 4
    for rot in range(0, possible_rotations):
        if rot == 0:
            some_part_tetris.get_frozen()
            if appear_as_subpart(some_part_tetris.frozen, goal_part):
                return rot
        else:
            some_part_tetris.rotate90()
            some_part_tetris.get_frozen()
            if appear_as_subpart(some_part_tetris.frozen, goal_part):
                return rot
    return np.inf