2016-09-04 51 views
1

我有事实:male,femalechild
例如。使用序言找到家族树的姐妹关系

/* 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. 

姐妹关系,但它会导致重复响应。我如何改进以获得单一答案?

+2

您是指在两个姐妹之间写一个关系,或者只是两个参数中的一个应该是一个妹妹? (变量名称声称两个,实现声称只有一个) –

回答

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^绑定了变量 - 我们获得了一组中的所有实例,与Y的绑定无关。