我是一个初学者,我想创造“兄弟”关系。
这个关系应该是对称的,就像brother(alin,alex)是真的,brother(alex,alin)也是。
它也应该是可传递的,就像brother(alin,alex)和brother(alex,claudiu)是真的一样,brother(alin,claudiu)也应该是真的。
结合to属性,如果brother(alex,alin)和brother(alex,claudiu)是真的,那么brother(alin,claudiu)也应该是真的。
这是我的代码:

r_brother(alin, alex).
r_brother(alin, ciprian).
r_brother(alex, claudiu).

s_brother(X, Y) :- r_brother(X, Y).
s_brother(X, Y) :- r_brother(Y, X).

brother(L1, L2) :-
    t_brother(L1, L2, []).

t_brother(L1, L2, _) :-
    s_brother(L1, L2).

t_brother(L1, L2, IntermediateNodes) :-
    s_brother(L1, L3),
    \+ member(L3, IntermediateNodes),
    t_brother(L3, L2, [L3 | IntermediateNodes]).

兄弟是最基本的关系
súbrother-是对称的兄弟关系(这很有效)
兄弟-这应该是传递的对称关系,我保留中间节点,这样就不会得到循环
问题在于:
?- brother(X, alin).

是:
X = alex ;
X = ciprian ;
X = alin ;
X = alin ;
X = alin ;
X = alin ;
X = alex ;
X = alex ;
X = alex ;
X = alex ;
X = ciprian ;
X = ciprian ;
X = claudiu ;
X = claudiu ;
false.

我仔细看了一下痕迹,知道问题出在哪里,但不知道怎么解决。
alin不应该是一个可能的答案,其他的应该出现一次。

最佳答案

我认为最基本的问题是你没有检查在t戥brother/3的第一个子句中是否已经找到了L2首字母L1应添加到brother/2中的列表中:

brother(L1, L2) :-
  t_brother(L1, L2, [L1]).                   % <-- [L1] instead of []

t_brother(L1, L2, IntermediateNodes) :-
  s_brother(L1, L2),
  \+ member(L2, IntermediateNodes).          % <-- added this check

t_brother(L1, L2, IntermediateNodes) :-      % <-- this clause is unchanged
  s_brother(L1, L3),
  \+ member(L3, IntermediateNodes),
  t_brother(L3, L2, [L3 | IntermediateNodes]).

仍然可以使用析取来缩短解决方案:
t_brother(L1, L2, IntermediateNodes) :-
  s_brother(L1, L3),
  \+ member(L3, IntermediateNodes),
  ( L2=L3
  ; t_brother(L3, L2, [L3 | IntermediateNodes])).

关于prolog - 序言中对称关系上的及物闭合,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28990855/

10-10 13:50