def get_successors(self, tower_state: Tower_State): print("Building succesors for state of height:{}".format(tower_state._max_level)) pp(tower_state) all_possible_son_desc = [] for father_block in tower_state.gen_blocks(no_floor=False, filter_saturated_block=False): if father_block.is_saturated(tower_state): self._num_of_blocks_saturated += 1 continue all_possible_son_desc.extend(filter( lambda desc: not tower_state.is_bad_block(Block.gen_str(desc)), father_block.gen_possible_block_descriptors( limit_orientation=lambda o: father_block.is_perpendicular(o), limit_len=self._limit_sons, random_order=self._gen_randomly ) ) ) if self._gen_randomly: shuffle(all_possible_son_desc) else: all_possible_son_desc.sort(key=lambda desc: desc[1][Z], reverse=True) for _ in range(self._limit_branching): new_tower = copy(tower_state) actions = [] while len(actions) < self._num_of_blocks_in_action: if all_possible_son_desc: desc = all_possible_son_desc.pop() else: break if tower_state.is_bad_block(Block.gen_str(desc)): self._num_of_descriptors_disqualified += 1 continue son_block = Block(BLOCK_MESH, *desc) if new_tower.can_add(son_block): new_tower.add(son_block) actions.append(son_block) else: self._num_of_blocks_disqualified += 1 if actions: yield (new_tower, actions, len(actions)) else: print( "\tNum bad from hash:\t{}\n\tNum of blocks disqualified:\t{}\n\tNum of blocks saturated:\t{}".format( tower_state._bad_block_calls, self._num_of_blocks_disqualified, self._num_of_blocks_saturated )) return #successors.append((new_tower, actions, len(actions))) print("\tNum of desc disqualified:\t{}\n\tNum of blocks disqualified:\t{}\n\tNum of blocks saturated:\t{}".format( self._num_of_descriptors_disqualified, self._num_of_blocks_disqualified, self._num_of_blocks_saturated ))
def get_successors(self, state: Tower_State): new_states = [copy(state) for _ in range(self._limit_branching)] successors = [] pp(state) for new_state in new_states: num_of_blocks_added = 0 actions = [] for father_block in state.gen_blocks(no_floor=False): if father_block.is_saturated(new_state): self._num_of_blocks_saturated += 1 continue if len(actions) > self._num_of_blocks_in_action: break son_descriptors = list(father_block.gen_possible_block_descriptors( limit_len=self._limit_sons, limit_orientation=self._son_orientation_filter, random_order=self._gen_randomly )) if self._gen_randomly: shuffle(son_descriptors) for desc in son_descriptors: if len(actions) > self._num_of_blocks_in_action: break if state.is_bad_block(Block.gen_str(desc)): self._num_of_descriptors_disqualified += 1 else: # good block description, lets try it out blocks = [Block(BLOCK_MESH, *desc)] if self._use_symmetry: sub_descriptors = Block_Search.propagate(*desc, dist=self._symmetrical_base_distance) # qualified_symmetrical_brothers = len(sub_descriptors) for sym_desc in sub_descriptors: if state.is_bad_block(Block.gen_str(desc)): self._num_of_descriptors_disqualified += 1 # qualified_symmetrical_brothers -= 1 else: blocks.append(Block(BLOCK_MESH, *sym_desc)) to_add = [] for candidate_block in blocks: if new_state.can_add(candidate_block): to_add.append(candidate_block) else: self._num_of_blocks_disqualified += 1 # else: # if self._use_symmetry: # qualified_symmetrical_brothers -= 1 if self._use_symmetry: if len(to_add) >= self._sym_son_threshold: for good_block in to_add: new_state.add(good_block) actions.append(good_block) num_of_blocks_added += 1 else: for good_block in to_add: self._num_of_blocks_disqualified += 1 new_state.disconnect_block_from_neighbors(good_block) else: for good_block in to_add: new_state.add(good_block) actions.append(good_block) num_of_blocks_added += 1 successors.append((new_state, actions, len(actions))) # if DISPLAY: # display_colored([b.render() for b in state.gen_blocks()]) # return True # print("\tNum of desc disqualified:{}\tNum of blocks disqualified:{}\tNum of staturated:{}".format( # self._num_of_descriptors_disqualified, # self._num_of_blocks_disqualified, # self._num_of_blocks_saturated # )) return successors
def is_goal_state(self, state: Tower_State): if state._max_level >= self._height_goal: if DISPLAY: display([b.render() for b in state.gen_blocks()], scale=self._height_goal * 0.7) return True return False