Kapitel 9: Grafalgoritmer



Relevanta dokument
Föreläsning 8 Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT036)

Föreläsning Datastrukturer (DAT037)

Föreläsning 7 Datastrukturer (DAT037)

TNK049 Optimeringslära

Föreläsning 5: Grafer Del 1

Föreläsning Datastrukturer (DAT036)

Föreläsning Datastrukturer (DAT036)

Föreläsning 6 Datastrukturer (DAT037)

Föreläsningsanteckningar F6

Föreläsning 8 Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT037)

Föreläsning 10. Grafer, Dijkstra och Prim

Föreläsning 10. Grafer, Dijkstra och Prim

Föreläsning 10. Grafer, Dijkstra och Prim

Grafer, traversering. Koffman & Wolfgang kapitel 10, avsnitt 4

Datastrukturer. föreläsning 9. Maps 1

Datastrukturer. föreläsning 8. Maps 1

729G04 - Diskret matematik. Lektion 4

Graphs (chapter 14) 1

Ekvivalensrelationer

Datastrukturer. föreläsning 8. Lecture 6 1

Grafer MST Top. sortering Starkt samm. komponenter Kortaste avstånd. Grafalgoritmer 1. Douglas Wikström KTH Stockholm

Grafer, allmänt. Med datastrukturen graf menas vanligen: en mängd av noder (vertices) och en mängd av bågar (edges).

Lösningar Datastrukturer TDA

FÖRELÄSNING 11 DATALOGI I

Lösningsförslag till tentamen Datastrukturer, DAT037,

Trädstrukturer och grafer

Föreläsning 9: NP-fullständighet

Kaliningrad) låg vid bägge sidor av floden Pregel samt på

Föreläsning 12+13: Approximationsalgoritmer

Lösningsförslag till tentamen Datastrukturer, DAT037 (DAT036), Tiden det tar att utföra en iteration av loopen är oberoende av värdet på

Föreläsning 6 Datastrukturer (DAT037)

Prov i DAT 312: Algoritmer och datastrukturer för systemvetare

Avancerad Problemlösning och Programmering i Praktiken

Algoritmer, datastrukturer och komplexitet

Tentamen Datastrukturer, DAT037 (DAT036)

Tentamen Datastrukturer, DAT037 (DAT036)

Föreläsning 5: Giriga algoritmer. Kruskals och Prims algoritmer

Föreläsning 4 Datastrukturer (DAT037)

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Algoritmer och datastrukturer, föreläsning 11

ADT Prioritetskö. Föreläsning 13 Innehåll. Prioritetskö vs FIFO-kö. Prioritetskö Exempel på användning. Prioritetsköer och heapar

Föreläsning 5: Giriga algoritmer. Kruskals och Prims algoritmer

Föreläsning Datastrukturer (DAT036)

Föreläsning 4: Giriga algoritmer. Giriga algoritmer

Algoritmer, datastrukturer och komplexitet

Tentamen Datastrukturer för D2 DAT 035

Föreläsning 4 Datastrukturer (DAT037)

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 9 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Näst nästa gång: Nästa gång: mer grafer (kap 10) Grafer 1 1. ! uppspännande träd. ! minimala uppspännande träd. ! Prims algoritm. !

Datastrukturer. föreläsning 9. Maps 1

Algoritmer, datastrukturer och komplexitet

Tentamen med lösningsförslag Datastrukturer för D2 DAT 035

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Föreläsning 13 Innehåll

Tentamen Datastrukturer (DAT036/DAT037/DIT960)

Föreläsning 1. Introduktion och sökning i graf. Vad är en algoritm?

Lösningsförslag för tentamen i Datastrukturer (DAT037) från

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 8 Erik Nilsson, Institutionen för Datavetenskap, LiU

729G04 - Diskret matematik. Lektion 4

Föreläsning 2: Grafer. Exempel på graf

N = {i}: noder (hörn) Graf: G = (N, B) Definitioner. Väg: Sekvens av angränsande bågar. Cykel: Väg som startar och slutar i samma nod.

Datastrukturer och Algoritmer D0041D

Algoritmer, datastrukturer och komplexitet

Lösningsförslag för tentamen i Datastrukturer (DAT036) från

Algoritmer, datastrukturer och komplexitet

Seminarium 13 Innehåll

Grafer. 1 Grafer. Grunder i matematik och logik (2015) 1.1 Oriktade grafer. Marco Kuhlmann

Algoritmanalys. Inledning. Informationsteknologi Malin Källén, Tom Smedsaas 1 september 2016

Tentamen Datastrukturer (DAT036)

Frågan om P=NP? Är P=NP? Bakgrund. "Snabb lösning"?!

Tentamen Datastrukturer D DAT 035/INN960

ORDINARIE TENTAMEN I DATASTRUKTURER OCH ALGORITMER DVG B kl. 08:15 13:15

Föreläsning 13 Datastrukturer (DAT037)

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

ADT Prioritetskö. Föreläsning 12 Innehåll. Prioritetskö. Interface för Prioritetskö. Prioritetsköer och heapar

Algoritmer, datastrukturer och komplexitet

Datastrukturer och algoritmer. Föreläsning 15 Inför tentamen

Tentamen Datastrukturer (DAT037)

Exempeltenta GruDat 2002/2003

Några svar till TDDC70/91 Datastrukturer och algoritmer

träd dag graf båge och vikt Grafer definitioner och terminologi

Föreläsningsanteckningar S6 Grafteori

Föreläsning 6. Slumptal Testa slumptal Slumptal för olika fördelningar Grafer Datastrukturen graf

Algoritmer, datastrukturer och komplexitet

Träd. Sats. Grafer. Definition. En fullständig graf har en båge mellan varje par av noder. Definition

Programmering II (ID1019) :00-17:00

Algoritmer, datastrukturer och komplexitet

Tentamen, Algoritmer och datastrukturer

Träd. Sats. Grafer. Definition. En fullständig graf har en båge mellan varje par av noder. Definition

Föreläsning 5 Innehåll

Programkonstruktion och Datastrukturer

Algoritmer, datastrukturer och komplexitet

Föreläsning 1. Introduktion. Vad är en algoritm?

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Träd. Sats. Grafer. Definition. En fullständig graf har en båge mellan varje par av noder. Definition

Lösningsförslag till tentamen Datastrukturer, DAT037,

Föreläsning 6: Nätverksoptimering

Transkript:

Kapitel 9: Grafalgoritmer En graf G = (V, E) karakteriseras av två mängder en ändlig icke-tom mängd V av noder (vertex) en mängd E av bågar (edges eller arcs) varje båge är ett par (v, w), där v, w är element av V dvs. en båge är ett par av noder om paret är ordnat kallas grafen riktad, eller kort en digraf Två noder säges vara närbelägna (adjacent) om det existerar en båge mellan noderna med bågen kan associeras ett tal, vikt eller kostnad Exempel En riktad graf med 7 noder och bågar V = {,, 3,, 5, 6, 7} E = {(,), (,3), (,), (,), (,5), (3,6), (,3), (,6), (,7), (5,), (5,7), (7,6)} Noderna och är närbelägna eftersom det finns en båge (,) noderna och 5 är inte närbelägna 3 5 6 7

