Prolog:从间接关系中消除循环
我有一个用户事实列表,定义如下:Prolog:从间接关系中消除循环,prolog,transitive-closure,Prolog,Transitive Closure,我有一个用户事实列表,定义如下: user(@michael). user(@ana). user(@bob). user(@george). user(@john). 等等。此外,我还有一系列事实: follows(@michael,@ana). follows(@ana,@bob). follows(@bob,@michael). 我试图编写一个间接关系(user1,user1),它将告诉我user1是否间接跟随user2。 然而,我无法消除循环关系 就像在给定的示例中,michael-
user(@michael).
user(@ana).
user(@bob).
user(@george).
user(@john).
等等。此外,我还有一系列事实:
follows(@michael,@ana).
follows(@ana,@bob).
follows(@bob,@michael).
我试图编写一个间接关系(user1,user1),它将告诉我user1是否间接跟随user2。
然而,我无法消除循环关系
就像在给定的示例中,michael->ana->bob->michael将导致一个循环
从间接(user1,user2)的结果中消除这些周期的最佳方法是什么?您可以制定一个规则,传递到目前为止“看到”的额外用户列表,并忽略来自这些用户的以下内容:
遵循(a,B,seen)
为此,请定义一个“follow transitive”规则来包装实际规则,如下所示:
follows_tx(A, B) :- follows(A, B, []).
现在您可以这样定义遵循/3
规则:
follows(A, B, Seen) :-
not_member(B, Seen),
follows(A, B).
follows(A, B, Seen) :-
follows(A, X),
not_member(X, Seen),
follows(X, B, [A|Seen]).
基子句表示,如果有一个关于<代码> a < /> > <代码> b>代码>的事实,我们认为谓词已经被证明,只要我们以前没有见过代码> b>代码> .< 否则,我们会找到跟随
A
的人,通过检查not_member/2
来检查我们是否还没有看到该用户,最后查看该用户是否直接或间接跟随B
最后,这里是如何定义非成员:
not_member(_, []).
not_member(X, [H|T]) :- dif(X, H), not_member(X, T).
请参见closure/3
为什么要在名称前加@
?@false,我正在尝试使用prolog创建twitter,给我的规则之一是用户名以@开头。请尝试编写规范(@abx)。
它给出了@(abx)
。也就是说,@
是(SWI的)前缀运算符。如果你真的想在名字里写@
“@name”
,我会试试。谢谢@false。我在这里发布了另一个问题。任何帮助或提示都对我有用。现在,遵循(A,B)
只有三种解决方案。这就是为什么在非会员/2
中(\=)/2
不是一个好主意。谢谢@dasblinkenlight的帮助。@na899欢迎您!看看false最后一条评论的最后一次编辑(将=`替换为dif/2`)。@false再次感谢,我已经忘记了Prolog有时有多么棘手(我上一次在Prolog中编程是在20年前)。
indirect( A0,A) :-
closure(follows, A0,A).