3

私はこの結果を得るためにこのプログラムを書きます: "X=john" "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) ??????

4

3 に答える 3

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

ジョンはジェーンが好きです。


今、問題があります。2 番目のクエリをよく見てください。

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

ええとああ。

ジョンが誰かを好きなら、ジョンも誰かを好きになる(そして、.....)

まあ、最初の試行では幸運でした:Y = jane, Z = mary次のルールがあるため、Prolog エンジンが見つかりました

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

そして止まりました。しかし、それは再び自問しました:

likes(john,Y) ?

最初の 2 つのルールは既に使用したので、3 番目のルールを試してみましょう。

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

等々..

于 2013-04-10T20:35:55.287 に答える
3

「X=john」「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.
于 2013-04-10T20:43:31.703 に答える
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)?
                     ............

それがデバッガーに表示されます。

この動作を防ぐには、推移閉包述語の名前を次のように変更します。

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

pals(X,Y) :-               % {4b}
    likes(X,Z),            % {5b} 
    pals(Z,Y).             % {6b}
于 2013-04-11T09:58:47.267 に答える