【发布时间】:2019-03-01 16:46:35
【问题描述】:
我对以下结果感到困惑。我正在使用 SWI-Prolog。
?- bagof(Q, (Q=A, (A=[a,_] ; A=[_,b])), X).
A = [_G16898, b],
X = [[_G16898, b]] ;
A = [a, _G16892],
X = [[a, _G16892]].
请注意,[a,_] 和 [_,b] 没有统一生成答案 A = [a,b], X=[[a,b],[a,b]]。
现在,让我们尝试使用算术约束:
?- bagof(Q, (Q=A, (A in 1..5 ; A in 3..8)), X).
X = [A, A],
A in 3..5.
奇怪的是,这一次算术约束被放在一起,但没有答案A in 1..5, X=[A] 和A in 3..8, X=[A]。
现在让我们用另一种方式试试这个:
?- bagof(Q, (Q=A, ((1 #=< A, A #=< 5) ; (3 #=< A, A #=< 8))), X).
X = [A],
A in 3..5 ;
X = [A],
A in 3..5.
算术约束像以前一样组合在一起,但我们有两个答案而不是一个。
如何解释这一切?
编辑:一些更奇怪的结果。比较一下:
?- A=[_,_], bagof(Q, K1^K2^(Q=A, (A=[a,K1] ; A=[K2,b])), X).
A = [_G16886, b],
X = [[_G16886, b]] ;
A = [a, _G16889],
X = [[a, _G16889]].
用这个:
?- A=[a,b], bagof(Q, K1^K2^(Q=A, (A=[a,K1] ; A=[K2,b])), X).
A = [a, b],
X = [[a, b], [a, b]].
【问题讨论】:
-
我想你的意思是这个分号是一个逗号:
(A=[a,_] , A=[_,b])。用分号表示 A 是一个以 a 开头或以 b 结尾的两项列表,而不是两者。我不知道 clpfd 为什么/如何能够结合这些约束。 -
不,我的意思是分号。我知道,它看起来很奇怪......这段代码不是来自真实程序。我只是想了解这个谓词应该如何工作。
-
你的第一个结果是有道理的。最后一个比较
A=[_,_]约束行为与A=[a,b]也是如此。在这些情况下你会期待什么?在您的最后一个中,您限制了A=[a,b],因此结果必然是A=[a,b]和A = [[a,b], [a,b]](bagof只有两个不同的替代方案)。 CLP(FD) 的例子很有趣,也是唯一让我第一眼感到惊讶的例子,我需要考虑一下。至少in/2和#=</2与#>=/2的行为是一致的。 -
我在 SWI Prolog 和 Gnu Prolog 中都使用了 CLP(FD) 案例,得到了不同的结果。在 SWI 中,我得到了你展示的结果。在 Gnu Prolog 中,结果取决于
;/2! 中参数的顺序!所以如果我查询,bagof(A, (Q=A, ((1 #=< A, A #=< 5) ; (3 #=< A, A #=< 8))), X).我会得到X = [_#2098023(1..5),_#2098023(1..5)]。如果我查询,bagof(A, (Q=A, ((1 #=< A, A #=< 5) ; (3 #=< A, A #=< 8))), X).我得到,X = [_#2098023(3..8),_#2098023(3..8)]!有些东西告诉我 CLP(FD) 和bagof/3在这里混合得不好。 -
尽量避免混合约束和 bagof/setof/3
标签: prolog prolog-setof