prolog中的递归引用
我在尝试实施时遇到了一些问题prolog中的递归引用,prolog,transitive-closure,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) 我问?-朋友(mia,X)。,它一直在回答X=mia 我不明白,为什么它是递归的?朋友/2的这一条款有缺陷: friends(X,
friends(mia, ellen).
friends(mia, lucy).
friends(X,Y) :-
friends(X,Z),
friends(Y,Z).
当我问?-friends(mia,X)。
时,它的本地堆栈就用完了
然后我加上
friends(ellen, mia) friends(lucy, mia)
我问?-朋友(mia,X)。
,它一直在回答X=mia
我不明白,为什么它是递归的?朋友/2的这一条款有缺陷:
friends(X,Y) :- friends(X,Z),friends(Y,Z).
把它翻译成英语:“如果X
和Y
有一个共同的朋友Z
,那么X
和Y
就是朋友。”
或者,让我们专业化,让X
成为“我”,让Y
成为我的邻居“富伯特”,让Z
成为“你”:所以如果我是你的朋友,富伯特是你的朋友。。。这能让我和富伯特成为朋友吗?我不这么认为,我讨厌那个家伙——他回家后总是砰的一声关上门
我建议你考虑关系<代码>朋友/ 2 < /代码>应该有的,可能有的,不应该有的。那么自反性、对称性、反对称性、及物性呢?
首先,两个假设:- 您想要编写的实际代码如下所示,带有适当的点:
friends(mia,ellen). friends(mia,lucy). friends(X,Y) :- friends(X,Z), friends(Z,Y).
- 短暂性:朋友的朋友也是我的朋友(我更愿意将友谊建模为一种距离:“a接近B”,“B接近C”并不一定意味着“a接近C”)。首先弄清楚你想建模什么是正确的
朋友(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\u 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\u friends/2
的两个子句相同的答案,但没有找到传递子句的任何答案:这里的区别是known\u friends
会有一点进步,即找到mia
(无递归),并尝试(递归地)查找该朋友是否是其他人的朋友
朋友的朋友
如果我们添加已知的朋友(ellen,bishop):-),那么朋友也会找到Y=bishop
,因为:
known\u friends(米娅,艾伦)
hold,and
friends(ellen,bishop)
是递归查找的
圆度
如果您在友谊图中添加循环依赖项(在known\u friends
中),那么您将使用friends
无限遍历此图。在修复之前,你必须考虑以下问题:
friends(X,Y)friends(Y,X)
是否适用于所有(X,Y)
- 对于所有的
X
,朋友(X,X)
呢
然后,在评估
朋友
时,您应该保留一组所有见过的人,以便在考虑上述属性的情况下,检测您在已知的朋友
之间循环的时间。如果您想尝试,这应该不会太难实现。源文件中的friends/2
子句不在一起意味着在friends/2
子句的定义之间定义了其他子句。请注意,friends(mia,ellen)friends(mia,lucy)。
不是有效的语法。所以我假设你所展示的并不是你的代码看起来的样子。。我只学了几个小时的序言。我想知道是否有人曾经用它来证明几何学中的某些东西,比如a线与b线平行,b线与c线平行,然后a线与c线平行。谢谢,现在我知道它为什么没有堆栈了。这是明确和有益的。