8C080 deel BioModeling en bioInformatica

advertisement
Tentamen Algoritmen voor BIOMIM, 8C080,
22 april 2009,14.00-17.00u.
Vijf algemene opmerkingen
• Het tentamen bestaat uit 2 delen, een deel van BioModeling & bioInformatics en een
deel van BioMedische Beeldanalyse. Om het beoordelingsproces te bevorderen wordt je
verzocht de delen op verschillende bladen te maken. Voor ieder deel kun je een maximale
score van 5 punten behalen.
• Het deel van BioModeling en bioInformatica bestaat uit 3 opgaven en het deel van Biomedische Beeldanalyse uit 7 opgaven.
• Onderaan de laatste pagina van het BioModeling & bioInformatica deel staat voor iedere
opgave het maximale aantal punten dat voor de opgave behaald kan worden!
• In geval van een Python programma mag je gebruik maken van de graafrepresentatie van
een relatie en kun je van de op het formuleblad gegeven methodes gebruik maken.
• Enkel het formuleblad mag gebruikt worden, dus noch het boek noch de collegeaantekeningen noch een notebook zijn bij dit tentamen toegestaan.
Succes!!!
8C080 deel BioModeling en bioInformatica
Opgave 1
Laat G een ongerichte graaf zijn, waarbij er niet noodzakelijk een pad bestaat tussen ieder
tweetal knopen.
(a) Wat is de graad van een knoop?
(b) Wat is de graad van G?
(c) Wat is een samenhangende component van G?
(d) Ontwerp een Python programma dat een lijst van de groottes van de samenhangende
componenten van G retourneert.
Uitwerking opgave 1
(a) De graad van een knoop is het aantal buren dat de knoop heeft. Formeel, de graad
van knoop n is:
gr(n) = len(G.edges(n)) .
(b) De graad van een graaf is de hoogste graad van enig van zijn knopen.
gr(G) = (M AXn : n ∈ G.nodes() : gr(n)) .
1
(c) Een samenhangende component van een graaf is een subgraaf met de eigenschappen
dat
• er een pad bestaat tussen ieder tweetal knopen van de subgraaf, en
• de subgraaf niet uitgebreid kan worden met een knoop met deze eigenschap.
(d) Zoals op het college is uitgelegd kun je voor het bepalen van de samenhangende
componenten en dus ook hun grootte gebruikmaken van de ’BMT’-methode:
B(lack): die knopen waarvoor de samenhangende componenten al bepaald is of deel
uitmaken van de huidige samenhangende component
M(iddle): die knopen die al bezocht zijn en tot de huidige samenhangende component behoren maar nog nader beschouwd moeten worden, en
T(ail): de overige knopen die nog niet bezocht zijn.
Omdat er meerdere samenhangende componenten kunnen zijn is er een herhaling
nodig. Als we ons concentreren op de huidige samenhangende component, die in het
algoritme beschouwd wordt, dan bestaat deze uit knopen waartussen een pad bestaat,
maar de verzameling knopen hoeft nog niet maximaal te zijn. Met welke kno(o)p(en)
kan de component nog uitgebreid worden: met die knopen die een tak gemeenschappelijk hebben met een van de al bezochte knopen van de huidige component. Als
we die laatste bijhouden door ze ’middle’ te kleuren, dan moeten we gedurig na het
’black’ kleuren van een (’middle’) knoop nagaan of deze nog ’tail’ buren heeft. Deze
laatste moeten dan ’middle’ gekleurd worden.
Als we de grootte van de huidige component bijhouden in de variabele sizecomp en de
groottes van de reeds bepaalde samenhangende componenten in de lijst compsizelist
dan wordt het algoritme:
B=[]; M=[]; T=G.nodes()
#B+M+T=G.V
compsizelist=[]
sizecomp=0
while M or T:
if M:
# selecteer een willekeurige ’middle’ en kleur deze ’black’
# en verhoog het aantal knopen in de huidige component met 1
m=M[0]; B.append(m); M.remove(m); sizecomp=sizecomp+1
# kleur alle ’tail’ buren van m ’middle’
for p in G.neighbours(m):
if p in T:
T.remove(p); M.append(p)
else:
if sizecomp>0:
compsizelist.append(sizecomp)
sizecomp=0
# selecteer een willekeurige ’tail’ knoop
w=T[0]; T.remove(w); M.append(w)
compsizelist.append(sizecomp)
2
Normering opgave 1
onderdelen (a), (b) 1/4 punt
onderdeel (c): 1/2 punt, waarbij de term ’maximaal’ 1/4 punt waar is
onderdeel (d): 1 punt: analyse 0.4, progr 0.6
Opgave 2
Laat G een ongerichte graaf zijn.
(a) Geef de definitie van een pad in de graaf G.
(b) Wat is een enkelvoudig pad?
(c) Bewijs dat als er een pad in de graaf van een knoop u naar een knoop v bestaat, dat
er dan ook een enkelvoudig pad van u naar v is.
(d) Ontwerp een Python programma dat uit een pad van knoop u naar v gegeven als een
lijst van knopen een enkelvoudig pad van u naar v construeert.
Uitwerking opgave 2
(a) Een pad in een graaf is een rij knopen met de eigenschap dat er tussen ieder tweetal
opeenvolgende knopen een tak bestaat. Formeel:
v(i : 0 ≤ i ≤ r) rij knopen
met
(∀i : 0 ≤ i < r : (v(i), v(i + 1)) ∈ G.edges())
(b) Een enkelvoudig pad is een pad waarbij alle knopen verschillend zijn met uitzondering
van de begin- en eindknoop die gelijk mogen zijn. Formeel, pad v(i : 0 ≤ i ≤ r) is
een enkelvoudig pad als:
(∀i, j : 0 ≤ i < j ≤ r : v(i) = v(j) ⇒ (i = 0 ∧ j = r))
(c) We gebruiken voor het bewijs het principe van volledige inductie:
Inductiehypothese: “Ieder pad ter lengte r van u naar v is te reduceren tot een
enkelvoudig pad r van u naar v”
basisstap r = 0: Als r = 0 dan bestaat het pad uit een enkele knoop en is dus per
definitie enkelvoudig.
3
inductiestap: Stel dat ieder pad ter lengte hoogstens r van u naar v te reduceren
is tot een enkelvoudig pad van u naar v. Dan moeten we nu laten zien dat ook
ieder pad ter lengte r + 1 van u naar v ook te reduceren is tot een enkelvoudig
pad van u naar v.
Laat p een pad ter lengte r + 1 van u naar v zijn. Als p enkelvoudig is, dan
hoeven we verder niets te doen, dus stel dat p niet enkelvoudig is. Dan is er een
knoop w verschillend van u en v die minstens 2 keer voorkomt. Laat firstw
het eerste voorkomen van w op p zijn en lastw het laatste voorkomen. Dan is
p[0:firstw+1] een pad van u naar w en p[lastw:] een pad van w naar v, en
de concatenatie van deze twee is een pad van u naar v met een lengte kleiner dan
r + 1. Op dit laatste pad kunnen we de inductiehypothese toepassen en dus is
het te reduceren tot een enkelvoudig pad van u naar v. Oftewel ons originele pad
van u naar v is dus te reduceren tot een enkelvoudig pad van u naar v.
(d) Het Python programma is een implementatie van de oplossing gegeven in onderdeel
(c). Omdat we van iedere knoop op het pad het eerste en het laatste voorkomen, die
als de knoop maar één keer voorkomt, dus aan elkaar gelijk zijn, moeten bepalen,
construeren we allereerst een dictionary met als key het knoopnummer en als value
de lijst van voorkomens van de knoop op het pad:
# p is het pad van u naar v bestaande uit de lijst van knopen op het pad.
d={}
i=0
while i<len(p):
if p[i] not in d: d[p[i]]=[i]
else: d[p[i]].append(i)
i=i+1
enkelvp=[]
i=0
while i<len(p):
w=p[i]
firstw=i; lastw=d[w][-1]
if firstw != lastw:
i=lastw+1
else:
i=i+1
enkelvp.append(w)
Normering opgave 2
onderdelen (a), (b), (c): 1/3 punt
onderdeel d: 1 punt: analyse 0.4, progr 0.6
4
Opgave 3
Laat G een ongerichte graaf zijn waarbij iedere knoop een kleur heeft. De kleur van knoop
n wordt gegeven door colour[n]. Het doel van deze opgave is een recursief algoritme te
ontwerpen dat retourneert of de graaf G een pad van 10 verschillende knopen heeft die
allen dezelfde kleur hebben. Hierbij kun je als representatie van een pad in Python een
lijst gebruiken. Ontwerp dit programma in de volgende 3 stappen.
(a) Laat p een pad ter lengte k van verschillende knopen met dezelfde kleur zijn. Ontwerp
een methode met p als parameter, die een lijst l van alle paden ter lengte k + 1 van
verschillende knopen met dezelfde kleur en die als beginstuk p hebben, genereert.
(Mogelijkerwijs zijn er 0 zulke paden.)
(b) Ontwerp een recursief algoritme dat retourneert of de graaf G een pad van 10 verschillende knopen heeft die allen dezelfde kleur hebben en die beginnen in een vaste
beginknoop n. N.B.: Een oplossing zonder recursie wordt niet goed gerekend.
(c) Gebruik de methode die je onder (b) hebt ontworpen om te bepalen of de graaf G een
pad van 10 verschillende knopen heeft die allen dezelfde kleur hebben.
Uitwerking opgave 3
(a) def extendWithOneNodeOfSameColour(p):
l=[]
if p==[]:
l=G.nodes()[:]
else:
# p is not empty
lastnode=p[-1]
color=colour[lastnode]
for nb in G.neighbors(lastnode):
if (nb not in p) and (colour[nb]==color):
l.append(p[:]+[nb])
return l
(b) def extendWithOneNodeOfSameColour(p):
l=[]
# p is not empty
lastnode=p[-1]
color=colour[lastnode]
for nb in G.neighbors(lastnode):
if (nb not in p) and (colour[nb]==color):
l.append(p[:]+[nb])
return l
def pathlength10samecolor(p):
allsolutions=[]
5
l=extendWithOneNodeOfSameColour(p)
for newp in l:
# newp is a path of different nodes that
# all have the same color and
# has one more node than p
if len(newp)==10:
allsolutions.append(newp)
else:
allsolutions.extend(pathlength10samecolor(newp))
return allsolutions
allsolutions=pathlength10samecolor([n])
if allsolutions:
print True
else:
print False
(c) pathfound=False
i=0
while (i<len(G.nodes()) and not pathfound:
allsolutions=pathlength10samecolor([G.nodes()[i]])
pathfound=allsolutions!=[]
i=i+1
Normering opgave 3
onderdelen (a) en (c): 1/4 punt
onderdeel (b): 1/2 punt: analyse 0.2, progr 0.3
Honorering: opgave 1 maximaal 2 punt
opgave 2 maximaal 2 punt
opgave 3 maximaal 1 punt
6
Download