我是初学者,我想创建“兄弟”关系。
关系应该是对称的,如果兄弟(alin,alex)为真,兄弟(alex,alin)也应该是。
它也应该是传递性的,如果兄弟(alin,alex)和兄弟(alex,claudiu)是真的,兄弟(alin,claudiu) 也应该如此。
结合使用属性,如果兄弟(alex,alin)和兄弟(alex,claudiu)是真的,兄弟(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 不应该是一个可能的答案,其他人应该出现一次。
答案 0 :(得分: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])).
答案 1 :(得分: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添加到您的代码中以摆脱&#34; alin&#34;作为解决方案。