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).