4

我是序言初学者,我想创建“兄弟”关系。

关系应该是对称的,如果兄弟(alin,alex)是真的,兄弟(alex,alin)也应该是。

它也应该是传递的,如果兄弟(alin, alex)兄弟(alex, claudiu)为真,兄弟(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]).

r_brother - 是基本关系

s_brother - 是对称兄弟关系(这很好用)

t_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不应该是一个可能的答案,其他人应该出现一次。

4

2 回答 2

3

我认为基本问题是您不检查是否已在 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])).
于 2014-05-08T11:08:24.307 回答
1

你可以这样写兄弟关系(就像传递定义一样)

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

brother(X,Y) :- s_brother(X, Y).
brother(X,Y) :- s_brother(X, Z),s_brother(Z, Y),X\=Y.

这意味着如果 X 是对称兄弟,则 X 是 Y 的兄弟,或者他们有共同的兄弟,并加上他们不同的条件。

尝试将 X\=Y 添加到您的代码中,以摆脱“alin”作为解决方案。

于 2014-05-08T11:02:39.893 回答