使用prolog从家谱中找到姐妹关系

时间:2016-09-04 07:59:22

标签: prolog

我有事实:malefemalechild 例如

/* tg and yem are mother and father. rika,kiku and susu are children*/

female(rika). 
female(tg).
male(kiku). 
male(susu).
male(yem).
child(rika,tg). 
child(kiku,tg).  
child(susu,tg).
child(rika,yem).
child(kiku,yem).  
child(susu,yem).

现在我需要一个查询来提取姐妹关系,如

sister(Sister1,Sister2):-
     female(Sister1),
     child(Sister1,X),child(Sister2,X), 
     Sister1 \= Sister2.

但它会导致重复的回复。如何改进以获得单一答案?

1 个答案:

答案 0 :(得分:2)

由于谓词始终终止,您可以使用谓词setof/3删除重复的解决方案:

?- setof(X-Y, sister(X,Y), Xs).
Xs = [rika-kiku, rika-susu].

第一个参数定义表示一个解决方案的术语模板,第二个参数定义要收集答案替换的目标,第三个参数是实例化模板术语列表。

如果父母有两个女儿成为姐妹,你仍然会有裁员。例如。如果你添加事实

female(ala).
child(ala,tg).
child(ala,yem).

到您的知识库,然后查询包含所有姐妹两次。

?- setof(X-Y, sister(X,Y), Xs).
Xs = [ala-kiku, ala-rika, ala-susu, rika-ala, rika-kiku, rika-susu].

一个原因是你用两个论点定义了你的谓词姐妹:姐妹是Sister1和她的兄弟姐妹之间的关系。 (你写它的方式,变量名Sister2给出了错误的直觉,兄弟姐妹也是女性,但这只是一个旁注)。如果我们只想知道谁是姐妹,这是一个集合(或一个地方的谓词) - 让我们称之为is_sister/1

is_sister(Xs) :-
  setof(X, Y^sister(X,Y), Xs).

如果查看答案替换,查询setof(X, sister(X,Y), Xs).setof(X, Y^sister(X,Y), Xs).会有很大差异。原因是Y在第一个模板中是免费的,您将根据Y的可能替换获得一组。在第二个例子中,Y^绑定变量 - 我们在一个集合中获得X的所有实例化,与Y的绑定无关。