[英]Recursive reference in prolog
我尝试实施时遇到了一些问题
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
。
我无法理解,为什么它是递归的?
friends/2
这一条款有缺陷:
friends(X,Y) :- friends(X,Z),friends(Y,Z).
把它翻译成英文:“如果X
和Y
有一个共同的朋友Z
,那么X
和Y
就是朋友。”
或者,让我们专注,让X
成为“我”,让Y
成为我的邻居“FooBert”,让Z
成为“你”:所以,如果我是你的朋友而FooBert是你的朋友......这是否让我和FooBert成为朋友? 我不这么认为,我讨厌那个人 - 他回家后总是砸门。 :)
我建议你考虑一下friends/2
应该拥有的代数属性,它可能具有的代数属性,以及它不 应该有的代数属性。 反身性,对称性,反对称性,传递性如何?
首先,两个假设:
您要编写的实际代码是以下代码,并带有适当的点:
friends(mia,ellen). friends(mia,lucy). friends(X,Y) :- friends(X,Z), friends(Z,Y).
变性持有:朋友的朋友也是我的朋友(我宁愿模仿友谊作为距离:“A在B附近”,“B在C附近”并不一定意味着“A在C附近”)。 重复的答案是关于先弄清楚你想要建模的东西。
现在,让我们看看为什么我们进入无限递归。
那么,当我们问: friends(mia,X)
时会发生什么?
Y=ellen
(你要求更多解决方案) Y=lucy
(你再次询问更多解决方案) friends(mia,Y)
持有某个变量Y
是否存在变量Z
,以便friends(mia,Z)
持有?
请注意,除了从Y
到Z
重命名之外,我们问的问题与上面的第1步相同吗? 这闻起来像无限递归 ,但让我们看看...
friends
的前两个条款,但后来因为没有friends(ellen,Y)
和friends(lucy,Y)
而失败,所以...... 此问题类似于无上下文语法中的无限左递归 。
有两个谓词:
known_friends/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).
现在,当我们问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)
? X
, friends(X,X)
怎么样? 然后,在评估friends
时,你应该保留一组所有见过的人,以便检测你何时循环通过known_friends
,同时考虑上述属性。 如果你想尝试,这也不应该太难实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.