我定义了改进的变体
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/3
和ltB/3
逻辑等效,
lteA/3
和lteB/3
,gteA/3
和gteB/3
以及gtA/3
和gtB/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/3
和gtA/3
获得紧凑的答案---就像lteA/3
和gteA/3
一样?
答案 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)都这样做。传播变量导致 联合查找算法等。
再见