[英]Out of local stack when applying recursion
上下文,第一。 我试图用 prolog 建模的是两个单独的图,它们都代表一组朋友,所以在它们两个中我都可以放置friend(X,Y)
关系,并且,因为它没有意义,友谊不是'在这个模型中是相互的,我也把关系放在了friend(Y, X)
。
所以这意味着两个图在它们的元素之间都有双向关系。
例如:
friend(foo1, foo2).
friend(foo2, foo1).
friend(foo3, foo4).
friend(foo4, foo3).
其中foo1
与foo2
相关, foo3
和foo4
,但前两个与另外两个无关。
因为是一群朋友,所以也没有感觉,在同一群朋友中,同一群的两个人不是朋友,所以我使用递归来确定一个人是否是另一个人的朋友。
definitivefriend(X, Z) :- friend(X, Z).
definitivefriend(X, Z) :- friend(X, Y), definitivefriend(Y, Z).
我遇到的问题是,当我尝试检查一组中的一个人是否是另一组中的一个人的朋友时。 换句话说,检查图的一个元素是否与另一个图的另一个元素相关。
编译器(在本例中为 SWI-Prolog)并没有得到 false ,这是预期的结果,而是给了我一个out of local stack的错误。
我想知道如何解决这个问题。
编辑
所以多亏了 CapelliC,我有了解决这个问题的方法。 因为主要目标已经完成,但还有一个次要问题,我将从现在开始描述它。
这是我正在使用的两个图表。 记住我之前说过,两个图都是双向的。
这是我在序言中的程序:
writeit :- write('Frienship').
definitivefriend(X, Z) :- friend(X, Z), friend(Z, X).
definitivefriend(X, Y) :- friend(X, Z), X @< Z, definitivefriend(Z, Y), Y \= X.
friend(amanda, ryan). % graph1 %
friend(ryan, amanda).
friend(ryan, lisa).
friend(lisa, ryan).
friend(bryan, ryan).
friend(ryan, bryan).
friend(sara, ryan).
friend(ryan, sara).
friend(sara, simone).
friend(simone, sara). % graph2 %
friend(sandra, jeff).
friend(jeff, sandra).
friend(betty, jeff).
friend(jeff, betty).
friend(jeff, antonia).
friend(antonia, jeff).
friend(jeff, oskar).
friend(oskar, jeff).
friend(jeff, leslie).
friend(leslie, jeff).
这是我得到的一些输出
?- definitivefriend(amanda, ryan).
true . % It's correct, both nodes are neighbours %
?- definitivefriend(amanda, simone).
true . % It's correct, both nodes are in the same graph %
?- definitivefriend(ryan, simone).
true . % It's correct, same explanation as before %
?- definitivefriend(simone, amanda).
false. % It's wrong, expected result is true %
?- definitivefriend(ryan, jeff).
false. % It's correct, nodes are in different graphs %
?- definitivefriend(amanda, leslie).
false. % It's correct, same explanation as before %
?- definitivefriend(sandra, oskar).
false. % It's wrong, expected result is true %
?- definitivefriend(oskar, sandra).
false. % It's wrong, expected result is true %
?- definitivefriend(betty, oskar).
true . % It's correct, both nodes are in the same graph %
?- definitivefriend(oskar, betty).
false. % It's wrong, expected result is true %
正如我在评论中所说的那样,即使有相同图形的某些元素(除了相邻的元素), definitivefriend
也会给我错误。 并且在某些情况下,当我执行 expiredfriend definitivefriend(X, Y)
我会得到正确的结果,但是当我 execite definitivefriend(Y, X)
我会得到错误的结果。
我觉得你没有以正确的方式建模,无论如何这似乎有效(滥用 Jean-Bernard 的建议,+1)
definitivefriend(X, Y) :-
friend(X, Y),
friend(Y, X).
definitivefriend(X, Y) :-
friend(X, Z), X @< Z,
definitivefriend(Z, Y), Y \= X.
编辑:这不适用于您的模型。 除了遵循丹尼尔的建议(+1)之外,我看不到任何其他方式。
对于您的第二个definitivefriend
规则,添加 X < Y 的条件。这将避免循环。 然后简单地添加一个规则:
definitivefriend(X,Y) :- definitivefriend(Y,X)
就像现在一样,你可以:
definitivefriend(1,2) :- friend(1,3), definitivefriend(3,2)
definitivefriend(3,2) :- friend(2,1), definitivefriend(1,2)
这导致无限递归
问题基本上是周期。 您的图表是非循环的,但您的代码不是。 这是问题。 假设我给出查询:- definitivefriend(foo1, foo2).
. 是什么阻止 Prolog 像这样扩展:
definitivefriend(foo1, foo2)
:- friend(foo1, foo2), definitivefriend(foo2, foo2). % by clause 2
:- friend(foo1, foo2), friend(foo2, foo1), definitivefriend(foo1, foo2). % by clause 2
:- friend(foo1, foo2), friend(foo2, foo1), friend(foo1, foo2),
definitivefriend(foo2, foo2). % by clause 2
等等。
@Jean-Bernard Pellerin 通过强制完全排序提供了一种防止循环的有用方法。 我不认为这是正确的方法,但我不能完全说明原因。 但是,您可以做的一件事是提供一个访问过的列表来检查而不是重新输入您已经访问过的节点。 该代码将如下所示:
definitivefriend(X, Z) :- definitivefriend(X, Z, [X]).
definitivefriend(X, Y, Visited) :-
friend(X, Y), \+ memberchk(Y, Visited).
definitivefriend(X, Z, Visited) :-
friend(X, Y), \+ memberchk(Y, Visited),
definitivefriend(Y, Z, [Y|Visited]).
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.