def exporter(obj, filename): """Generic Pickling Exporter Method Helper method used to export any object to a Pickle file. ::Note::: This function does not support objects of type "Puzzle." They should use the class' specialized Pickling functions. Args: obj: Object to be exported to a specified Pickle file. filename (str): Name of the Pickle file. """ start_time = time.time() # If the file directory does not exist create it. file_directory = os.path.dirname(os.path.abspath(filename)) if not os.path.isdir(file_directory): logging.debug("Creating pickle export directory \"%s\"." % file_directory) os.makedirs(file_directory) logging.info("Beginning pickle EXPORT of file: \"" + filename + "\"") # Dump pickle to the file. f = open(filename, 'w') pickle.dump(obj, f) f.close() logging.info("Completed pickle EXPORT to file: \"" + filename + "\"") print_elapsed_time(start_time, "pickle EXPORT of file: \"" + filename + "\"")
def run(self): """ Executes all steps involved in the multipuzzle solver. Returns (List[Puzzle]): Puzzle solutions from the solver. """ logging.info("Multipuzzle Solver Started") self._find_initial_segments() self._perform_stitching_piece_solving() self._build_similarity_matrix() self._perform_hierarchical_clustering() self._select_starting_pieces_from_clusters() self._perform_placement_with_final_seed_pieces() self._final_puzzles = self._build_output_puzzles() logging.info("Multipuzzle Solver Complete") print_elapsed_time(self._start_timestamp, "entire multipuzzle solver.") return self._final_puzzles
def importer(filename): """ Generic Pickling Importer Method Helper method used to import any object from a Pickle file. ::Note::: This function does not support objects of type "Puzzle." They should use the class' specialized Pickling functions. Args: filename (str): Pickle Filename Returns: The object serialized in the specified filename. """ start_time = time.time() # Check the file directory exists file_directory = os.path.dirname(os.path.abspath(filename)) if not os.path.isdir(file_directory): raise ValueError("The file directory: \"" + file_directory + "\" does not appear to exist.") logging.info("Beginning pickle IMPORT of file: \"" + filename + "\"") # import from the pickle file. f = open(filename, 'r') obj = pickle.load(f) f.close() logging.info("Completed pickle IMPORT of file: \"" + filename + "\"") print_elapsed_time(start_time, "pickle IMPORT of file: \"" + filename + "\"") return obj
def run_paikin_tal_solver(image_filenames, puzzle_type, piece_width): """ Paikin & Tal Solver This function takes a set of inputs and runs the Paikin and Tal solver. It can be sped-up by importing the calculations of distances from existing Pickle files. Args: image_filenames (List[String]): Path to the image files used to create the puzzles puzzle_type (PuzzleType): Type of the puzzle to be solved piece_width (int): Width/length of all puzzle pieces Returns (PaikinTalSolver): Solved Paikin & Tal result. """ pickle_filename = PickleHelper.build_filename( PaikinTalSolver.POST_INITIAL_CONSTRUCTOR_PICKLE_FILE_DESCRIPTOR, image_filenames, puzzle_type ) # Optionally import the images from disk if FORCE_RECALCULATE_DISTANCES or not os.path.exists(pickle_filename): combined_pieces, puzzles = Puzzle.get_combined_pieces_multiple_images(image_filenames, piece_width) # Select whether or not to use fixed puzzle dimensions puzzle_dimensions = puzzles[0].grid_size if USE_KNOWN_PUZZLE_DIMENSIONS and len(images) == 1 else None # Create the Paikin Tal Solver logging.info("Beginning calculating of Paikin & Tal inter-piece distance information") start_time = time.time() paikin_tal_solver = PaikinTalSolver( combined_pieces, top_level_calculate_asymmetric_distance, len(image_filenames), puzzle_type, fixed_puzzle_dimensions=puzzle_dimensions, image_filenames=image_filenames, ) print_elapsed_time(start_time, "Paikin & Tal inter-piece distance calculations") else: paikin_tal_solver = PaikinTalSolver.pickle_import_after_initial_construction(image_filenames, puzzle_type) if config.IS_SOLVER_COMPARISON_RUNNING: paikin_tal_solver.reset_actual_puzzle_count() # Run the Solver paikin_tal_solver.run_standard() # Export the solved results return paikin_tal_solver
def _find_initial_segments(self, skip_initialization=False, go_directly_to_segmentation=False): """ Through iterative single puzzle placing, this function finds a set of segments. Args: skip_initialization (bool): Skip the initial segments setup. go_directly_to_segmentation (bool): Skips right to segmentation. This feature is largely for debug of segmentation via pickle. """ if not skip_initialization and not go_directly_to_segmentation: self._paikin_tal_solver.allow_placement_of_all_pieces() self._numb_segmentation_rounds = 0 # Essentially a Do-While loop while True: time_segmentation_round_began = time.time() if not go_directly_to_segmentation: self._numb_segmentation_rounds += 1 logging.info("Beginning segmentation round #%d" % self._numb_segmentation_rounds) # In first iteration, the solver settings are still default. if self._numb_segmentation_rounds > 1: self._paikin_tal_solver.restore_initial_placer_settings_and_distances() # Perform placement as if there is only a single puzzle self._paikin_tal_solver.run_single_puzzle_solver() if MultiPuzzleSolver._ALLOW_POST_SEGMENTATION_PLACEMENT_PICKLE_EXPORT: self._pickle_export_after_segmentation_puzzle_placement() # Proceed with placement as normal. go_directly_to_segmentation = False # Get the segments from this iteration of the loop solved_segments = self._paikin_tal_solver.segment(perform_segment_cleaning=True) max_segment_size = self._process_solved_segments(solved_segments[0]) if MultiPuzzleSolver._SAVE_EACH_SINGLE_PUZZLE_RESULT_TO_AN_IMAGE_FILE: self._save_single_solved_puzzle_to_file(self._numb_segmentation_rounds) solver_helper.print_elapsed_time(time_segmentation_round_began, "segmentation round #%d" % self._numb_segmentation_rounds) if MultiPuzzleSolver._ALLOW_POST_SEGMENTATION_ROUND_PICKLE_EXPORT: self._pickle_export_after_segmentation_round() # Stop segmenting if no pieces left or maximum segment size is less than the minimum if max_segment_size < MultiPuzzleSolver._MINIMUM_SEGMENT_SIZE \ or self._numb_pieces - len(self._piece_id_to_segment_map) < MultiPuzzleSolver._MINIMUM_SEGMENT_SIZE: break # Re-allow all pieces to be placed. self._paikin_tal_solver.allow_placement_of_all_pieces() self._paikin_tal_solver.reset_all_pieces_placement() self._log_segmentation_results() if MultiPuzzleSolver._ALLOW_POST_SEGMENTATION_COMPLETED_PICKLE_EXPORT: self._pickle_export_after_all_segmentation_completed()