Как мне найти все решения для цели в Прологе?

У меня есть предикат 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 таков, что существует X и существует Y такой, что p(X,Y,Z) ". findall действует как bagof со всеми свободными переменными автоматически экзистенциально количественно. К тому же findall возвращает пустой список [] нет цели удовлетворения, тогда как bagof выходит из строя.

Другие вопросы по тегам