Как найти все решения для цели в Prolog?

У меня есть предикат P1, который возвращает значения один за другим следующим образом:

-? P1(ARGUMENTS, RETURN).
-? RETURN = 1;
-? RETURN = 2;
-? RETURN = 3;
-? fail.

У меня также есть другой предикат, называемый P2:

P2(ARGUMENTS, LIST) :- P1(ARGUMENTS, RETURN),... % SOMEHOW HERE I NEED TO INSERT ALL VALUES OF RETURN TO LIST.

Как найти все значения RETURN и назначить их LIST?

Ответы

Ответ 1

Используйте findall, чтобы выполнить это:

P2(ARGUMENTS, LIST) :- findall(X, P1(ARGUMENTS, X), LIST).

Это связано с функцией bagof, упомянутой в вопросе, связанной с Андерсом Линдалем. Существует хорошее объяснение взаимосвязи между двумя функциями (и третьей функцией setof) здесь:

Чтобы проиллюстрировать различия, небольшой пример:

listing(p).

p(1,3,5).
p(2,4,1).
p(3,5,2).
p(4,3,1).
p(5,2,4).

Попробуйте выполнить следующие задачи. (Ответ дисплеи были изменены для сохранения пространство.)

?- bagof(Z,p(X,Y,Z),Bag).
Z = _G182 X = 1 Y = 3 Bag = [5] ;
Z = _G182 X = 2 Y = 4 Bag = [1] ;
Z = _G182 X = 3 Y = 5 Bag = [2] ;
Z = _G182 X = 4 Y = 3 Bag = [1] ;
Z = _G182 X = 5 Y = 2 Bag = [4] ;
No

?- findall(Z,p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [5, 1, 2, 1, 4] ;
No

?- bagof(Z,X^Y^p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [5, 1, 2, 1, 4] ;
No

?- setof(Z,X^Y^p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [1, 2, 4, 5] ;
No

Предикаты bagof и setof дают коллекции для индивидуальных привязок свободные переменные в цели. setofдает отсортированную версию сбор без дубликатов. к избегайте связывания переменных, используйте экзистенциальное кванторное выражение. Для пример цели bagof(Z,X^Y^p(X,Y,Z),Bag) просит "Сумка Z такая, что существует a X и существует Y такое, что p(X,Y,Z)". findall действует как bagofсо всеми свободными переменными автоматически экзистенциально количественно. К тому же findall возвращает пустой список [] там не является удовлетворением цели, тогда как bagofвыходит из строя.