Arbre genealògic

Volem utilitzar un digraf de networkx per a representar un arbre genealògic familiar. Els nodes del graf seran els noms de les persones (strings). Cada persona rebrà com a màxim dues arestes dirigides des dels seus dos progenitors, en cas que es coneguin. A més a més, cada node tindrà associat un atribut de nodes de networkx, anomenat 'naix', corresponent a la data de naixement. Aquest atribut serà una instància de la classe datetime.date.

Per exemple, el següent arbre genealògic representa una família amb 20 persones:

../../../_images/familia1.svg

Deseu totes les funcions d’aquest exercici en el mòdul de nom genealogia.py.

Funció afegir_persona

genealogia.afegir_persona(g, nom, data, mare, pare)
Paràmetres:
  • g (networkx.DiGraph) – Graf que representa un arbre genealògic

  • nom (str) – nom d’una persona

  • data (datetime.date) – data del seu naixement

  • mare (str) – noms del seu primer progenitor

  • pare (str) – noms del seu segon progenitor

Afegeix a g la persona nom, assignant-li com a data de naixement data i com a progenitors mare i pare. Si un dels dos progenitors és desconegut, el valor del paràmetre pare i/o mare serà un string buit; en aquest cas, no s’ha d’establir la relació de parentesc del(s) progenitor(s) desconegut(s). Quan s’especifiquen, tant pare com mare han de ser nodes ja existents al graf g.

Per exemple, el següent exemple crea el graf d’un fragment de l’arbre genealògic de la figura anterior:

>>> import networkx as nx
>>> from datetime import date
>>> from genealogia import afegir_persona

>>> g = nx.DiGraph()
>>> afegir_persona(g, 'Nadia', date(1910, 5, 10), '', '')
>>> afegir_persona(g, 'Felip', date(1910, 6, 9), '', '')
>>> afegir_persona(g, 'Maria', date(1938, 10, 10), '', '')
>>> afegir_persona(g, 'Robert', date(1936, 2, 20), 'Nadia', 'Felip')
>>> afegir_persona(g, 'Neus', date(1938, 12, 8), 'Nadia', 'Felip')
>>> afegir_persona(g, 'Pau', date(1961, 3, 7), 'Maria', 'Robert')
>>> sorted(g.nodes)
['Felip', 'Maria', 'Nadia', 'Neus', 'Pau', 'Robert']
>>> g.number_of_edges()
6
>>> sorted(g['Felip'])
['Neus', 'Robert']
>>> g.nodes['Nadia']['naix']
datetime.date(1910, 5, 10)
>>> g.nodes['Robert']['naix']
datetime.date(1936, 2, 20)

Al fitxer tests-afegir.txt hi teniu altres jocs de proves , incloent la creació de l’arbre genealògic de l’exemple sencer.

Nota

Per tal de poder fer proves fàcilment us proporcionem el fitxer familia.py, on hi ha la funció graf_familia(), que crea i retorna el graf complet de l’exemple de la figura. Per comoditat, podeu fer servir aquesta funció en el desenvolupament de la resta d’apartats. Cal, però, que la hàgiu desenvolupat correctament la funció afegir_persona().

Funció nets

genealogia.nets(g, nom)
Paràmetres:
  • g (networkx.DiGraph) – Graf que representa un arbre genealògic

  • nom (str) – nom d’una persona

Retorna una llista ordenada lexicogràficament amb els noms dels nets de la persona donada. A la llista retornada no hi pot haver noms repetits.

Per exemple, essent g el graf genealògic corresponent a la figura anterior, aquesta funció ha de respondre així:


>>> from genealogia import nets
>>> nets(g, 'Gregori')
['Joan', 'Mireia']
>>> nets(g, 'Mireia')
[]
>>> nets(g, 'Elisenda')
['David', 'Olga', 'Oriol']
>>> nets(g, 'Felip')
['Carlota', 'Pau']

Disposeu de jocs de proves complementaris al fitxer tests-nets.txt.

Funció avis

genealogia.avis(g, nom)
Paràmetres:
  • g (networkx.DiGraph) – Graf que representa un arbre genealògic

  • nom (str) – nom d’una persona

Retorna una llista ordenada lexicogràficament amb els noms dels avis coneguts de la persona donada. A la llista retornada no hi pot haver noms repetits.

Per exemple, essent g el graf genealògic corresponent a la figura anterior, aquesta funció ha de respondre així:


>>> from genealogia import avis
>>> avis(g, 'Nil')
['Carlota', 'Martha', 'Oriol', 'Pau']
>>> avis(g, 'Mireia')
['Gregori', 'Higinio', 'Remei']
>>> avis(g, 'Remei')
[]

Disposeu de jocs de proves complementaris al fitxer tests-avis.txt.

Funció germans

genealogia.germans(g, nom)
Paràmetres:
  • g (networkx.DiGraph) – Graf que representa un arbre genealògic

  • nom (str) – nom d’una persona

Retorna el conjunt de noms (un set de python) amb els noms dels germans de la persona donada. Considerem que dues persones són germanes si en el graf hi consta que són filles del mateix pare i mare.

Per exemple, essent g el graf genealògic corresponent a la figura anterior, aquesta funció ha de respondre així:


>>> from genealogia import germans
>>> germans(g, 'Oriol') == {'Olga', 'David'}
True
>>> germans(g, 'Robert') == {'Neus'}
True
>>> germans(g, 'Pau') == set()
True

Disposeu de jocs de prova al fitxers tests-germans.txt.

Funció Primer_avantpassat

genealogia.primer_avantpassat(g, nom)
Paràmetres:
  • g (networkx.DiGraph) – Graf que representa un arbre genealògic

  • nom (str) – nom d’una persona

Retorna el nom de l’avanpassat de la persona donada que va néixer abans, segons consta en g.

Per exemple, essent g el graf genealògic corresponent a la figura anterior, aquesta funció ha de respondre així:


>>> from genealogia import primer_avantpassat
>>> primer_avantpassat(g, 'Nil')
'Nadia'
>>> primer_avantpassat(g, 'Mireia')
'Felip'
>>> primer_avantpassat(g, 'Maria')
'Maria'

Disposeu de jocs de prova al fitxers tests-avantpassat.txt.

Solucions

Disposeu de les solucions proposades al fitxer genealogia.py.