什么会导致Prolog在匹配中成功,但在要求标记输出时失败?
作为一个学习练习,我正在尝试用Prolog解决问题,我认为我已经使用GNU Prolog有限域求解器正确地映射了这个问题 当我运行solve函数时,Prolog返回:yes和一个变量列表,所有变量都在0..1范围内(布尔值,因为我限制了它们)。问题是,当我试图添加一个fd_标签(解决方案)子句时,Prolog关于faces并抛出:no 我是这门语言的新手,在我真正要求它标注答案之前,我似乎找不到任何攻击途径来找出为什么一切似乎都有效…显然,你没有“正确”地将问题映射到FD,因为当你尝试标注变量时,你会得到一个“否” 在约束逻辑编程中,您要做的是建立一个约束模型,其中有一个域的变量(在您的例子中,域[0,1]为布尔值),以及这些变量之间的许多约束。每个约束都有一个传播规则,该规则尝试实现发布约束的变量域的一致性。不一致的值将从域中删除。有几种类型的一致性,但它们有一个共同点:约束本身通常不会给出完整的解决方案,甚至不会告诉您约束模型是否有解决方案 例如,假设您有两个变量X和Y,都有域[1..10],约束X什么会导致Prolog在匹配中成功,但在要求标记输出时失败?,prolog,gnu-prolog,Prolog,Gnu Prolog,作为一个学习练习,我正在尝试用Prolog解决问题,我认为我已经使用GNU Prolog有限域求解器正确地映射了这个问题 当我运行solve函数时,Prolog返回:yes和一个变量列表,所有变量都在0..1范围内(布尔值,因为我限制了它们)。问题是,当我试图添加一个fd_标签(解决方案)子句时,Prolog关于faces并抛出:no 我是这门语言的新手,在我真正要求它标注答案之前,我似乎找不到任何攻击途径来找出为什么一切似乎都有效…显然,你没有“正确”地将问题映射到FD,因为当你尝试标注变量时
| ?- 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),最早的约束系统之一,做到了这一点
另一种使这一点不那么神秘的方法是显示所涉及的实际约束。威斯康辛州投资局这样做:
?- 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的回答解读为:是的,有一个解决方案,前提是所有这些细节都是真实的!
唉,这些细节是错误的
解决这个问题的另一种方法是获得一致性更强的所有不同/1
的实现。但这只适用于特定情况
?- length(Vs,3), Vs ins 0..1, all_distinct(Vs).
false.
在一般情况下,您不能期望系统保持全局一致性。原因:
- 保持一致性可能非常昂贵。通常最好将此类决策委托给标签部门。事实上,简单的
通常比all_distinct/1
快all_distinct/1
- 更好的一致性算法通常非常复杂
- 在一般情况下,保持全局一致性是一个无法确定的问题