我对以下结果感到困惑。我正在使用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]].
答案 0 :(得分:1)
这是SWI-Prolog的人工制品,它在复制findall / 3副本的同时也复制属性变量。在执行keysort / 2之前,在bagof / 3内使用findall / 3副本。但是效果已经可以通过findall / 3来解释:
SWI-Prolog,findall / 3个副本归因变量条件:
?- findall(A, A in 1..5, L).
L = [_3464],
_3464 in 1..5.
?- findall(A, (A in 1..5, (true; true)), L).
L = [_3762, _3768],
_3762 in 1..5,
_3768 in 1..5
Jekejeke Prolog,findall / 3不复制属性变量条件:
?- findall(A, A in 1..5, L).
L = [_A]
?- findall(A, (A in 1..5, (true; true)), L).
L = [_A, _B]
在bagof / 3内,不仅有keysort / 2步骤,而且还有还原变量的步骤。在SWI-Prolog的此步骤中,可能会存在约束,因为会存在约束。
这说明了OP问题中的第一个结果。 OP问题中的第二个结果可以解释为:SWI-Prolog在(#= <)/ 2的情况下进行目标扩展并引入新变量。您可以检查一下自己:
?- [user].
test(A) :- A in 1..5 ; A in 3..8.
test(A) :- (1 #=< A, A #=< 5) ; (3 #=< A, A #=< 8).
?- listing(test/1).
test(A) :-
( ( integer(A)
-> between(1, 5, A)
; clpfd:clpfd_in(A, 1..5)
)
; integer(A)
-> between(3, 8, A)
; clpfd:clpfd_in(A, 3..8)
).
test(A) :-
( ( integer(A)
-> A>=1
; B=1,
clpfd:clpfd_geq(A, B)
),
( integer(A)
-> 5>=A
; C=5,
clpfd:clpfd_geq(C, A)
)
; ( integer(A)
-> A>=3
; D=3,
clpfd:clpfd_geq(A, D)
),
( integer(A)
-> 8>=A
; E=8,
clpfd:clpfd_geq(E, A)
)
).
(in)/ 2的扩展中没有新鲜的变量。但是我猜想(#= <)/ 2扩展内的新鲜变量会导致bagof / 3看到两个解决方案,而不是一个。
编辑19.08.2019:
现在,我想知道使用CLP(FD)进行制表如何解决该问题...