Algoritmiek: Minimum Spanning Trees

advertisement
Minimum Opspannende Bomen
Algoritmiek
Toepassingen
• Verbinden van punten met zo min mogelijk
bekabeling
– Netwerkontwerp
• Deelroute in andere algoritmen
• …
2
Algoritmiek
Probleemstelling
• Gegeven: een ongerichte graaf G=(N,A)
– Iedere kant representeert potentieel aan te
leggen verbinding
– Kosten/lengte voor elke kant
• Gevraagd: Een verzameling kanten F  A van
minimale totale kosten/lengte zodat de deelgraaf
G’=(N,F) samenhangend is
3
Algoritmiek
Minimum Opspannende Bomen
• Gegeven:
– Ongerichte samenhangende graaf G=(N,A)
– Lengte l(a) voor elke kant a in A.
• Gevraagd: Een boom T = (N, F), zodat
– F  A, d.w.z. T is een deelboom van G
– Elke knoop in G in T zit
– De totale lengte van alle kanten in T zo klein
mogelijk is.
• T is een (minimum) opspannende deelboom
4
Algoritmiek
Voorbeeld
4
e
c
e
3
c
3
a
3
2
11
5
4
a
3
2
1
1
5
4
d
b
d
1
b
17
1
f
Opspannende boom;
Geen minimum opspannende boom
5
4
Algoritmiek
f
Minimum opspannende
boom
Inhoud
• Een principe om minimum opspannende bomen te
laten groeien
• Twee greedy algoritmen + tijd en datastructuren:
– Het algoritme van Kruskal
– Het algoritme van Prim-Jarnik
6
Algoritmiek
Greedy aanpak
• Begin met een woud
zonder kanten T=(N,)
• Herhaal tot T een boom is
– Kies een kant {v,w},
zodat …
– Voeg deze kant aan T
toe
• Output T
7
• Noem T een goed woud
als T er een minimum
opspannende boom van G
bestaat waar T een
deelgraaf van is.
• We willen als invariant
van Greedy algoritme:
– T is een goed woud.
• Initieel geldt de invariant.
Algoritmiek
Goed woud: voorbeelden
4
e
4
e
3
c
5
4
3
2
5
4
a
3
a
c
3
2
d
1
b
d
1
f
e
f
5
4
a
1
c
3
1
b
4
3
2
d
1
b
1
8
Algoritmiek
f
Veilige kanten
• Stel T=(N,F) is een
goed woud.
• Een kant {v,w} is veilig,
als T’ =(N,F{v,w})
ook een goed woud is.
4
e
9
5
3
2
a
1
1
f
3
2
{a,b} is veilig
d
b
5
4
d
1
b
3
a
3
c
4
c
e
Algoritmiek
1
f
Greedy algoritme
• Begin met een woud zonder kanten T=(N,)
• Herhaal tot T een boom is
– Kies een veilige kant {v,w}
– Voeg {v,w} toe aan T
• Output T
Maar: welke kanten zijn er veilig??
10
Algoritmiek
Termen
• Deelboom in woud
• Een kant verlaat een
deelboom, als de kant
precies 1 eindpunt in
de deelboom heeft.
c
e
3
5
4
a
3
2
d
1
b
Elk van de rode
kanten verlaat de
deelboom met
knopen b en f
11
Algoritmiek
1
f
Stelling
• Stel T is een goed woud. Stel W is een deelboom
uit T. Laat de kant {v,w} deelboom W verlaten, en
minimum lengte hebben ten opzichte van alle
kanten die W verlaten. Dan is {v,w} veilig.
c
e
3
5
4
a
3
2
{d,f} is veilig
d
1
b
12
1
f
Algoritmiek
Bewijs (1)
• Stel T is een goed woud, W een deelboom van T,
en {v,w} kant van minimum lengte die W verlaat
(als in stelling).
• Er is een minimum opspannende boom T’ van G
die T als deelwoud heeft.
– Omdat T goed is.
• Als {v,w} in T’ zit, dan is {v,w} veilig: klaar.
• Stel dat {v,w} niet in T’ zit.
13
Algoritmiek
Bewijs (2)
• T’+{v,w} heeft een cycle.
• Deze cycle bevat zowel knopen
in W als knopen niet in W.
• Er moet nog een kant zijn die
W verlaat op de cycle, zeg a.
• T’+{v,w} – a is een
opspannende boom van G.
• De totale lengte van T’+{v,w}
– a is hooguit de totale lengte
van T’.
– Want l({v,w})  l(a).
• Dus {v,w} is veilig.
14
Algoritmiek
w
v
a
v
w
Greedy algoritme
• Begin met een woud zonder kanten T=(N,)
• Herhaal tot T een boom is
– Kies een kant {v,w} die minimum lengte heeft
t.o.v. alle kanten die een deelboom van T
verlaten
– Voeg {v,w} toe aan T
• Output T
Maar: hoe vind je zo’n kant snel?
15
Algoritmiek
Twee methoden: overzicht
• Kruskal
– Kanten worden in volgorde van stijgende lengte
bekeken
– Groeit verschillende boompjes in woud
• Prim-Jarnik
– Groeit 1 boom in woud
– Steeds wordt de goedkoopste uitgaande kant genomen
– Verschillende implementaties
16
Algoritmiek
Kruskal: algoritme
Sorteer de kanten op niet-dalende lengte, zeg k(1),
… , k(a).
Begin met een woud zonder kanten T=(N,).
for i = 1 to a
do if kant k(i) verbindt twee verschillende boompjes
in T
then voeg kant k(i) toe aan T.
(else: we doen niets met deze kant.)
Output T.
17
Algoritmiek
Kruskal: voorbeeld
4
e
c
3
5
4
a
3
2
d
1
b
1
18
Algoritmiek
f
Kruskal: voorbeeld
4
e
c
3
5
4
a
3
2
d
1
b
1
19
Algoritmiek
f
Kruskal: correctheid
• Invariant: T is een goed woud
• Blijft behouden omdat toegevoegde kant veilig is
(minimum lengte en verlaat deelboom van T)
– Mogelijk heeft deze deelboom 1 knoop
20
Algoritmiek
Kruskal: implementatie
• Belangrijkste problemen:
– Bijhouden deelbomen
– Testen of kant tussen twee verschillende deelbomen is
• Disjuncte verzamelingen datastructuur (union-find)
• Voor elke deelboom van T hebben we een verzameling,
die de knopen in de deelboom bevat.
• Initieel: create(v) voor elke knoop v.
• Testen of kant {v,w} tussen twee verschillende boompjes:
– Kijk of Find(v)  Find(w)
• Bij toevoegen van kant {v,w}: Union (Find(v), Find(w) ).
21
Algoritmiek
Kruskal: analyse
• Sorteren van de kanten kost O(a log a) = O(a log n).
• Acties op disjuncte verzamelingen datastructuur:
– O(n) creates
– O(a) find operaties
– O(n) union operaties
– O(n+a log* n) tijd totaal (eigenlijk: O(a a(n)).)
• Totaal O(a log n) tijd.
• Sneller wanneer we de kanten al gesorteerd hebben.
• Kan wat versneld worden in praktijk door te stoppen zodra
T n – 1 kanten heeft.
22
Algoritmiek
Prim-Jarnik: algoritme
Kies een knoop s.
B = {s}; T=(N, )
veilig
while (B  N)
do vind kant e = {v,w} die B verlaat met minimum
lengte (v  B, w  N – B)
T = T { e};
B = B { w };
Output T.
23
Algoritmiek
Prim-Jarnik: voorbeeld
4
e
c
3
5
4
a
3
2
d
1
b
1
24
Algoritmiek
f
Prim-Jarnik: voorbeeld
4
e
c
3
5
4
a
3
2
d
1
b
1
25
Algoritmiek
f
Prim-Jarnik: correctheid
• Invariant: T is een goed woud
• Blijft behouden omdat toegevoegde kant veilig is
(minimum lengte en verlaat B, een deelboom van
T)
26
Algoritmiek
Prim-Jarnik: Implementatie
• Houd voor elke knoop v in N – B bij
– De kortste kant van een knoop in B naar v:
kantnaarb[v]
– De lengte van deze kant: dichtbij[v]
27
Algoritmiek
Prim-Jarnik: Implementatie
Kies een knoop s.
B = {s}; T = (B, );
for all v do dichtbij[v] = maxint; kantnaarb[v] = ongedef;
for all {s,v}  A do dichtbij[v] = l({s,v}); kantnaarb[v] = {s,v};
while (B  N) (of: doe n – 1 keer)
do Vind v  N - B met kleinste waarde van dichtbij[v]
T = T {kantnaarb[v]};
B = B {v};
for all {v,w}  A met w  N - B
do if (l({v,w}) < dichtbij[w] )
then dichtbij[w] = l({v,w}); kantnaarb[w] = {v,w};
Output T.
28
Algoritmiek
Prim-Jarnik: voorbeeld
4
e
c
dichtbij kantnaarb
3
5
4
a
3
2
d
1
b
1
29
a maxint
ongedef
b 1
{b,f}
c
ongedef
d 1
{d,f}
e
ongedef
f
f
Algoritmiek
maxint
maxint
Prim-Jarnik: voorbeeld
4
e
c
dichtbij kantnaarb
3
a 2
5
4
a
3
2
1
b
1
30
b
c
d
f
Algoritmiek
{a,b}
maxint
ongedef
d 1
{d,f}
e
maxint
ongedef
f
maxint
ongedef
Prim-Jarnik: voorbeeld
4
e
c
dichtbij kantnaarb
3
a 2
5
4
a
3
2
b
31
5
{c,d}
maxint
ongedef
d
1
1
b
c
d
{a,b}
e
f
f
Algoritmiek
Prim-Jarnik: voorbeeld
4
e
c
dichtbij kantnaarb
3
a
5
4
a
3
2
c
d
b
32
4
{a,c}
3
{a,e}
d
1
1
b
e
f
f
Algoritmiek
Prim-Jarnik: voorbeeld
4
e
c
dichtbij kantnaarb
3
a
5
4
a
3
2
c
d
d
1
b
1
33
b
e
f
f
Algoritmiek
4
{a,c}
Prim-Jarnik: voorbeeld
4
e
c
dichtbij kantnaarb
3
a
5
4
a
3
2
c
d
d
1
b
1
34
b
e
f
f
Algoritmiek
Prim-Jarnik: Analyse
• Belangrijkste probleem: hoe vinden we de kant met de
kleinste waarde van dichtbij?
• Gebruik priority queue.
– Operaties: extract-min, update
• O(n) iteraties
• O(n) keer een extract min operatie.
• O(a) keer een update van een waarde.
• Met een gebalanceerde boom: O(a log n) tijd.
• Met Fibonacci of hollow heap: O(a + n log n) tijd
• Vergelijk met Kruskal: met heap is tijd vergelijkbaar op
dichte grafen; met queue
implementatie sneller op ijle
35
Algoritmiek
grafen, maar langzamer op dichte grafen.
Kruskal vs. Prim-Jarnik
• Kruskal
– Kanten in volgorde van stijgende lengte
– Groeit verschillende boompjes in woud
– O(a log n + a a(n) )
• Prim-Jarnik
– Groeit 1 boom in woud
– Steeds wordt de goedkoopste uitgaande kant genomen
– O(a + n log n)
36
Algoritmiek
Download