在prolog中回答真实答案后不要停止

时间:2013-04-10 19:47:07

标签: prolog transitive-closure

我写这个程序给我这个结果: “X =约翰” “Y =简”

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

3 个答案:

答案 0 :(得分:3)

您的查询({1}}和X都是变量)对于您定义Y

的方式来说过于“宽泛”

尝试

likes/2

prolog引擎有什么作用?好吧,它在其事实数据库中搜索。


首先它发现(第一条规则)

?- likes(john, Y).

所以约翰喜欢玛丽


然后它找到了

likes(john, mary).

所以它问自己:对于什么Z,likes(john,Y) :- likes(john,Z), likes(Z,Y). 是真的吗?好吧,数据库说likes(john,Z),所以likes(john, mary)。让我们把它放在规则中:

Z = mary

所以它问自己:因为{是{1}}的Y是真的吗?好吧,数据库说likes(john,Y) :- likes(john,mary), likes(mary,Y). ,所以likes(mary,Y)。让我们把它放在规则中:

likes(mary, jane)

所以 john喜欢jane


现在我们遇到了问题。仔细查看第二个查询:

Y = jane

UH-哦。

约翰喜欢某人如果约翰喜欢某人(和,......)

好吧,第一次尝试我们很幸运:Prolog引擎找到了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) ?

依旧......

答案 1 :(得分: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.

答案 2 :(得分: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}