Prolog CLPFD 传递性

Prolog CLPFD Transitivity

"Obvious" 不是随便说说的,但为什么 SWI-Prolog 的 CLPFD 能正确解决这个问题:

?- A+1 #= A*2.
A = 1.

但不是这个:

?- B #= A + 1, B #= A * 2.
A+1#=B,
A*2#=B.

(labelindomain 产生 Arguments are not sufficiently instantiated。)

难道只是...求解器没有捕捉到这种情况? (我肯定期望它应用传递性。)或者它是一些更深层次的句法难题的症状,还是什么?

它试图从每个变量域中的值来解决约束!由于 BA 的域是无限的且不受约束,因此将延迟满足约束的回溯并停止程序。

这意味着它试图为约束 B #= A + 1 找到一些解决方案,但它找到了很多(AB 的无限值)并且第二个约束也相同.因此它将在这里停止,因为 AB 的可能值是无限的。然而,结果并不是NoYes 有 2 个延迟进球。

B = B{-1.0Inf .. 1.0Inf}
A = A{-1.0Inf .. 1.0Inf}
There are 2 delayed goals.

要解决这个问题,您需要至少绑定AB之一。例如,如果您 运行 此查询 A::1..1000, B#=A+1, B #= A*2.,您将获得与示例中第一个查询相同的结果。而且,clpfd 中没有任何推论来解决回溯方法中使用的传递性。

总之,这是您使用的库的缺点之一,因为当具有多个变量的约束域具有无限域时,它将停止,您可以通过设置一个来解决它至少一个变量的有界域。