How can remove the duplicate search result

Hi, I want to use prolog to make One Hundred Years of Solitude 's family tree, and when i try to search result, I find there are the duplicate part? So could you tell me how to fix it? Or could you give me some advice to let it better? Thanks!

My code is here:

% One Hundred Years of Solitude 's family tree in Prolog
% Wiki picture: https://en.wikipedia.org/wiki/One_Hundred_Years_of_Solitude#/media/File:One_Hundred_Years_Of_Solitude_Buendia%27s_Family_Tree.svg

% See here:https://codereview.stackexchange.com/questions/143116/family-tree-in-prolog

% predicate(X,Y) means "X is Y 's XXX ."
% eg. father(X,Y) means "X is Y 's father."

% Generation I
man('José Arcadio Buendía').
woman('Úrsula Iguarán').

marry('JosĂ© Arcadio BuendĂ­a','Úrsula IguarĂĄn').

% Generation II
man('José Arcadio').
man('Colonel Aureliano BuendĂ­a').
woman('Amaranta').
woman('Remedios Moscote').
woman('Rebeca').
woman('Pilar Ternera').

parent('José Arcadio Buendía','José Arcadio').
parent('José Arcadio Buendía','Colonel Aureliano Buendía').
parent('José Arcadio Buendía','Amaranta').
parent('Úrsula IguarĂĄn','JosĂ© Arcadio').
parent('Úrsula Iguarán','Colonel Aureliano Buendía').
parent('Úrsula Iguarán','Amaranta').
marry('Colonel Aureliano BuendĂ­a','Remedios Moscote').
marry('Rebeca','José Arcadio').
amorousAffairsy('Pilar Ternera','José Arcadio').
amorousAffairsy('Pilar Ternera','Colonel Aureliano BuendĂ­a').

% Generation III
woman('Aureliano José').
woman('Arcadio').
man('Santa SofĂ­a de la Piedad').

marry('Santa SofĂ­a de la Piedad','Arcadio').
illegitimateChild('17 sons by unknown women','Colonel Aureliano BuendĂ­a').
parent('Pilar Ternera','Arcadio').
parent('José Arcadio Buendía','Arcadio').
% Generation IV
woman('Remedios the Beauty').
man('José Arcadio II').
man('Aureliano II').
woman('Petra Cotes').
woman('Fernanda del Carpio').

marry('Aureliano II','Fernanda del Carpio').
amorousAffairsy('Petra Cotes','Aureliano II').
parent('Santa SofĂ­a de la Piedad','Remedios the Beauty').
parent('Santa Sofía de la Piedad','José Arcadio II').
parent('Santa SofĂ­a de la Piedad','Aureliano II').
parent('Arcadio','Remedios the Beauty').
parent('Arcadio','José Arcadio II').
parent('Arcadio','Aureliano II').
% Generation V
man('GastĂłn').
man('José Arcadio').
man('Mauricio Babilonia').
woman('Amaranta Úrsula').
woman('Renata Remedios').

marry('Amaranta Úrsula','Gastón').
amorousAffairsy('Renata Remedios','Mauricio Babilonia').
parent('Aureliano II','Amaranta Úrsula').
parent('Aureliano II','José Arcadio').
parent('Aureliano II','Renata Remedios').
parent('Fernanda del Carpio','Amaranta Úrsula').
parent('Fernanda del Carpio','José Arcadio').
parent('Fernanda del Carpio','Renata Remedios').
% Generation VI
man('Aureliano Babilonia').
parent('Mauricio Babilonia','Aureliano Babilonia').
parent('Renata Remedios','Aureliano Babilonia').

amorousAffairsy('Amaranta Úrsula','Aureliano Babilonia').
% Generation VII
man('Aureliano').
parent('Aureliano Babilonia','Aureliano').
parent('Amaranta Úrsula','Aureliano').

% --------  Start defining the relationships -------- 

:- discontiguous man/1, woman/1, marry/2,amorousAffairsy/2.

father(X,Y) :- parent(X,Y), man(X), X\=Y.
mother(X,Y) :- parent(X,Y), woman(X), X\=Y.
%parent(X,Y) :- father(X,Y); mother(X,Y).
parents(X,Y,Z) :- (father(X,Z), mother(Y,Z)); (father(Y,Z), mother(X,Z)), X\=Y, X\=Z,Z\=Y.
marry(X,Y) :- marry(X,Y), marry(Y,X), X\=Y.
amorousAffairsy(X,Y) :- amorousAffairsy(X,Y), amorousAffairsy(Y,X), X\=Y.
child(X,Y) :- father(Y,X); mother(Y,X),X\=Y.
illegitimateChild(X,Y) :- illegitimateChild(X,Y), X\=Y.
son(X,Y) :- child(X,Y),man(X),X\=Y.
daughter(X,Y) :- child(X,Y),woman(X),X\=Y.

