def __search(self, notes: List[str], cube: Cube, depth: int, estimate: int) -> Tuple[int, str]: """A function to actually perform the search to the current search depth by using recursion. Also contains the pruning if the minimum distance increases""" if self.__checked % 10000 == 0: print(f"Depth: {depth:2d}, checked: {self.__checked:,}+, " + f"(pruned: {self.__skipped:,}+)", end="\r") if len(notes) >= depth or estimate <= 0: if cube.is_solved: return (len(notes), " ".join(notes)) return (-1, "") for move in cube.moves: if Cube.skip_move(notes, move): self.__skipped += 1 continue new_cube = copy.deepcopy(cube) new_cube.twist_by_notation(move) new_estimate = self.__tables.get_distance(self.coordinate(cube)) if new_estimate != -1: if estimate < new_estimate: self.__skipped += 1 continue estimate = new_estimate + 1 self.__checked += 1 result = self.__search(notes + [move], new_cube, depth, estimate - 1) if result[0] > 0: return result return (-1, "")
def __search(self, phase, notes: List[str], cube: Cube, depth: int) -> Tuple[int, str]: """A function to actually perform the search to the current search depth by using recursion. TODO: Also contains the pruning if the minimum distance increases. Return a tuple with the amount of moves as the first item and the solution as a notation str as the second item. In case a valid solution was not found the amount of moves is negative. (currently always -1)""" if self.__checked % 10000 == 0: print(f"Depth: {depth:2d}, checked: {self.__checked:,}+ " + f"(pruned: {self.__skipped:,}+)", end="\r") if depth <= len(notes): if phase == 1 and cube.is_domino or cube.is_solved: return (len(notes), " ".join(notes)) return (-1, "") for move in Cube.moves if phase == 1 else self.phase2_moves: if Cube.skip_move(notes, move): self.__skipped += 1 continue new_cube = copy.deepcopy(cube) new_cube.twist_by_notation(move) self.__checked += 1 result = self.__search(phase, notes + [move], new_cube, depth) if result[0] > 0: return result return (-1, "")
def generation_search(self, notes: List[str], cube: Cube, depth: int, distance: int) -> None: """A function to search all of the patterns indexes to generate the pruning tables required by the Korf's algorithm to solve any cube in less than about 10^12 years. Unfortunately this function currently takes about 10^13 years with depth 20 to finish on a modern desktop computer.""" # FIXME: Optimize to run in less than a week. # FIXME: Pruning while generating doesn't seem to work correctly. if distance >= depth: self.__tables.set_distance(self.coordinate(cube), distance) return for move in cube.moves: if Cube.skip_move(notes, move): continue new_cube = copy.deepcopy(cube) new_cube.twist_by_notation(move) estimate = self.__tables.get_distance(self.coordinate(new_cube)) if estimate != -1 and estimate - depth < distance: # print(f"Depth: {depth}, distance: {distance}, move: {move}") continue self.generation_search(notes + [move], new_cube, depth, distance + 1)