[英]Which operators and predicates can be used with clp(fd)?
首先, clp(fd) 文檔提到:
在現代 Prolog 系統中,算術約束包含並取代整數上的低級謂詞。 算術約束的主要優點是它們是真實的關系並且可以在所有方向上使用。 對於大多數程序,算術約束是您唯一需要從這個庫中獲得的謂詞。
其次,在先前提出的問題中,提到include/3
與 clp(fd) 不兼容。
這是否意味着在使用 clp(fd) 庫編寫 prolog 時只能使用clp(fd) 運算符和clp(fd) 謂詞?
此外,例如,為什么include/3
與 clp(fd) 不兼容? 是因為它不使用 clp(fd) 運算符嗎? 要在 clp(fd) 代碼中使用include/3
,是否需要重寫一個使用 clp(fd) 運算符和約束的版本?
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-prolog 中的結果:
?- test_include(F).
F = [_A, _B],
_A in 6..sup,
_B in 9..sup.
上面的代碼是安全的,因為與 clpfd 一起使用的變量與 clpfd一致地使用,並且指定的約束導致gt_3_fd的具體gt_3_fd
是不必要的。
一旦根據用例變量是 nonvar/ground(clpfd 處理整數,而不是復合項,因此 nonvar 就足夠了),那么變量也可以在 clpfd 之外使用。 例子:
?- I = 5, I > 4, I @> 4, I #> 4.
I = 5.
>
等運算符使用變量的實際值,並忽略可能已由 clpfd 添加到變量的任何屬性。
邏輯純度,例如在include/3
之后而不是之前向列表L
中的元素添加約束是一個單獨的問題,並且也適用於非屬性變量。
總結:一個程序可能在 clpfd 中使用一些整數,在 clpfd 之外使用一些整數,即混合。 這沒關系,只要始終如一地應用內部或外部區別,同時它是相關的(因為例如標簽將產生實際值)。
為什么
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. % missing second answer
因此, (#\=)/2
只有在充分實例化的情況下才適用於這種情況。 你怎么能確定它是? 好吧,沒有直接的安全測試。 因此在某些情況下你會得到不正確的結果。 只要這些示例適合一行,就很容易發現錯誤。 但是對於更大的程序,這實際上是不可能的。 因此,constraints 和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
的一個安全變體是library(reif)
的tfilter/3
。 但在使用它之前,我建議您閱讀這篇文章。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.