grandma(X,Y) :- (mother(X,W), mother(W,Y)); (father(X,W), mother(W,Y)),X\=Y.
grandpa(X,Y) :- (father(X,W), father(W,Y)); (mother(X,W), father(W,Y)),X\=Y.
grandparents(X,Y,Z) :- (grandma(X,Z), grandpa(Y,Z)); (grandma(Y,Z), grandpa(X,Z)), X\=Y, X\=Z,Z\=Y.

siblings(A,B) :- father(F,A), father(F,B), mother(M,A), mother(M,B), A\=B.
uncle(U,N) :- man(U), ((siblings(U,M), father(M,N)) ; (siblings(U,F), father(F,N))),U\=N.
aunt(U,N) :- woman(U), ((siblings(U,M), mother(M,N)) ; (siblings(U,F), mother(F,N))),U\=N.

sister(X,Y) :- siblings(X,Y), woman(X), X\=Y.
brother(X,Y) :- siblings(X,Y), man(X), X\=Y.

ancestor(X,Y):-parent(X,Y),X\=Y.
ancestor(X,Y):-parent(X,Z),ancestor(Z,Y).

% --------  End defining the relationships -------- 

It seems that the aunt/2

aunt(U,N) :- woman(U), ((siblings(U,M), mother(M,N)) ; (siblings(U,F), mother(F,N))),U\=N.

should have been

aunt(U,N) :- woman(U), siblings(U,M), mother(M,N), U\=N.

What is the duplicate (siblings(U,F), mother(F,N)) alternative for?

Try reading the program as a natural language text:

U is an aunt of N if

  1. U is a woman,
  2. there is an M such that
    1. U is a sibling of M,
    2. M is the mother of N,
  3. U is not N.

Compare that to your original program:

U is an aunt of N if

  1. U is a woman,
  2. at least one of these is true:
    1. there is an M such that
      1. U is a sibling of M,
      2. M is the mother of N;
    2. there is an F such that
      1. U is a sibling of F,
      2. F is the mother of N.
      3. (But what is this for? This is the same as “there is an M 
”, only with M renamed to F?)
  3. U is not N.

Thus, your actual problem is not about removing duplicate search result, but about how to state the problem in Prolog. :slight_smile:

@edom
Sorry, i am wrong when i coding, it means aunt of father’s or mother’s . So it is correct code.

aunt(U,N) :- woman(U), ((siblings(U,M), father(M,N)); (siblings(U,F), mother(F,N))), U\=N.

But i have another quesion? How to descripte mutual relationship? For exmple. XX is YY 's sister.
YY is XX’s sister too.

I try to edit my code,here it this:



% See here:https://codereview.stackexchange.com/questions/143116/family-tree-in-prolog

% predicate(X,Y) means "X is Y 's XXX ."
% eg. father(X,Y) means "X is Y 's father."

:- encoding(utf8).
:- discontiguous man/1, woman/1, marry/2,amorousAffairsy/2,parent/2,father/2,mother/2,child/2,illegitimateChild/2.

% Generation I
man('José Arcadio Buendía').
woman('Úrsula Iguarán').

marry('JosĂ© Arcadio BuendĂ­a','Úrsula IguarĂĄn').

% Generation II
man('José Arcadio').
man('Colonel Aureliano BuendĂ­a').
woman('Amaranta').
woman('Remedios Moscote').
woman('Rebeca').
woman('Pilar Ternera').

parent('José Arcadio Buendía','José Arcadio').
parent('José Arcadio Buendía','Colonel Aureliano Buendía').
parent('José Arcadio Buendía','Amaranta').
parent('Úrsula IguarĂĄn','JosĂ© Arcadio').
parent('Úrsula Iguarán','Colonel Aureliano Buendía').
parent('Úrsula Iguarán','Amaranta').
marry('Colonel Aureliano BuendĂ­a','Remedios Moscote').
marry('Rebeca','José Arcadio').
amorousAffairsy('Pilar Ternera','José Arcadio').
amorousAffairsy('Pilar Ternera','Colonel Aureliano BuendĂ­a').

% Generation III
woman('Aureliano José').
woman('Arcadio').
man('Santa SofĂ­a de la Piedad').

