Почему мое решение не может решить задачу 8puzzle для досок, требующих более 1 хода?

Я пытаюсь решить 8 задач на Python, приведенных здесь в этом задании -https://www.cs.princeton.edu/courses/archive/fall12/cos226/assignments/8puzzle.html

Мое целевое состояние немного отличается от того, что указано в задании -

#GOAL STATE
goal_state =  [[0,1,2],[3,4,5],[6,7,8]]

Глючная часть, похоже, связана с функцией isSolvable. Он реализован корректно, но при тестировании доски считает целевым состоянием состояние, в котором сохраняется относительный порядок, а пустое место может быть где угодно. Таким образом, может случиться так, что доска разрешима, но она может не привести к текущему определенному целевому состоянию. Поэтому я не могу придумать метод, с помощью которого я мог бы проверить все возможные целевые состояния во время выполнения решающей функции *

Кроме того, моя функция решения была неправильно реализована. Я рассматривал только того соседа, у которого было минимальное манхэттенское значение, и когда я зашел в тупик, я не рассматривал другие штаты. Это можно сделать с помощью приоритетной очереди. Я не совсем уверен, как приступить к его реализации. Я написал его часть (см. ниже), что также неправильно, поскольку я не помещал родителя в кучу. Пожалуйста, дайте мне руководство для этого.

Вот мой полный код: https://pastebin.com/q7sAKS6a

Обновленный код с неполной функцией решения - https://pastebin.com/n4CcQaks

Я использовал манхэттенские значения для расчета эвристических значений и значение Хэмминга для устранения ничьей.

моя функция isSolvable, функция Манхэттена и функция решателя:

Разрешимая функция -

#Conditions for unsolvability -->
#https://www.geeksforgeeks.org/check-instance-8-puzzle-solvable/
    def isSolvable(self):
        self.one_d_array = []

        for i in range(0,len(self.board)):
            for j in range(0,len(self.board)):
                self.one_d_array.append(self.board[i][j])

        inv_count = 0
        for i in range(0,len(self.one_d_array)-1):
            for j in range(i+1, len(self.one_d_array)):
                if (self.one_d_array[i] != 0 and self.one_d_array[j] != 0 and self.one_d_array[i] > self.one_d_array[j]):
                    inv_count = inv_count + 1

        if(inv_count % 2 == 0):
            print("board is solvable")
            return True
        else:
            print("board is not solvable")
            return False

Манхэттенская функция

    def manhattan_value(self,data=None):
        manhattan_distance = 0
        for i in range(0,len(data)):
            for j in range(0,len(data)):
                if(data[i][j] != self.goal_state[i][j] and data[i][j] != 0):
                    #correct position of the element
                    x_goal , y_goal = divmod(data[i][j],3)
                    manhattan_distance = manhattan_distance + abs(i-x_goal) + abs(j-y_goal)

        return manhattan_distance

Обновленная функция решения

    #implement A* algorithm
    def solver(self):
        moves = 0
        heuristic_value = []
        prev_state = []
        curr_state = self.board
        output = []
        heap_array = []
        store_manhattan_values = []


        if(curr_state == self.goal_state):
            print("goal state reached!")
            print(curr_state)
            print("number of moves required to reach goal state --> {}".format(moves))

        else:
            while(True):
                min_heuristic_value = 99999999999
                min_pos = None
                moves = moves + 1
                output = self.get_neighbours(curr_state)

                for i in range(len(output)):
                    store_manhattan_values.append([self.manhattan_value(output[i]),i])

                #print(store_manhattan_values)
                for i in range(len(store_manhattan_values)):
                    heapq.heappush(heap_array,store_manhattan_values[i])

                #print(heap_array)
                #print(heapq.heappop(heap_array)[1])


                #if(moves > 1):
                #    return
            return

