Решение 8 головоломок с поиском лучших в прологе

Как следует из названия, я должен сделать пролог-программу, которая решает 8 задач с использованием поиска по принципу "лучший вначале", я новичок в Прологе и ИИ, поэтому мне трудно.

На данный момент у меня есть правила перемещения:

%% move left in the top row
move([X1,0,X3, X4,X5,X6, X7,X8,X9],
     [0,X1,X3, X4,X5,X6, X7,X8,X9]).
move([X1,X2,0, X4,X5,X6, X7,X8,X9],
     [X1,0,X2, X4,X5,X6, X7,X8,X9]).

%% move left in the middle row
move([X1,X2,X3, X4,0,X6,X7,X8,X9],
     [X1,X2,X3, 0,X4,X6,X7,X8,X9]).
move([X1,X2,X3, X4,X5,0,X7,X8,X9],
     [X1,X2,X3, X4,0,X5,X7,X8,X9]).

%% move left in the bottom row
move([X1,X2,X3, X4,X5,X6, X7,0,X9],
     [X1,X2,X3, X4,X5,X6, 0,X7,X9]).
move([X1,X2,X3, X4,X5,X6, X7,X8,0],
     [X1,X2,X3, X4,X5,X6, X7,0,X8]).

%% move right in the top row 
    move([0,X2,X3, X4,X5,X6, X7,X8,X9],
     [X2,0,X3, X4,X5,X6, X7,X8,X9]).
move([X1,0,X3, X4,X5,X6, X7,X8,X9],
     [X1,X3,0, X4,X5,X6, X7,X8,X9]).

%% move right in the middle row 
move([X1,X2,X3, 0,X5,X6, X7,X8,X9],
     [X1,X2,X3, X5,0,X6, X7,X8,X9]).
move([X1,X2,X3, X4,0,X6, X7,X8,X9],
     [X1,X2,X3, X4,X6,0, X7,X8,X9]).

%% move right in the bottom row
move([X1,X2,X3, X4,X5,X6,0,X8,X9],
     [X1,X2,X3, X4,X5,X6,X8,0,X9]).
move([X1,X2,X3, X4,X5,X6,X7,0,X9],
     [X1,X2,X3, X4,X5,X6,X7,X9,0]).

%% move up from the middle row
move([X1,X2,X3, 0,X5,X6, X7,X8,X9],
     [0,X2,X3, X1,X5,X6, X7,X8,X9]).
move([X1,X2,X3, X4,0,X6, X7,X8,X9],
     [X1,0,X3, X4,X2,X6, X7,X8,X9]).
move([X1,X2,X3, X4,X5,0, X7,X8,X9],
     [X1,X2,0, X4,X5,X3, X7,X8,X9]).

%% move up from the bottom row
move([X1,X2,X3, X4,X5,X6, X7,0,X9],
 [X1,X2,X3, X4,0,X6, X7,X5,X9]).
move([X1,X2,X3, X4,X5,X6, X7,X8,0],
     [X1,X2,X3, X4,X5,0, X7,X8,X6]).
move([X1,X2,X3, X4,X5,X6, 0,X8,X9],
     [X1,X2,X3, 0,X5,X6, X4,X8,X9]).

%% move down from the top row
move([0,X2,X3, X4,X5,X6, X7,X8,X9],
     [X4,X2,X3, 0,X5,X6, X7,X8,X9]).
move([X1,0,X3, X4,X5,X6, X7,X8,X9],
     [X1,X5,X3, X4,0,X6, X7,X8,X9]).
move([X1,X2,0, X4,X5,X6, X7,X8,X9],
     [X1,X2,X6, X4,X5,0, X7,X8,X9]).

%% move down from the middle row
move([X1,X2,X3, 0,X5,X6, X7,X8,X9],
     [X1,X2,X3, X7,X5,X6, 0,X8,X9]).
move([X1,X2,X3, X4,0,X6, X7,X8,X9],
     [X1,X2,X3, X4,X8,X6, X7,0,X9]).
move([X1,X2,X3, X4,X5,0, X7,X8,X9],
     [X1,X2,X3, X4,X5,X9, X7,X8,0]).

(Я знаю, что есть более простой способ использования списков, но это то, что сработало для меня)

И лучший первый код, который я нашел в Интернете: http://www.cs.unm.edu/~luger/ai-final/code/PROLOG.best.html

Но в этом лучшем первом коде есть эвристическая функция, которая не запускается:

go(Start, Goal) :- 
   empty_set(Closed),
   empty_sort_queue(Empty_open),
   heuristic(Start, Goal, H),
   state_record(Start, nil, 0, H, H, First_record),
   insert_sort_queue(First_record, Empty_open, Open),
   path(Open,Closed, Goal).

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

Так что я подумал об использовании эвристики "тайлы с места" для головоломки "8", так как она звучит проще, чем манхэттенское расстояние или что-то еще. Но теперь я застрял в том, как это программировать, везде гуглил, как сравнивать списки и как добавлять переменные, и я вроде как сделал это, что я не знаю, сработает ли это:

heuristic([],[],H).
heuristic([Head1|Tail1],[Head2|Tail2], H):-
   not(samePlace(Head1,Head2))->H1 is H + 1,
   heuristic(Tail1, Tail2, H1).

Моя идея состоит в том, что он ищет каждый элемент стартового списка и сравнивает его со списком целей, а затем, если они отличаются, добавляет 1 к H, где H количество плиток неуместно.

Для чего я также определил "плитки в тех же правилах места":

samePlace([X,_,_,_,_,_,_],[X,_,_,_,_,_,_]).
samePlace([_,X,_,_,_,_,_],[_,X,_,_,_,_,_]). 
samePlace([_,_,X,_,_,_,_],[_,_,X,_,_,_,_]).
samePlace([_,_,_,X,_,_,_],[_,_,_,X,_,_,_]).
samePlace([_,_,_,_,X,_,_],[_,_,_,_,X,_,_]).
samePlace([_,_,_,_,_,X,_],[_,_,_,_,_,X,_]).
samePlace([_,_,_,_,_,_,X],[_,_,_,_,_,_,X]). 
(etc...)

Но, конечно, я получаю "ОШИБКА: эвристика /3: Аргументы не достаточно созданы", что, как я полагаю, означает, что я никогда не инициализировал H.

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

Мои вопросы: - Я на правильном пути, или я совершенно не понял, что означает эта "эвристическая" функция? - Как я могу инициализировать H? - Является ли мой код эвристической функции синтаксически правильным?

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

Заранее спасибо.

1 ответ

Решение

( ->;;)/2 в Прологе была введена для упрощения моделирования логики if..then..else.., но имеет важное отличие от императивных языков: без ветки 'else' происходит сбой, когда условие не выполняется.

Теперь вы пропустите ветку else в эвристике /3. Это может быть задумано, но я думаю, что если samePlace(Head1,Head2) где-то имеет значение true, это не сможет вернуть значение, и, таким образом, начинается возврат в вызывающий код. По моему опыту, это часто является причиной для последующих странных сообщений об ошибках, таких как то, что вы сообщаете.

Другая проблема заключается в том, что вы не можете "вернуть" значение, даже когда предикат успешно выполняется: попробуйте вместо

heuristic([],[],0).
heuristic([Head1|Tail1],[Head2|Tail2], H):-
   heuristic(Tail1, Tail2, H1),
   (   not(samePlace(Head1,Head2))
   ->  H is H1 + 1
   ;   H is H1
   ).
Другие вопросы по тегам