2013-04-10 4 views
3

я пишу это программку для дать мне этот результат: «X = джон» «Y = JANE»не останавливается после истинного ответа в прологе

likes(john,mary). 
likes(mary,jane). 
likes(l,k). 

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

, но если запустить эту программку таким образом, что этот результат: Я думаю, что программа попадает в цикл! Я хочу остановиться после истинного ответа!

1 ?- likes(X,Y). 
X = john, 
Y = mary ; 
X = mary, 
Y = jane ; 
X = l, 
Y = k ; 
X = john, 
Y = jane ; 
ERROR: Out of local stack 

У меня есть ошибка! как решить эту проблему?

по отладке:

[debug] 3 ?- likes(john,Y). 
T Call: (6) likes(john, _G2162) 
T Exit: (6) likes(john, mary) 
Y = mary ; 
T Redo: (6) likes(john, _G2162) 
T Call: (7) likes(john, _G2267) 
T Exit: (7) likes(john, mary) 
T Call: (7) likes(mary, _G2162) 
T Exit: (7) likes(mary, jane) 
T Exit: (6) likes(john, jane) 
Y = jane ; 
T Redo: (7) likes(mary, _G2162) 
T Call: (8) likes(mary, _G2267) 
T Exit: (8) likes(mary, jane) 
T Call: (8) likes(jane, _G2162) 
T Call: (9) likes(jane, _G2267) 
T Call: (10) likes(jane, _G2267) 
T Call: (11) likes(jane, _G2267) 
T Call: (12) likes(jane, _G2267) 
T Call: (13) likes(jane, _G2267) 
T Call: (14) likes(jane, _G2267) 
T Call: (15) likes(jane, _G2267) 

и так далее .. почему любит (джейн, _G2267) ??????

ответ

2

Ваш код:

likes(john,mary).   % {1} 
likes(mary,jane).   % {2} 
likes(l,k).    % {3} 

likes(X,Y) :-    % {4} 
    likes(X,Z),   % {5} 
    likes(Z,Y).   % {6} 

Запрос likes(john,Y) протекает следующим образом:

likes(john,Y)? 
%% {1} Y = mary.  ; redo 
%% {4} likes(john,Y) :- 
    %% {5} likes(john,Z)? 
     %% {1} Z=mary. 
    %% {6} likes(mary,Y)? 
     %% {2} Y=jane.  ; redo 
     %% {4} likes(mary,Y) :- 
     %% {5} likes(mary,Z2)? 
      %% {2} Z2=jane, 
     %% {6} likes(jane,Y)? 
      %% {4} likes(jane,Y):- 
       %% {5} likes(jane,Z3)? 
        %% {4} likes(jane,Z3):- 
        %% {5} likes(jane,Z4)? 
        ............ 

и это то, что вы видите в отладчике.

Чтобы предотвратить такое поведение, переименовать transitive closure предикат следующим образом:

likes(john,mary).   % {1b} 
likes(mary,jane).   % {2b} 
likes(l,k).    % {3b} 

pals(X,Y) :-    % {4b} 
    likes(X,Z),   % {5b} 
    pals(Z,Y).    % {6b} 
3

Ваш запрос (как X и Y являются переменными) слишком «широкий» за то, как вы определили likes/2

Попробуйте

?- likes(john, Y). 

Что делает пролог двигатель? Ну, он ищет в своей базе данных фактов.


Сначала он считает, что (первое правило)

likes(john, mary). 

так джон любит Мэри.


Тогда он находит, что

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

так он спрашивает себя: за то, что Z это правда, что likes(john,Z)? Ну, база данных говорит, что likes(john, mary), поэтому Z = mary. Скажем в правиле:

likes(john,Y) :- 
    likes(john,mary), 
    likes(mary,Y). 

так он спрашивает себя: для того, что Y это правда, что likes(mary,Y)? Ну, база данных говорит, что likes(mary, jane), поэтому Y = jane. Скажем в правиле:

likes(john,jane) :- 
    likes(john,mary), 
    likes(mary,jane). 

так джон любит джан.


Теперь у нас есть проблема. Посмотрите внимательно на второй запрос:

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

uh-oh.

Джон любит кого-то, если кому-то нравится кто-то (и, .....)

хорошо, с первой попытки нам повезло: двигатель Пролог нашел Y = jane, Z = mary, потому что мы имеем следующие правила

likes(john,mary). 
likes(mary,jane). 

и остановилась. Но потом он спросил себя, снова:

likes(john,Y) ? 

мы уже использовали первые два правила, так что давайте попробуем с третьим:

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

неприятности!

likes(john,Someone) :- 
    likes(john,Someone2), ..... 

likes(john,Someone2) :- 
    likes(john,Someone3), ..... 

likes(john,Someone3) :- 
    likes(john,Someone4), ..... 

и так далее ..

+0

спасибо! Я думаю, underestand! :) – user2254798

+0

см. Мой отредактированный вопрос! – user2254798

3

Если вам нужно "X =" Джон "Y = -Jane", то вы должны переименовать:

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

для другого имени, пример:

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

Таким образом, вы можете получить решение, что вам нужно:

1 ?- transitivelikes(X,Y).  
X = john,  
Y = jane;  
false. 
+0

поблагодарить его работы :) – user2254798

+0

см. Мой отредактированный вопрос! – user2254798

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