首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >prolog中的true答案后未停止

prolog中的true答案后未停止
EN

Stack Overflow用户
提问于 2013-04-11 03:47:07
回答 3查看 181关注 0票数 3

我写这个程序是为了得到这个结果:"X=john“"Y=jane”

代码语言:javascript
复制
likes(john,mary).
likes(mary,jane).
likes(l,k).

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

但是如果运行这个程序,结果是:我认为程序陷入了循环!我想在得到真实答案后停下来!

代码语言:javascript
复制
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

我有错误!如何解决这个问题?

通过调试:

代码语言:javascript
复制
[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)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-11 17:58:47

你的代码:

代码语言:javascript
复制
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)如下所示:

代码语言:javascript
复制
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谓词,如下所示:

代码语言:javascript
复制
likes(john,mary).          % {1b}
likes(mary,jane).          % {2b}
likes(l,k).                % {3b}

pals(X,Y) :-               % {4b}
    likes(X,Z),            % {5b} 
    pals(Z,Y).             % {6b}
票数 2
EN

Stack Overflow用户

发布于 2013-04-11 04:35:55

您的查询( XY都是变量)对于您定义likes/2的方式来说太“宽泛”了

试一试

代码语言:javascript
复制
?- likes(john, Y).

prolog引擎做些什么?嗯,它在它的事实数据库中搜索。

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

代码语言:javascript
复制
likes(john, mary).

所以玛丽·约翰喜欢。

然后它会发现

代码语言:javascript
复制
likes(john,Y) :-
    likes(john,Z),
    likes(Z,Y).

所以它会问自己:什么Z是真的,likes(john,Z)?数据库上说likes(john, mary)所以Z = mary.让我们把它放在规则中:

代码语言:javascript
复制
likes(john,Y) :-
    likes(john,mary),
    likes(mary,Y).

所以它会问自己:likes(mary,Y)是什么意思?数据库上说likes(mary, jane)所以Y = jane.让我们把它放在规则中:

代码语言:javascript
复制
likes(john,jane) :-
    likes(john,mary),
    likes(mary,jane).

所以简·约翰喜欢。

现在我们有问题了。仔细观察第二个问题:

代码语言:javascript
复制
likes(john,Y) :-
    likes(john,Z),
    .....

啊哦。

如果约翰喜欢某人,约翰就会喜欢上他(……)(……)

在第一次尝试时,我们很幸运: Prolog引擎找到了Y = jane, Z = mary,因为我们有以下规则

代码语言:javascript
复制
likes(john,mary).
likes(mary,jane).

然后它停了下来。但随后它再一次问自己:

代码语言:javascript
复制
likes(john,Y) ?

我们已经使用了前两个规则,所以让我们尝试第三个规则:

代码语言:javascript
复制
likes(X,Y) :-
    likes(X,Z),
    likes(Z,Y).

麻烦!

代码语言:javascript
复制
likes(john,Someone) :-
    likes(john,Someone2), ..... 

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

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

以此类推..

票数 3
EN

Stack Overflow用户

发布于 2013-04-11 04:43:32

如果您需要"X=john“"Y=jane”,则必须重命名:

代码语言:javascript
复制
likes(X,Y) :- likes(X,Z), likes(Z,Y).

对于其他名称,例如:

代码语言:javascript
复制
likestransitive(X,Y) :- likes(X,Z), likes(Z,Y).

这样您就可以获得您需要的解决方案:

代码语言:javascript
复制
1 ?- transitivelikes(X,Y).    
X = john,    
Y = jane;    
false.
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15935053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档