Почему в этом простом примере происходит сбой Пролога?

likes(tom,jerry).
likes(mary,john).
likes(mary,mary).
likes(tom,mouse).
likes(jerry,jerry).
likes(jerry,cheese).
likes(mary,fruit).
likes(john,book).
likes(mary,book).
likes(tom,john).

likes(john,X):-likes(X,john), X\=john.

Привет! Выше приведен очень простой файл пролога с некоторыми фактами и только одним правилом: Джон любит всех, кто любит его. Но загрузив этот файл и задав Prolog следующий запрос:

likes(john,X).

Программа вылетает. Причина в том, что пролог каким-то образом застревает на likes(john,john), хотя правило гласит, что X\=john.

Любой совет?


person Yukio Fukuzawa    schedule 28.04.2012    source источник
comment
Из любопытства, а что будет, если X\=john появится раньше лайков?   -  person pedrofurla    schedule 28.04.2012
comment
Достаточно странно, если вы поместите это перед телом, Пролог вернет: X = book ; false. Я понятия не имею, почему он останавливается сразу после book.   -  person Yukio Fukuzawa    schedule 28.04.2012


Ответы (2)


По иронии судьбы, учитывая сайт, на котором мы находимся, вы получаете переполнение стека.

Он делает это из-за порядка выполнения, который использует пролог, он войдет в бесконечную рекурсию на likes(X,john) в вашем правиле, он снова активирует правило — не факт — никогда не дойдет до X\=john бита .

Один из способов исправить это — назвать ваше правило иначе, чем ваш факт, например:

kindoflikes(tom,jerry).
kindoflikes(mary,john).
kindoflikes(mary,mary).
kindoflikes(tom,mouse).
kindoflikes(jerry,jerry).
kindoflikes(jerry,cheese).
kindoflikes(mary,fruit).
kindoflikes(john,book).
kindoflikes(mary,book).
kindoflikes(tom,john).

likes(Y,X):- kindoflikes(X,Y), X\=Y.
likex(Y,X):- kindoflikes(Y,X), X\=Y.

Обратите внимание на изменение местами X и Y в типах симпатий в двух определениях правил. Итак, вы получаете:

?- likes(john,X).
X = mary ;
X = tom ;
X = book.

Но вы не ограничены поиском того, что нравится Джону, и вы можете сделать следующее:

?- likes(jerry,X).
X = tom ;
X = cheese.
person GregHNZ    schedule 28.04.2012
comment
@GregHNZ: Пролог не выполняет правила заранее - person m09; 28.04.2012

Ваш первый вопрос был о том, почему ваша программа дает сбой. Я не уверен, какую систему Пролога вы используете, но многие системы выдают чистую "ошибку ресурса", которую можно обработать из Пролога.

Ваша фактическая проблема заключается в том, что ваша программа не завершается для запроса likes(john, X). Он дает вам ожидаемые ответы и только потом зацикливается.

?- likes(john,X).
X = book ;
X = mary ;
X = tom ;
ERROR: Out of local stack

Вам очень повезло, что вы так быстро обнаружили эту проблему. Представьте себе больше ответов, и не было бы так очевидно, что у вас хватит терпения просмотреть все ответы. Но для этого есть ярлык. Вместо этого спросите:

?- likes(john, X), false.

Эта false цель никогда не бывает верной. Так что это легко предотвращает любой ответ. В лучшем случае запрос с false в конце завершается. В настоящее время это не так. Причину этого незавершения лучше всего видно при рассмотрении следующих failure-slice (подробнее см. другие ответы):

?- likes(john,X), false.

likes(tom,jerry) :- false.
likes(mary,john) :- false.
likes(mary,mary) :- false.
likes(tom,mouse) :- false.
likes(jerry,jerry) :- false.
likes(jerry,cheese) :- false.
likes(mary,fruit) :- false.
likes(john,book) :- false.
likes(mary,book) :- false.
likes(tom,john) :- false.
likes(john,X) :-
   likes(X,john), false,
   X\=john.

Так что именно эта крошечная часть вашей программы отвечает за переполнение стека. Чтобы решить проблему, мы должны что-то сделать в этой крошечной части. Вот один из них: добавьте цель dif(X, john) так, чтобы правило читалось так:

likes(john,X) :-
   dif(X, john),
   likes(X,john).

dif/2 доступен во многих системах Prolog, таких как: SICStus, SWI, YAP, B, IF.

person false    schedule 14.11.2012