def _select_starting_pieces_from_clusters(self): """ From the segment clusters, this function builds the starting pieces for each of the output puzzles. """ piece_to_cluster_map = {} cluster_has_seed = {} for cluster in self._segment_clusters: # Used to determine if each cluster has a starting piece cluster_has_seed[MultiPuzzleSolver.create_cluster_key(cluster.id_number)] = False # Build a map from piece ID number to cluster for piece_id in cluster.get_pieces(): key = PuzzlePiece.create_key(piece_id) # Verify no duplicates if config.PERFORM_ASSERT_CHECKS: assert key not in piece_to_cluster_map piece_to_cluster_map[key] = cluster.id_number # Get the starting piece ordering starting_piece_ordering = self._paikin_tal_solver.get_initial_starting_piece_ordering() # Find the start pieces. self._final_starting_pieces = [] starting_piece_cnt = 0 while len(self._final_starting_pieces) != len(self._segment_clusters): # Get the cluster number (if any) for the starting piece candidate starting_piece_candidate = starting_piece_ordering[starting_piece_cnt] piece_key = PuzzlePiece.create_key(starting_piece_candidate) try: cluster_number = piece_to_cluster_map[piece_key] cluster_key = MultiPuzzleSolver.create_cluster_key(cluster_number) # If the cluster has no seed, use this seed piece if not cluster_has_seed[cluster_key]: self._final_starting_pieces.append(starting_piece_candidate) cluster_has_seed[cluster_key] = True # Log the clustering information piece_initial_puzzle = self._paikin_tal_solver.get_piece_original_puzzle_id(starting_piece_candidate) logging.info("Seed piece for cluster %d is piece id %d from initial puzzle %d" % (cluster_number, starting_piece_candidate, piece_initial_puzzle)) except KeyError: pass starting_piece_cnt += 1 if MultiPuzzleSolver._ALLOW_POST_SELECT_STARTING_PIECES_PICKLE_EXPORT: self._pickle_export_after_select_starting_pieces()
def _get_stitching_pieces(self): """ Iterates through all of the segments found by the initial solver, and builds a list of the piece identification numbers for all of the stitching pieces. Returns (List[List[StitchingPieceSegment]]): List of stitching pieces for each segment. """ all_stitching_pieces = [] existing_piece_ids = {} for segment_id_numb in xrange(0, len(self._segments)): # Verify the identification number matches what is stored in the array if config.PERFORM_ASSERT_CHECKS: assert segment_id_numb == self._segments[segment_id_numb].id_number # Separate the stitching pieces by segments all_stitching_pieces.append([]) segment_stitching_pieces = self._segments[segment_id_numb].select_pieces_for_segment_stitching() for segmentation_piece_id in segment_stitching_pieces: all_stitching_pieces[segment_id_numb].append(StitchingPieceInfo(segmentation_piece_id, segment_id_numb)) # Verify no duplicate stitching pieces if config.PERFORM_ASSERT_CHECKS: key = PuzzlePiece.create_key(segmentation_piece_id) assert key not in existing_piece_ids existing_piece_ids[key] = segmentation_piece_id return all_stitching_pieces
def add_solver_piece(self, solved_piece_id, piece_segment_id): """ After the solver is run using the stitching piece as the seed, pieces from the solved puzzle are added to the stitching piece information object. Args: solved_piece_id (int): Identification number of piece in stitching piece solver piece_segment_id (int): Identification number of the segment where the piece with identification number of "solved_piece_id" was assigned in initial segmentation. This value is "None" if the piece has no associated segment. """ self._total_numb_solved_pieces += 1 # Ensure no duplicate pieces. if config.PERFORM_ASSERT_CHECKS: key = PuzzlePiece.create_key(solved_piece_id) assert key not in self._all_solver_pieces self._all_solver_pieces[key] = solved_piece_id # Handle the case where the piece was not assigned to any segment initially if piece_segment_id is None: self._solver_piece_without_segment.append(solved_piece_id) return while len(self._solver_piece_segments) < piece_segment_id + 1: self._solver_piece_segments.append([]) self._solver_piece_segments[piece_segment_id].append(solved_piece_id)
def _select_segment_for_solver(self, selected_segment): """ Segment is selected for use by the solver. Args: selected_segment (PuzzleSegment): Segment selected to be used by the solver """ initial_segment_id = selected_segment.id_number # Add the segment to the list selected_segment.update_segment_for_multipuzzle_solver(len(self._segments)) self._segments.append(selected_segment) # Store the segment for piece_id in selected_segment.get_piece_ids(): self._paikin_tal_solver.disallow_piece_placement(piece_id) # Store the mapping of piece to segment. key = PuzzlePiece.create_key(piece_id) self._piece_id_to_segment_map[key] = selected_segment.id_number logging.info("Saved segment #%d has %d pieces." % (selected_segment.id_number, selected_segment.numb_pieces)) # Optionally output the segment image to a file. if MultiPuzzleSolver._SAVE_SELECTED_SEGMENTS_TO_AN_IMAGE_FILE: zfill_width = 4 filename_descriptor = "segment_number_" + str(selected_segment.id_number).zfill(zfill_width) filename_descriptor += "_puzzle_round_" + str(self._numb_segmentation_rounds).zfill(zfill_width) single_puzzle_id = 0 self._paikin_tal_solver.save_segment_to_image_file(PuzzleSolver.MultiPuzzle, single_puzzle_id, initial_segment_id, filename_descriptor, self._image_filenames, self._start_timestamp)
def _process_stitching_piece_solver_result(self, segment_numb, stitching_piece_numb): """ After the solver is run for a stitching piece, this function process those results including adding the pieces in the solved result to the StitchingPieceInfo object. This includes tracking the segment to which each piece in the solved output belows (if any). Args: segment_numb (int): Identification number of the segment whose stitching piece is being processed stitching_piece_numb (int): Index of the stitching piece in the associated segment list """ solved_puzzle, _ = self._paikin_tal_solver.get_solved_puzzles() single_puzzle_id_number = 0 for piece in solved_puzzle[single_puzzle_id_number]: piece_id = piece.id_number # Get segment associated with the piece if any try: piece_segment_numb = self._piece_id_to_segment_map[PuzzlePiece.create_key(piece_id)] except KeyError: piece_segment_numb = None # Add the piece to the stitching piece information self._stitching_pieces[segment_numb][stitching_piece_numb].add_solver_piece(piece_id, piece_segment_numb) self._stitching_pieces[segment_numb][stitching_piece_numb].log_piece_to_segment_mapping(len(self._segments))