bagof / 3 непредсказуемо - PullRequest
0 голосов
/ 01 марта 2019

Я сбит с толку следующими результатами.Я использую 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]].

1 Ответ

0 голосов
/ 19 августа 2019

Это артефакт SWI-Prolog, который также копирует атрибутивные переменные при получении findall / 3 копии.findall / 3 копии используются внутри bagof / 3 перед выполнением сортировки ключей / 2.Но эффект уже можно объяснить с помощью 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 есть не только шаг сортировки ключей / 2, но и шаг восстановления переменных.На этом этапе для SWI-Prolog ограничения могут быть объединены, так как ограничения будут присутствовать.

Это объясняет первый результат в вопросе OP.Второй результат в вопросе OP можно объяснить тем, что SWI-Prolog выполняет расширение цели и вводит новые переменные в случае (# = <) / 2.Вы можете проверить себя: </p>

?- [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 увидеть два решения вместо одного.</p>

Редактировать 19.08.2019:
Теперь мне интересно, как таблинг с помощью CLP (FD) решает проблему ...

...