Stigar En följd av noder w, w,..., w N i en oriktad resp. riktad graf är en stig (path) resp. en riktad stig från w till w N om det mellan varje par (w i,w i+ ) existerar en båge i grafen stigens längd är antalet bågar, dvs. N- En enkel (simple) stig är en stig så att alla noder är olika, utom möjligen första och sista En cykel i en riktad graf är en stig av längden minst så att w = w N i en oriktad graf måste alla bågar i en cykel vara olika stigen u, v, u i en oriktad graf är ingen cykel, eftersom (u,v) och (v,u) är samma båge i en riktad graf är de här olika bågar och u,v,u är en cykel u u v v 3 Exempel,,5,7,6 är en riktad stig av längd i grafen, eftersom grafen innehåller bågarna (,), (,5), (5,7) och (7,6) Exempelgrafen är acyklisk finns ingen stig av längd sådan att startnoden är lika med slutnoden 3 5 6 7 En riktad acyklisk graf kallas en DAG, directed acyclic graph

Mera definitioner En graf kan innehålla en båge från en nod till sig själv en stig som inte innehåller någon nod har längden noll Om en graf innehåller en båge (v,v) från en nod till sig själv kallas stigen v,v för en loop v En oriktad graf är kopplad (connected) om det finns en stig från varje nod till varje annan nod en riktad graf med den här egenskapen kallas starkt kopplad (strongly connected) I en fullständig graf (complete graph) finns det en båge mellan varje par av noder a b för varje nod gäller att alla andra noder är närbelägna c d 5 Exempel på tillämpningar av grafer Modell av flygförbindelser varje flygfält är en nod två noder är förbundna med en båge om det existerar en direkt flygförbindelse mellan de två flygfälten bågarna kan ha vikter som t.ex. representerar flygtiden, distansen eller priset för resan bildar en riktad graf, eftersom t.ex. priset för att flyga från a till b och b till a inte behöver vara det samma grafen är starkt kopplad, eftersom det är möjligt att med flyg ta sig från vilken flygplats som helst till vilken annan som helst Vi vill t.ex. kunna avgöra vilken som är den bästa rutten mellan två noder bäst kan betyda billigaste, kortaste, snabbaste, med minsta antal mellanlandningar, osv. 6 3

Exempel på tillämpningar av grafer Datornätverk modelleras med hjälp av grafer datorer och routers är noder i grafen kommunikationslinjerna mellan dessa är bågar i grafen Ruttning av meddelande görs genom att sända meddelande längs den bästa stigen från avsändaren till destinationen bästa kan betyda stigen av kortaste längd, med största kapacitet, med minst belastning, osv. Beräkning av rutt-tabeller görs med hjälp av en grafalgoritm beräknar kortaste vägen i en riktad graf med vikter 7 Representation av grafer Det finns två olika sätt att representera grafer incidensmatriser incidenslistor Vi beskriver här hur man representerar riktade grafer oriktade grafer lagras på samma sätt i en oriktad graf lagras en båge (u,v) som två riktade bågar: (u,v) och (v,u) u v u v oriktad graf riktad graf Vi antar att alla noder kan numreras startande från 8

Incidensmatris För att representera en graf med N noder kan man använda en incidensmatris (adjacency matrix) A av storleken N x N A[i,j] = om bågen (w i, w j ) finns i grafen, annars 0 om bågen har associerad en vikt sätts A[i,j] till viktens värde i stället för Utrymmesbehovet är kvadratiskt: Ω( V ) V betecknar antalet noder i grafen och E antalet bågar representationen är effektiv om grafen är tät, dvs. om det existerar en båge mellan de flesta par av noder 3 0 0 0 0 0 7 3 9 3 0 7 0 0 0 0 0 9 3 3 0 0 0 0 0 3 3 0 0 0 3 0 0 0 riktad graf utan vikter riktad graf med vikter 9 Incidenslista Om grafen inte är tät, dvs. den är gles, är en incidenslista (adjacency list) en mera effektiv representation För varje nod håller vi en lista av närbelägna noder utrymmeskravet är O( E + V ), dvs. proportionerligt mot antalet bågar plus antalet noder, vilket är linjärt med storleken på grafen Om vi har en viktad graf inkluderas också ett fält för vikten i de länkade listorna Om vi har en oriktad graf förekommer varje båge (u,v) i två listor: (u,v) och (v,u) 3 3 3 3 5 5 5 0 5

Topologisk sortering En topologisk sortering (ordning) är en ordning av noderna i en riktad acyklisk graf G (en DAG) så att om det finns en stig från v i till v j så förekommer v j efter v i i ordningen om det inte finns en stig från v i till v j kan noderna komma i godtycklig ordning i den topologiska sorteringen Exempel: G kunde vara en graf där noderna representerar kurser och en båge (v,w) anger att kurs v måste avklaras innan kurs w kan tas en topologisk sortering för dessa kurser är vilken som helst kursföljd så att alla förkunskaper för varje kurs listas före kursen själv Algoritm för topologisk sortering En enkel algoritm för att hitta en topologisk ordning är att först bestämma någon nod utan inkommande bågar vi listar denna nod och tar bort den tillsammans med dess bågar från grafen letar reda på nästa nod utan inkommande bågar och upprepar behandlingen, tills alla noder är listade Om grafen inte har någon nod med ingraden noll så har grafen en cykel För att formalisera detta och utveckla det till ett program, definierar vi ingraden av en nod v som antalet bågar (u,v) exempel: en nod v med ingraden u v z 6

Algoritm (forts.) Vi representerar grafen med en incidenslista och beräknar ingraderna för alla noder i grafen det här är en linjär operation, går bara igenom alla bågar en gång vi lagrar ingraden för varje nod i en räcka Indegree Metoden findnewvertexofindegreezero letar igenom Indegreeräckan efter en nod med ingrad 0 som inte redan har tilldelats ett ordningsnummer Den returnerar null om ingen sådan nod existerar grafen har då en cykel om noderna u och v ingår i en cykel så kommer både u före v och v före u Den topologiska ordningen är inte nödvändigtvis entydig det kan finnas flera olika topologiska ordningar 3 Pseudokod för topologisk sortering findnewvertexofindegreezero är en enkel sekventiell genomgång av räckan av noder varje anrop av den tar O( V ) tid. eftersom det finns V dylika anrop är körtiden O( V ) void topsort() throws CycleFound { Vertex v, w; for (int counter = 0; counter < Num_Vert; counter++) { v = findnewvertexofindegreezero(); if ( v == null ) throw new CycleFound(); v.topnum = counter; for each w adjacent to v w.indegree--; } } 7

En effektivare algoritm Om grafen är gles så får bara några få noder sina ingrader uppdaterade under varje iteration algoritmen undersöker (potentiellt) alla noder vid sökningen efter en nod med ingrad 0, även om bara några få har ändrats bara de närliggande noderna får sin ingrad ändrad Vi håller alla (obehandlade) noder som har ingrad 0 i en speciell låda findnewvertexofindegreezero plockar ut en av noderna i lådan (vilken som helst) när vi minskar ingraderna av de närliggande noderna, checkar vi varje nod och placerar den i lådan om dess ingrad minskar till noll 5 Datastruktur för lådan För att implementera lådan kan vi antingen använda en stack eller en kö vi väljer att använda en kö (men en stack fungerar lika bra) Alla noder med ingrad 0 placeras i en initialt tom kö så länge som kön inte är tom ta bort en nod v minska ingraderna på alla noder som är närliggande till v med ett när en nods ingrad faller till 0 sätts den in i kön Den topologiska ordningen är då ordningen i vilken noderna tas ut ur kön 6 8

