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)
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
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
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))
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
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
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)
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)
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
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
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
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
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
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
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)
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
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
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
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
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
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))
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
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
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