Пролог findall/3: более одной сумки
Я пишу ИИ для игр типа Фокс и Гуси. Один из моих предикатов выглядит так:
moveFox(+PrevState, -NextState, -PegList, +VisitedStates, -NewVisitedStates)
Он принимает игровое состояние и делает ход с лисой. Полученное состояние унифицировано с NextState
и фактический ход объединяется с PegList
, Все работает как положено.
Я рассчитываю счет полезности для всех ходов NextState
, Чтобы найти штат с наивысшим баллом полезности, я использую findall/3
чтобы получить все состояния в списке, прежде чем сравнивать их оценки полезности.
findall(NextState, moveFox(...), NextStatesList)
Находя максимальную оценку полезности, я знаю NextState
(а также его положение в списке) с наибольшим баллом полезности. Есть только одна проблема, в настоящее время я не написал ни одного предиката, чтобы определить, какой шаг был сделан, чтобы прийти к NextState
Например:
getMove(+PrevState, +NextState, -PegList)
Вместо написания такого предиката я бы предпочел использовать findall/3
или эквивалент. У меня вопрос, есть ли способ получить две разные переменные в двух разных списках. Я так думаю (если бы это сработало):
findall([NextState, PegList], moveFox(...), [NextStatesList, MoveList])
Могу ли я реализовать такую функциональность, не запуская findall/3
дважды (некрасиво) или напишите, что getMove(+PrevState, +NextState, -PegList)
предикат?
1 ответ
Эту проблему можно решить, создав список пар, а затем разделив элементы, как это делает библиотека ( пары)
...
findall(NextState-PegList, moveFox(...), Pairs),
pairs_keys_values(Pairs, NextStates, Pegs),
...
Если у вашего Пролога нет пары pair_keys_values /3, его легко написать либо с помощью maplist, либо с помощью рекурсивного предиката. Вот способ отображения списка:
pkv(K-V, K, V).
pairs_keys_values(Pairs, Keys, Vals) :-
maplist(pkv, Pairs, Keys, Vals).