clpfd中具有reification的残差约束

时间:2015-05-06 06:26:45

标签: prolog swi-prolog clpfd

我定义了改进的变体 clpfd约束(#<)/2(#=<)/2(#>=)/2(#>)/2

:- use_module(library(clpfd)).

ltA(X,Y,Truth)  :- X #<  Y #<==> B, bool01_truth(B,Truth).
ltB(X,Y, true)  :- X #<  Y.
ltB(X,Y,false)  :- X #>= Y.

lteA(X,Y,Truth) :- X #=< Y #<==> B, bool01_truth(B,Truth).
lteB(X,Y, true) :- X #=< Y.
lteB(X,Y,false) :- X #>  Y.

gteA(X,Y,Truth) :- X #>= Y #<==> B, bool01_truth(B,Truth).
gteB(X,Y, true) :- X #>= Y.
gteB(X,Y,false) :- X #<  Y.

gtA(X,Y,Truth)  :- X #>  Y #<==> B, bool01_truth(B,Truth).
gtB(X,Y, true)  :- X #>  Y.
gtB(X,Y,false)  :- X #=< Y.

当然,ltA/3ltB/3 逻辑等效lteA/3lteB/3gteA/3gteB/3以及gtA/3gtB/3

然而,我使用这些谓词得到的答案在大小和可读性上有所不同。我使用SWI-Prolog 7.1.37运行了以下查询:

好消息,首先!

?- lteA(X,Y,Truth).
Truth = false, Y#=<X+ -1 ;
Truth = true,  Y#>=X.
?- lteB(X,Y,Truth).
Truth = true,  Y#>=X ;
Truth = false, Y#=<X+ -1.

?- gteA(X,Y,Truth).
Truth = false, X#=<Y+ -1 ;
Truth = true,  X#>=Y.
?- gteB(X,Y,Truth).
Truth = true,  X#>=Y ;
Truth = false, X#=<Y+ -1.

好的!但是其他两个呢?

?- ltA(X,Y,Truth).
Truth = false, X+1#=_G968, Y#=<_G968+ -1 ;
Truth = true,  X+1#=_G912, Y#>=_G912.
?- ltB(X,Y,Truth).
Truth = true,  X#=<Y+ -1 ;
Truth = false, X#>=Y.

?- gtA(X,Y,Truth).
Truth = false, X#=<_G1301+ -1, Y+1#=_G1301 ;
Truth = true,  X#>=_G1243,     Y+1#=_G1243.
?- gtB(X,Y,Truth).
Truth = true,  Y#=<X+ -1 ;
Truth = false, Y#>=X.

不完全!

如何使用ltA/3gtA/3获得紧凑的答案---就像lteA/3gteA/3一样?

1 个答案:

答案 0 :(得分:0)

它违背了CLP(FD)的基本思想 答案。由于CLP(FD)通常不做高斯消除和 类似的事情。它不像计算机代数系统(CAS)。

在CLP(FD)中,您通过输入基本上为您的问题建模 不公平,系统不允许这样做 只要你不打电话labeling,就会出现不公平。

某些CLP(FD)实现已经检查了一些的一致性 输入不等式和/或已经简化的程度 和传播。但这不是强制性的。

在你的例子中,你有E#= X,其中E是一个表达式 X是一个变量。无法保证发生 当进入模型时,X被E替换。

通常这不是在CLP(FD)中完成的,因为它会爆炸 输入的模型。你可以直接测试一下 没有简化:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.4)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).
true.
?- A#=X+1, Y#=<A+ -1.
Y#=<A+ -1,
X+1#=A.

Jekejeke Prolog也是如此。 CLP(FD) Jekejeke Prolog是开源的here。改造本身 计划但尚未实施:

Jekejeke Prolog, Runtime Library 1.0.7
(c) 1985-2015, XLOG Technologies GmbH, Switzerland
?- use_module(library(finite/clpfd)).
% 11 consults and 0 unloads in 513 ms.
Yes
?- A#=X+1, Y#=<A+ -1.
A #= 1+X,
-1+A #>= Y

典型的等式E#= X只会导致替换 E也是变量或常数。这可能解释了为什么你的 例子看起来有所不同。

在这里你看到SWI-Prolog简化了A#= X.我刚修改过 稍微上面的例子,以便E是一个变量:

?- A#=X, Y#=<A+ -1.
A = X,
Y#=<X+ -1.

在这里你看到Jekejeke Prolog正在做这件事(Todo bug fix:I 我想我需要重新排序规则,以便它 在这里给出A = X而不是X = A):

?- A#=X, Y#=<A+ -1.
X = A,
-1+A #>= Y

E#= X的情况,其中E是常数,在这里 传播的值称为前向检查。这是 CLP(FD)必须能够做到的最低要求,否则 标签不起作用。

但已经是E#= X的情况,其中E是变量a 传播不是强制性的。但上面的测试显示 很多CLP(FD)都这样做。传播变量导致 联合查找算法等。

再见