marry('Santa SofĂ­a de la Piedad','Arcadio').
illegitimateChild('17 sons by unknown women','Colonel Aureliano BuendĂ­a').
parent('Pilar Ternera','Arcadio').
parent('José Arcadio Buendía','Arcadio').
% Generation IV
woman('Remedios the Beauty').
man('José Arcadio II').
man('Aureliano II').
woman('Petra Cotes').
woman('Fernanda del Carpio').

marry('Aureliano II','Fernanda del Carpio').
amorousAffairsy('Petra Cotes','Aureliano II').
parent('Santa SofĂ­a de la Piedad','Remedios the Beauty').
parent('Santa Sofía de la Piedad','José Arcadio II').
parent('Santa SofĂ­a de la Piedad','Aureliano II').
parent('Arcadio','Remedios the Beauty').
parent('Arcadio','José Arcadio II').
parent('Arcadio','Aureliano II').
% Generation V
man('GastĂłn').
man('José Arcadio').
man('Mauricio Babilonia').
woman('Amaranta Úrsula').
woman('Renata Remedios').

marry('Amaranta Úrsula','Gastón').
amorousAffairsy('Renata Remedios','Mauricio Babilonia').
parent('Aureliano II','Amaranta Úrsula').
parent('Aureliano II','José Arcadio').
parent('Aureliano II','Renata Remedios').
parent('Fernanda del Carpio','Amaranta Úrsula').
parent('Fernanda del Carpio','José Arcadio').
parent('Fernanda del Carpio','Renata Remedios').
% Generation VI
man('Aureliano Babilonia').
parent('Mauricio Babilonia','Aureliano Babilonia').
parent('Renata Remedios','Aureliano Babilonia').

amorousAffairsy('Amaranta Úrsula','Aureliano Babilonia').
% Generation VII
man('Aureliano').
parent('Aureliano Babilonia','Aureliano').
parent('Amaranta Úrsula','Aureliano').

% --------  Start defining the relationships -------- 

father(X,Y) :- parent(X,Y), man(X), X\=Y.
mother(X,Y) :- parent(X,Y), woman(X), X\=Y.
%parent(X,Y) :- father(X,Y); mother(X,Y).
parents(X,Y,Z) :- (father(X,Z), mother(Y,Z)); (father(Y,Z), mother(X,Z)), X\=Y, X\=Z, Z\=Y.
couple(X,Y) :- marry(X,Y), X\=Y. 
couple(Y,X) :- marry(X,Y), X\=Y.
amorousAffairsy(X,Y) :- amorousAffairsy(X,Y), amorousAffairsy(Y,X), X\=Y.
child(X,Y) :- father(Y,X); mother(Y,X), X\=Y.
illegitimateChild(X,Y) :- illegitimateChild(X,Y), X\=Y.
son(X,Y) :- child(X,Y), man(X), X\=Y.
daughter(X,Y) :- child(X,Y), woman(X), X\=Y.

grandma(X,Y) :- (mother(X,W), mother(W,Y)); (father(X,W), mother(W,Y)), X\=Y.
grandpa(X,Y) :- (father(X,W), father(W,Y)); (mother(X,W), father(W,Y)), X\=Y.
grandparents(X,Y,Z) :- (grandma(X,Z), grandpa(Y,Z)); (grandma(Y,Z), grandpa(X,Z)), X\=Y, X\=Z, Z\=Y.

siblings(A,B) :- father(F,A), father(F,B), mother(M,A), mother(M,B), A\=B.
%siblings(B,A) :- father(F,A), father(F,B), mother(M,A), mother(M,B), A\=B.
uncle(U,N) :- man(U), ((siblings(U,M), father(M,N)); (siblings(U,F), mother(F,N))), U\=N.
aunt(U,N) :- woman(U), ((siblings(U,M), father(M,N)); (siblings(U,F), mother(F,N))), U\=N.

sister(X,Y) :- siblings(X,Y), woman(X), woman(Y), X\=Y.
%sister(Y,X) :- siblings(X,Y), woman(X), woman(Y), X\=Y.
brother(X,Y) :- siblings(X,Y), man(X), man(Y), X\=Y.
%brother(Y,X) :- siblings(X,Y), man(X), man(Y), X\=Y.

ancestor(X,Y):- parent(X,Y), X\=Y.
ancestor(X,Y):- parent(X,Z), ancestor(Z,Y).

% --------  End defining the relationships -------- 

