我们给出了一个包含以下事实的图表:
edge(a,b)
edge(a,c)
edge(b,a)
edge(c,d)
edge(d,d)
edge(d,e)
edge(e,f)
edge(f,g)
edge(g,e)
我们被要求定义一个规则cycle(X)
,用于确定是否存在从节点X
开始的循环。
我真的迷失了如何做到这一点,我试图遍历节点并检查下一个节点是否会再次成为起始节点,但我似乎无法让它工作
答案 0 :(得分:4)
Archie的想法是一个很好的起点,但如果在搜索路径时发现另一个循环,它将创建一个无限循环。
我也没有多年使用过prolog,但你需要像path(X,Y,Visited)
这样的东西,你可以跟踪被访问的节点,防止无限循环。
答案 1 :(得分:3)
如果我们在遍历期间遇到任何被访问节点,则它使用深度优先搜索和访问节点列表返回true。我用小输入测试它看起来像是正常工作。
cycle(X):- cycleh(X,[X]).
cycleh(X,Visited) :- edge(X,Y), (member(Y,Visited) -> !,true; cycleh(Y,[Y|Visited])).
答案 2 :(得分:2)
这应该可以解决问题:
cycle( X ) :-
cycle( X , [] ).
cycle( Curr , Visited ) :-
member( Curr, Visited ) ,
!.
cycle( Curr , Visited ) :-
edge( Curr , Next ) ,
cycle( Next , [Curr|Visited] ) .
虽然它似乎是与@GökhanUras类似的解决方案 - 伟大的思想家也一样!或者是什么B ^)
基本逻辑是,如果当前节点已被访问,则有一个循环(cycle/2
辅助谓词中的第一个子句。此时,我们剪切(!)并声明成功的原因cut(!)就是没有它,回溯将导致重新访问已经访问过的节点,从而产生一组无限的循环。
如果尚未访问当前节点,我们抓住锚定在当前节点的边缘并访问该节点。回溯到cycle/2
的第2个子句会访问下一个边缘,因此一旦特定路径耗尽,cycle/2
就会回溯并尝试另一条路径。
答案 3 :(得分:1)
如果你的Prolog系统有一个正向链接器,你可以用它来确定周期。但请注意,它可能会占用相当多的记忆,因为它会生成并保留path/2
个事实。
以下是您需要如何在正向链接器中制定不会自动删除重复的规则。 \+
用于明确消除重复项:
:- forward edge/2.
:- forward path/2.
path(X,Y) :- edge(X,Y), \+ path(X,Y).
path(X,Y) :- edge(X,Z), path(Z,Y), \+ path(X,Y).
cycle(X) :- path(X,X).
为了使示例更有趣,结果是什么,我放弃了edge(d,d)
。这是一个示例运行:
?- postulate(edge(a,b)), postulate(edge(a,c)), postulate(edge(b,a)),
postulate(edge(c,d)), postulate(edge(d,e)), postulate(edge(e,f)),
postulate(edge(f,g)), postulate(edge(g,e)), cycle(X).
X = a ;
X = b ;
X = e ;
X = f ;
X = g
postulate/1
谓词在这里发布一个事件并保持正向链接的传播者运行。如何编写前向规则取决于您正在使用的Prolog系统各自的库。
P.S。:还有一些研究正在进行:
http://x10.sourceforge.net/documentation/papers/X10Workshop2011/elton_slides.pdf
答案 4 :(得分:0)
我使用Prolog已经有一段时间了,但也许这种方法可行:路径是一系列边缘,其中每条边都在前一边缘结束的节点上开始(例如a - &gt ; b,b - > c,c - > d)。平凡路径是单个边缘,通过采用现有路径并向其添加边缘,可以形成更复杂的路径。循环是在同一节点上开始和结束的路径。您可以使用这些定义来构建Prolog规则吗?
答案 5 :(得分:-1)
我有一段时间没有使用Prolog,但这是解决这个问题的方法。
您可以制定规则path(X,Y)
,检查是否存在从节点X
到Y
的路径。路径是单个边缘或通向路径的边缘。有了这个,很容易找到从节点X
开始的循环 - 它只是path(X,X)
。这是我的实现(取自我的头脑,不一定正确,但给出了想法):
path(X,Y) :- edge(X,Y).
path(X,Y) :- edge(X,Z), path(Z,Y).
cycle(X) :- path(X,X).