I'm trying to make this but for a different language. In this language there are different kinds of names for uncles and aunts. We call paternal aunt something else and maternal aunt something else.
I came across a graph database 'neo4j'. I created 5 members. I got this approach to work just like I want. But the problem in this is that I've to create n * (n-1)
relationships. I'm create a full tree here and not just 5 members of a family.
Also, this is more like brute force. I'm creating all the possibilities.
I'm looking for a smarter way to do this. Creating rules like for example Father's sister = paternal-aunt
and Mother's sister = maternal-aunt
I also want queries Father's wife's sister
but don't want to define them separately.
You can create functions that establish the rules, e.g.:
def is_maternal_aunt(individual, member):
return member in individual.mother.sister
These can be arbitrary complex:
def is_maternal_aunt(individual, member):
return is_sister(individual.mother, member)
def is_sister(individual, member):
return individual.mother == member.mother
It will be a matter of design for which you consider are primary relationships and which are derived. You can probably derive everything from parent child relationships (and marriage).
You don't have to create the bidirectional relationships, and you also don't have to create short-cut-relationships, you can just infer the information in the other direction or across multiple steps.
MATCH path = allShortestPaths((p1:Person {name:"Jane"})-[*]-(p2:Person {name:"John"}))
RETURN [r in relationships(path) | type(r)] as rels
which would then return ["husband","father"] e.g. for an Father-in-Law
or ["mother","sister"] for an maternal aunt.
You can then map those tuples either still in cypher (with case
) or in your python program.
Prolog is a reasonable choice... For instance I have this small library to draw 'genealogy trees' like this
from this definition (genre definitions are used only to change node' color)
:- module(elizabeth, [elizabeth/0]).
:- use_module(genealogy).
elizabeth :- genealogy(elizabeth, 'Elizabeth II Family').
female('Elizabeth II').
female('Lady Elizabeth Bowes-Lyon').
female('Princess Mary of Teck').
female('Cecilia Cavendish-Bentinck').
parent_child('George VI', 'Elizabeth II').
parent_child('Lady Elizabeth Bowes-Lyon','Elizabeth II').
parent_child('George V', 'George VI').
parent_child('Princess Mary of Teck', 'George VI').
parent_child('Cecilia Cavendish-Bentinck','Lady Elizabeth Bowes-Lyon').
parent_child('Claude Bowes-Lyon', 'Lady Elizabeth Bowes-Lyon').
It requires SWI-Prolog and Graphviz.
edit adding some facts
female('Rose Bowes-Lyon').
parent_child('Cecilia Cavendish-Bentinck','Rose Bowes-Lyon').
parent_child('Claude Bowes-Lyon', 'Rose Bowes-Lyon').
and the rule
is_maternal_aunt(Person, Aunt) :-
parent_child(Parent, Person),
female(Parent),
parent_child(GranParent, Parent),
parent_child(GranParent, Aunt),
Aunt \= Parent.
we get
?- is_maternal_aunt(X,Y).
X = 'Elizabeth II',
Y = 'Rose Bowes-Lyon' ;