def solve(cls, start, computation_progress=None, analysis_graph=None, heuristic=None, distance=lambda state1, state2: 1): if not start.is_solvable(): return None open_set = PriorityQueue() open_set.add_task(start, priority=heuristic(start)) closed_set = set() came_from = {} g_score = defaultdict(lambda: float('inf')) g_score[start] = 0 f_score = defaultdict(lambda: float('inf')) f_score[start] = heuristic(start) current = open_set.pop_task() while current: closed_set.add(current) if len(closed_set) % 1000 == 0: start.update_computation_progress(computation_progress, len(closed_set)) if current.is_goal(): result = cls.reconstract_path(came_from, current) if analysis_graph: analysis_graph.update(len(result), len(closed_set)) return result for neighbor in current.next_states(): #if neighbor in closed_set: # continue tentative_g_score = g_score[current] + distance( current, neighbor) if tentative_g_score < g_score[neighbor]: came_from[neighbor] = current g_score[neighbor] = tentative_g_score f_score[neighbor] = g_score[neighbor] + heuristic(neighbor) open_set.add_task(neighbor, priority=f_score[neighbor]) current = open_set.pop_task() return None
def solve(cls, start, computation_progress=None, distance=lambda state1, state2: 1): distances = defaultdict(lambda: float('inf')) distances[start] = 0 open_set = PriorityQueue() open_set.add_task(start, priority=distances[start]) closed_set = set() came_from = {} current = open_set.pop_task() while current: closed_set.add(current) print(len(closed_set)) if len(closed_set) % 1000 == 0: start.update_computation_progress(computation_progress, len(closed_set)) if current.is_goal(): return cls.reconstract_path(came_from, current) for neighbor in current.next_states(): if neighbor in closed_set: continue new_distance = distances[current] + distance(current, neighbor) if new_distance < distances[neighbor]: came_from[neighbor] = current distances[neighbor] = new_distance open_set.add_task(neighbor, priority=new_distance) current = open_set.pop_task() return None
class Puzzle: def __init__(self, size): """ Initialize the puzzle size by the specified size,open and closed lists to empty """ self.n = size self.open = [] self.closed = [] def accept(self): """ Accepts the puzzle from the user """ puz = [] for i in range(0, self.n): temp = input().split(" ") puz.append(temp) return puz def reconstract_path(self, came_from, current): total_path = [current] while current in came_from.keys(): current = came_from[current] total_path.append(current) total_path.reverse() return total_path def f(self, start, goal, heuristic): """ Heuristic Function to calculate hueristic value f(x) = h(x) + g(x) """ return heuristic(start.data, goal) + start.level #Misplaced tiles heuristic function def h1(self, start, goal): """ Calculates the different between the given puzzles """ temp = 0 for i in range(0, self.n): for j in range(0, self.n): if start[i][j] != goal[i][j] and start[i][j] != '_': temp += 1 return temp #Manhattan distance heuristic function def h2(self, start, goal): temp = 0 for i in range(0, self.n): for j in range(0, self.n): val = start[i][j] correct_position = [(index, row.index(start[i][j])) for index, row in enumerate(goal) if start[i][j] in row] temp += abs(i - correct_position[0][0]) + \ abs(j - correct_position[0][1]) return temp def identical(self, start, goal): temp = 0 for i in range(0, self.n): for j in range(0, self.n): if start[i][j] != goal[i][j] and start[i][j] != '_': return False return True #CLI process def process(self): """ Accept Start and Goal Puzzle state""" print("Entrer la matrice initiale du jeu de taquin \n") start = self.accept() print("Entrer la matrice finale à atteindre \n") goal = self.accept() print("Choisir votre fonction heuristique: \n") choice = None while choice != '1' and choice != '2': if (choice): print('Veuillez choisir un choix valable!\n\n') print("1* Nombres de pieces mal placées") print("2* Somme de la distance Manhattan") choice = input() if (choice == '1'): heuristic = self.h1 else: heuristic = self.h2 print(type(start)) print(start) print(goal) start = Node(start, 0, 0) start.fval = self.f(start, goal, heuristic) """ Put the start node in the open list""" self.open.append(start) self.open_set = PriorityQueue() self.closed_set = set() self.open_set.add_task(start, priority=start.fval) print("\n\n") came_from = {} cur = self.open_set.pop_task() while True: try: data = [''.join(idx for idx in sub) for sub in cur.data] data = ''.join(map(str, data)) self.closed_set.add(data) """ If the difference between current and goal node is 0 we have reached the goal node""" if (self.identical(cur.data, goal)): total_path = self.reconstract_path(came_from, cur) #Print out the results for i in total_path: print("") print(" | ") print(" | ") print(" \\\'/ \n") for k in i.data: for j in k: print(j, end=" ") print("") print('Résolue apres ' + str(len(total_path) - 1) + ' etats \n') print("") print("Cet algorithme a parcouru " + str(len(self.closed_set)) + " etats \n") return total_path for i in cur.generate_child(): data = [''.join(idx for idx in sub) for sub in i.data] data = ''.join(map(str, data)) if data in self.closed_set: continue i.fval = self.f(i, goal, heuristic) # for node in self.open: # if node.data == i.data: # self.open.remove(node) self.open_set.add_task(i, priority=i.fval) came_from[i] = cur # self.open.append(i) self.closed.append(cur) #del self.open[0] cur = self.open_set.pop_task() except: print('This puzzle is not solvable!') break #GUI process def process_game(self, start, goal, analysis_graph=None): print("Choisir votre fonction heuristique: \n") choice = None while choice != '1' and choice != '2': if (choice): print('Veuillez choisir un choix valable!\n\n') print("1* Nombres de pieces mal placées") print("2* Somme de la distance Manhattan") choice = input() if (choice == '1'): heuristic = self.h1 else: heuristic = self.h2 print(type(start)) print(start) print(goal) start = Node(start, 0, 0) start.fval = self.f(start, goal, heuristic) """ Put the start node in the open list""" self.open.append(start) self.open_set = PriorityQueue() self.closed_set = set() self.open_set.add_task(start, priority=start.fval) print("\n\n") came_from = {} cur = self.open_set.pop_task() while True: data = [''.join(idx for idx in sub) for sub in cur.data] data = ''.join(map(str, data)) self.closed_set.add(data) """ If the difference between current and goal node is 0 we have reached the goal node""" if (self.identical(cur.data, goal)): total_path = self.reconstract_path(came_from, cur) if analysis_graph: if heuristic == self.h2: analysis_graph.name = "h2" analysis_graph.update_graph(len(total_path), len(self.closed_set)) print('Résolue apres ' + str(len(total_path) - 1) + ' etats \n') print("") print("Cet algorithme a parcouru " + str(len(self.closed_set)) + " etats \n") return total_path for i in cur.generate_child(): data = [''.join(idx for idx in sub) for sub in i.data] data = ''.join(map(str, data)) if data in self.closed_set: continue i.fval = self.f(i, goal, heuristic) # for node in self.open: # if node.data == i.data: # self.open.remove(node) self.open_set.add_task(i, priority=i.fval) came_from[i] = cur # self.open.append(i) self.closed.append(cur) #del self.open[0] cur = self.open_set.pop_task()