“或”运算符仅返回第一个语句

时间:2014-01-04 15:49:36

标签: prolog

我有典型的关系示例。

m(thomas).
m(leon).
w(nina).
born(thomas, nina, leon).

born(Father, Mother, Child) :- born(Mother, Father, Child).
father(Father, Child) :- born(Father, Mother, Child), m(Father).
mother(Mother, Child) :- born(Father, Mother, Child), w(Mother).
parent(Parent, Child) :- (father(Parent, Child); mother(Parent, Child)).

当我问父母之后,只会列出父亲:

?- parent(X, leon).
X = thomas ;
X = thomas ;
.....

我想要父母双方:

?- parent(X, leon).
X = thomas ;
X = nina ;

我该怎么办?

编辑:问题:

我的问题不是or,因为它normally会回复两个陈述。

问题是上面代码中的born/3是一个循环。 我试图让母亲和父亲互相交换。

修改:修复:

我从ChristianF和CapelliC得到了两个答案。他们都帮助我理解我的陈述有什么问题。

我自己的解决方案:

m(thomas).
m(leon).
w(nina).
b(thomas, nina, leon).

born(Father, Mother, Child)
    :- (m(Father), w(Mother), b(Father, Mother, Child)); b(Mother, Father, Child).
father(Father, Child) :- born(Father,_, Child), m(Father).
mother(Mother, Child) :- born(_, Mother, Child), w(Mother).
parent(Parent, Child) :- (father(Parent, Child); mother(Parent, Child)).

3 个答案:

答案 0 :(得分:2)

你的规则中有'循环'。删除born / 3规则,你会得到

?- parent(P,leon).
P = thomas ;
P = nina.

编辑,因为您需要父母可以留在第一或第二“位置”而不论性别,我建议

father(Father, Child) :-
   m(Father), (born(Father, _, Child) ; born(_, Father, Child)).

我在出生/ 3查询之前移动了性别测试,似乎更有效避免重复查询......

答案 1 :(得分:1)

问题是,由于存在无限递归,因此父亲显示born的方式有很多种。

m(thomas).                                                                  
m(leon).                                                                    
w(nina).                                                                    

born(thomas, nina, leon).                                                   

born_sym(Father, Mother, Child) :- born(Father, Mother, Child).             
born_sym(Father, Mother, Child) :- born(Mother, Father, Child).             

father(Father, Child) :- born_sym(Father, Mother, Child), m(Father).        
mother(Mother, Child) :- born_sym(Father, Mother, Child), w(Mother).        
parent(Parent, Child) :- (father(Parent, Child); mother(Parent, Child)).    

答案 2 :(得分:0)

另一个修复实际上是使用cut来避免无限递归:

m(thomas).
m(leon).
w(nina).

born(thomas, nina, leon) :- !.
born(Father, Mother, Child) :- born(Mother, Father, Child).

father(Father, Child) :- born(Father, Mother, Child), m(Father).
mother(Mother, Child) :- born(Father, Mother, Child), w(Mother).
parent(Parent, Child) :- father(Parent, Child); mother(Parent, Child).

另一种修复无限递归的方式,也许不是一种好的风格:)