Your current definition of sister represents ‘sisters’ since both arguments have to be woman.
Did you want sister(X,Y), to mean ‘X is a sister of Y’, in which case, Y could be either a man or a woman.

Thanks. But I mean if i try search sisters(X,Y) on the database, I hope X and Y have mutual relationship.Because X is Y’s sister and Y is X’s sister too. The database will introduce these conclusions based on facts, but not is mutual relationship. And i try to write rule to do this like sister(Y,X):-sister(X,Y), This will bring infinite recursion of the query, the StackOverflow suggest me to use another predicate to write rule.But i am not sure,so could you give me some advice? Thanks !

A generic way of removing duplicates from a goal is to replace the call to goal(..., X) by:

setof(X, goal(..., X), Xs), member(X, Xs).

Explanation:
setof(X, goal(..., X), Xs) finds all the X values that are a solution to goal(..., X) and puts them into the list Xs (without duplicates); member(X, Xs) gets the results one-by-one on backtracking.

Another way of removing duplicates is to use sort/2. Or (less efficiently): list_to_set/2.

The trick is called stratification, i.e. making layers. The lowest layer are the facts:

sister_fact(a, b).
sister_fact(c, d).
...

sister(X,Y) :- sister(X,Y).
sister(X,Y) :- sister(Y,X).

note The sister relation is in fact not symmetric, Mary is the sister of Bob, but Bob is the brother of Mary.

1 Like

Jan, should that be:

sister(X,Y) :- sister_fact(X,Y).
sister(X,Y) :- sister_fact(Y,X).

Yes. Sorry

Thanks to all people who is helping me!
So you suggestion only apply to X,Y who are women,and there have symmetric?
In fact, i think couple may can use grammar like this because of symmetric. Do you think that my thinking is wrong? What about you? Could you tell me? Thanks!

like this:

marry(A,B).
marry(C,D).
....
couple(X,Y) :- marry(Y,X).
couple(X,Y) :- marry(X,Y).

Thank you,

Jan said the sister relation is in fact not symmetric.

So perhaps add sex fact more useful? like this?

sister(X,Y) :- sister_fact(X,Y), woman(X), woman(Y).
sister(X,Y) :- sister_fact(Y,X), woman(X), woman(Y).

If X,Y has symmetric’s sister relation, they should be as woman.

X is a sister of Y if X and Y share both parents and X is female. I guess it is your task to write that down in Prolog. Which facts do you need?

Thanks. And I think i have no problem about this.

I reorganized the relationship and corrected the problem.

Here are my code:

% One Hundred Years of Solitude 's family tree in Prolog
% Wiki picture: https://en.wikipedia.org/wiki/One_Hundred_Years_of_Solitude#/media/File:One_Hundred_Years_Of_Solitude_Buendia%27s_Family_Tree.svg


% See here:https://codereview.stackexchange.com/questions/143116/family-tree-in-prolog

% predicate(X,Y) means "X is Y 's XXX ."
% eg. father(X,Y) means "X is Y 's father."

:- encoding(utf8).
:- discontiguous man/1, woman/1, marry/2,amorousAffairsy/2,parent/2,father/2,mother/2,child/2,illegitimateChild/2.

% Generation I
man('José Arcadio Buendía').
woman('Úrsula Iguarán').

marry('JosĂ© Arcadio BuendĂ­a','Úrsula IguarĂĄn').

% Generation II
man('José Arcadio').
man('Colonel Aureliano BuendĂ­a').
woman('Amaranta').
woman('Remedios Moscote').
woman('Rebeca').
woman('Pilar Ternera').

parent('José Arcadio Buendía','José Arcadio').
parent('José Arcadio Buendía','Colonel Aureliano Buendía').
parent('José Arcadio Buendía','Amaranta').
parent('Úrsula IguarĂĄn','JosĂ© Arcadio').
parent('Úrsula Iguarán','Colonel Aureliano Buendía').
parent('Úrsula Iguarán','Amaranta').
marry('Colonel Aureliano BuendĂ­a','Remedios Moscote').
marry('Rebeca','José Arcadio').
amorousAffairsy('Pilar Ternera','José Arcadio').
amorousAffairsy('Pilar Ternera','Colonel Aureliano BuendĂ­a').

% Generation III
woman('Aureliano José').
woman('Arcadio').
man('Santa SofĂ­a de la Piedad').

