Какие операторы и предикаты можно использовать с clp(fd)?

Во-первых, в документации clp(fd) упоминается:

В современных системах на Прологе арифметические ограничения включают и заменяют низкоуровневые предикаты над целыми числами. Основное преимущество арифметических ограничений состоит в том, что они являются истинными отношениями и могут использоваться во всех направлениях. Для большинства программ арифметические ограничения являются единственными предикатами, которые вам когда-либо понадобятся в этой библиотеке.

Во-вторых, в ранее заданном вопросе было упомянуто, что include/3 несовместим с clp(fd).

Означает ли это, что при написании пролога с помощью библиотеки clp(fd) можно использовать только операторы clp(fd) и предикаты clp(fd)?

Кроме того, например, почему include/3 несовместим с clp(fd)? Это потому, что не использует операторы clp(fd)? Чтобы использовать include/3 в коде clp(fd), нужно ли переписывать версию, в которой используются операторы и ограничения clp(fd)?

Вы видели Понимание кода CLP(FD) Prolog задачи N-ферзей, в частности утверждение в самом конце, those predicates generate constraints that are maintained internally ? Это должно дать вам еще некоторые необходимые знания.

Guy Coder 11.01.2023 14:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
119
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

include/3 не обязательно должен быть несовместим с clpfd (или любым другим использованием атрибутивных переменных ) - зависит от безопасного (для целей программы, а не обязательно "логически чистого") использования атрибутивных переменных. Например.:

:- use_module(library(clpfd)).

test_include(F) :-
    L = [N1, N2, N3, N4],
    N1 #< 2,
    N2 #> 5,
    N3 #< 3,
    N4 #> 8,
    include(gt_3_fd, L, F).

gt_3_fd(I) :-
    I #> 3.

Результат в swi-прологе:

?- test_include(F).
F = [_A, _B],
_A in 6..sup,
_B in 9..sup.

Приведенный выше код безопасен, потому что переменные, используемые с clpfd, используются последовательно с clpfd, а указанные ограничения приводят к тому, что повторениеgt_3_fd становится ненужным.

Как только переменные являются непеременными/заземленными в зависимости от варианта использования (clpfd работает с целыми числами, а не, например, с составными терминами, поэтому непеременная достаточно хороша), тогда переменные также можно использовать вне clpfd. Пример:

?- I = 5,  I > 4, I @> 4, I #> 4.
I = 5.

Оператор , такой как >, использует фактическое значение переменной и игнорирует любые атрибуты, которые могли быть добавлены к переменной, например. клпфд.

Логическая чистота, например. добавление ограничений к элементам в списке L после include/3, а не перед ним, является отдельной проблемой и также относится к переменным без атрибутов.

Вкратце: программа может использовать некоторые целые числа с clpfd и некоторые целые числа вне clpfd, т. е. смесь. Это нормально, пока различие между внутренним и внешним применяется последовательно, пока оно актуально (поскольку, например, маркировка будет давать фактические значения).

Да я вижу. Если я правильно понимаю, я могу использовать любой предикат, если я непротиворечив в переменных и операторах, которые я использую с ними. Просто чтобы уточнить, скажем, я использую предикат из библиотеки p(X) :- X > 5., смогу ли я вызвать его из моего кода clp(fd) с помощью X in 1..5, p(X). или это не сработает, потому что предикат p не использует оператор сравнения #>?

nich 11.01.2023 02:44
X > 5 выдает ERROR: Arguments are not sufficiently instantiated, если X в этот момент имеет значение var - swi-prolog.org/pldoc/doc_for?object=var/1
brebs 11.01.2023 08:49

Как вы можете отличить приведенный выше случай от «незначительного» варианта, скажем, N4 #< 8, где вы получаете неправильный результат?

false 11.01.2023 10:52

@false Я бы обвинил программиста в том, что он не использует овеществление, если овеществление (например, tfilter вместо include, как вы упомянули) требуется в этот момент для правильной работы программы :-) Или, возможно, перепишите программу, чтобы использовать include после переменных были созданы экземпляры.

brebs 11.01.2023 11:58

В том то и смысл, что они несовместимы.

false 11.01.2023 14:07

@false Я думаю, наша разница в том, что меня интересует программа, которая работает (т.е. отвечает заявленным требованиям), тогда как вы продвигаете логически чистый стиль, который имеет свое применение, но для большинства вопросов о Прологе на этом сайте , является излишним и показал бы Пролог новичкам слишком сложным и медленным.

brebs 11.01.2023 14:32

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

false 11.01.2023 14:34

...так что это не имеет ничего общего с чистым стилем как таковым. Подумайте о (=\=)/2, который просто безопасен, но чрезвычайно ограничен.

false 11.01.2023 14:35

Когда мы говорим о «совместимости», мы всегда имеем в виду «совместимость в общем случае», мы никогда не имеем в виду «совместимость иногда» или «совместимость при благоприятных условиях». Таким образом, include/3 совместим с clpfd тогда и только тогда, когда он никогда не бывает с ним несовместим.

repeat 14.01.2023 10:39

На первый взгляд код, который вы представляете, кажется логичным. Но если заглянуть глубже, он развалится. Почему? Это зависит от внутренних деталей реализации используемой вами библиотеки clpfd. Учтите, что (#>)/2 может оставить после себя остаточные цели. В вашем надуманном примере нет, а вообще может!

repeat 14.01.2023 10:47

@repeat Заметьте, я не утверждаю, что include всегда безопасно использовать. Но говорить, что это всегда небезопасно, неправильно.

brebs 14.01.2023 11:36

Конечно, но OTOH тоже никто не говорит, что «это всегда небезопасно». Центральный вопрос: на какие свойства может положиться пользователь include/3? Таким образом, в данном контексте «небезопасный» означает не «никогда не безопасный», а «не всегда безопасный». Пользователь не может полагаться на include/3 безопасность с clpfd (не зная деталей внутренней реализации, которые, кстати, могут быть изменены), поэтому мы говорим: «(в целом) include/3 небезопасно использовать с clpfd».

repeat 14.01.2023 11:51

почему include/3 несовместим с clp(fd)?

?- X = 1, include(#\=(1),[0,X,2],Xs), X = 1.
   X = 1,
   Xs = [0,2].     % looks good
?-        include(#\=(1),[0,X,2],Xs), X = 1.
   false, unexpected.
?-        include(#\=(1),[0,X,2],Xs).   % generalization
   Xs = [0,X,2],
   X in inf..0/2..sup
;  unexpected. % missing second answer

Итак, (#\=)/2 работает в этом случае, только если он достаточно конкретизирован. Как вы можете быть уверены, что это так? Ну, нет прямого безопасного теста. И, таким образом, вы получите неправильные результаты в определенных случаях. Пока эти примеры помещаются в одну строку, довольно легко обнаружить ошибку. Но с большей программой это практически невозможно. Из-за этого ограничения и include/3 несовместимы.

Выходом из ситуации было бы создание ошибок инстанцирования в случаях с недостаточным инстанцированием, но в контексте clpfd это довольно сложно. Другие встроенные предикаты, такие как (=\=)/2, делают это, и их применимость ограничена.

?- X = 1, include(=\=(1),[0,X,2],Xs), X = 1.
   X = 1,
   Xs = [0,2].
?-        include(=\=(1),[0,X,2],Xs), X = 1.
   instantiation_error.    % much better than an incorrect answer

Безопасный вариант include/3 — это tfilter/3 из library(reif). Но прежде чем использовать его, я рекомендую вам прочитать это.

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