Prolog CLPFD可传递性

时间:2019-05-09 00:18:25

标签: prolog clpfd

“显而易见”这个词并不容易,但是为什么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。)

仅仅是……求解器没有发现这种情况? (我肯定会期望它会应用传递性。)或者这是一些更深的语法难题的征兆,还是什么?

1 个答案:

答案 0 :(得分:3)

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

这意味着它试图找到约束B #= A + 1的某种解决方案,但发现了很多(AB的无穷大),第二个约束也相同。因此,此处将停止,因为AB的可能值是无限的。但是,结果不是No。这是Yes,有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中没有任何推论可以解决传递性,因为它是通过回溯方法使用的。

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