Exempel Tabellen visar hur algoritmen fungerar för den acykliska grafen nedan v v v 3 v Iteration VERTEX 3 5 6 7 v 0 0 0 0 0 0 0 v 0 0 0 0 0 0 v 3 0 0 0 v 3 0 0 0 0 0 0 0 0 0 v 6 3 3 3 3 0 v 7 0 0 0 Inköa v v v v 3,v 7 v 6 Avköa v v v v 3 v 7 v 6 7 Pseudokod void topsort() throws CycleFound { Queue q; int counter = 0; Vertex v, w; q = new Queue(); // Skapa en tom kö for each vertex v // Sätt in noder med ingrad 0 if (v.indegree == 0) q.enqueue(v); while(!q.isempty()) // Tills kön är tom { v = q.dequeue(); // Ta ut en nod v v.topnum = ++counter; // Ge den ett ordningsnummer for each w närliggande till v // Uppdatera närliggande if (--w.indegree == 0) q.enqueue(w); // Sätt in i kön om ingrad = 0 } } if (counter!= Num_Vert) throw new CycleFound(); 8 9

Körtid för topologisk sortering Körtiden för den förbättrade versionen av topologisk sortering är O( E + V ) d.v.s. linjärt med storleken på grafen I initieringen gås alla noder igenom linjärt alla noder med en ingrad = 0 sätts in i kön for-loopens behandling (--w.indegree==0) utförs högst en gång per båge Varje nod sätts in respektive tas ut ur kön exakt en gång 9 Kortaste väg algoritmer Givet en vägd graf G = (V, E), och en viss startnod s, bestäm den kortaste vägda vägen från s till vilken som helst annan nod i G varje båge (v i, v j ) har en kostnad c i,j Kostnaden för att använda en stig v, v,... v N är kallas för den vägda stiglängden N c i,i+ Om vi inte har en graf med vikter är stiglängden bara antalet bågar i stigen, dvs. N- i= 0 0

Exempel I grafen nedan har den kortaste vägda stigen som går från v till v 6 den totala kostnaden 6 går från v till v, v 7 och v 6 Den kortaste ovägda stigen från v till v 6 har kostnaden går från v till v och v 6 Vi antar att alla kostnader är positiva v 3 5 v 3 v 0 v 8 6 v 6 v 7 Kortaste väg utan vikter Om grafen inte har vikter är den kortaste vägen stigen med minst antal bågar specialfall av kortaste vägen i en graf där alla bågar har vikten ett Vi söker den kortaste vägen från startnoden v 3 till alla andra noder i grafen nedan v v v 3 v

Beskrivning av algoritmen Vi markerar att kortaste vägen från startnoden v 3 till v 3 har längden 0 0 v v v 3 v Vi letar efter alla noder på distans från startnoden dvs. alla noder som är närliggande till startnoden v 3 noderna v och v 6 är närliggande, så de markeras att vara på distans från startnoden 3 Beskrivning av algoritmen Markerar att noderna v och v 6 är på distans från startnoden 0 v v v 3 v Vi fortsätter med att leta efter noder på distans från startnoden markerar alla noder närliggande till v och v 6 med distansen. v 6 har inga närliggande noder, så noderna v och v får distansen

Beskrivning av algoritmen 0 v v v 3 v Till sist markerar vi alla hittills omärkta noder som är närliggande till v och v med distansen 3, dvs. noderna och v 7 noderna v 3 och v 6 är också närliggande till v men de är redan märkt med en distans mindre än 3 5 Resultat 0 v v 3 v 3 v 3 Alla noder har nu blivit behandlade, och algoritmen terminerar Algoritmen gör en breadth-first sökning av grafen 6 3

Variabler För varje nod håller vi reda på följande: nodens distans dist från startnoden bågen som ingår i den kortaste vägen path en logisk variabel known som sätts till sann när en nod har behandlats. Initialt är dist = och known = FALSE för alla noder Genom att följa bågen till noden som är finns i variabeln path bakåt från en nod får man den kortaste vägen till startnoden 7 Algoritm Pseudokod för kortaste vägen utan vikter körtiden för algoritmen är O( V ) void unweighted (Vertex s) { Vertex v, w; s.dist = 0; for (int curdist=0; curdist<num_vertices; curdist++) for each vertex v if (!v.known && v.dist == curdist) { v.known = TRUE; for each w adjacent to v if (w.dist == INFINITY) // w är obehandlad { w.dist = curdist+; w.path = v; } } } 8

Förbättrad algoritm Vi får en effektivare algoritm genom att undvika att gå igenom den yttersta for-loopen för alla noder vi går bara igenom de noder som inte ännu har behandlats, i rätt ordning Vi använder en kö på samma sätt som i algoritmen för topologisk sortering initialt innehåller kön startnoden, på distans currdist vi sätter in närbelägna noder, på distans currdist+ behandlar noderna i den ordning de tas ut ur kön, dvs. noder med mindre distans till startnoden först Körtiden blir O( E + V ), enligt samma resonemang som för topologisk sortering 9 Algoritm Vi behöver inte known-variabeln mera en nod är färdigt behandlad när den tagits ut ur kön den kan inte sättas in i kön igen void unweighted (Vertex s) { Queue q; Vertex v, w; q = new Queue(); // Skapa en kö q.enqueue(s); s.dist = 0; // Sätt in startnoden while (!q.isempty() ) // Tills kön är tom { v = q.dequeue(); // Tag ut en nod v for each w adjacent to v // Uppdatera närliggande if (w.dist == INFINITY) { w.dist = v.dist+; w.path = v; q.enqueue(w); // Sätt in i kön } } } 30 5

Dijkstra s algoritm För vägda grafer blir problemet att hitta kortaste stigen något svårare vi kan använda samma idéer som i föregående fall Algoritmen kallas Dijkstra s algoritm (959) Edsger W. Dijkstra, 930 00 Bra exempel på en girig algoritm väljer i varje steg det alternativ som just då ser mest fördelaktigt ut 3 Algoritm Vi upprätthåller samma information som tidigare för varje nod known sätts till SANT för noder som redan behandlats dist är kortaste distansen från en nod till startnoden, med användande av enbart behandlade (known) noder path sätts till den nod som sist förorsakade en ändring i nodens distans Algoritmen utförs i ett antal steg välj den obehandlad nod v som har minsta distans till startnoden noden v märks som behandlad (known) och distanserna för de närliggande noder uppdateras upprepa behandlingen tills alla noder är markerade som known 3 6

Uppdatering av distanser Distansen till en närliggande nod w, dist w uppdateras till dist v + c v,w om det här är mindre än det nuvarande dist värdet på dist s w s c v,w är distansen mellan noderna v och w Algoritmen väljer att använda stigen via v för att nå w, i stället för att direkt gå från s till w kostnaden för stigen från s till v till w (+ = 6) är mindre än kostnaden från s till w (0) v 0 w 33 Illustration Vi letar kortaste vägen från startnoden v till alla andra noder i grafen nedan Initialkonfigurationen för variablerna i Dijkstra s algoritm visas i tabellen v 3 5 v 8 3 v v 0 6 v known dist v path v v F 0 0 v F 0 v 3 F 0 v F 0 F 0 v 6 F 0 v 7 F 0 3 7

Illustration (forts.) Startnoden s = v I första steget väljs v, eftersom den har minsta dist-värde 0 vi markerar att distansen från s till v (dvs. till sig själv) är 0 noden v märks som known, och vi uppdaterar distanserna för de noder som är närliggande till v de närliggande noderna till v är v och v v known dist v path v v F 0 0 v F 0 v 3 F 0 v F 0 F 0 v 6 F 0 v 7 F 0 v 3 5 0 v 8 3 v v 6 0 35 Illustration (forts.) Kortaste distansen till v är 0+=, vilket är bättre än den hittills kortaste kända distansen ( ) vi uppdaterar dist för v eftersom dist ändrar för v sätter vi path för v till den nod som förorsakade ändringen, dvs. till v Kortaste distansen till v är 0+=, så vi uppdaterar också dist för v och sätter path till v v known dist v path v v T 0 0 v F v v 3 F 0 v F v F 0 v 6 F 0 v 7 F 0 v 3 5 0 v 8 3 v v 6 0 36 8

Illustration (forts.) I det andra steget väljs v, eftersom den har det minsta distvärdet (), och markerar v som known noderna v 3,, v 6 och v 7 är närliggande och vi uppdaterar distanserna och path-värdet för de här: dist 3 = min(, +) = 3 dist 5 = min(, +) = 3 dist 6 = min(, +8) = 9 dist 7 = min(, +) = 5 v known dist v path v v T 0 0 v F v v 3 F 3 v v T v F 3 v v 6 F 9 v v 7 F 5 v 0 v v 0 3 3 3 v 3 v 8 5 6 9 5 37 Illustration (forts.) I nästa steg väljer vi v och markerar den som known, eftersom den har det minsta dist-värdet () bland de obehandlade noderna noderna v och är närliggande, men v är redan behandlad (known) så den skall inte behandlas igen distansen till via v blir +0=, vilket är större än det nuvarande dist-värdet för (3), så inget uppdateras v known dist v path v v T 0 0 v T v v 3 F 3 v v T v F 3 v v 6 F 9 v v 7 F 5 v 0 v v 0 3 3 3 v 3 v 8 5 6 9 5 38 9

Illustration (forts.) Noderna v 3 och har nu det minsta dist-värdet bland de obehandlade vi väljer och markerar den som known (vi kunde lika gärna ha valt v 3 eftersom den har samma dist-värde) enda närliggande nod till är v 7. Eftersom 3+6=9 > 5 skall den inte uppdateras Sedan väljs v 3 med dist = 3 och den markeras som known noden v är redan behandlad, så enda närliggande obehandlade nod är v 6 distansen till v 6 genom v 3 är 3+5=8, vilket är mindre än 9 så tabellen uppdateras för v 6 v known dist v path v v T 0 0 v T v v 3 T 3 v v T v T 3 v v 6 F 8 v 3 v 7 F 5 v 0 v v 0 3 3 3 v 3 v 8 5 6 8 5 39 Illustration (forts.) I nästa steg väljs v 7 med dist-värdet 5, eftersom den har mindre distans än v 6, som är den enda andra obehandlade noden som är kvar noden v 7 märks known och dess enda närliggande nod v 6 uppdateras, eftersom distansen via v 7 är 5+=6 vilket är mindre än det tidigare värdet 8 v known dist v path v v T 0 0 v T v v 3 T 3 v v T v T 3 v v 6 F 6 v 7 v 7 T 5 v 0 v v 0 3 3 3 v 3 v 8 5 6 6 5 0 0

Illustration (forts.) I sista steget i algoritmen väljs den sista noden som inte ännu är known, dvs. v 6, och den markeras som known den har inga närliggande noder att kolla, och alla noder är behandlade, så algoritmen terminerar v known dist v path v v T 0 0 v T v v 3 T 3 v v T v T 3 v v 6 T 6 v 7 v 7 T 5 v 0 v v 0 3 3 3 v 3 v 8 5 6 6 5 Kortaste stigen Den kortaste stigen från en nod tillbaka till startnoden fås genom att följa stigen som bildas av noderna i path-variablerna Exempel: kortaste stigen från v 6 till v fås genom att följa stigen bakåt från v 6 till v 7 till v och till v v known dist v path v v T 0 0 v T v v 3 T 3 v v T v T 3 v v 6 T 6 v 7 v 7 T 5 v 0 v v 0 3 3 3 v 3 v 8 5 6 6 5

Implementation Vi antar att vi har objekt av typen Vertex för att lagra den information vi behöver för en nod för varje nod har vi variablerna known, dist och path Vi antar att vi har en funktion Cost(u,v) som returnerar vikten c u,v av bågen mellan noderna u och v om den existerar, annars returneras värdet 3 Algoritm Pseudokod för Dijkstra s algoritm void dijkstra (Vertex s) { Vertex v, w; s.dist = 0; for ( ; ; ) { v = noden med minsta dist bland de noder som inte är known; if (v == null) break; v.known = TRUE; for (varje w närliggande till v) // Kolla närliggande if (!w.known) if (v.dist + Cost(v,w) < w.dist) // Bättre stig? { w.dist = v.dist + Cost(v,w); // Uppdatera w.path = v; } } }

Algoritm För att skriva ut kortaste stigen använder vi rutinen printpath implementerad som en rekursiv funktion rekursionen avslutas när v har path-värdet null, dvs. när vi når startnoden void printpath (Vertex v) { if (v.path!= null) { printpath(v.path); System.out.print( to ); } System.out.print(v); } 5 Körtid för Dijkstra s algoritm Om vi för varje nod letar igenom alla noder sekventiellt för att hitta den med minsta dist-värde blir körtiden kvadratisk: O( V ) tiden för att uppdatera distanserna till närliggande noder är O( E ) vi gör högst en uppdatering för varje båge, med en konstant tid för varje båge totala körtiden är således O( E ) + O( V ) = O( V ) Om grafen är tät är det här en effektiv algoritm annars, om grafen är gles, är algoritmen ineffektiv 6 3

Effektivare datastrukturer Vi kan undvika att leta igenom alla noder för att hitta den med minsta dist-värde om nodernas distanser hålls i en prioritetskö att ta ut noden med minsta distans och sätta den till known implementeras av en deletemin-operation uppdateringen av det nya dist-värdet kan implementeras som en decresekey-operation Vi kan då hitta det minsta dist-värdet i O(log V ) tid, och uppdateringen tar också O(log V ) tid körtiden blir då O( E log V + V log V ) = O( E log V ) 7 Acykliska grafer Om grafen är acyklisk kan vi använde en effektivare algoritm än Dijkstra s vi ändrar på ordningen i vilken noder markeras som kända så att vi behandlar noderna i topologisk ordning algoritmen gör då en enda genomgång av noderna när vi har valt och behandlat en nod v i en acyklisk graf kan dess distans till startnoden inte mera ändra, eftersom noden då har en ingrad = 0, dvs. den har inga inkommande bågar från obehandlade noder vi behöver inte använda en prioritetskö för att välja nästa nod, utan vi väljer bara en obehandlad nod med ingraden 0 som i algoritmen för topologisk ordning Körtiden är O( E + V ) som i topologisk sortering 8

Tillämpningar av acykliska grafer En tillämpning där acykliska grafer används är critical path analysis (kritisk-stig analys) används för att analysera tidsberoenden i t.ex. projektplanering Grafen nedan är en aktivitetsnod-graf (activity-node graph) och beskriver aktiviteter i ett projekt och deras beroenden noderna anger aktivitetens namn och hur lång tid de tar en båge (u,v) anger att u måste slutföras förrän v kan starta 9 Aktivitetsnod-grafer Noder representerar aktiviteter som skall utföras och den tid som de kräver en båge mellan två noder (u, v) betyder att u måste slutföras före v kan påbörjas två aktiviteter som inte (direkt eller indirekt) är beroende kan utföras samtidigt Aktivitetsnod-grafer är alltid acykliska Frågor som man kan analysera med hjälp av grafer av den här typen är t.ex. när kan projektet tidigast bli färdigt när måste en viss aktivitet senast bli färdig för att inte riskera att hela projektet försenas hur lång tid kan vi uppskjuta en aktivitet utan att hela projektet försenas 50 5

Händelsenod-graf Vi konverterar aktivitetsnod-grafen till en händelsenod-graf (event-node graph) noder representerar slutförandet av en aktivitet och alla de aktiviteter som den beror på bågarna representerar beroenden, och har som kostnad tiden för att utföra aktiviteten 5 Konvertering till händelsenod-graf I en händelsenod-graf representerar noder slutförandet av en aktivitet och bågarna representerar beroenden bågarna har som kostnad tiden för att utföra aktiviteten För att konvertera en aktivitetsnod graf till en händelsenod graf sätter vi in hjälpnoder och bågar med kostnaden noll (dvs. som inte tar någon tid) i grafen för att bibehålla beroendeförhållandena Aktivitetsnod-graf Händelsenod-graf 3 A B D 3 A B 0 0 D 5 6

Earliest completion time För att beräkna tiden när projektet tidigast kan bli färdigt (earliest completion time) söker vi efter den längsta stigen från startnoden till slutnoden eftersom grafen är acyklisk är den längsta stigen väldefinierad Om EC i betecknar när nod i tidigast kan vara slutförd har vi: EC = 0 EC w = max(ec v + c v,w ) för alla (v,w) E Earliest completion time beräknas i topologisk ordning Exempel: EC a EC w är det största av a c a,w EC a + c a,w och EC b + c w b,w b c b,w EC b 53 Exempel på earliest completion time Exempel på beräkning av earliest completion time EC = 0 EC w = max(ec v + c v,w ) för alla (v,w) E 5 7

Latest completion time Tiden för när en aktivitet senast måste vara färdig, (latest completion time), dvs. deadline för aktiviteten, kan beräknas som LC n = EC n (hela projektet skall slutföras så fort som möjligt) LC v = min(lc w - c v,w ) för alla (v,w) E Latest completion time beräknas i omvänd topologisk ordning börjar från slutnoden och går bakåt mot startnoden Exempel: LC v är det minsta av LC a c v,a och LC b c v,b v c v,a c v,b LC a a LC b b 55 Exempel på latest completion time Exempel på beräkning av latest completion time LC n = EC n LC v = min(lc w - c v,w ) för alla (v,w) E 56 8

Slacktid Slacktiden för en båge i händelsenod-grafen anger hur mycket vi kan fördröja en aktivitet utan att hela projektet fördröjs Slack (v,w) = LC w EC v - c v,w EC v LC w v c v,w w De aktiviteter som har slacktiden noll är kritiska aktiviteter som måste bli färdiga i tid för att projektets tidtabell skall hålla Det finns åtminstone en stig av aktiviteter med slacktiden noll, kallad den kritiska stigen (critical path) 57 Exempel på slacktid Exempel på beräkning av slacktid Slack (v,w) = LC w EC v - c v,w 58 9

Flöde i nätverk Vi har en riktad graf G = (V,E) med vikter c v,w, vilka anger flödeskapacitet över bågen (v, w) kapaciteten kan t.ex. vara mängden vätska som kan flöda genom ett rör, maximala mängden trafik på en väg eller kommunikationskapaciteten i ett datornät Grafen har två noder s (source) och t (sink) och uppgiften är att beräkna det maximala flödet mellan s och t Genom varje båge (u,v) kan vi maximalt ha ett flöde på c u,v enheter för varje nod gäller att det totala inkommande flödet måste vara lika med det utgående flödet 59 Exempel Grafen nedan har det maximala flödet 5 från startnoden s till slutnoden t 60 30

En enkel algoritm för maximalt flöde Vi presenterar först en enkel (men bristfällig) algoritm för maximalt flöde i ett nätverk Från den ursprungliga grafen G konstruerar vi en flödesgraf G f som beskriver flödet över bågarna under algoritmens exekvering initialt har alla bågar i G f flödet noll Vi konstruerar en annan graf G r som kallas den residuala grafen anger hur mycket flöde vi ännu kan sätta till på varje båge beräknas genom att subtrahera det nuvarande flödet över en båge från dess kapacitet (dvs. G - G f för varje båge) en båge i G r kallas för en residualbåge 6 Grafer i algoritmen Algoritmen använder tre grafer för att representera flödet G grafen som beskriver nätverkets kapacitet G f flödesgrafen som beskriver flödet igenom nätverket G r residualgrafen som beskriver den kvarvarande kapaciteten Initialkonfigurationen för graferna visas nedan 6 3

Algoritm För varje steg i algoritmen söker vi fram en stig från s till t i residualgrafen G r Bågen med minsta vikt i stigen anger hur mycket flöde vi kan sätta till på varje båge i stigen från s till t vi sätter till den här mängden till varje båge i stigen i flödesgrafen G f och uppdaterar residualgrafen G r (dvs. beräknar G - G f för varje båge) när vi har använt all kapacitet på en båge tas den bort från residualgrafen G r Det här upprepas tills vi inte mera hittar någon stig från s till t i G r 63 Illustration Vi letar efter en stig från s till t i residualgrafen och hittar stigen s, b, d, t minsta vikten på en båge i den här stigen är Vi sätter till flödet längs stigen s, b, d, t och uppdaterar residualgrafen 6 3

Illustration (forts.) Letar efter nästa stig från s till t i residualgrafen och hittar stigen s, a, c, t minsta vikten på en båge i den här stigen är Vi sätter till flödet längs stigen s, a, c, t och uppdaterar residualgrafen 65 Illustration (forts.) Fortsätter att leta efter en stig från s till t i residual-grafen och hittar stigen s, a, d, t minsta vikten på en båge i den här stigen är Vi sätter till flödet längs stigen s, a, d, t och uppdaterar residualgrafen 66 33

Icke-deterministiskt val Algoritmen terminerar, eftersom det inte mera finns någon stig från s till t i residualgrafen resultatet, flödet 5, är korrekt Algoritmen är icke-deterministisk det kan finnas flera stigar från s till t vi kan välja vilken som helst av de möjliga stigarna från s till t Vissa val leder till ett korrekt resultat, men andra val orsakar att algoritmen terminerar med ett felaktigt resultat vi måste utveckla algoritmen så att den fungerar för alla möjliga val av stigar 67 Felaktigt beteende Den presenterade algoritmen fungerar inte i alla situationer För att se det här, antag att vi först väljer stigen s, a, d, t, som ger 3 enheter flöde och som ser ut att vara ett bra val Algoritmen terminerar, eftersom det inte mera finns någon stig från s till t, resultat för det maximala flödet, 3, är fel! 68 3

En korrekt algoritm för maximalt flöde För att algoritmen alltid skall ge som resultat det maximala flödet måste den ha en möjlighet att ändra sig när den har valt en stig som den sätter till flöde på görs genom att för varje båge (u,v) med flödet f u,v i flödesgrafen sätta till en båge (v,u) med flödet f u,v i residualgrafen sätter till en båge i motsatt riktning ger algoritmen en möjlighet att ångra ett val som den har gjort och styra flöde tillbaka i motsatt riktning 69 Illustration Vi väljer stigen s, a, d, t med flödet 3 med den korrekta algoritmen bågarna (a,s), (d,a) och (t,d) med flödet 3 sätts till i residualgrafen Som nästa stig i residualgrafen hittar vi s, b, d, a, c, t med flödet 70 35

Illustration (forts.) Sätter till flödet längs stigen s, b, d, a, c, t Uppdaterar residualgrafen och sätter till bågarna (b,s), (d,b), (a,d), (c,a) och (t,c) med flödet Nu finns ingen mera stig från s till t och algoritmen terminerar med ett korrekt värde 5 7 Körtid Man kan visa att om bågarnas kapaciteter är rationella tal kommer algoritmen alltid att ge det maximala flödet Algoritmen fungerar också för grafer med cykler vi har använt acykliska grafer som illustration för enkelhetens skull Om kapaciteterna är heltalsvärden är algoritmens komplexitet O(f E ), där f är det maximala flödet flödet ökar med minst ett för varje gång vi sätter till en stig från s till t, och en stig kan hittas i O( E ) tid 7 36

Värsta fall Värsta-falls beteendet för algoritmen illustreras i grafen nedan Vi ser genast att det maximala flödet är 000000 Algoritmen kan i värsta fall i varje steg välja stigen som innehåller bågen (a,b) eller (b,a), med kapacitet det här kunde upprepas 000000 gånger förrän algoritmen terminerar Om vi alltid väljer stigen med minsta antalet noder blir körtiden O( E V ) s 000000 000000 a 000000 000000 t b 73 Minimalt spännträd Ett minimalt spännträd är ett träd som uppspänner en oriktad graf i den meningen att den når varje nod och är det billigaste av alla dylika träd billigaste betyder att summorna av vikterna längs bågarna är den minsta möjliga det minimala spännträdet förenar alla noder i trädet så att summan av bågarnas kostnader är den minsta möjliga Antalet bågar i ett minimalt spännträd för en graf med med N noder är N- antalet noder är ju naturligtvis fortfarande N Vi antar att grafen är sammanhängande och oriktad 7 37

Illustration Det minimala spänntädet är inte nödvändigtvis unikt kan finnas flera spännträd med samma minsta kostnad Det är ett träd, eftersom det är acykliskt Det är uppspännande, eftersom det når alla noder Det är minimalt, eftersom det har den minsta totala bågkostnaden Exempel på en graf och dess minimala spännträd: v 3 5 v 3 v v 7 8 0 6 v 3 v v v 6 75 Egenskaper hos spännträd Om vi sätter till en båge e som inte ingår i ett spännträd skapas en cykel om vi tar bort vilken som helst båge från cykeln, får vi igen ett spännträd om bågen e har lägre kostnad än den båge som tas bort från cykeln får vi ett spännträd med lägre total kostnad När vi bygger ett spännträd, om vi alltid sätter till bågar av minimal kostnad som undviker att skapa cykler så får vi det minimala spännträdet dvs. spännträdets kostnad kan inte förbättras Vi presenterar två giriga algoritmer för att bygga minimala spännträd skiljer sig i hur man väljer bågar att inkludera i trädet 76 38

Prim s algoritm Robert Prim, 957 Börja med att välja en nod som rot och en båge från den med minsta vikt placera bågen i spännträdet om det finns flera bågar med samma minsta vikt från rotnoden så väljs en av dessa godtyckligt Lägg successivt till trädet bågar av minimal vikt som är incidenta till en nod redan i trädet och som inte bildar en enkel cykel med de bågar som redan finns i trädet en enkel cykel är en cykel som inte innehåller samma båge mera än en gång Sluta när N- bågar har lagts till 77 Illustration Initialtillståndet i Prim s algoritm är följande: v known dist v path v v F 0 0 v F 0 v 3 F 0 v F 0 F 0 v 6 F 0 v 7 F 0 v 3 5 v v 3 v 7 8 0 6 Det uppspännande trädet: v v v 3 v 78 39

Illustration (forts.) Startnoden v väljs och markeras som known de närliggande noderna är v, v 3 och v de har alla en distans, vilken uppdateras till längden på bågen till v Dist-värdet för en nod v uppdateras till dist v = min (dist v, c w,v ) för alla närliggande obehandlade noder w v known dist v path v v T 0 0 v F v v 3 F v v F v F 0 v 6 F 0 v 7 F 0 v 3 v v v 79 Illustration (forts.) Som nästa nod väljs v, eftersom bågen (v, v ) har den minsta kostnaden () för alla bågar (v, u) där u inte är known och är närliggande till v alla noder är närliggande till v vi undersöker inte v, eftersom den är redan known v skall inte uppdateras, eftersom dist = och bågen (v, v ) har kostnaden 3 alla andra noder uppdateras med längden på bågen till v v known dist v path v v T 0 0 v F v v 3 F v v T v F 7 v v 6 F 8 v v 7 F v v 3 v v v 80 0

Illustration (forts.) Som nästa nod väljs v, eftersom den har minsta distansen,, av de obehandlade noderna v 3 har samma distans, men vi väljer v de närliggande noderna till v är v, v och endast är obehandlad, men den uppdateras inte eftersom (v, ) har längden 0 och dist 5 = 7 Sedan väljs v 3 med närliggande noder v, v och v 6 endast v 6 är obehandlad, vilken uppdateras och får en ny distans 5, eftersom (v 3, v 6 ) har längden 5 och dist 6 var 8 v known dist v path v v T 0 0 v T v v 3 T v v T v F 7 v v 6 F 5 v 3 v 7 F v v 3 v v v 8 Illustration (forts.) v 7 har nu minsta distans av de obehandlade noderna de närliggande noderna och v 6 uppdateras båda, eftersom (v 7, ) har längden 6, vilket är mindre än 7 och (v 7, v 6 ) har längden vilket är mindre än 5 v known dist v path v v T 0 0 v T v v 3 T v v T v F 6 v 7 v 6 F v 7 v 7 T v v 3 v v v 8

Illustration (forts.) Efter det väljs v 6. alla dess närliggande noder v 3, v och v 7 är redan behandlade så vi behöver inte uppdatera någon Som sista nod väljs alla dess närliggande noder är också redan behandlade Algoritmen terminerna v known dist v path v v T 0 0 v v v T v v 3 T v v T v v 3 v T 6 v 7 v 6 T v 7 6 v 7 T v 83 Implementation Spännträdet fås från varje nods path-variabel (v, v ), (v 3, v ), (v, v ), (, v 7 ), (v 6, v 7 ) och (v 7, v ) Implementationen av Prim s algoritm är i princip den samma som för Dijkstra s algoritm, men regeln för att uppdatera distanserna är enklare när vi har valt en obehandlad nod v att sätta till i spännträdet uppdateras distansen för alla närliggande noder w till det minsta av dist w och Cost(w,v). 8

Kruskal s algoritm Joseph Kruskal, 957 Välj en båge i grafen med minimal vikt Lägg successivt till bågar med minimal vikt som inte bildar en enkel cykel med dem som redan valts Sluta när N- bågar har valts Vi behöver ordna bågarna för att få deterministisk algoritm annars kan man välja bågar med lika vikt i godtycklig ordning Girig algoritm väljer alltid bågen med minsta vikt att sätta in i trädet 85 Illustration Vi går igenom Kruskal s algoritm för samma exempel som tidigare Bågarna i grafen är listade ordnade enligt vikt i en tabell Båge Vikt Åtgärd (v, v ) Accepterad (v 6, v 7 ) Accepterad (v, v ) Accepterad (v 3, v ) Accepterad (v, v ) 3 Förkasta (v, v 3 ) Förkasta (v, v 7 ) Accepterad (v 3, v 6 ) 5 Förkasta (, v 7 ) 6 Accepterad (v, ) 7 (v, v 6 ) 8 (v, ) 0 v 3 5 v v 3 7 v 8 0 6 86 3

Illustration Först väljs bågen (v, v ) med vikt och sätts in i trädet v 3 v v v Följande båge är (v 6, v 7 ) också med vikt Den introducerar ingen cykel, så den sätts in v v 3 v v 87 Illustration (forts.) Följande båge är (v, v ) med vikt som inte heller orsakar någon cykel, så den sätts in v v v v 3 Bågen (v 3, v ) med vikt kan också sättas in utan att någon cykel bildas v v 3 v v 88

Illustration (forts.) Bågen (v, v ) med vikten 3 är följande, men den skulle orsaka en cykel, så den förkastas v v v v 3 Bågen (v, v 3 ) med vikten är följande, men den skulle också orsaka en cykel, så den förkastas också v v v 3 v 89 Illustration (forts.) Bågen (v, v 7 ) med vikten kan sättas in utan att någon cykel bildas v v 3 v v Bågen (v 3, v 6 ) med vikten 5 skulle orsaka en cykel, så den förkastas v v 3 v v 90 5

Illustration (forts.) Som sista båge sätts (, v 7 ) med vikten 6 in vi har nu satt in N- bågar i trädet, och algoritmen terminerar v v v 3 v 6 Vi upprätthåller en skog, dvs. en samling av träd när vi sätter in en båge kombineras två träd med varandra, så att resultatet också blir ett träd när algoritmen terminerar är alla noder i ett och samma träd, det minimala uppspännande trädet Vi kan använda Union/Find-algoritmen för att avgöra om en båge kan sättas in utan att en cykel bildas 9 Implementation Två noder hör till samma mängd om och endast om de båda hör till samma träd i skogen som beskriver vårt spännträd initialt hör varje nod till sin egen mängd Om noderna u och v hör till samma mängd så förkastas bågen (u,v) bågen (u,v) skulle förorsaka en cykel, eftersom u och v redan hör till samma träd Om noderna u och v hör till skilda mängder accepteras bågen vi gör en Union på de mängder till vilka u och v hör de två träden kombineras till ett nytt träd 9 6

Implementation (forts.) För att effektivt kunna välja bågen med minsta vikt håller vi bågarna i en heap vi gör en deletemin-operation för att ta ut bågen med minsta vikt I värsta fall måste vi testa alla E bågar förrän vi får det minimala uppspännande trädet körtiden är O( E log E ), eftersom varje deletemin tar O(log E ) tid Exempel på en graf som ger värsta-falls beteende: v v 3 5 v 3 v 7 8 0 6 00 v 8 93 Algoritm public void kruskal() { int edgesaccepted; DisjSet s; PriorityQueue h; Vertex u, v; SetType uset, vset; Edge e; h = readgraphintoheaparray(); // Läs in grafen h.buildheap(); // Bygg heap s = new DisjSet (NUM_VERTICES); // Skapa disj.mängd edgesaccepted = 0; while (edgesaccepted < NUM_VERTICES) { e = h.deletemin(); // Edge e=(u,v) } } uset = s.find (u); // Hitta rötterna till vset = s.find (v); // u och v if (uset!= vset) { // Acceptera bågen (u,v) } edgesaccepted++; s.union (uset, vset); // Sätt in bågen (u,v) 9 7

Euler circuit Leonhard Euler, 707 783 En Euler stig i en oriktad graf G=(E,V) är en stig som besöker varje båge i E exakt en gång vi får besöka en nod flera gånger, dvs. det behöver inte vara en enkel stig En Euler circuit i en oriktad graf G=(E,V) är en cykel som besöker varje båge i E exakt en gång dvs. en Euler stig som startar och slutar i samma nod 95 Euler circuit En Euler circuit existerar endast om grafen är kopplad och varje nod har ett jämnt antal bågar måste både kunna komma till en nod och gå bort från den Om exakt två noder har udda grad existerar en Euler stig i grafen vi kan både starta och sluta stigen i noderna med udda grad om flera än två noder har udda grad existerar ingen Euler stig i grafen Man kan visa att i alla grafer där noderna har en jämn grad existerar en Euler circuit 96 8

Algoritm I en graf där alla noder har en jämn grad kan vi hitta en Euler circuit i linjär tid dvs. i körtiden O( E + V ) Algoritmen baseras på en djupet-först genomgång (depth-first search) av grafen void dfs(vertex v) { v.visited = true; för varje w närliggande till v if (!w.visited) dfs(w); } 97 Algoritm Problemet med att hitta en Euler circuit är att vi kan ha gått igenom bara en del av grafen när vi kommer tillbaka till startnoden en del av bågarna kan fortfarande vara oanvända när vi igen når startnoden När vi kommer tillbaka till startnoden kontrollerar vi alla noder i den resulterande cykeln om någon nod har bågar som inte har blivit använda så startar vi en ny DFS från den bågen resultatet av den här sökningen är en ny cykel, som fogas in i den föregående detta upprepas rekursivt tills alla bågar har blivit använda 98 9

Exempel Vi letar efter en Euler circuit i grafen nedan grafen har en Euler circuit, eftersom alla noder har en jämn grad Vi startar från nod 5 vi besöker t.ex. noderna 5,, 0, 5 8 återkommer till startnoden en del av grafen är fortfarande obesökt Vi fortsätter sökningen från en av de besökta noderna som fortfarande har oanvända bågar nod är den första sådana, så vi startar en ny DFS från den 6 3 9 7 0 5 99 Exempel Om vi tar bort de använda bågarna ur grafen ser den ut såhär: 3 5 6 7 Vi startar en ny sökning från nod den har fortfarande oanvända bågar Antag att den nya sökningen hittar noderna,, 3, 7,,, 0, 7, 9, 3, Om vi sätter in den här stigen i den förra får vi 5,,, 3, 7,,, 0, 7, 9, 3,, 0, 5 8 9 0 00 50

Exempel Den återstående grafen är då: Nästa nod med oanvända bågar är 3 startar en ny sökning från den Antag att sökningen hittar noderna 3,, 8, 9, 6, 3 sätter in dessa i stigen och får 5,,, 3,, 8, 9, 6, 3, 7,,, 0, 7, 9, 3,, 0, 5 8 6 3 9 7 0 5 0 Exempel (forts.) Kvar av grafen blir: Nästa nod med oanvända bågar är 9 startar en sökning från den och hittar 9,, 0, 9 Sätter in den här cykeln i den förra och får cykeln 5,,, 3,, 8, 9,, 0, 9, 6, 3, 7,,, 0, 7, 9, 3,, 0, 5 Algoritmen terminerar alla bågar har blivit använda, vi har en Euler circuit 8 6 3 9 7 0 5 0 5

Implementation För att få en effektiv implementation måste vi använda lämpliga datastrukturer för att effektivt kunna kombinera cykler som vi hittar representeras de som länkade listor vi lagrar information om vilken båge som senast används i incidenslistorna, så behöver vi inte gå igenom dem upprepade gånger vi börjar söka efter en nod med oanvända bågar från den första noden som fogades in i cykeln Körtiden för algoritmen blir då O( E + V ) 03 NP-fullständiga problem En grov klassificering delar in algoritmer i de som exekverar i polynomiell tid och de som exekverar i exponentiell tid introducerad av Jack Edmonds och Alan Cobham, 965 En algoritm sägs vara beräkningsmässigt effektiv om dess kostnad inte är större än någon potens av N, t.ex N k för något heltal k beräkningstiden kan beskrivas av ett polynom av N En algoritm sägs vara beräkningsmässigt ineffektiv om dess kostnad är en exponentiell funktion av N exekveringstiden beror på a N för något reellt tal a > 0 5

Beräkningsmässigt ineffektiva algoritmer Beräkningsmässigt effektiva algoritmer kan sannolikt utföras inom en rimlig tid även för ganska stora värden på N Beräkningsmässigt ineffektiva algoritmer tar för lång tid att vara praktiskt användbar för stora problem Tabellen visar beräkningstiden vid 0 7 op/s för beräkningsmässigt effektiva och ineffektiva algoritmer N=0 N=0 N=70 N 0,0000 s 0,0006 s 0,0009 s N 0,000 s 30,5 h 3736 århundraden 05 Komplexitetsklasserna P och NP Problem för vilka det finns en algoritm som exekverar i polynomiell tid i värsta fall sägs höra till komplexitetsklassen P kan lösas av en deterministisk automat i polynomiell tid Problem som kan lösas av en icke-deterministisk automat i polynomiell tid, men för vilka ingen deterministisk algoritm som exekverar i polynomiell tid är känd, sägs höra till komplexitetsklassen NP Nondeterministisk Polynomiell Alla problem som hör till klassen P hör också till klassen NP NP P 06 53

Komplexitetsklassen P Problem för vilka vi känner till en beräkningsmässigt effektiv algoritm har en värsta-falls exekveringstid som uttrycks av ett polynom c x n + c x n- + c 3 x n- +... c n- x + c n- x + c n Klassen av polynom är sluten under addition, multiplikation och funktionell komposition för två polynom p(n) och q(n) gäller att p(n)+q(n), p(n)q(n) och p(q(n)) också är polynom Vi kan kombinera polynomiell-tids algoritmer, och resultatet kommer att bli en polynomiell-tids algoritm 07 Komplexitetsklassen NP Ett enkelt sätt att avgöra om ett problem hör till klassen NP är att formulera det som en fråga som besvaras med ja eller nej problemet är i NP om vi i polynomiell tid kan verifiera att ett ja-svar är korrekt vi behöver inte kunna verifiera att ett nej-svar är korrekt Exempel: givet en graf G där bågarna har heltalsvikter, och ett heltal k, har G ett uppspännande träd med en vikt som är högst k? givet en graf G, har grafen en Euler circuit? för båda dessa problem känner vi till polynomiell-tids algoritmer, dvs. de är i komplexitetsklassen P komplexitetsklassen NP inkluderar klassen P 08 5

Hamilton circuit En Hamilton circuit i en oriktad graf G=(V,E) är en stig som besöker varje nod i V exakt en gång observera skillnaden till en Euler circuit, som besöker varje båge exakt en gång Hamilton circuit problemet är i komplexitetsklassen NP givet en lösning, dvs. en cykel i grafen, så kan vi enkelt (i polynomiell tid) kontrollera att den är korrekt kontrollerar bara att varje båge i cykeln (v i, v i+ ) E, samt att (v N, v ) E, där N = E Vi känner inte till någon effektiv algoritm för att lösa Hamilton circuit problemet den enda lösningsmetoden som garanterar att vi hittar ett korrekt svar är att undersöka all möjliga alternativ körtiden för algoritmen växer exponentiellt Hamilton circuit problemet hör alltså till NP men vi vet inte om det finns någon polynomiell tids algoritm för det 09 Komplexitetsklasserna P och NP Alla problem som hör till komplexitetsklassen P hör också till komplexitetsklassen NP om ett problem kan lösas av en deterministisk automat i polynomiell tid så kan det också lösas av en icke-deterministisk automat i polynomiell tid Det finns problem som är i NP men för NP vilka vi inte vet om de är i P P t.ex. Hamilton circuit problemet Man har inte för något problem i NP kunnat bevisa att det inte existerar en polynomiell-tids algoritm Man vet inte om P NP det här är en av de stora fundamentala frågorna inom datavetenskap valt som ett av Clay Mathematics Institute Millennium problem 0 55

NP-fullständiga problem Bland problemen i NP finns en mängd kallad NP-fullständiga (NP-complete) problem vilket som helst problem i NP kan i polynomiell tid reduceras till ett NP-fullständigt problem dvs. vi kan uttrycka vilket som helst problem i NP som ett av de NP-fullständiga problemen Om vi skulle hitta en polynomiell-tids lösning till ett NP-fullständigt problem så kunde vi lösa alla problem i NP i polynomiell tid Exempel på NP-fullständiga problem Hamilton cykel givet en graf G, hitta en enkel cykel som besöker varje nod exakt en gång Handelsresandens problem (Travelling salseperson problem, TSP) givet en fullständig graf G med vikter, hitta en enkel cykel som besöker alla noder exakt en gång och som har den minsta kostnaden Satisfiability givet ett logiskt uttryck bildat av Boolska variabler kombinerade med operatorerna AND, OR och NOT, kan vi ge logiska värden (TRUE/FALSE) åt variablerna så att uttryckets värde blir TRUE 56

Exempel på NP-fullständiga problem Graph coloring givet en oriktad graf G och k olika färger, kan man färglägga noderna så att inga närliggande noder har samma färg Subset sum givet en mängd S med n stycken heltal, och ett heltal k, finns det en delmängd av S sådan att dess summa är k Subgraph isomorphism given två grafer G och G, är G isomorfisk med G Många problem inom skedulering och resursplanering hör till klassen NP för dessa är man tvungen att använda sub-optimala lösningsmetoder 3 57