marry('Santa SofĂ­a de la Piedad','Arcadio').
illegitimateChild('17 sons by unknown women','Colonel Aureliano BuendĂ­a').
parent('Pilar Ternera','Arcadio').
parent('José Arcadio Buendía','Arcadio').
% Generation IV
woman('Remedios the Beauty').
man('José Arcadio II').
man('Aureliano II').
woman('Petra Cotes').
woman('Fernanda del Carpio').

marry('Aureliano II','Fernanda del Carpio').
amorousAffairsy('Petra Cotes','Aureliano II').
parent('Santa SofĂ­a de la Piedad','Remedios the Beauty').
parent('Santa Sofía de la Piedad','José Arcadio II').
parent('Santa SofĂ­a de la Piedad','Aureliano II').
parent('Arcadio','Remedios the Beauty').
parent('Arcadio','José Arcadio II').
parent('Arcadio','Aureliano II').
% Generation V
man('GastĂłn').
man('José Arcadio').
man('Mauricio Babilonia').
woman('Amaranta Úrsula').
woman('Renata Remedios').

marry('Amaranta Úrsula','Gastón').
amorousAffairsy('Renata Remedios','Mauricio Babilonia').
parent('Aureliano II','Amaranta Úrsula').
parent('Aureliano II','José Arcadio').
parent('Aureliano II','Renata Remedios').
parent('Fernanda del Carpio','Amaranta Úrsula').
parent('Fernanda del Carpio','José Arcadio').
parent('Fernanda del Carpio','Renata Remedios').
% Generation VI
man('Aureliano Babilonia').
parent('Mauricio Babilonia','Aureliano Babilonia').
parent('Renata Remedios','Aureliano Babilonia').

amorousAffairsy('Amaranta Úrsula','Aureliano Babilonia').
% Generation VII
man('Aureliano').
parent('Aureliano Babilonia','Aureliano').
parent('Amaranta Úrsula','Aureliano').

% --------  Start defining the relationships -------- 

% The couple relation is in fact symmetric.
couple(X,Y) :- marry(X,Y), X\=Y. 
couple(X,Y) :- marry(Y,X), X\=Y.

% The amorous affairsy relation is also in fact symmetric.
illegitimateLover(X,Y) :- amorousAffairsy(X,Y); amorousAffairsy(Y,X), X\=Y.

father(X,Y) :- parent(X,Y), man(X), X\=Y.
mother(X,Y) :- parent(X,Y), woman(X), X\=Y.

% X or Y is Z's parents. X may be Z's father or mother,Y may be Z's mother or father.
parents(X,Y,Z) :- (father(X,Z), mother(Y,Z)); (father(Y,Z), mother(X,Z)), X\=Y, X\=Z, Z\=Y.
parents(X,Y,Z) :- (father(X,Z), mother(Y,Z)); (father(Y,Z), mother(X,Z)), X\=Y, X\=Z, Z\=Y.

% X is Y's child. => Y is X's father or mother.
child(X,Y) :- (father(Y,X); mother(Y,X)), X\=Y.
illegitimateChild(X,Y) :- illegitimateChild(X,Y), X\=Y.
son(X,Y) :- child(X,Y), man(X), X\=Y.
daughter(X,Y) :- child(X,Y), woman(X), X\=Y.

% Grandma or grandpa is someone's mother or father 's mother or father.
grandma(X,Y) :- (mother(X,M), mother(M,Y)); (mother(X,F),father(F,Y)), X\=Y.
grandpa(X,Y) :- (mother(X,M), father(M,Y)); (father(X,F), father(F,Y)), X\=Y.
grandparents(X,Y,Z) :- (grandma(X,Z), grandpa(Y,Z)); (grandma(Y,Z), grandpa(X,Z)), X\=Y, X\=Z, Z\=Y.

% Siblings need having same father and mother.
siblings(A,B) :- father(F,A), father(F,B), mother(M,A), mother(M,B), A\=B.

% Uncle or aunt is someone's mother or father 's siblings.
uncle(U,N) :- man(U), ((siblings(U,F), father(F,N)); (siblings(U,M), mother(M,N))), U\=N.
aunt(A,N) :- woman(A), ((siblings(A,F), father(F,N)); (siblings(A,F), mother(F,N))), A\=N.

% Y's sister or brother is woman or man. 
sister(X,Y) :- siblings(X,Y), woman(X), X\=Y.
brother(X,Y) :- siblings(X,Y), man(X), X\=Y.

% Ancestor may be someone's parent or they are someone's parent's ancestor.
ancestor(X,Y):- parent(X,Y), X\=Y.
ancestor(X,Y):- parent(X,Z), ancestor(Z,Y).

% --------  End defining the relationships --------