【问题标题】:bagof/3 is unpredictablebagof/3 是不可预测的
【发布时间】: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#=&lt;/2#&gt;=/2的行为是一致的。
  • 我在 SWI Prolog 和 Gnu Prolog 中都使用了 CLP(FD) 案例,得到了不同的结果。在 SWI 中,我得到了你展示的结果。在 Gnu Prolog 中,结果取决于 ;/2! 中参数的顺序!所以如果我查询,bagof(A, (Q=A, ((1 #=&lt; A, A #=&lt; 5) ; (3 #=&lt; A, A #=&lt; 8))), X). 我会得到X = [_#2098023(1..5),_#2098023(1..5)]。如果我查询,bagof(A, (Q=A, ((1 #=&lt; A, A #=&lt; 5) ; (3 #=&lt; A, A #=&lt; 8))), X). 我得到,X = [_#2098023(3..8),_#2098023(3..8)]!有些东西告诉我 CLP(FD) 和 bagof/3 在这里混合得不好。
  • 尽量避免混合约束和 bagof/setof/3

标签: prolog prolog-setof


【解决方案1】:

这是 SWI-Prolog 的人工制品,它在获取 findall/3 副本时也会复制属性变量。 findall/3 副本在进行 keysort/2 之前在 bagof/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 step,还有恢复变量的step。在 SWI-Prolog 的这一步中,可能会加入约束,因为会存在约束。

这解释了 OP 问题的第一个结果。 OP 问题的第二个结果可以解释为 SWI-Prolog 在 (#=

?- [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 的展开没有新的变量。但我猜 (#=

编辑 19.08.2019:
现在我想知道使用 CLP(FD) 的制表如何解决这个问题......

【讨论】:

    猜你喜欢
    • 2021-10-20
    • 1970-01-01
    • 2021-01-05
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多