“显而易见”这个词并不容易,但是为什么SWI-Prolog的CLPFD可以正确地解决这个问题:
?- A+1 #= A*2.
A = 1.
但不是这样:
?- B #= A + 1, B #= A * 2.
A+1#=B,
A*2#=B.
({label
和indomain
产生Arguments are not sufficiently instantiated
。)
仅仅是……求解器没有发现这种情况? (我肯定会期望它会应用传递性。)或者这是一些更深的语法难题的征兆,还是什么?
答案 0 :(得分:3)
它试图根据每个变量域中的值来解决约束!由于B
和A
的域是无限且不受限制的,因此超过约束满足的回溯将被延迟,程序将停止。
这意味着它试图找到约束B #= A + 1
的某种解决方案,但发现了很多(A
和B
的无穷大),第二个约束也相同。因此,此处将停止,因为A
和B
的可能值是无限的。但是,结果不是No
。这是Yes
,有2个延迟目标。
B = B{-1.0Inf .. 1.0Inf}
A = A{-1.0Inf .. 1.0Inf}
There are 2 delayed goals.
要解决此问题,您需要绑定A
或B
中的至少一个。例如,如果运行此查询A::1..1000, B#=A+1, B #= A*2.
,将获得与示例中第一个查询相同的结果。而且,clpfd
中没有任何推论可以解决传递性,因为它是通过回溯方法使用的。
总而言之,这是您所使用的库的缺点之一,因为当一个变量多于一个约束的约束域具有无限域时,它会停止,您可以通过为设置一个有界域来解决该问题。至少一个变量。