在clpfd中制定二次方程

时间:2014-03-25 17:36:52

标签: prolog quadratic clpfd

CLPFD系统主要不是为了有效处理二次方程,但是,是否有更好的方法来制定如下问题?

似乎问题归结为如下方程​​式。 SWI library(clpfd)给出了:

?- time( ((L+7)^2#=L^2+189, L in 0..10000000) ).
% 252,169,718 inferences, 87208.554 CPU in 87445.038 seconds (100% CPU, 2892 Lips)
ERROR: Out of local stack

但现在the latest version in SWI给出了

?- time( ((L+7)^2#=L^2+189, L in 0..10000000) ).
% 3,805,545,940 inferences, 868.635 CPU in 870.311 seconds (100% CPU, 4381063 Lips)
L = 10.

在SICStus 4.3beta7中我得到:

| ?- statistics(runtime,_).
yes
| ?- (L+7)*(L+7)#=L*L+189, L in 0..10000000.
L = 10 ? ;
no
| ?- statistics(runtime,[_,T_ms]).
T_ms = 2550 ? ;
no

1 个答案:

答案 0 :(得分:0)

为了快速解决这个问题,已经具有原始X#= Y ^ 2约束的约束求解器也可能实现以下规则:

规则#1:

X #= (Y+C)^2 --> H #= Y^2, X #= H + 2*C*Y + C^2
% where C is an integer and X,Y variables

规则#2:

X #= Z^2, Y #= Z^2 --> X #= Z^2, X #= Y.
% where X,Y,Z are variables

上述规则将等式简化为线性方程式,无论如何直接由一个体面的CLP(FD)系统解决。在这里,您可以看到有和没有规则#2的系统之间的区别:

没有规则#2:

?- (L+7)*(L+7) #= L*L+189, stored.
_C #= 140+_B-14*L.
_B #>= 0.
_C #>= 0.
_B #= L*L.
_C #= L*L.
Yes

使用规则#2:

?- (L+7)*(L+7) #= L*L+189, stored.
L = 10
?- statistics(time, S), (L+7)*(L+7) #= L*L+189, statistics(time, T), U is T-S.
U = 3

但是规则#2对我来说有点特别。还不确定是否应该保留它。

再见