Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
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()