Дизъюнкция G1; G2 против If-then-else Cond -> G1; G2 - PullRequest
3 голосов
/ 06 июня 2019

Я столкнулся с программой Prolog, содержащей вложенное условие if-then-else в форме

p(X,Y) :-
     (cond1(X,Y) -> q(X)); true,
     (cond2(X,Y) -> q(Y)); true.

с неожиданными ответами.Причина такого поведения та же, что и в следующих запросах:

?- (true, (true -> X=a)); X=b.
X = a ;
X = b.

?- ((true -> X=a), true); X=b.
X = a ;
X = b.

?- (true -> X=a); X=b.
X = a.

Первый запрос имеет два ответа, а второй - только один.В чем причина разного поведения?

PS: я знаю разницу, но я не нашел ТАК вопрос, который касается этого довольно запутанного явления.Так почему бы не зафиксировать это таким образом?

Ответы [ 2 ]

2 голосов
/ 08 июня 2019

По поводу прослеживаемости дизъюнкции.Эти два запроса структурно различаются:

trace, (true -> X=a); X=b.

trace, ((true -> X=a); X=b).

Вы можете использовать write_canonical / 1, чтобы увидеть разницу:

?- write_canonical((trace, (true -> X=a); X=b)), nl.
;(','(trace,->(true,=(A,a))),=(A,b))
true.

?- write_canonical((trace, ((true -> X=a); X=b))), nl.
','(trace,;(->(true,=(A,a)),=(A,b)))
true.

И они также ведут себя по-разному:

?- trace, (true -> X=a); X=b.
   Call: (9) true ? creep
   Exit: (9) true ? creep
   Call: (9) _428=a ? creep
   Exit: (9) a=a ? creep
X = a 
   Call: (9) _428=b ? creep
   Exit: (9) b=b ? creep
X = b.

[trace]  ?- trace, ((true -> X=a); X=b).
   Call: (9) true ? creep
   Exit: (9) true ? creep
   Call: (9) _706=a ? creep
   Exit: (9) a=a ? creep
X = a.

Только второй запрос будет проверен (true -> X = a);Х = Ь.

0 голосов
/ 07 июня 2019

Сначала давайте обратимся к исходному предикату: форматирование предполагает вложенный if-then-else, но круглые скобки вокруг второй группы тел первой true в ветвь else:

?- listing(p).
p(A, B) :-
    (   cond1(A, B)
    ->  q(A)
    ;   true,
        (   cond2(A, B)
        ->  q(B)
        )
    ;   true
    ).

Вот какмы заканчиваем запросами, начинающимися с true, ....Вторая проблема здесь заключается в том, что использование ; перегружено: термин формы G1; G2 интерпретируется как дизъюнкция, только если G1 не имеет формы (Cond -> Goal).В противном случае это интерпретируется как если-то-еще.Давайте рассмотрим различные случаи:

  • (true, true -> X=a); X=b интерпретирует ; как дизъюнкцию, потому что самый внешний функтор с левой стороны является соединением ,.Пролог сообщает о замене ответа для каждой ветви.
  • (true -> X=a, true); X=b: это дизъюнкция по той же причине
  • (true -> X=a); X=b: это if-then-else, потому что самый внешний функтор слевасо стороны - оператор if-then ->.Пролог сообщает только о замене ответа для ветви true.

Интересно, что когда мы помещаем условие в переменную, это больше не работает (на SWI 8):

?- G1 = (true -> (X = a)), (G1 ; X=b).
G1 =  (true->a=a),
X = a ;
G1 =  (true->b=a),
X = b.

То же самое происходит, когда я заключаю G1 в call/1:

?- G1 = (true -> (X = a)), (call(G1) ; X=b).
G1 =  (true->a=a),
X = a ;
G1 =  (true->b=a),
X = b.

Если я правильно прочитал ответ на предыдущий вопрос, первый долженбыть другим.

Я бы предположил, что различное поведение трассировки заключается в том, что точки останова мешают обнаружению if-then-else. Моя ошибка во время трассировки состояла в том, что вы нажали enter, чтобы подкрастьсяно не понял, что мне нужно было ввести ;, когда был получен фактический ответ.

...