prolog中的递归引用

时间:2015-04-28 16:05:32

标签: prolog transitive-closure

我尝试实施

时遇到了一些问题
friends(mia, ellen).
friends(mia, lucy).
friends(X,Y) :-
  friends(X,Z),
  friends(Y,Z).

当我问?- friends(mia, X).时,它会耗尽本地堆栈。

然后我添加

friends(ellen, mia) friends(lucy, mia) 

我问?- friends(mia, X).,它不断回复X = mia

我无法理解,为什么它是递归的?

2 个答案:

答案 0 :(得分:2)

friends/2的这一条款存在缺陷:

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

将其翻译成英语:"如果XY有共同的朋友Z,那么XY就是朋友。& #34;

或者,让我们专注,让X成为" me",让Y成为我的邻居" FooBert",然后让{{ 1}} be"你":所以,如果我是你的朋友而FooBert是你的朋友......这会让我和FooBert成为朋友吗?我不这么认为,我讨厌那个人 - 他回家后总是砸门。 :)

我建议您考虑Z 应该所拥有的代数属性,可能所拥有的代数属性,以及不应该< / em>有。那么反身性,对称性,反对称性,传递性呢?

答案 1 :(得分:2)

首先,两个假设:

  • 您要编写的实际代码如下,并带有适当的点:

    friends(mia,ellen).
    friends(mia,lucy).
    friends(X,Y) :- 
       friends(X,Z),
       friends(Z,Y).
    
  • 变性持有:朋友的朋友也是我的朋友(我宁愿把友谊模仿为距离:“A在B附近”,“B在C附近”并不一定意味着“A在C附近”) 。 repeat's answer首先要弄清楚你想要建模的内容。

现在,让我们看看为什么我们进入无限递归。

步骤一步

那么,当我们问:friends(mia,X)

时会发生什么
  1. 第一句提供Y=ellen(您需要更多解决方案)
  2. 第二句提供Y=lucy(您再次要求提供更多解决方案)
  3. 堆栈溢出!
  4. 让我们详细说明第三个条款:

    1. 我想知道friends(mia,Y)是否适用于某个变量Y
    2. 是否存在Z变量friends(mia,Z)

      请注意,除了从Y重命名为Z之外,我们问的问题与上面的第1步相同吗? 这闻起来像无限递归,但让我们看看......

    3. 我们尝试friends的前两个条款,但之后我们失败了,因为没有friends(ellen,Y)也没有friends(lucy,Y),所以......
    4. 我们打电话给第三个条款,以便找出是否存在传递友谊,我们又回到了第1步而没有进一步发展=&gt;无限递归。
    5. 此问题类似于无上下文语法中的无限Left recursion

      修复

      有两个谓词:

      1. known_friends/2,提供直接关系。
      2. friends/2,也编码传递性

        known_friends(mia,ellen).
        known_friends(mia,lucy).
        
        friends(X,Y) :- known_friends(X,Y).
        friends(X,Y) :- known_friends(X,Z), friends(Z,Y).
        
      3. 现在,当我们问friends(mia,X)时,friends/2给出与known_friends/2的两个条款相同的答案,但没有找到传递条款的任何答案:这里的区别是known_friends会取得一些进展,即找到mia的已知朋友(没有递归),并试图找到(递归)该朋友是否是其他人的朋友。

        朋友的朋友

        如果我们添加known_friends(ellen, bishop) : - ),那么friends也会找到Y=bishop,因为:

        • known_friends(mia,ellen)成立,
        • friends(ellen,bishop)是递归发现的。

        圆形

        如果您在友谊图表中添加循环依赖关系(在known_friends中),那么使用friends对此图表进行无限遍历。在解决这个问题之前,您必须考虑以下问题:

        • friends(X,Y) <=> friends(Y,X)对所有人(X,Y)都有效吗?
        • friends(X,X)对所有X
        • 怎么样?

        然后,在评估friends时,您应该保留一组所有看到的人,以便检测您何时循环known_friends,同时考虑上述属性。如果你想尝试,这也不应该太难实现。