2012-04-28 2 views
4
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.

Любые советы?

+0

Из любопытства, что произойдет, если X \ = john предстанет перед подобными? – pedrofurla

+0

Странно, если вы положите это перед телом, Prolog вернется: 'X = book; false.' Я понятия не имею, почему он останавливается сразу после «книги». –

ответ

3

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

Он делает это из-за порядка выполнения, пролога использования, он собирается идти в бесконечную рекурсию в 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 в kindoflikes в двух определений правил. Таким образом, вы получите:

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

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

?- likes(jerry,X). 
X = tom ; 
X = cheese. 
+0

Это прекрасный ответ, спасибо! –

+0

@GregHNZ: Prolog не выполняет правила до фактического – m09

2

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

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

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

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

 
?- likes(john, X), false. 

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

 
?- 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 доступен во многих системах Пролога как: SICStus, SWI, ПЕА, B, IF.

Смежные вопросы