2013-04-10 73 views
3

我寫這篇文章PROGRAMM爲給我這樣的結果: 「X =約翰」 「Y =簡」沒有停止在序言

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

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

,但如果運行這個PROGRAMM這樣,這個結果: 我認爲程序進入循環! 我想在真正的答案後停止!

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

您的查詢(包括XY是變量)是你定義likes/2

的方式過於「寬泛」嘗試

?- likes(john, Y). 

是什麼序言引擎呢?那麼,它會在其事實數據庫中進行搜索。


首先它發現(第1章)

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), 
    ..... 

恩 - 哦。

約翰喜歡有人,如果約翰喜歡有人(和.....)

好,第一次嘗試,我們是幸運的:在序言引擎發現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 2013-04-10 21:01:51

+0

請看我編輯的問題! – user2254798 2013-04-11 06:22:18

3

如果你需要 「X =約翰」 「Y =簡」,那麼你必須重新命名:

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 2013-04-10 21:01:24

+0

請看我編輯的問題! – user2254798 2013-04-11 06:22:39