Нежелательные свойства CLPB

library(clpb) в настоящее время доступен в SICStus (исходная версия) и SWI (по мату). Позвольте мне прийти к сути довольно быстро:

?- X = 1+1, sat(X), X = 1+1.
X = 1+1.

?-          sat(X), X = 1+1.
false.

Итак, это аналогичная проблема, поскольку она существует в состоянии по умолчанию library(clpfd).

Что делать в такой ситуации?

Обновление: в library(clpfd) мата для этого теперь есть функтор # /1. В идеале, с объявлением оператора op(100,fx,#), мы можем теперь написать:

?- X = 1+1, #X #= Y.
ERROR: Type error: `integer' expected, found `1+1' (a compound)

Чтобы обеспечить полные алгебраические свойства, нужно объявить:

:- set_prolog_flag(clpfd_monotonic, true).

Теперь переменные, которые остаются двусмысленными (таким образом, будучи либо целыми, либо выражениями), создают ошибки создания экземпляра:

?-  1 + 1 #= Y.
ERROR: Arguments are not sufficiently instantiated
?- 1 + 1 #= #Y.
Y = 2.

Ответ 1

Да, то же самое в CLP (FD) и CLP (B):

Ситуация

CLP (FD), (+)/2 действует как добавление в конечной области:

?- X = 1+1, X #= 2.
X = 1+1.

?- X #= 2.
X = 2

?- X #= 2, X = 1+1.
false.

CLP (B), (+)/2 действует как дизъюнкция в булевой области:

?- X = 1+1, sat(X)
X = 1+1

?- sat(X)
X = 1

?- sat(X), X = 1+1.
false

Но теперь следите, такие вещи происходят уже в обычном прологе:

?- X = 3, X \= 4.
X = 3.

?- X \= 4, X = 3.
false.

Проблема

Итак, что мы должны сказать ученикам? Я не думаю, что CLP (FD) или CLP (B).

Его больше укоренилось в (=)/2, и невозможность зацепить (=)/2, так что он выполняет больше, чем check_attribute/3.

В идеальном мире (=)/2 работала бы алгебраически, а X = 1 + 1 не подведет, система увидит, что 1 + 1 равно 2 (случай FD) соответственно 1 + 1 равно 1 (случай B).

Но для этого система Prolog потребует типов в начале, иначе (=)/2 не может интерпретировать (+)/2, он имеет две разные интерпретации в нашем примере.

Решение

Решение состоит в том, чтобы воздерживаться от использования (=)/2, где нужны конкретные типы. Настоящим я рекомендую прочитать:

Программирование логики Constraint с использованием ECLiPSe
Кшиштоф Р. Апт и Марк Уоллес,
16 мая 2006 г. Полный текст PDF

В приведенной выше статье немного подчеркивается мотивация символа хэша (#) в качестве префикса для таких операторов, как (=)/2, (<)/2 и т.д. Его уже аннотация типа. В этой статье есть еще один префикс: знак доллара ($).

В ECLiPSe Prolog хеш-знак (#) влечет за собой целые числа ограничений /1, а знак доллара ($) влечет затухания связи /1. Эти ограничения можно также использовать независимо, как показано в следующем примере:

?- integers([X,Y]), X = 3, Y = 4.5.
No

?- reals(X), X = [1,2.1,a].
No

Возвращаясь к вашей проблеме не коммутативности (=)/2. Хотя (=)/2 некоммутативен, (# =)/2 и его булевский брат, конечно, являются коммутативными. Мы имеем:

CLP (FD), (+)/2 действует как сложение в конечной области, а с (# =)/2 коммутатив существует:

?- X #= 1+1, X #= 2.
X = 2

?- X #= 2, X #= 1+1.
X = 2

CLP (B), (+)/2 действует как дизъюнкция в булевой области, а с sat/1 и (=: =)/2 есть коммутативность:

?- sat(X=:=1+1), sat(X).
X = 1.

?- sat(X), sat(X=:=1+1).
X = 1

Ключ verify_attribute/3 будет только активировать ограничения, которые могут дополнительно привести к объединению доменов Herbrand. Но они не могут оценивать термины "на лету", прежде чем назначать их переменной Prolog.

Только ограничения woken up могут присваивать значения другим переменным. Но, например, текущий SICStus Spec для проверки_атрибут/3 даже рекомендует не делать этого напрямую и только в очереди продолжения. См. Недавнее обсуждение группы SWI-Prolog.

Так долго говорите, короткое объяснение: никогда не забывайте, что (=)/1 работает только для домена Herbrand в Prolog, даже если мы зацепились за ограничения. Я не говорю, что система Prolog не может работать по-другому, но это состояние систем стада или пролога.

Bye