Перейдите по ссылке PASTEBIN для получения полного кода и всех ссылок (https://pastebin.com/r7TngdFc).

Обновленный код с неполной функцией решения - https://pastebin.com/n4CcQaks

В данной ссылке для моего кода (на основе моих тестов и отладки до сих пор) - эти функции работают правильно - manhatten_value, hamming_value, append_in_list, get_neighbours

Что делают эти функции -

isSolvable — сообщает, можно ли решить доску или нет.

manhattan_value — вычисляет манхэттенское значение переданной ему доски.

hamming_value — вычисляет значение hamming переданной ему доски.

append_in_list — вспомогательная функция для получения соседей. Он меняет значения местами, затем сохраняет результирующее состояние в массиве, а затем меняет их местами, чтобы вернуться в исходное положение для дальнейшего обмена и получения других возможных состояний.

get_neighbours — получает всех возможных соседей, которые можно сформировать, поменяв местами пустой элемент (0 элемент).

решатель — реализует алгоритм A*

Я не могу найти свою ошибку. Пожалуйста, направьте меня в этой проблеме. Заранее спасибо за вашу помощь!

Я заранее извиняюсь, так как я не могу создать минимальную версию моего кода для этой проблемы. Никак не могу придумать, как использовать все функции и выдать минимальную версию кода.


person HARSHIT BAJPAI    schedule 14.09.2019    source источник
comment
Спасибо за правильный форум. Мне нужно подождать 40 минут, прежде чем я отправлю еще один вопрос. Я сделаю это, как только закончится срок.   -  person HARSHIT BAJPAI    schedule 14.09.2019
comment
@SpghttCd На самом деле CR предназначен только для рабочего кода. Этот код не работает. Прежде чем давать рекомендации по миграции, ознакомьтесь с темой.   -  person ggorlen    schedule 14.09.2019
comment
@HARSHITBAJPAI Этот вопрос в его нынешнем виде состоит из 250 строк кода, которые не работают - почему? который не по теме. Пожалуйста, опубликуйте минимально воспроизводимый пример и разбейте проблему, чтобы изолировать ее. По крайней мере, четко опишите, какой компонент не работает и как работает код. Какие части точно работают? Что делает каждый модуль? Какой именно ввод/вывод вы ему подаете и чего вы ожидали?   -  person ggorlen    schedule 14.09.2019
comment
@ggorlen извините, мое заблуждение, спасибо, что указали на это. Я всегда думал, что обзор будет включать в себя поиск, например. трудно отследить ошибки. -› рекомендация удалена   -  person SpghttCd    schedule 14.09.2019
comment
@SpghttCd Нет проблем! CR содержит трудно отслеживаемые ошибки, но они должны быть неизвестны автору во время публикации.   -  person ggorlen    schedule 14.09.2019
comment
@ggorlen Спасибо за ваши предложения. Я добавил информацию о функциях, которые работают (по моему мнению). Мне очень жаль, но я не могу придумать способ создания минимальной версии приведенного выше кода.   -  person HARSHIT BAJPAI    schedule 14.09.2019
comment
@ggorlen Пожалуйста, дайте мне знать, если с моей стороны потребуются дополнительные объяснения, которые могут быть полезны другим читателям.   -  person HARSHIT BAJPAI    schedule 14.09.2019
comment
Это полезное обновление, спасибо.   -  person ggorlen    schedule 14.09.2019
comment
Я обновил вопрос, немного лучше поняв, в чем именно проблема. Пожалуйста, дайте мне знать, если у вас есть какие-либо предложения сейчас @גלעדברקן   -  person HARSHIT BAJPAI    schedule 15.09.2019


Ответы (1)


(Обратите внимание, что этот ответ отличается от более ранней версии, к которой относились многие из приведенных ниже комментариев.)

Я не вижу, как текущий код реализует очередь. Кажется, что цикл while в решателе каждый раз выбирает одно новое состояние доски из списка возможных ходов, а затем рассматривает следующий список, сгенерированный этим новым состоянием доски.

С другой стороны, очередь с приоритетом, насколько я понимаю, будет иметь всех (действительных) соседей из текущего состояния доски, вставленных в нее и расставленных по приоритетам таким образом, чтобы следующее выбранное состояние доски было удалено из очередь и проверка будут иметь наивысший приоритет.

(Чтобы быть полностью уверенным в отладке, я мог бы добавить запоминание, чтобы определить, завершается ли код повторным посещением состояний доски — ах, если подумать, я верю в условие в описании задания, что количество текущих ходов добавляется к назначение приоритета исключило бы повторное посещение того же состояния доски, если очередь приоритетов соблюдается правильно, поэтому мемоизация может не понадобиться.)

person גלעד ברקן    schedule 14.09.2019
comment
Почему вы остановились после 5 ходов? Вы достигли целевого состояния? Рассмотрим эту доску - [[3,1,2],[0,4,5],[6,7,8]] Дайте мне знать, во многих ли ходах это достигает целевого состояния? Спасибо за вашу помощь в этом - person HARSHIT BAJPAI; 14.09.2019
comment
Если вы видите 3-ю последнюю и 2-ю последнюю строку кода, я пытался сделать то, что вы предложили, ограничивая количество итераций. Я не мог добраться до ошибки, хотя. - person HARSHIT BAJPAI; 14.09.2019
comment
То, как я написал код, заключается в том, что я передаю доску, а затем код сам находит необходимые ходы, чтобы добраться до целевого состояния. Так что мне действительно не нужно давать ходы решению. Эта доска - [[3,1,2],[0,4,5],[6,7,8]] разрешима. Тем не менее, когда я передаю это, код застревает в бесконечном цикле while. Раскомментируйте строку 210, и вы увидите, как будет вести себя код. - person HARSHIT BAJPAI; 14.09.2019
comment
Мне жаль. Попробуйте этот - [[1,2,3],[4,5,6],[0,7,8]] - person HARSHIT BAJPAI; 14.09.2019
comment
Может быть доска, которая может потребовать 10-12 ходов или даже больше, и я не смогу вручную рассчитать последовательность. Но функция isSolvable проверяет условие и возвращает true, если доска разрешима. - person HARSHIT BAJPAI; 14.09.2019
comment
[[1,2,3],[4,5,6],[0,7,8]] — это начальная стадия, которую я дам коду. Затем код сообщит, сколько минимальных ходов требуется для достижения целевого состояния. В этом случае он должен сообщить о двух необходимых ходах. - person HARSHIT BAJPAI; 14.09.2019
comment
Ебена мать! Ты прав! Когда я занимался отладкой, я предполагал, что целевое состояние неверно. Я только что проверил доску - [[3,1,2],[6,4,5],[7,8,0]] . Это требует 4 движения, и это работает нормально. Я изучаю isSolvable прямо сейчас. Дайте мне знать, если вы видите какую-либо очевидную ошибку в этой функции - person HARSHIT BAJPAI; 14.09.2019
comment
Это было бы неправильно согласно спецификации в задании. Кроме того, тогда остальная часть упорядочения станет относительно других элементов, а не абсолютным порядком. - person HARSHIT BAJPAI; 14.09.2019
comment
Я немного обновил функцию решения и информацию о вопросе. Не могли бы вы поделиться своими мыслями о том, буду ли я кодировать это. Я реализовал немного, но это тоже неправильно, я думаю. Дайте мне знать, как я буду действовать в этом случае? - person HARSHIT BAJPAI; 15.09.2019
comment
@HARSHITBAJPAI Я бы погуглил учебник по Python с приоритетной очередью, я уверен, что есть много примеров. В вашем случае, если у вас есть библиотека для очереди, идея проста — либо вставить в нее, либо получить из нее следующий элемент. Присваивание уже говорит вам, каков приоритет, и вы можете использовать кортежи, где первый является приоритетом, а второй - любыми данными, необходимыми для обработки элемента. - person גלעד ברקן; 15.09.2019
comment
@HARSHITBAJPAI также, вместо while (True), у вас может быть while (queue is not empty). - person גלעד ברקן; 15.09.2019