Охранные пункты в прологе?

Они существуют? Как они реализованы?

Сопутствующие предикаты SWI-Пролог (freeze, when, dif и т. д.) имеют функциональность охранников. Как они вписываются в предпочтительный стиль программирования Prolog?

Я очень плохо знаком с логическим программированием (с Прологом и в целом) и несколько смущен тем фактом, что оно не является чисто декларативным и требует процедурных соображений даже в очень простых случаях (см. Этот вопрос об использовании \== или же dif). Я что-то упустил?

3 ответа

Решение

Сначала терминологическая проблема: ни то, ни другое freeze/2 ни when/2 ни dif/2 называются охранниками при любых обстоятельствах. Охранники появляются в таких расширениях, как CHR, или родственных языках, таких как GHC (ссылка на японском языке) или других языках программирования с параллельной логикой; Вы даже (при определенных ограничениях) могли бы рассмотреть пункты формы

Голова :- охрана, !,...

поскольку пункты, содержащие охрану и сокращение, в этом случае будут скорее называться коммитом. Но ничто не относится к вышеупомянутым примитивам. Охранники скорее вдохновлены " Охранным командным языком" Дейкстры 1975 года.

freeze(X, Goal) (изначально называется geler) такой же как when(nonvar(X), Goal) и оба они декларативно эквивалентны Goal, Там нет прямого отношения к функциональности охранников. Тем не менее, при использовании вместе с if-then-else вы можете реализовать такую ​​защиту. Но это совсем другое.

freeze/2 и подобные конструкции в течение некоторого времени рассматривались как общий способ улучшения механизма исполнения Пролога. Тем не менее, они оказались очень хрупкими в использовании. Зачастую они были слишком консервативны, что задерживало цели без необходимости. То есть, почти каждый интересующий запрос выдает "колеблющийся" ответ, как и запрос ниже. Кроме того, граница между завершающими и не завершающими программами теперь намного сложнее. Для чисто монотонных программ Prolog, которые завершаются, добавление некоторой конечной цели в программу сохранит завершение всей программы. Однако с freeze/2 это больше не так. Тогда с концептуальной точки зрения, freeze/2 не очень хорошо поддерживали верхние уровни систем: только несколько систем продемонстрировали отложенные цели всесторонним образом (например, SICStus), что крайне важно для понимания разницы между успехом / ответами и решением. С отсроченными целями Пролог может теперь дать ответ, который не имеет решения, как этот:

? - заморозить (X, X = 1), заморозить (X, X = 2).
заморозить (X, X = 1),
заморозить (X, X = 2).

Еще одна сложность с freeze/2 было то, что условия прекращения гораздо сложнее определить. Так что пока freeze должен был решить все проблемы с терминацией, это часто создавало новые проблемы.

И есть также больше технических трудностей, связанных с freeze/2 в частности, для составления таблиц и других методов предотвращения петель. Считай цель freeze(X, Y = 1) ясно, Y сейчас 1 даже если он еще не связан, он все еще ждет X быть связанным первым. Теперь реализация может рассмотреть таблирование для цели g(Y), g(Y) теперь не будет ни решения, ни одного решения Y = 1, Этот результат теперь будет храниться как единственное решение для g/1 так как freezeцель не была непосредственно видна цели.

Именно по таким причинам freeze/2 считается переходом к программированию логики ограничений.

Еще одна проблема dif/2 который сегодня считается ограничением. В отличие от freeze/2 и другие сопутствующие примитивы, ограничения намного лучше способны управлять согласованностью, а также поддерживать гораздо лучшие свойства завершения. Это в первую очередь связано с тем, что ограничения вводят четко определенный язык, в котором конкретные свойства могут быть доказаны, а конкретные алгоритмы были разработаны и не допускают общих целей. Однако даже для них можно получить ответы, которые не являются решениями. Подробнее об ответе и успехе в CLP.

freeze/2 и когда / 2 подобны "переходу" логического программирования. Они не чисты, коммутативны и т. Д.

DIF /2, с другой стороны, является полностью чистым и декларативным, монотонным, коммутативным и т. д. DIF / 2 является декларативным предикатом, он имеет место, если его аргументы отличаются. Что касается "предпочтительного стиля программирования Пролога": укажите, что имеет место. Если вы хотите выразить ограничение, что два общих термина различны, diff/2 как раз и утверждает это.

Процедурные соображения, как правило, наиболее необходимы, когда вы не программируете в чисто декларативном подмножестве Prolog, но используете нечистые предикаты, которые не являются коммутативными и т. Д. В современных системах Prolog нет особых причин когда-либо оставлять чистое и декларативное подмножество.

Есть статья Эвана Тика, объясняющая CC:

Неформально вызов процедуры фиксирует предложение, сопоставляя аргументы заголовка (пассивное объединение) и выполняя защитные цели. Когда цель может зафиксировать более одного предложения в процедуре, она выполняет одно из них недетерминированно (другие кандидаты отбрасываются). Структуры, появляющиеся в заголовке и охране пункта, вызывают приостановку исполнения, если соответствующий аргумент цели не был достаточно инстанцирован. Приостановленный вызов может быть возобновлен позже, когда переменная, связанная с приостановленным вызовом, становится достаточно инстанцированной.

РАЗОБРЕТЕНИЕ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ СОВМЕСТНОЙ ЛОГИКИ
Эван Тик - 1995
https://core.ac.uk/download/pdf/82787481.pdf

Таким образом, я полагаю, что с некоторой магией "/2" код с выбором совершенного кода можно переписать в обычный Пролог. Подход был бы следующим. Для набора утвержденных правил выбора одного и того же предиката:

H1 :- G1 | B1.
...
H2 :- Gn | Bn.

Это можно переписать следующим образом, где Hi и Gi должны реализовать пассивную унификацию. Например, с помощью ISO Corrigendum subsumes_term/2.

H1' :- G1', !, B1.
..
H1' :- Gn', !, Bn.
H :- term_variables(H, L), when_nonvar(L, H).

Приведенный выше перевод не будет работать для CHR, поскольку CHR не выбрасывает кандидатов.

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