Esempio n. 1
0
    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 + "\"")
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
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
Esempio n. 5
0
    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()