Включает ли SWI-Prolog `foreach / 2`` freeze / 2`? - PullRequest
1 голос
/ 18 января 2020

В SWI Пролог foreach / 2 мы читаем:

Description of

Совместимость «агрегатной» библиотеки, которая содержит предикат foreach/2 заявлен как

Quintus, SICStus 4. forall / 2 является встроенным SWI-Prolog, а term_variables / 3 является SWI-Prolog встроенный с различной семантикой.

Из документации SICStus Prolog :

foreach(:Generator, :Goal)

для каждого доказательства Генератор в свою очередь, мы делаем копию Goal с соответствующей заменой, затем выполняем эти копии последовательно. Например, foreach(between(1,3,I), p(I)) эквивалентно p(1), p(2), p(3).

Обратите внимание, что это не то же самое, что forall/2. Например, forall(between(1,3,I), p(I)) эквивалентно

\+ \+ p(1), \+ \+ p(2), \+ \+ p(3).

Хитрость в foreach/2 состоит в том, чтобы гарантировать, что переменные Goal , которые не встречаются в Генератор восстановлен правильно. (Если таких переменных нет, вы также можете использовать forall/2.)

Как и forall/2, этот предикат выполняет l oop, управляемый сбоем, по сравнению с Generator . В отличие от forall/2, Цели выполняются как обычное соединение и могут быть успешными несколькими способами.

Взяв пример на странице Пролог SWI, без окончательной объединение:

?- foreach(between(1,4,X), dif(X,Y)).
dif(Y, 4),
dif(Y, 3),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 3),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1).

Я не уверен, почему есть выходные данные всех dif/2 экземпляров и почему есть повторения одной и той же подцели.

foreach/2 должно быть решено что соединение нескольких dif(Y,i) истинно, поскольку несвязанная переменная Y явно dif из целого числа i .

Но теперь:

?- foreach(between(1,4,X), dif(X,Y)), Y = 5.
Y = 5.

Хорошо, поэтому ничего не выводится, кроме Y=5, потому что цель успешна. Но что меняет Y=5? После foreach/2 Пролог уже может решить, что foreach/2 истинно (учитывая состояние Y во время запуска foreach/2), поэтому добавление Y=5 ничего не должно изменить.

Но тогда:

?- foreach(between(1,4,X), dif(X,Y)), Y = 2.
false.

Последующее объединение меняет исход foreach/2. Как?

Я подумал, что freeze/2 на Y может помочь сделать ситуацию интересной, потому что в действительности мы вычисляем:

freeze(Y,foreach(between(1,4,X), dif(X,Y))).

Это более или менее объясняет распечатки. Например:

?- freeze(Y,foreach(between(1,4,X), dif(X,Y))).
freeze(Y, foreach(between(1, 4, X), dif(X, Y))).

?- freeze(Y,foreach(between(1,4,X), dif(X,Y))), Y=5.
Y = 5.

?- freeze(Y,foreach(between(1,4,X), dif(X,Y))), Y=2.
false.

Это то, что происходит?

1 Ответ

3 голосов
/ 18 января 2020

Наблюдаемое вами поведение «замораживания» связано с dif / 2, а не foreach / 2.

Предикат dif / 2 гарантирует, что его два аргумента не идентичны и не станут идентичными. Таким образом, если два аргумента могут стать идентичными, dif / 2 приостанавливается до тех пор, пока не будет решено, идентичны они или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...