ОШИБКА: вне локального стека в моем коде Prolog

Я не могу понять, почему следующий запрос из данного кода Пролога генерирует ошибку Out of local stack.

Пролог-код:

likes(g,c).
likes(c,a).
likes(c,b).
likes(b,a).
likes(b,d).

likes(X,Z) :- likes(X,Y), likes(Y,Z).

запрос

?- likes(g,X).

приводит к

X = c ;
X = a ;
X = b ;
ERROR: Out of local stack

Редактировать 1 Вот как я думаю, что Пролог должен обрабатывать этот запрос,

likes(g,c) is a fact, so X={c}
likes(g,b) <= likes(g,c) and likes(c,b), so X={c,b}
likes(g,a) <= likes(g,b) and likes(b,a), so X={c,b,a}
likes(g,d) <= likes(g,b) and likes(b,d), so X={c,b,a,d}
              likes(g,a) and false, so nothing to add to X
              likes(g,d) and false, so nothing to add to X 
end of backtracking search.

Редактировать 2 Мне удалось получить то, что я искал, с помощью следующей модификации кода:

likes(g,c).
likes(c,a).
likes(c,b).
likes(b,a).
likes(b,d).

indirect_likes(A,B):- likes(A,B).
indirect_likes(A,C):- likes(B,C), indirect_likes(A,B).

запрос

?- косвенные_лайки(г,какой).

приводит к

Which = c ;
Which = a ;
Which = b ;
Which = a ;
Which = d ;
false.

Тем не менее, есть еще кое-что, что я не могу понять в обосновании. Если я изменю последнее правило на

indirect_likes(A,C):- indirect_likes(A,B), likes(B,C).

Тогда я получаю ERROR: Out of local stack! Насколько я знаю, логическая конъюнкция коммутативна.


person Rasoul    schedule 07.01.2014    source источник
comment
Где определяется supp/2?   -  person C.B.    schedule 07.01.2014
comment
Чего-то не хватает...   -  person false    schedule 07.01.2014
comment
@C.B. Я только что исправил это. Это часть моего более длинного кода на Прологе.   -  person Rasoul    schedule 07.01.2014
comment
Связано: stackoverflow. ком/вопросы/10360223/   -  person false    schedule 07.01.2014


Ответы (2)


Чтобы получить transitive-close бинарное отношение R_2, используйте meta-predicate closure/3 вот так:

?- closure(R_2,From,To).

Давайте запустим пример запроса closure/3 вместе с likes/2!

?- closure(likes,X,Y).
  X = g, Y = c
; X = g, Y = a
; X = g, Y = b
; X = g, Y = a                    % redundant
; X = g, Y = d
; X = c, Y = a
; X = c, Y = b
; X = c, Y = a                    % redundant
; X = c, Y = d
; X = b, Y = a
; X = b, Y = d
; false.                          % query terminates universally

Мы получаем те же ответы, когда используем indirect_likes/2, но в другом порядке:

?- indirect_likes(X,Y).
  X = g, Y = c
; X = c, Y = a
; X = c, Y = b
; X = b, Y = a
; X = b, Y = d
; X = g, Y = a
; X = g, Y = b
; X = c, Y = a                    % redundant
; X = g, Y = a                    % redundant
; X = c, Y = d
; X = g, Y = d
; false.                          % query terminates universally

Как вы указали в своих комментариях к ответу @CB, бинарные отношения не обязательно рефлексивны и/или симметричны. Согласно данному вами определению, likes/2 не является ни тем, ни другим:

?- likes(X,X).
false.                            % not reflexive (not even close)

?- likes(X,Y), likes(Y,X).
false.                            % not symmetric (not even close)

Пока все хорошо!

Давайте предварительно добавим в вашу базу данных следующий дополнительный факт:

likes(b,b).

С этим расширенным определением indirect_likes/2 ведет себя хаотично:

?- indirect_likes(b,b).
  true
; true
; true
...                               % does not terminate universally

?- indirect_likes(X,Y), false.    % do we get finite failure?
...                               % no! query does not terminate universally

Что мы можем сделать? Давайте воспользуемся мета-предикатом closure/3 с расширенная версия likes/2!

?- closure(likes,b,b).
  true                            % succeeds non-deterministically
; false.                          % query terminates universally

?- closure(likes,X,Y), false.     % do we get finite failure?
false.                            % yes! query terminates universally

Итог?

В чистом Прологе конъюнкция коммутативна, насколько это касается логического смысла.

Из-за разрешения SLD в Прологе цель false,repeat окончательно терпит неудачу, а repeat,false — нет. Программист должен позаботиться о завершении, но обычно это небольшая цена за грубую производительность и контроль, которые предлагает Пролог.

В этом ответе я передал «беспокойство о прекращении» разработчику мета-предикат closure/3 :)

person repeat    schedule 03.09.2015

Вы уходите в бесконечную рекурсию.

Как только вы доберетесь до likes(b,a), вы вызовете likes(a,_G4382), факт которого не определен, поэтому он переключается на правило likes(X,Z) :- likes(X,Y), likes(Y,Z).. Он вызывает likes(a,_G4383), который вызывает likes(X,Z) :- likes(X,Y), likes(Y,Z). снова и снова, и снова.

Возможно, вы захотите определить вспомогательный предикат aux_likes/2, который содержит все ваши факты. Это будет работать только в том случае, если нет круговых отношений, то есть aux_likes(b,c) и aux_likes(c,b). Вам также необходимо определить likes(X,X). Это, по сути, проблема графа, и в теории графов узел должен быть соединен сам с собой. Если вы используете его в качестве генератора, он уйдет в бесконечную рекурсию (если у вас есть циклы), если вы не добавите cuts, которые не идеальны.

Если вы используете swi-prolog, не стесняйтесь вводить запрос debug или spy, чтобы увидеть, что происходит.

Код:

aux_likes(g,c).
aux_likes(c,a).
aux_likes(c,b).
aux_likes(b,a).
aux_likes(b,d).

likes(X,Z) :- aux_likes(X,Y), likes(Y,Z).

likes(X,X).

Вывод с новым предикатом:

?- likes(g,X),print(X),nl,fail.
a
a
d
b
c
g
false.

Это говорит о том, что g может понравиться от a до c или до b. Ему нравится от d до b, ему нравится от b до c и ему нравится напрямую c. Он также должен нравиться себе, чтобы делать подобные запросы. Если вы предпочитаете режим использования (+,+), что означает, что вы предоставляете ему как термины, так и переменные (в качестве средства проверки), вы можете сделать

?- likes(g,c).
true .
person C.B.    schedule 07.01.2014
comment
В моем коде одновременно могут быть и likes(a,b), и likes(b,a). - person Rasoul; 07.01.2014
comment
@Rasoul В чем разница между отношениями? направлен ли предикат likes? то есть likes(g,b) означает, что g любит быть, но не b любит g? - person C.B.; 07.01.2014
comment
a likes b не обязательно означает, что b likes a. likes - это направленная связь. - person Rasoul; 07.01.2014
comment
@Rasoul на самом деле это должно работать для циклических зависимостей - я просто забыл добавить прямую проверку. См. правку выше. - person C.B.; 07.01.2014
comment
Вывод с новым предикатом не завершен! Это должны быть X=a, X=b, X=c и X=d. Я не вижу d в ответе. КСТАТИ! Не могли бы вы поместить весь измененный код в свой ответ? - person Rasoul; 07.01.2014
comment
Немного обновил. Может быть не совсем то, что вы хотите. - person C.B.; 08.01.2014