看来您正在处理 CLP(FD)。这些求解器区分求解约束问题的设置阶段和标记阶段。
CLP(FD) 求解器不会在设置阶段完全减少问题。因为它有机会在标记阶段减少变量范围。因此,在设置过程中可能会提出一个问题,该问题可以被其他求解器减少为“否”,但不会使用 CLP(FD) 求解器。只有在标记过程中才会检测到“否”。
在设置阶段减少多少很大程度上取决于给定的 CLP(FD) 系统。一些 CLP(FD) 系统在设置阶段做更多的减少,而其他做更少。例如,GNU Prolog 使用一些索引传播,而 SWI Prolog 则没有。因此,我们发现例如,而不是您的示例:
SWI-序言:
?- X #< Y, Y #< Z, Z #< X.
Z#=<X+ -1,
X#=<Y+ -1,
Y#=<Z+ -1.
GNU 序言:
?- X #< Y, Y #< Z, Z #< X.
(7842 ms) no
此外,由于您使用的是具体化约束,因此它还取决于具体化的完成程度。但我想在目前的情况下它只是传播问题。我们现在为您的示例找到:
SWI-序言:
?- X #< 4 #==> X #< 7.
X+1#=_G1330,
X+1#=_G1342,
7#>=_G1330#<==>_G1354,
_G1354 in 0..1,
_G1377#==>_G1354,
_G1377 in 0..1,
4#>=_G1342#<==>_G1377.
GNU 序言:
?- X #< 4 #==> X #< 7.
X = _#22(0..268435455)
在设置阶段减少更多工作和将更多工作留给标记阶段之间存在权衡。整个事情也取决于给定的例子。但是当您在设置旁边也有标签时,您不会看到结果有任何差异:
SWI-序言:
?- X in 0..9, X #< 4 #==> X #< 7, label([X]).
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5 ;
X = 6 ;
X = 7 ;
X = 8 ;
X = 9.
GNU 序言:
?- fd_domain(X,0,9), X #< 4 #==> X #< 7, fd_labeling([X]).
X = 0 ? ;
X = 1 ? ;
X = 2 ? ;
X = 3 ? ;
X = 4 ? ;
X = 5 ? ;
X = 6 ? ;
X = 7 ? ;
X = 8 ? ;
X = 9
我没有使用 SICStus Prolog 或 B-Prolog 进行测试。但我猜他们会在 SWI-Prolog 和 GNU Prolog 附近的某个地方表现出来。
如果您的域确实是 FD,则 CLP(Q) 不是真正的选择,因为它会错过一些“否”减少,而 CLP(FD) 不会错过。例如,以下在 CLP(FD) 中是不可满足的,但在 CLP(Q) 中是可满足的:
X = Y + 1, Y < Z, Z < X.
再见