什么会导致Prolog在比赛中取得成功,但在被要求标记输出时失败?

时间:2011-11-07 04:03:45

标签: prolog gnu-prolog

我试图用Prolog解决a logic puzzle作为学习练习,我想我已经使用GNU Prolog有限域解算器正确地映射了问题。

当我运行求解函数时,Prolog会回吐:是和一个变量列表都在0..1范围内(布尔值,因为我对它们进行了约束)。问题是,当我尝试添加一个fd_labeling(Solution)子句时,Prolog关于faces并吐出:no。

我是这种语言的新手,我似乎无法找到任何攻击过程来弄清楚为什么一切似乎都有效,直到我真的要求它标注答案...

2 个答案:

答案 0 :(得分:4)

显然,您没有“正确”将问题映射到FD,因为当您尝试标记变量时,您会收到“否”。

你在Constraint Logic Programming中做的是设置一个约束模型,你有一个带域的变量(在你的情况下是带有域[0,1]的布尔值),以及这些变量之间的一些约束。每个约束都有一个传播规则,试图实现发布约束的变量域的一致性。从域中删除不一致的值。有几种类型的一致性,但它们有一个共同点:约束通常不会为您提供完整的解决方案,甚至可以告诉您是否存在约束模型的解决方案。

作为一个例子,假设你有两个变量X和Y,都有域[1..10],约束X< Y.然后传播规则将从Y的域中删除值1并从X的域中删除10.然后它将停止,因为域现在是一致的:对于一个域中的每个值,在另一个域中存在值域,以便满足约束。

为了获得解决方案(所有变量都绑定到值),您需要标记变量。每个标记都会唤醒附加到标记变量的约束,从而触发另一轮传播。这将导致一个解决方案(所有变量绑定到值,回答:是)或失败(在搜索树的每个分支中,某个变量以空域结束,回答:否)

由于每个约束仅旨在使其所发布的变量的域的一致性,因此在传播阶段期间不会检测到由约束组合引起的不可行性。例如,具有域[1..2]的三个变量X,Y,Z和成对不等式约束。这似乎与您的约束模型有关。

如果您确定必须有解决方案,那么您的约束模型包含一些不可行性。也许对这些约束的敏锐观察已足以发现它。

如果您没有看到任何明显的不可行性(例如,某些矛盾的约束,如上面的不等式示例),您需要调试您的程序。如果可能,请不要使用内置的标签谓词,而是编写自己的标签谓词。然后你可以添加一些输出谓词,它允许你跟踪实例化的变量以及由此引起的布尔决策变量的变化或是否导致失败。

答案 1 :(得分:3)

(@ twinterer已经给出了解释,我的回答试图从不同的角度来看)

当您向Prolog输入查询时,您获得的是答案。通常答案包含解决方案,有时它包含多个解决方案,有时它根本不包含任何解决方案。这两个概念经常混淆。让我们看看GNU Prolog的例子:

| ?- length(Vs,3), fd_domain_bool(Vs).                                       

Vs = [_#0(0..1),_#19(0..1),_#38(0..1)]

yes

在这里,我们有一个包含8个解决方案的答案。那就是:

| ?- length(Vs,3), fd_domain_bool(Vs), fd_labeling(Vs).

Vs = [0,0,0] ? ;

Vs = [0,0,1] ? ;

...

Vs = [1,1,1]

yes

现在另一个查询。这就是@twinterer提到的例子。

| ?- length(Vs,3), fd_domain_bool(Vs), fd_all_different(Vs).

Vs = [_#0(0..1),_#19(0..1),_#38(0..1)]

yes

答案与以前一样。但是,它不再包含解决方案。

| ?- length(Vs,3), fd_domain_bool(Vs), fd_all_different(Vs), fd_labeling(Vs).

no

理想情况下,在这种情况下,顶级不会说“是”而是“可能”。实际上,CLP(R)是最早的约束系统之一,它就是这样做的。

使这一点变得不那么神秘的另一种方法是显示所涉及的实际约束。 SWI这样做:

?- length(Vs,3), Vs ins 0..1, all_different(Vs).
Vs = [_G565,_G568,_G571],
_G565 in 0..1,
all_different([_G565,_G568,_G571]),
_G568 in 0..1,
_G571 in 0..1.

?- length(Vs,3), Vs ins 0..1, all_different(Vs), labeling([], Vs).
false.

因此,SWI向您展示了为获得具体解决方案而必须满足的所有约束。阅读SWI的答案为:是的,有一个解决方案,只要所有这些精美的印刷品都是真的! 唉,细则是假的。

另一种解决此问题的方法是使all_different/1的实现具有更强的一致性。但这仅适用于特定情况。

?- length(Vs,3), Vs ins 0..1, all_distinct(Vs).
false.

在一般情况下,您不能指望系统保持全局一致性。原因:

  • 保持一致性可能非常昂贵。将这些决定委托给标签通常会更好。事实上,简单的all_different/1通常比all_distinct/1更快。

  • 更好的一致性算法通常非常复杂。

  • 在一般情况下,维持全球一致性是一个不可判定的问题。