Datastrukturer föreläsning 8 Maps 1
Att hitta den kortaste vägen 0 8 A 4 2 8 B 7 2 C 1 D 2 5 3 9 8 E F 5 3 Lecture 6 2
Viktade grafer I en viktad graf tillordnar vi ett tal till varje båge. Detta tal kallas en vikt Vikter kan representera avstånd, kostnader mm Exempel: avstånd mellan flygplatser SFO 337 1843 ORD 802 849 LGA PVD 1205 HNL LAX 1233 DFW 1120 MIA Lecture 6 3
Att finna kortaste vägen Givet en viktad graf och två noder u och v, finn en väg mellan dem vars bågar har minimal sammanlagd vikt Tillämpningar Färdplaner för flyg, tåg, bilar, osv Snabbaste vägen att skicka ett paket över internet Exempel: HNL Kortaste vägen mellan PVD och HNL SFO 337 LAX 1843 1233 ORD 802 DFW 849 1120 LGA PVD MIA Lecture 6 4 1205
Hur man finner kortaste vägen mellan två noder i en riktad graf Dijkstras algoritm är en generalisering av BFS som beräknar kortaste vägar i en viktad graf. Den besöker noderna i avståndsordning från startnoden. Den beräknar även avståndet från startnoden till alla andra noder. Lecture 6 5
DFS, BFS och Dijkstras algoritm Dessa tre algoritmer delar in noderna i besökta, kandidatnoder (grannar till besökta noder), och obesökta noder. DFS har en stack med kandidatnoder BFS har en kö med kandidatnoder Dijkstras algoritm har en prioritetskö med kandidatnoder Obs. Kön i pseudokoden för BFS är implicit! Lecture 6 6
Exempel: kortaste vägar från noden A till övriga noder 0 8 A 4 2 B 7 C 1 D 3 9 2 E F 5 Besökta noder: 0 Prioritetskö Q: (0,A) Lecture 6 7
Steg 1: besök A och lägg dess grannar i Q! 8 A 4 8 2 2 4 7 1 B C D 3 9 2 5 E F Besökta noder: 1 Prioritetskö Q:(2,C) (4,D) (8,B) Lecture 6 8
Steg 2 8 A 4 8 2 2 3 7 1 B C D 5 3 9 11 2 5 E F Besökta noder: 2 Prioritetskö Q: (3,D)(5,E)(8,B)(11,F) Besök C och lägg till grannarna E och F som inte redan finns i Q. Uppdatera också avståndet till D eftersom en kortare väg från startnoden A har hittats. Lecture 6 9
Steg 3 8 A 4 8 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 3 Prioritetskö Q: (5,E)(8,B)(8,F) Nu är alla noder antingen besökta eller ligger i Q. Vi måste dock uppdatera avståndet till F. Lecture 6 10
Steg 4 8 A 4 7 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 4 Prioritetskö Q: (7,B)(8,F) Nu uppdaterade vi avståndet till B. Lecture 6 11
Steg 5 8 A 4 7 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 5 Prioritetskö Q: (8,F) Lecture 6 12
Steg 6 8 A 4 7 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 6 Q: tom Lecture 6 13
Hur man implementerar Dijkstras algoritm Input: en graf G med icke-negativa vikter och en startnod s Output: För varje nod u det kortaste avståndet D[u] från s. Från början sätter vi D[s] till 0 och D[u] till oändligheten. Under exekveringen av algoritmen kommer D[u] att innehålla de hittills funna kortaste avstånden från s. Algoritmen använder sig av en prioritetskö Q som innehåller alla obesökta noder u med D[u] som prioriteter. Vi besöker den nod som har högst prioritet i Q. Om vi vill returnera kortaste vägar och inte bara kortaste avstånd låter vi D[u] även innehålla en pekare till föregående nod på den kortaste vägen. Om vi vill kunna uppdatera prioriteten i Q för en viss nod behöver vi dessutom lagra platsen som noden lagras på i Q. (Om Q är en heap så lagrar vi index i fältet som lagrar Q.) Lecture 6 14
Dijkstras algoritm Algorithm ShortestPath(G,s) D[s] = 0, D[u] = infinity for all nodes u different from s. Q new priority queue containing all nodes u with priorities D[u] while Q.isEmpty() u Q.removeMinNode() ( visit u) for each node z adjacent to u and not yet visited do if D[u] + weight(u,z) < D[z] then D[z] D[u] + weight(u,z) and update the priority of z in Q return D[u] for each node u En implementeringsdetalj: Q i exemplet tidigare visar inte de avstånd D[u] som är oändligheten. En alternativ implementering har inte dessa med i Q. Lecture 6 15
Några egenskaper Egenskap 1: En delväg till en kortaste väg är också en kortaste väg Egenskap 2: Det finns ett träd av kortaste vägar från en startnod till de alla de andra noderna Exempel: Träd med kortaste vägar från PVD SFO ORD LGA PVD HNL 337 1843 802 849 1205 LAX 1233 DFW 1120 MIA Lecture 6 16
Komplexiteten hos Dijkstra med heap Om grafen har n noder och m bågar och vi implementerar Q med en uppdaterbar heap gäller att Heapmetoderna (ta bort minsta och ändra prioriteten på ett element i Q) är O(log n). Man tar bort minsta elementet n gånger Man ändrar en prioritet för någon nod maximalt en gång för varje båge, dvs O(m). Alltså är komplexiteten O((m+n)log n) Lecture 6 17
Komplexiteten hos Dijkstra med Q som fält Om vi i stället implementerar Q med ett osorterat fält av noder och grafen har n noder och m bågar är Att ta bort minsta elementet är O(n) och man gör detta maximalt n gånger. Totala tiden för denna operation är alltså O(n 2 ). Att ändra prioriteten på ett element är O(1) och man gör detta maximalt en gång för varje båge. Totala tiden för denna operation är alltså O(m). Alltså är komplexiteten O(n 2 + m). Detta är bättre än O((m+n)log n) om vi har en tät graf. Lecture 6 18
Heuristisk sökning Om man letar efter en specifik nod i en graf kan man förbättra Dijkstras algoritm om man har ytterligare heuristisk information T ex kan man uppskatta tiden det tar att åka till en viss hållplats om man vet det geografiska avståndet ( as the crow flies ) När man väljer kandidatnod rankar man noderna efter summan av tiden från utgångspunkten och den uppskattade tiden till målet Denna algoritm kallas A* (brukar betraktas som AI) Heuristik = tumregel Lecture 6 19
Riktade och oriktade grafer Djupet-först, bredden-först och Dijkstras algoritm fungerar på väsentligen samma sätt för riktade grafer som för oriktade grafer (exemplen var oriktade) Lecture 6 20
Transitiva höljet D E B A C Lecture 6 21
Transitiva höljet Antag att du är i en glesbygd. Du vill åka buss från Hammerfest till Rovaniemi. Du bryr dig inte om hur långt tid det tar (kortaste vägen). Du är nöjd om det överhuvudtaget går. Hur tar du reda på det? Med hjälp av en dator på mest effektiva sätt. Lecture 6 22
Transitiva höljet Transitiva höljet av en riktad graf G är en riktad graf G* som har samma noder som G om G har en väg från u till v (u v), så har G* en båge från u till v Transitiva höljet beskriver vilka noder man kan nå från andra noder ( reachability ) Vi kan beräkna transitiva höljet genom att använda DFS én gång för varje nod. Exekveringstiden blir då O(n(n + m)). Fungerar för oriktade grafer också förstås - oriktade grafer är specialfall av riktade grafer! B A B A D C D C E G E G* Lecture 6 23
Floyd-Warshalls algoritm Grafen G är implementerad som en grannmatris A. Vilken tidskomplexitet har följande algoritm? Algorithm FloydWarshall(G) Output transitive closure G* of G A matrix representing the graph G n number of vertices for k 1 to n do for i 1 to n do for j 1 to n do A(i,j) A(i,j) (A(i,k) A(k,j)) return A Lecture 6 24
Topologisk ordning (sortering) Lecture 6 25
Topologisk ordning (sortering) Betrakta Chalmers kursutbud som en graf. Kurserna är noder Förkunskapskraven är bågar Grafen är acyklisk, dvs den saknar cykler Hur bestämmer man en fungerande läsordning? Lecture 6 26
Riktade acykliska grafer och topologiska ordningar En riktad acyklisk graf (directed acyclic graph, DAG) är en riktad graf som inte har några riktade cykler En topologisk ordning är en uppräkning v 1,, v n av noderna i en graf så att för varje båge (v i, v j ) gäller i < j Exempel: graf med kurser och förkunskapskrav. En topologisk ordning ger en följd av kurser som respekterar förkunskapskraven En riktad graf har en topologisk ordning omm grafen är acyklisk v 2 v 1 B A B A Lecture 6 27 D C D C E DAG G v 4 v 5 E v3 Topologisk ordning för G
Topologisk sortering Lagra information om antalet inkommande bågar (u.indegree) för varje nod u Besök en nod med u.indegree = 0. Varje gång en nod v besöks räknar vi ned u.indegree för alla grannar u till v. I exemplet med kurser och förkunskapskrav anger u.indegree antalet återstående förkunskapskrav för kursen u Lecture 6 28
Topologisk sortering Indata: DAG G. Utdata: topologisk ordning av G (en lista L av noder) Algorithm TopologicalSort(G) S empty stack (will hold nodes with indegree 0) L empty list (will hold the topological ordering) for all v G.vertices() if v.indegree = 0 then S.push(v) while S.notEmpty() do u S.pop() L.addLast(u) for all w u.adjacentvertices do w.indegree w.indegree 1 if w.indegree = 0 then S.push(w) Lecture 6 29
Minsta uppspännande träd Lecture 6 30
Minsta uppspännande träd Uppspännande träd till graf fritt delträd innehåller alla noderna Minsta uppspännande träd (MST) är det uppspännande träd som har minst totalvikt (summera bågarnas vikter) Tillämpningar Kommunikationsnätverk Transportnätverk DEN 4 DFW 1 8 9 ORD 6 STL 10 3 5 ATL PIT DCA 2 7 Lecture 6 31
Kruskals algoritm för MST De snåla kommunalpolitikernas algoritm för att asfaltera vägar i kommunen! 1. Asfaltera den kortaste vägen i kommunen 2. Asfaltera den näst kortaste vägen i kommunen, osv 3. Asfaltera dock aldrig någon väg mellan två noder som redan är förbundna med asfalterade vägar DEN 4 DFW 1 8 9 ORD STL 10 ATL PIT Lecture 6 32 6 5 3 DCA 2 7
Prims algoritm för MST Kommunalpampens algoritm för att asfaltera vägar i kommunen 1. Välj en startnod (kommunalpampens hus) t ex DCA 2. Asfaltera kortaste vägen från DCA. Den går till ATL. 3. Utvidga sedan successivt det sammanbundna asfaltsvägnätet med så korta vägar som möjligt som ger en förbindelse till en ny nod. DEN 4 DFW 1 8 9 ORD 6 STL 10 3 5 ATL PIT DCA 2 7 Lecture 6 33
Prims algoritm för MST Kommunalpampens algoritm för att asfaltera vägar i kommunen 1. Kommunalpampen bor i DCA 2. Asfaltera DCA - ATL (kortaste vägen från DCA) 3. Asfaltera DCA STL (kortaste vägen till ny nod från DCA eller ATL) 4. Asfaltera STL ORD (kortaste vägen till ny nod från DCA, ATL eller STL). Etc. DEN 4 DFW 1 8 9 ORD STL 10 ATL PIT Lecture 6 34 6 5 3 DCA 2 7
Prims algoritm Algoritmen liknar Dijkstras algoritm. Även här har vi en prioritetskö Q med obesökta noder. För varje nod u lagrar vi en båge e = E[u] med vikt w = D[u]. Vikten används som nodens prioritet. Vi bygger dessutom upp ett träd T med besökta noder och bågar som spänner upp dem. När algoritmen terminerar innehåller T ett minsta uppspännande träd. Lecture 6 35
Prims algoritm Algorithm Prim(G,s) D[s] 0, D[u] infinity for all nodes u different from s. E[u] null for all nodes u T new free tree, initially empty Q new priority queue with triples (D[u],(u,E[u])), where weights D[u] are priorities. while Q.isEmpty() (u,e) Q.removeMin() ( visit u along e) add node u and edge e to T for each node z adjacent to u such that z is in Q do if weight(u,z) < D[z] then D[z] weight(u,z) and E[z] the edge from u to z update the priority of z in Q return D[u] for each node u Lecture 6 36
Prims algoritm (alternativ pseudokod) Algorithm Prim(G,s) Q new priority queue T new free tree for all (v,w) s.adjacentedges() Q.insertItem(w,(s,v)) add s to T while vertices in the tree < vertices in the graph do (u,e) Q.minElement() w Q.minKey() Q.removeMin() if v.isadded then add e to T e.isadded true add (u,v) to T for all (z,w) v.adjacentedges() do Q.insertItem(w,(v,z)) Lecture 6 37
Summering, grafalgoritmer Djupet först och bredden först sökning: O(n+m) med grannlista Hitta ev. cykler, uppspännande träd, en väg mellan två givna noder. Upprepad DFS eller BFS på alla noder i grafen ger transitiva höljet O(n(n+m)) Bredden först sökning hittar dessutom kortaste vägen till en viss nod Lecture 6 38
Summering: grafalgoritmer Floyd-Warshall: O(n 3 ) om areadjacent är O(1) Beräknar transitiva höljet av en riktad graf Topologisk sortering: riktade acykliska grafer O(n+m) med grannlista Sortera grafen. Exempel: graf med förkunskaper för kurser, i vilken ordning kan vi läsa kurserna? Lecture 6 39
Summering: grafalgoritmer Dijkstras algoritm: viktad graf O((m+n)logn) med heap och grafen implementerad med grannlista. O(m+n 2 ) med osorterat fält och grafen implementerad med grannlista (bättre för täta grafer med många bågar). Hittar kortaste avståndet/vikten mellan två noder. Ett slags BFS-sökning för viktade grafer Lecture 6 40
Summering: grafalgoritmer Kruskals och Prims algoritmer: O((m+n)log n) = O(m log n) (sammanhängande graf)s Minsta uppspännande träd. Prims och Kruskals algoritmer liknar Dijkstras, men prioritetsköerna innehåller bågvikter i stället för längden på kortaste vägen till startnoden. Kruskal, Prim och Dijkstra är alla exempel på giriga ( greedy ) algoritmer. Se algoritmkursen om andra allmänna tekniker, t ex söndra och härska ( divide and conquer ). Lecture 6 41