Как мне найти все решения для цели в Прологе?
У меня есть предикат 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
выходит из строя.