O(V 2 ) bwfs(v, i=1) λ[v] = i for each neighbor u of v if 0 < λ[u] < i bwfs(u, i) for each neighbor u of v if λ[u] = 0 bwfs(u, i+1) Bacwards-first search; traverserer en graf med kvadratisk worst-casekjøretid. Fra «Pessimal Algorithms and Simplexity Analysis» av Andrei Broder og Jorge Stolfi (1986) <http://citeseer.ist.psu.edu/334813.html>. Den har også perler som SlowSort og Reluctant Search. 1
Amøbeproblemet nok en gang. Hva er 1+2+4+ +n/2? 2 Skal la være å trekke frem binærtrefiguren igjen ;-) La oss se på det på en litt annen måte.
Zenos paradoks. Hvis vi skal fra x til y må vi først innom A. Og fra A til y må vi først innom B osv. Hvordan kommer vi noensinne frem? La oss for enkelhets skyld anta at vi har endelig oppløsning, og at ting går opp. Vi kan da anta at E er 1 unna y i dette tilfellet. Hvis vi lar avstanden fra x til y være n så får vi følgende sum: n/2 (fra x til A) + n/4 (fra A til B) + n/ 8 (fra B til C) etc., helt til vi tar det siste skrittet på lengde 1, og er da 1 unna y. Hvor langt har vi reist? n 1. Nok et bevis for rekkesummen 1 + 2 + + n/2 = n 1. 3
Fra forrige gang 4
Tell hvor mange vi har av hver Gjør telle-tabellen (C) kumulativ Tallet angir nå posisjonen til den siste forekomsten Gå igjennom A (baklengs) og bruk C til å finne posisjon Oppdater C etter hvert (dekrementer posisjonen) 5
for i = 0 to k C[i] = 0 for j = 1 to n C[A[j]] = C[A[j]] + 1 for i = 1 to k C[i] = C[i] + C[i 1] for j = n downto 1 B[C[A[j]]] = A[j] C[A[j]] = C[A[j]] 1 Her gjelder det å gå systematisk til verks Her har vi «downto» for å holde sorteringen stabil. Ser du hvorfor det må være sånn? Bonusspørsmål: Klarer du å lage en versjon som *ikke* bruker downto, men som er stabil likevel? 6
Sorter heltall Eller lignende Verdier O(n) Tell forekomster Regn ut indeks Lineær Strenge krav O(n) Tellesortering 7
Lineær sortering Radix sort 8
Sorter hvert siffer for seg Bruk en stabil sortering (f.eks. CS) for å bevare arbeidet så langt Vi må begynne med minst signifikante siffer Konstant antall siffer: Lineær kjøretid 9
A09>3H <:P T;< P+R R<; ];. T<; ]+T PV+ PV+ ];. T;< ]+T R<; T<; <:P P+R ]+T P+R <:P R<; T<; ];. T;< PV+ <:P T<; T;< P+R PV+ ]+T ];. R<; 10
A09>3H <:P T;< P+R R<; ];. T<; ]+T PV+ PV+ ];. T;< ]+T R<; T<; <:P P+R ]+T P+R <:P R<; T<; ];. T;< PV+ <:P T<; T;< P+R PV+ ]+T ];. R<; 11
Hva om tallene har ulikt antall siffer? Hva om det er veldig stor forskjell? Kan vi få til O(m), der m er det totale antall siffer brukt? (Det ville kunne brukes på vilkårlige strenger også.) Bryter vi i så fall den nedre grensen vår? Korrekthet kan vises ved induksjon på antall pass Kjøretid Θ(n + k) (evt. Θ((n + k)d) Hvordan bryter radix sort reglene for sammenligningssortering? Vi kan få informasjon ut over bare å sammenligne to nøkler. Vi bruker nøkler som tabellindekser! 12 Det kan vi gjøre fordi vi kjenner verdiområdet.
Sorter heltall Eller lignende Verdier O(n k ) Sorter siffer Stabilt Lineær Ganske strenge krav O(kn) Radikssortering 13 Evt. gruntallssortering :-)
Lineær sortering Bucket sort 14
Anta uniformt fordelte verdier i [0,1) Del [0,1) i n like store bøtter Fordél verdiene i bøttene Gå igjennom bøttene i rekkefølge Skriv ut verdiene sortert 15
Bøttene sorteres (med en enkel algoritme) Hver bøtte har O(1) forventet størrelse Totalt O(n) kjøretid 16
Sortering Uniformt [0,1) Ordnet hashing Lineær Krav O(n) Bøttesortering 17
Select 18
Seleksjon: Finn i-ende ordens statistic Eksempler: minimum, maksimum, median min/maks: enkle spesialtilfeller Vi ønsker ikke å sortere 19
I stedet for å sortere begge halvdeler fortsetter vi bare i den som inneholder posisjon i, som er den vi leter etter. Randomized-Select Eksempel på tavla. ½ QuicksortVerste tilfelle blir som for Quicksort. Beste tilfelle blir Theta(n). Forventet kjøretid, forenklet: T(n) = T(n/2) + n 20 Regnes på tavla.
Select Hårete og søt 21
Del i grupper på 5, og finn medianen i hver Finn «medianen til medianene», rekursivt Bruk denne som pivot i Partition Select rekursivt på «halvparten» Median-av-5: Konstant tid (insertion sort, f.eks.) for hver; O(n) totalt. Median-av-medianer: T(n/5). Merk: Etter utført algoritme vil dataene allerede være partisjonerte rundt elementet vi leter etter. Så ved å kjøre select etter element k så finner vi automatisk de k minste elementene i tabellen. 22 Partition: O(n). Rekursivt kall T(7n/10 + 6), hvis T(n) er monotont stigende. Mao: Vi får en «prosent-deling» i rekursjonen.
Finn median Og lignende Halv Quicksort Kjapp O(n 2 ) WC O(n) Avg. Randomized Select 23
Finn median Og lignende Pivot = m. av m. finnes rekursivt Kjapp O(n) Select 24
Bellman-Ford BFS/DFS Binære søketrær Binærsøk Bubblesort Bucket sort Counting sort Dijkstra DAGshortest-path Edmonds- Karp Floyd- Warshall Hashing Heapsort Huffmankoding Insertion sort Kruskal Merge sort Prim Quicksort Radix sort Randomized Select Select Selection sort Sterke komponenter Topologisk sortering 25
Bellman-Ford BFS/DFS Binære søketrær Binærsøk Bubblesort Bucket sort Counting sort Dijkstra DAGshortest-path Edmonds- Karp Floyd- Warshall Hashing Heapsort Huffmankoding Insertion sort Kruskal Merge sort Prim Quicksort Radix sort Randomized Select Select Selection sort Sterke komponenter Topologisk sortering 26
Fra A til B Syvende forelesning 27
Bellman-Ford BFS/DFS Binære søketrær Binærsøk Bubblesort Bucket sort Counting sort Dijkstra DAGshortest-path Edmonds- Karp Floyd- Warshall Hashing Heapsort Huffmankoding Insertion sort Kruskal Merge sort Prim Quicksort Radix sort Randomized Select Select Selection sort Sterke komponenter Topologisk sortering 28
Bellman-Ford BFS/DFS Binære søketrær Binærsøk Bubblesort Bucket sort Counting sort Dijkstra DAGshortest-path Edmonds- Karp Floyd- Warshall Hashing Heapsort Huffmankoding Insertion sort Kruskal Merge sort Prim Quicksort Radix sort Randomized Select Select Selection sort Sterke komponenter Topologisk sortering 29
Microsofts MapPoint (tidlig 2005) gir forslag til korteste vei fra Haugesund til Trondheim. Via bl.a. London. 1685.9 miles. En annen variant involverer å ta ferge fra Haugesund til Newcastle Upon Tyne, og så ta ferge fra Newcastle Upon Tyne til Bergen. Senere løste MS problemet ved å forby deg å beregne en sti mellom disse byene. Det ser ut til at MapPoint nå fungerer bedre Korteste vei fra s til v: Den stien som har lavest vekt-sum over kantene. Korteste vei 30
{ { } ( 8 C B E * + A C D 9 F E G C B 99 A, - ( 8 C B E * + A C D 9 F E G C B 99 A, - 31
Bare bruk én-til-alle i stedet for én-til-én. Man kjenner ingen algoritme som har bedre asymtotisk worst-case (selv om det finnes «tweaks»). Varianter Bare snu kantene, så får du én-tilalle. Én-til-én Alle-til-én I dag Én-til-alle Senere Alle-til-alle 32
Optimal substruktur s x y z s x y z 33
Hvis vi tillater negative sykler kan vi bruke korteste vei til å løse lengste vei-problemet, som er NP-komplett. Ingen kjente løsninger. (Problemet er at vi da ikke lenger har optimal substruktur; evt. figur på tavla.) Sykler NPC whatevs < 0 0 34
Representasjon π[v] Forgjenger i den korteste stien Forgjengergraf: V π = {v V : π[v] nil} {s} E π = {(π[v], v) E : v V π {s}} 35
s![s] = nil x![x] = s y![z] y = x z![z] = y 36
Relax u v u v 5 2 9 5 2 6 u v u v 5 2 7 5 2 6 37
Se slutten av intro til kap. 24 og avsnitt 24.5. Om dere ikke henger med på alt, tenk at dette kan være forskjellige perspektiver eller innsikter som kan hjelpe dere til å forstå forklaringene som kommer etterpå. Korteste vei-egenskaper 38
Fra starten Initialize- Single- Source π[v] = nil for enhver node v d[s] = 0 d[v] = for enhver annen node v 39
Trekantulikheten s u δ(s, v) δ(s, u) + w(u, v) v 40
Overestimat s v d[v] δ(s, v) 41
Ingen sti s v d[v] = 42
Konvergens s s u Relax d[v] = δ(s, v) v v 43
Sti-oppdatering s s s x y y Path relaxation property. v v 44 v Helt essensiell for forståelse av algoritmene i dag! Kjøres relax i rekkefølge på den korteste stien, vil endenoden få riktig estimat. Om vi kjører ekstra relax-er spiller ingen rolle.
Forgjenger-delgraf Forg jengerpekerne utgjør «korteste veitrær» s x y v 45
Hvis alle kanter relaxes «i hytt og vær», igjen og igjen, så vil alt bli riktig til slutt, på grunn av egenskapvene vi har sett. De riktige estimatene «sprer» seg, for hver kant i en korteste vei som blir relaxet «i riktig rekkefølge». (Spørsmålet blir om vi kan finne en lur rekkefølge å kjøre Relax i, så vi slipper å jobbe så mye. Det er der de mer spesifikke algoritmene slår til.) Generell metode 46
Tenk parallellitet Path relaxation er kjernen: Hvis vi sørger for alle kanter i korteste vei-treet blir relaxet i riktig rekkefølge fra rota (*minst*) så blir svaret riktig. Alle nodene kan få nye «tilbud» De som får nye tilbud kan gi nye tilbud videre Til slutt vil vi (hvis alle kantene besøkes om hverandre) få et riktig svar 47
Relax *alle* kantene én gang. Mengden noder med korrekt estimat har da vokst «ett skritt utover» fordi vi har kjørt relax på alle de riktige kantene i riktig rekkefølge. Litt mye ekstra-arbeid, dog Bellman-Ford 48
Tillater negative kanter Kan oppdage negative sykler som kan nås Beregner d[v] og π[v] for alle v i V 49
Initialiser grafen Hvorfor V 1 iterasjoner? Hvordan virker den siste sjekken? Kjør Relax på alle kantene Gjenta forrige punkt V 2 ganger Sjekk om ytterligere forbedringer er mulig Ja: Negativ sykel Nei: Alt i orden 50
Anta en kortest sti (v 0,, vk) Første iterasjon vil relaxe (v 0, v1) Iterasjon k vil relaxe (v k 1, vk) Vi vet da at d[vk] = δ(v0, k) Det siste er pga. sti-oppdateringsegenskapen (path relaxation). 51
Hvorfor blir dette kjøretiden? Kjøretid: Θ(VE) 52
G2 * G2 H r x y z 1/s / / 4/s - F I H? J K 2 H GH > 2 GJ Her vises bare verdier etter hver iterasjon. = 1/s 1/r 1/r 2/r 1/s 1/r 2/x 2/r 1/s 1/r 2/x 2/r Nøyaktig hvilke verdier man får underveis kommer an på rekkefølgen man kjører Relax i, men det endelige svaret (for avstandene) blir likt. 53
Korteste vei Én til alle Ingen neg. sykler Relax alle kanter V 1 ganger Neg. vekter Sykelvarsel O(VE) Bellman Ford 54
Dynamisk programmering. Her vet vi riktig rekkefølge fra starten av (en topologisk sortering). Verdt å merke seg: All dynamisk programmering (som vi kommer til senere) er egentlig DAG-SP. Det er bare ikke alltid så lett å se DAG-en :-) «DAG-Shortest-Path» 55
Tillater (naturligvis) ikke sykler Tillater negative kanter Beregner også d og π 56
Kan gjøre det omvendt også og relaxe innkommende kanter. Sorter nodene topologisk Initialiser grafen For hver node u, i rekkefølge: For hver etterfølger v: Relax (u, v) 57
Enhver kortest vei vil gå fra venstre mot høyre Alle får relaxet kantene sine i riktig rekkefølge 58
Kjøretid: Θ(V + E) 59
X 6 ) $ @ A B M [ Y6 YM 5 M X \ ] Z I motsetning til grafer generelt kan vi her like gjerne finne *lengste* sti, såkalt critical path i prosjektanalyse. Ingen effektive metoder er kjent for å finne lengste sti i en graf generelt. s t x y z 0 2 6 0 2 6 6 4 0 2 6 5 4 0 2 6 5 3 M 60
Se http://www.seamcarving.com, for eksempel. En interaktiv demo finnes på: http://swieskowski.net/car ve Denne bruker DAG-shortest path det gjelder bare å finne DAG-en! 61
Anta at interessantheten til hver piksel er gitt av en bildebehandlingsoperator. Veldig enkel form for DAG-SP. Nodene har vekt eller, ekvivalent, alle kantene ut av en node har samme vekt. Alle har kanter til de tre under seg (og fra de tre over seg). 1 5 2 4 3 1 5 2 4 3 5 1 4 3 3 6 2 6 5 6 3 2 2 2 4 5 4 4 7 9 4 2 1 4 5 8 6 5 8 12 5 1 3 2 3 11 6 8 7 11 62
Evt. lengste! Korteste vei Én til alle Ingen sykler Top-sort + Relax inn eller ut Effektiv men kravstor O(V + E) DAG-Shortest-Path 63
Motivasjon En slags intuisjon bak Dijkstras algoritme. Vil være korrekt (om enn ikke nødvendigvis effektiv) for heltallsvekter. Heltallsvekter i BFS 64
BFS skiller ikke på kanter med ulik vekt. Vil ikke nødvendigvis finne riktige avstander eller riktige stier. (Kan du finne et enkelt moteksempel?) For heltall kan vi omforme grafen så BFS fortsatt finner korteste veier 2 65
Det er bare å splitte opp kantene. Vekt 2 blir til to kanter (med en ny «dummy-node»). Merk: Dette er ikke noe som brukes i praksis bare intuitiv motivasjon. BFS vil nå fungere akkurat som før det bør være opplagt at vi får riktig svar. Hvordan oppfører algoritmen seg, hvis vi ser på den opprinnelige grafen? 66
Vi lar dummy-nodene være «usynlige» hvordan vil algoritmen «se ut» da? Algoritmen «sprer» fortsatt nodebesøkene ut fra start-noden i nivåer men høye kantvekter forsinker den (med usynlige «mellomstasjoner». Tiden det tar før vi besøker en node er proporsjonalt med den korteste veien dit (litt som bølger som sprer seg i et kanal-nettverk eller dominoer som faller). Kan vi kanskje simulere dette direkte, uten å bruke dummynoder? Hvordan kan vi besøke noder i avstandsrekkefølge når vi ikke kjenner avstanden? Samme prinsipp som før: Vedlikehold estimater når kan vi nå en node hvis vi følger de veiene vi har funnet så langt? Hoved-innsikt: Vi vil aldri kunne finne snarveier til den som alt ser ut til å være nærmest, så det er trygt å besøke den. 67
Her finnes det også (minst) en riktig rekkefølge for Relax, men den må vi oppdage litt etter hvert. Tenk vann som sprer seg i rør: Vi behandler krysningspunktene i den rekkefølgen de fylles. Det må gi oss riktige svar. Altså litt som DAG-SP, men ikke topologisk sortert vi ordner (på magisk vis) etter faktisk avstand. (Hvis vi bare tar med kanter i de korteste stiene så er grafen topologisk sortert ) Dijkstras algoritme 68
69
I stedet for topologisk rekkefølge: Etter stigende avstand fra s Som BFS men prioritetskø (med d[v]) i stedet for FIFO-kø Takler ikke negative kanter! 70
For spinkle grafer: Bruker binær haug som prioritetskø Må kunne endre nøkler (dvs. d[v]) underveis Må ha kobling mellom mellom noder og haug-innslag Kan evt. legge inn noder flere ganger i stedet 71
Initialiser grafen Så lenge det finnes uferdige noder: Velg u med lavest d[u] For alle kanter (u, v): Relax(u, v) 72
Hvis nodene besøkes etter stigende avstand: Kantene i korteste veier bli relaxet i riktig rekkefølge Topologisk sortering av kantene som «teller» Men Hvordan vet vi at lavest d[v] faktisk er nærmest? 73
Bokas variant av korrekthetsbeviset. Merk: Det er snakk om nok et bevis ved kontradiksjon. Vi antar at d[u] ikke er korrekt i det en node u legges til, og viser at vi får en selvmotsigelse. Den neste er kanskje forelesningens vanskeligste slide. 74
Anta at u er den første som ikke har riktig d- verdi når den legges til. Da må x ha hatt riktig d- verdi, og siden (x, y) er relaxet, så må y også ha riktig d-verdi i det u legges til. d[y] = δ(s, y) δ(s, u) d[u] 2 ). H Vi vet her at y forekommer før u på den korteste stien (Merk at x og y godt kan sammenfalle med s her.) Husk også at d er et overestimat av. = Dette virker bare hvis vi ikke har negative kanter; ellers kan vi ta «snarveier» og vi vet ikke lenger hvilken node som er nærmest. 75 <. I Men Siden u ble valgt før y så vet vi at d[u] d[y]. d[u] d[y] % d[y] = δ(s, y) = δ(s, u) = d[u] Sandwitch!
Underliggende antagelse: u er den første med galt men minimalt avstandsestimat (blant de hittil ubesøkte). Vi har y med korrekt d d[y] = δ(s, y) Dette viste vi ved å se at det må finnes en y med en forgjenger x rett innenfor og som altså har fått kjørt relax på sin forgjengerkant i den korteste stien, og dermed har korrekt d. u ligger senere på korteste vei δ(s, y) δ(s, u) d[u] men besøkes likevel (feilaktig) Det er denne ulikheten som ikke gjelder hvis vi har negative kanter. Da kan en node tidligere på den korteste stien likevel ligge lenger unna startnoden. d[u] d[y] 76 Vi får altså både d[y] d[u] og d[u] d[y], dvs. d[y] = d[u], med de faktiske avstandene klemt imellom. Med andre ord: Begge avstandene er korrekte likevel og vi har en selvmotsigelse.
(Min egen variant av korrekthetsbeviset litt enklere (IMO) enn det i boka.) Hypotetisk: Vi ordner noder etter faktisk avstand. Vi har positive kanter, så bakoverkantene vil være irrelevante (selv om vi jo ikke vet hvilke de er). Med andre ord har vi en (skjult, ukjent) DAG. Vi ønsker å besøke nodene i avstandsrekkefølge *uten å kjenne til* denne rekkefølgen (eller DAG-en). Induksjon to the rescue 0 3 7??? Vi har besøkt de k 1 første nodene, og relaxet kantene ut. Disse nodene har nå riktig avstandsestimat og det har også den neste i rekka (selv om vi ikke vet hvilken det er ennå). Det er akkurat som i DAG-shortest-path. 77 Betrakt den neste i sortert rekkefølge. Den har korrekt estimat. Alle de gjenværende har større avstand, og minst like store estimater. Dermed må den med lavest estimat være den neste, og vi har løst problemet for k.
Kjøretid avhengig av prioritetskøen. Hver Relax (det vil si, hver kant) kan måtte bruke Decrease-Key som koster O(lg V). Hver Extract-Min (dvs. for hver node) koster også O(lg V). Vi har altså: O(E lg V) + O(V lg V). Hvis alle kan nås fra starten vil E dominere, og vi får O((E+V) lg V) = O(E lg V). Kjøretid: O(E lg V) * * Hvis alle noder kan nås fra s 78
]^ @ _ Z - ^ [ \ a B ` ] ` A s x y z 0 10 5 0 9 5 6 0 8 5 6 0 8 5 6 79
Korteste vei Én til alle Ingen neg. kanter Besøk nærmeste Relax til alle naboer Effektiv Spes. på spinkle G Kravstor O(E lg V) Dette er jo en gjenganger. Jo sterkere krav vi stiller, jo mer effektive er algoritmene. Dijkstras algoritme 80
Bellman-Ford BFS/DFS Binære søketrær Binærsøk Bubblesort Bucket sort Counting sort Dijkstra DAGshortest-path Edmonds- Karp Floyd- Warshall Hashing Heapsort Huffmankoding Insertion sort Kruskal Merge sort Prim Quicksort Radix sort Randomized Select Select Selection sort Sterke komponenter Topologisk sortering 81
Bellman-Ford BFS/DFS Binære søketrær Binærsøk Bubblesort Bucket sort Counting sort Dijkstra DAGshortest-path Edmonds- Karp Floyd- Warshall Hashing Heapsort Huffmankoding Insertion sort Kruskal Merge sort Prim Quicksort Radix sort Randomized Select Select Selection sort Sterke komponenter Topologisk sortering 82