CLP(FD) 和 dif/2 中的重复约束
Duplicate constraints in CLP(FD) and with dif/2
在 SWI-Prolog 中,以下查询给出此结果:
?- X mod 2 #= 0, X mod 2 #= 0.
X mod 2#=0,
X mod 2#=0.
虽然正确,但显然不需要第二个约束
同样:
?- dif(X,0), dif(X,0).
dif(X, 0),
dif(X, 0).
有没有办法避免这种重复约束? (显然最正确的方法是不编写导致这种情况的代码,但这并不总是那么容易)。
您可以避免发布冗余约束,或者使用类似于 setof/3
的结构来删除它们。两者都是非常具体的实现。 SICStus 提供了用于此目的的最佳界面。 YAP 或 SWI 等其他实现或多或少地复制了该接口,通过省略 . A recent attempt 来克服 SWI 的缺陷而被拒绝。
避免发布限制
在 SICStus 中,您可以使用 frozen/2
来达到这个目的:
| ?- dif(X,0), frozen(X,Goal).
Goal = prolog:dif(X,0),
prolog:dif(X,0) ? ;
no
| ?- X mod 2#=0, frozen(X, Goal).
Goal = clpfd:(X in inf..sup,X mod 2#=0),
X mod 2#=0,
X in inf..sup ? ;
no
否则,copy_term/3
可能就足够了,前提是约束之间没有太多相互关联。
消除冗余约束
在这里,类似 setof 的构造与 call_residue_vars/1
and copy_term/3
一起可能是最好的方法。同样,原始实现在 SICStus 中....
很少有约束规划系统实现收缩也与解析定理证明中的因子相关,因为CLP标签不是SMT. Contraction is a structural rule,它的内容如下,假设约束存储在(|-)/2之前否定形式。
G, A, A |- B
------------ (Left-Contraction)
G, A |- B
我们也可以将其扩展到两个 A 可推导等价的情况。这很可能没有实施,因为它很昂贵。例如 Jekejeke Minlog 已经实现了 CLP(FD) 的收缩,即有限域。我们发现查询类似于来自 OP 的第一个查询:
?- use_module(library(finite/clpfd)).
% 19 consults and 0 unloads in 829 ms.
Yes
?- Y+X*3 #= 2, 2-Y #= 3*X.
3*X #= -Y+2
?- X #< Y, Y-X #> 0.
X #=< Y-1
基本上我们分别归一化为 A1*X1+..+An*Xn #= B A1*X1+..+An*Xn #=< B 其中 gcd(A1,..,An)=1 和 X1, ..,Xn 是按词法排序的,然后我们检查约束存储中是否已经存在相同的约束。但是对于 CLP(H),即 Herbrand 域名术语,我们还没有实施收缩。我们还在酝酿一个高效的算法:
?- use_module(library(term/herbrand)).
% 2 consults and 0 unloads in 35 ms.
Yes
?- neq(X,0), neq(X,0).
neq(X, 0),
neq(X, 0)
dif/2 的收缩意味着通过 dif/2 约束中定义的实例化来实现一种 (==)/2 。也就是说,我们需要在 dif/2 约束中定义的变量和项与约束存储中已有的所有其他 dif/2 约束配对之后应用递归测试。测试包容而不是收缩也会更有意义。
可能只有在某些适当的索引技术的帮助下才能为 dif/2 实现收缩或包含。在 Jekejeke Minlog for example for CLP(FD) we index on X1, but we did not yet realize some indexing for CLP(H). What we first might need to figure out is a normal form for the dif/2 constraints, see also this problem here.
仅对于 dif/2
,可以在不借助任何内部结构的情况下测试蕴含:
difp(X,Y) :-
( X \= Y -> true
; dif(X, Y)
).
在 SWI-Prolog 中,以下查询给出此结果:
?- X mod 2 #= 0, X mod 2 #= 0.
X mod 2#=0,
X mod 2#=0.
虽然正确,但显然不需要第二个约束
同样:
?- dif(X,0), dif(X,0).
dif(X, 0),
dif(X, 0).
有没有办法避免这种重复约束? (显然最正确的方法是不编写导致这种情况的代码,但这并不总是那么容易)。
您可以避免发布冗余约束,或者使用类似于 setof/3
的结构来删除它们。两者都是非常具体的实现。 SICStus 提供了用于此目的的最佳界面。 YAP 或 SWI 等其他实现或多或少地复制了该接口,通过省略
避免发布限制
在 SICStus 中,您可以使用 frozen/2
来达到这个目的:
| ?- dif(X,0), frozen(X,Goal).
Goal = prolog:dif(X,0),
prolog:dif(X,0) ? ;
no
| ?- X mod 2#=0, frozen(X, Goal).
Goal = clpfd:(X in inf..sup,X mod 2#=0),
X mod 2#=0,
X in inf..sup ? ;
no
否则,copy_term/3
可能就足够了,前提是约束之间没有太多相互关联。
消除冗余约束
在这里,类似 setof 的构造与 call_residue_vars/1
and copy_term/3
一起可能是最好的方法。同样,原始实现在 SICStus 中....
很少有约束规划系统实现收缩也与解析定理证明中的因子相关,因为CLP标签不是SMT. Contraction is a structural rule,它的内容如下,假设约束存储在(|-)/2之前否定形式。
G, A, A |- B
------------ (Left-Contraction)
G, A |- B
我们也可以将其扩展到两个 A 可推导等价的情况。这很可能没有实施,因为它很昂贵。例如 Jekejeke Minlog 已经实现了 CLP(FD) 的收缩,即有限域。我们发现查询类似于来自 OP 的第一个查询:
?- use_module(library(finite/clpfd)).
% 19 consults and 0 unloads in 829 ms.
Yes
?- Y+X*3 #= 2, 2-Y #= 3*X.
3*X #= -Y+2
?- X #< Y, Y-X #> 0.
X #=< Y-1
基本上我们分别归一化为 A1*X1+..+An*Xn #= B A1*X1+..+An*Xn #=< B 其中 gcd(A1,..,An)=1 和 X1, ..,Xn 是按词法排序的,然后我们检查约束存储中是否已经存在相同的约束。但是对于 CLP(H),即 Herbrand 域名术语,我们还没有实施收缩。我们还在酝酿一个高效的算法:
?- use_module(library(term/herbrand)).
% 2 consults and 0 unloads in 35 ms.
Yes
?- neq(X,0), neq(X,0).
neq(X, 0),
neq(X, 0)
dif/2 的收缩意味着通过 dif/2 约束中定义的实例化来实现一种 (==)/2 。也就是说,我们需要在 dif/2 约束中定义的变量和项与约束存储中已有的所有其他 dif/2 约束配对之后应用递归测试。测试包容而不是收缩也会更有意义。
可能只有在某些适当的索引技术的帮助下才能为 dif/2 实现收缩或包含。在 Jekejeke Minlog for example for CLP(FD) we index on X1, but we did not yet realize some indexing for CLP(H). What we first might need to figure out is a normal form for the dif/2 constraints, see also this problem here.
仅对于 dif/2
,可以在不借助任何内部结构的情况下测试蕴含:
difp(X,Y) :-
( X \= Y -> true
; dif(X, Y)
).