简体   繁体   English

SWI-Prolog和约束,库CLP(FD)

[英]SWI-Prolog and constraints, library CLP(FD)

I'm playing around with constraints in (swi) prolog using the clpfd library. 我正在使用clpfd库来处理(swi)序言中的约束。

I'm trying to identify when one set of constraints encapsulates or subsumes the other, eg X<4 encapsulates X<7 as whenever the former is true, the latter is true. 我试图确定一组约束何时封装或包含另一组约束,例如X <4封装X <7,只要前者为真,后者为真。 This can be easily represented using logical implication. 使用逻辑含义可以很容易地表示出来。 However, I couldn't get the #==> operator to give me the result I wanted, so I resorted to using not(Co1 #/\\ #\\Co2) where Co1 and Co2 are constraints. 但是,我无法获得#==>运算符来提供所需的结果,因此我求助于使用not(Co1#/ \\#\\ Co2),其中Co1和Co2是约束。 This is fine for individual constraints, but I then wanted to pass a conjunctions of constraints into Co1 and Co2. 这对于单独的约束来说很好,但是我随后想将约束的结合传递到Co1和Co2中。

Now here is the rub. 现在这里是摩擦。 When I try 当我尝试

X#<7 #/\ #\X#<4.

I get back 我回来

X in 4..6,
X+1#=_G822,
X+1#=_G834,
_G822 in 5..7,
_G834 in 5..7.

(oddly enough, doing this in Sicstus results in a segmentation fault) (很奇怪,在Sicstus中执行此操作会导致分段错误)

When I pass in 当我通过时

X#<7,X#<4

I get the desired 我得到了想要的

X in inf..3.

Obviously, I can't pass the latter into not(Co1 #/\\ #\\Co2), but the former doesn't give me the result I want. 显然,我不能将后者传递给not(Co1#/ \\#\\ Co2),但是前者不能给我我想要的结果。 Can anyone explain why the two approaches yield different results, and how I can get the former to act like the latter? 谁能解释为什么两种方法会产生不同的结果,以及我如何才能使前者像后者一样行事?

Subsumption of general arithmetic constraints over the integers is undecidable in general, so all correct solvers have inherent limits beyond which they have to delay their answers until more is known. 一般而言,一般算术约束是否包含在整数上是无法确定的,因此所有正确的求解器都有其固有的局限性,超过这些固有的局限性,他们必须将其答案延迟直到知道更多为止。 If you know your domains to be finite, you can post the domains and then try to find counterexamples that would make the implication invalid, using the constraint solver's labeling/2 predicate. 如果您知道自己的域是有限的,则可以发布这些域,然后尝试使用约束求解器的labeling / 2谓词查找使蕴涵无效的反例。 Consider also that linear inequalities over Q are decidable, and that SWI-Prolog's library(clpq) is complete for them. 还考虑Q上的线性不等式是可确定的,并且SWI-Prolog的库(clpq)已为它们完成。 You can thus try your constraints in CLP(Q) with: 因此,您可以使用以下方法在CLP(Q)中尝试约束:

?- use_module(library(clpq)).
true.

?- { X < 4, X >= 7 }.
false.

and see that no such counterexample exists in Q (hence also not in Z), and thus the implication holds. 并且看到在Q中没有这样的反例(因此在Z中也不存在),因此含义成立。

It seems you are dealing with CLP(FD). 看来您正在处理CLP(FD)。 These solvers distinguish the setup phase and the labeling phase of solving a constraint problem. 这些求解器区分解决约束问题的设置阶段和标记阶段。

A CLP(FD) solver does not completely reduce a problem during the setup phase. 在设置阶段,CLP(FD)求解器不能完全减少问题。 Since it has the chance to reduce variable ranges during the labeling phase. 因为它有机会在贴标阶段减小可变范围。 Thus it could be that during setup a problem is posed which could be reduced by other solvers to "No", but it will not with a CLP(FD) solver. 因此,可能是在设置过程中出现了一个问题,可以通过其他求解器将其减少为“否”,但对于CLP(FD)求解器则不会。 Only during labeling a "No" will be detected. 仅在标记过程中会检测到“否”。

How much reduction is done during the setup phase highly depends on the given CLP(FD) system. 在设置阶段完成多少减少工作很大程度上取决于给定的CLP(FD)系统。 Some CLP(FD) systems do more reduction during the setup phase, while other do less. 某些CLP(FD)系统在设置阶段可做更多的减少,而其他系统则做得更少。 GNU Prolog for example uses some indexical propagation, whereas SWI Prolog does not. 例如,GNU Prolog使用一些索引传播,而SWI Prolog不使用。 So we find for example, not your example: 因此,我们找到了一个例子,而不是您的例子:

SWI-Prolog: SWI-Prolog:

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

GNU Prolog: GNU序言:

?- X #< Y, Y #< Z, Z #< X.
(7842 ms) no

Further since you are using reified constraints it also depends a little bit how clever the reification is done. 此外,由于您使用的是约束化约束,因此它还取决于实现约束的巧妙程度。 But I guess in the present case its only a matter of propagation. 但我想在目前情况下,这仅是传播问题。 We find now for your example: 现在为您的示例查找:

SWI-Prolog: SWI-Prolog:

?- X #< 4 #==> X #< 7.
X+1#=_G1330,
X+1#=_G1342,
7#>=_G1330#<==>_G1354,
_G1354 in 0..1,
_G1377#==>_G1354,
_G1377 in 0..1,
4#>=_G1342#<==>_G1377.

GNU Prolog: GNU序言:

?- X #< 4 #==> X #< 7.
X = _#22(0..268435455)

There is a tradeoff between doing more reduction in the setup phase and leaving more work to the labeling phase. 在设置阶段进行更多的缩减与标签阶段进行更多的工作之间需要权衡。 And the whole matter also depends on the given example. 整个问题还取决于给定的示例。 But when you have also labeling beside setup, you will not see any difference in terms of outcome: 但是,当您还在设置旁边贴上标签时,您将看不到任何结果方面的差异:

SWI-Prolog: SWI-Prolog:

?- X in 0..9, X #< 4 #==> X #< 7, label([X]).
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5 ;
X = 6 ;
X = 7 ;
X = 8 ;
X = 9.

GNU Prolog: GNU序言:

?- fd_domain(X,0,9), X #< 4 #==> X #< 7, fd_labeling([X]).
X = 0 ? ;
X = 1 ? ;
X = 2 ? ;
X = 3 ? ;
X = 4 ? ;
X = 5 ? ;
X = 6 ? ;
X = 7 ? ;
X = 8 ? ;
X = 9

I didn't test with SICStus Prolog or B-Prolog. 我没有使用SICStus Prolog或B-Prolog进行测试。 But I guess they will behave somewhere in the vincinity of SWI-Prolog and GNU Prolog. 但是我想它们将在SWI-Prolog和GNU Prolog的杰出表现中表现出来。

CLP(Q) is no real alternative if your domain is really FD, since it will miss some "No" reductions, which CLP(FD) would not miss. 如果您的域是FD,则CLP(Q)并不是真正的替代选择,因为它会错过某些“ No”减少,而CLP(FD)不会错过。 For example the following is unsatisfiable in CLP(FD), but satisfiable in CLP(Q): 例如,以下内容在CLP(FD)中无法满足,但在CLP(Q)中可以满足:

X = Y + 1, Y < Z, Z < X.

Bye 再见

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM