Пролог 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).
Другие вопросы по тегам