Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pa:laboratoare:shortest-paths-problem [2022/04/20 02:08]
darius.neatu created
pa:laboratoare:shortest-paths-problem [2023/05/08 22:20] (current)
radu.iacob [[Studiu de caz] k surse / destinații]
Line 1: Line 1:
-TODO Darius+====== Shortest-paths problem ====== 
 + 
 +===== Importanţă – aplicaţii practice ===== 
 + 
 +Algoritmii pentru determinarea drumurilor minime au multiple aplicații practice si reprezintă clasa de algoritmi pe grafuri cel mai des utilizată. Câteva exemple de aplicații sunt: 
 + 
 +  * Rutare în cadrul unei rețele de calculatoare. 
 +  * Găsirea drumului minim dintre două locații (Google Maps, GPS etc.). 
 +  * Stabilirea unei agende de zbor în vederea asigurării unor conexiuni optime. 
 + 
 +===== Shortest-paths problem ===== 
 + 
 +Puteți consulta capitolele **Single-Source Shortest Paths** și **All-Pairs Shortest Paths** din **Introduction to Algorithms** [0] pentru mai multe definiții formale. Această secțiune sumarizează principalele notații folosite în laboratoarele de PA.- [[#​shortest-paths-problem|Shortest-paths problem]] 
 + 
 +Cele mai uzuale notații din laboratoarele de grafuri sunt descrise în [[https://​ocw.cs.pub.ro/​courses/​pa/​skel_graph|Precizări laboratoare 07-12]] (ex. $n$, $m$, $adj$, $adj\_trans$,​ $(x, y)$, etc). 
 + 
 +Vom adăuga alte notații în continuarea celor introduse anterior. 
 + 
 + 
 + 
 +> **Costul unei muchii** / **edge cost**: $w[u][v]$ reprezintă costul muchiei de la nodul $u$ la nodul $v$. 
 + 
 +<spoiler Exemplu>​ 
 + 
 + 
 + 
 +> **Costul unei muchii** / **edge cost**: Fiind dat un graf orientat $G = (V, E)$, se consideră funcția $w: E -> W$, numită funcție de cost, care asociază fiecărei muchii o valoare numerică. 
 + 
 +Domeniul funcției poate fi extins, pentru a include și perechile de noduri între care nu există muchie (directă), caz în care valoarea este $+∞$ . 
 + 
 +{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab09-graph-cost-example.png?​512| Exemplu funcție de cost pentru graf orientat}} 
 + 
 +În exemplul atașat, avem un graf **orientat** cu următoare configurație:​ 
 + 
 +  * ''​%%n = 5%%'',​ ''​%%m = 6%%''​ 
 +  * Funcția de cost ''​%%w%%''​ are următorele valori finite (restul valorilor fiind $+∞$, pentru perechile de noduri între care nu există muchie): 
 +    * $w[1][2] = 100$ 
 +    * $w[1][3] = 1$ 
 +    * $w[2][3] = -1$ 
 +    * $w[3][4] = 2$ 
 +    * $w[2][5] = 5$ 
 +    * $w[4][5] = 2$ 
 + 
 +Observație:​ Costul pe o muchie poate să fie negativ! (sau chiar zero) </​spoiler>​ \\ 
 + 
 + 
 + 
 + 
 +> **Drum** / **Path**: $p = (v_1, v_2, ..., v_k)$ este un drum în graful $G = (V, E)$, dacă pentru oricare $i = 1:k - 1$, există muchia $(v_i, v_{i+1})$. 
 + 
 + 
 + 
 +> **Costul unui drum** / **path cost**: $w(p) = \sum_{i=1:​k-1} {w[v_i][v_{i+1}]}$ - costul unui drum $p$ este suma costurior muchiilor care îl compun. 
 + 
 +<spoiler Exemplu>​ 
 + 
 +{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab09-graph-cost-example.png?​512| Exemplu drumuri cu cost pentru graf orientat}} 
 + 
 +În exemplul atașat, avem un graf **orientat** cu următoare configurație:​ 
 + 
 +  * ''​%%n = 5%%'',​ ''​%%m = 6%%''​ 
 +  * Funcția de cost ''​%%w%%''​ are valorile menționate pe muchii. 
 +  * Avem următoarele costuri asociate pentru drumurile din graf: 
 +    * $p = (1, 2)$, $w(p) = 100$ 
 +    * $p = (1, 2, 3)$, $w(p) = 100 - 1 = 99$ 
 +    * $p = (1, 2, 3, 4)$, $w(p) = 100 - 1 + 2 = 101$ 
 +    * $p = (1, 2, 3, 4, 5)$, $w(p) = 100 - 1 + 2 + 3= 104$ 
 +    * $p = (1, 2, 5)$, $w(p) = 100 + 5= 105$ 
 +    * $p = (1, 3)$, $w(p) = 1$ 
 +    * $p = (1, 3, 4)$, $w(p) = 1 + 2 = 3$ 
 +    * $p = (1, 3, 4, 5)$, $w(p) = 1 + 2 + 3 = 6$ 
 +    * și tot așa pentru drumurile care încep cu 2, 3, etc. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 + 
 + 
 +> **Shortest-paths problem** / **problema drumurilor minime**: Dat fiind un graf $G = (V, E)$, dorim să aflăm drumul de cost / lungime minimă între anumite noduri din graf. 
 + 
 +<spoiler Exemplu>​ 
 + 
 +{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab09-graph-cost-example.png?​512| Exemplu drumuri cu cost pentru graf orientat}} 
 + 
 +În exemplul atașat, avem un graf **orientat** cu următoare configurație:​ 
 + 
 +  * ''​%%n = 5%%'',​ ''​%%m = 6%%''​ 
 +  * Funcția de cost ''​%%w%%''​ are valorile menționate pe muchii. 
 +  * Avem mai multe drumuri de cost diferite între diverse perechi de noduri din graf. 
 +  * Analizăm care dintre toate aceste drumuri au cost minim: 
 +    * Drumul minim de la $1$ la $2$ este $p = (1, 2)$ cu $w(p) = 100$. Este singurul drum posibil. 
 +    * Drumul minim de la $1$ la $3$ este $p = (1, 3)$ cu $w(p) = 1$. Mai există drumul $p = (1, 2, 3)$, dar de cost mai mare. 
 +    * Drumul minim de la $1$ la $4$ este $p = (1, 3, 4)$ cu $w(p) = 1 + 2 = 3$. Mai există drumul $p = (1, 2, 3, 4)$, dar de cost mai mare. 
 +    * Drumul minim de la $1$ la $5$ este $p = (1, 3, 4, 5)$ cu $w(p) = 1 + 2 + 3 = 6$. Mai există drumurile $p_1 = (1, 2, 3, 4, 5)$ și $p_2 = (1, 2, 5)$, dar de cost mai mare. 
 +    * Analog și pentru drumurile care pornesc din 2, 3, etc. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 +===== Shortest-paths:​ variants ===== 
 + 
 + 
 + 
 +> **Sursă unică** / **single-source shortest-paths problem**: Se dă un graf $G = (V, E)$ și un nod special $source$, considerat sursă. Se cere calculul distanței de la sursa **source** la toate nodurile din graf. Formal: $d[v] = distanța\ de\ la\ sursa\ ​ \textbf{source}\ la\ nodul\ \textbf{v}$. 
 + 
 +<spoiler Exemplu>​ 
 + 
 +{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab09-graph-distances-example.png?​512| Exemplu drumuri de cost minim - sursă unică}} 
 + 
 +În exemplul atașat, avem un graf **neorientat** cu următoare configurație:​ 
 + 
 +  * ''​%%n = 5%%'',​ ''​%%m = 6%%''​ 
 +  * Funcția de cost ''​%%w%%''​ are valorile menționate pe muchii. 
 +  * Avem mai multe drumuri de cost diferite între diverse perechi de noduri din graf. 
 +  * Pentru exemplificare,​ alegem $ source = 1 $ și obținem vectorul de distanțe : 
 + 
 +|node|1|2|3|4|5|6| \\ 
 +|d[node]|0|0|1|4|7|$+∞$| \\ 
 + 
 + 
 +  * Explicație:​ 
 +    * $d[1] = 0$, pentru că 1 este sursa 
 +    * $d[2] = 0$, pentru că druml minim de la 1 la 2 este $p = (1, 3, 2)$ de cost $w(p) = 1 - 1= 0$. 
 +    * $d[3] = 1$, pentru că druml minim de la 1 la 3 este $p = (1, 3)$ de cost $w(p) = 1$. 
 +    * $d[4] = 0$, pentru că druml minim de la 1 la 4 este $p = (1, 3, 4)$ de cost $w(p) = 1 + 3= 4$. 
 +    * $d[5] = 5$, pentru că druml minim de la 1 la 5 este $p = (1, 3, 2, 5)$ de cost $w(p) = 1 - 1 + 5 = 5$. 
 +    * $d[6] = +∞$, pentru că nodul 6 nu este accesibil din sursa 1. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 + 
 + 
 +> **Destinație unică** / **single-source shortest-paths problem**: Se dă un graf $G = (V, E)$ și un nod special $destination$,​ considerat destinație. Se cere calculul distanței de la fiecare nod la nodul **destination**. Putem reduce această problema la cea de **sursă unică** (pentru graf orientat, trebuie să folosim graful transpus). 
 + 
 +\\ 
 + 
 + 
 + 
 +> **Pereche unică** / **single-pair shortest-path problem**: Se dă un graf $G = (V, E)$. Se cere calculul drumului minim între 2 noduri **fixate** $u$ și $v$. Observăm că din nou putem reduce problem la **sursă unică**, alegând pe $u$ sau $v$ drept sursă. 
 + 
 +\\ 
 + 
 + 
 + 
 +> **Surse / destinații multiple** / **all-pairs shortest-paths problem:**: Se dă un graf $G = (V, E)$. Se cere calculul drumului minim între **oricare** 2 noduri $u$ și $v$. Formal: $d[u][v] = distanța\ de\ la\ nodul\ \textbf{u}\ la\ nodul\ \textbf{v}$. 
 + 
 +<spoiler Exemplu>​ 
 + 
 +{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab09-graph-distances-example.png?​512| Exemplu drumuri de cost minim - surse și destinații multiple}} 
 + 
 +În exemplul atașat, avem un graf **orientat** cu următoare configurație:​ 
 + 
 +  * ''​%%n = 5%%'',​ ''​%%m = 6%%''​ 
 +  * Funcția de cost ''​%%w%%''​ are valorile menționate pe muchii. 
 +  * Avem mai multe drumuri de cost diferite între diverse perechi de noduri din graf. 
 +  * Tabloul d este de această dată o matrice de distanțe 
 + 
 +|-|1|2|3|4|5|6| \\ 
 +|1|0|100|1|4|5|$+∞$| \\ 
 +|2|$+∞$|0|$+∞$|$+∞$|5|$+∞$| \\ 
 +|3|$+∞$|-1|0|3|4|$+∞$| \\ 
 +|4|$+∞$|$+∞$|$+∞$|0|3|$+∞$| \\ 
 +|5|$+∞$|$+∞$|$+∞$|$+∞$|0|$+∞$| \\ 
 +|6|$+∞$|$+∞$|$+∞$|$+∞$|$+∞$|0| \\ 
 + 
 + 
 +  * Explicație:​ 
 +    * $d[u][u] = 0$ (convenție) 
 +    * $d[u][v] = +∞$, dacă nu există muchia $(u, v)$ (convenție) 
 +    * Exemple 
 +      * $d[1][5] = 5$, pentru că drumul minim de la 1 la 5 este $p = (1, 3, 2, 5)$ de cost $w(p) = 1 - 1 + 5 = 5$. 
 +      * $d[3][5] = 4$, pentru că drumul minim de la 3 la 5 este $p = (3, 2, 5)$ de cost $w(p) = - 1 + 5 = 4$. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 +===== Edge relaxation ===== 
 + 
 + 
 + 
 +> **Relaxarea unei muchii** / **edge relaxation**:​ A relaxa o muchie $(u, v)$ constă în a testa dacă se poate **reduce distanța / costul drumului** de la sursa **source** până la nodul **v**, trecând prin nodul intermediar $u$ și apoi circuland pe muchia $(u, v)$. 
 + 
 +**Toți** algoritmii pentru topologii generale prezentați în laboratoarele 09 și 10 se bazează pe relaxare pentru a determina drumul minim. 
 + 
 +<spoiler Detalii și exemple>​ 
 + 
 +Presupunem următoarele notații: 
 + 
 +  * $w[u][v]$ costul muchiei $(u, v)$ 
 +  * $d[source][u]$ costul **drumului** de la sursa **source** la nodul **u** 
 +  * $d[source][v]$ costul **drumului** de la sursa **source** la nodul **v** 
 + 
 +Dacă $d[source][v] > d[source][u] + w[u][v]$ muchia $(u, v)$ este **relaxată** și drumul anterior $(source, ..., v)$ (care **nu** trece prin $u$) este înlocuit cu drumul $(source, ..., u, v)$ (care trece prin u și care are cost mai mic!). 
 + 
 +{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab09-graph-distances-example.png?​512| Exemplu relaxare muchii}} 
 + 
 +În exemplul atașat, avem un graf **orientat** cu următoare configurație:​ 
 + 
 +  * ''​%%n = 5%%'',​ ''​%%m = 6%%''​ 
 +  * Funcția de cost ''​%%w%%''​ are valorile menționate pe muchii. 
 +  * Avem mai multe drumuri de cost diferite între diverse perechi de noduri din graf. 
 +  * Alegem $source = 1$. 
 +  * Pentru că inițial cunoaștem doar drumurile directe (muchiile), singurele distanțe față de sursă pe care le cunoaștem sunt $d[1][1] = 0$, $d[1][2] = 100$, $d[1][3] = 1$. Restul distanțelor se consideră inițial ca fiind egale cu infinit. 
 +  * Vom relaxa muchia $(3, 2)$ de cost $w[3][2] = -1$. Aceasta ne permite să reactualizăm distanța de la sursa **1** la nodul **2** cu valoarea **0** deoarece $d[1][3] + w[3][2] = -1 + 1 = 0 < d[1][2]$. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 +===== RebuildPath ===== 
 + 
 +O să observăm că toți algoritmii studiați produc 2 rezultate: $d$ (distanțele față de sursă) și $p$ (vectorul de părinți, folosit pentru reconstituirea drumurilor). 
 + 
 +În această secțiune prezentăm procedura de reconstruire a drumului, pornind de la destinație către sursă, apoi inversând la final șirul de noduri obținut. Această metoda este independentă de algoritmul cu care vectorul de părinți **p** a fost calculat! 
 + 
 +===== RebuildPath - Pseudocod ===== 
 + 
 +<code cpp> 
 +// rebuild path from source to destination using parents vector p 
 +// (previously computed with a shortest-paths algorithm) 
 +// 
 +// source ​     = the source for the computing distances 
 +// destination = the destination node 
 +// p[node] ​    = parent of node on the shortest path from source to node 
 +RebuildPath(source,​ destination,​ p) { 
 +  // STEP 0: Create an empty path. 
 +  path = []; 
 + 
 +  // STEP 1:  Add nodes one by one, from destination to source going up on parents! 
 +  // (source, ..., p[destination],​ destination) 
 +  while (source != destination) { 
 +    path.push_back(destination);​ 
 +    destination = p[destination];​ 
 +  } 
 +  // STEP 1.1: Also add the source. 
 +  path.push_back(source);​ 
 + 
 +  // STEP 2: Reverse to actually get path (source, ..., destination). 
 +  reverse(path);​ 
 + 
 +  return path; 
 +
 + 
 +// Usage example: 
 +// * run algorithm for computing shortests-paths 
 +d, p = RunShortestPathsAlgorithm(source,​ G=(nodes, edges)) 
 +// * call rebuikd 
 +path = RebuildPath(source,​ destination,​ p) 
 +</​code>​ 
 +Analog se reconstitue drumul și dacă suntem pe cazul cu surse multiple, destinații multiple, unde tabloul $p$ este o matrice, iar atunci când cautăm un drum care începe cu nodul $source$, folosim doar elementele de pe linia $p[source]$. 
 + 
 +===== [Studiu de caz] Shortest-paths:​ particular topologies ===== 
 + 
 +Vom menționa câteva cazuri particulare de topologii de grafuri unde putem obține soluție optimă pentru **shortest-paths problem** cu noțiunile învățate anterior, nefiind necesar să folosim algoritmi mai complecși, pe care îi vom studia în continuare pentru topologii generale. 
 + 
 +==== Shortest-paths:​ no costs - BFS ==== 
 + 
 +Dacă avem un graf **fără costuri** sau **cu toate costurile egale**, o soluție optimă va folosi **BFS**. 
 + 
 +<spoiler Detalii>​ 
 + 
 +Dacă avem un graf **fără costuri** sau **cu toate costurile egale**, putem afla distanța minimă de la un nod $source$ la orice alt nod printr-o parcurgere BFS, considerând lungimea unui drum ca fiind numărul de muchii de pe drum (ulterior se înmulțește cu costul comun a muchiilor, dacă acesta există). 
 + 
 +  * **complexitate temporală**:​ $T = O(n + m)\ sau\ O(|V| + |E|)$ 
 +    * Complexitatea dată de parcurgere. 
 +  * **complexitate spațială** : $S = O(1)$ 
 +    * Nu avem memorie spațială auxialiară. ATENȚIE! Vom aloca tabloul $d$, însă acesta nu este specific algoritmului. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 +==== Shortest-paths:​ Tree - DFS ==== 
 + 
 +Dacă avem un **arbore** (graf neorientat acicllic), o soluție optimă va folosi **DFS**. 
 + 
 +<spoiler Detalii>​ 
 + 
 +Dacă avem un **arbore** (graf neorientat acicllic), există un singur drum între oricare două noduri, care poate fi aflat printr-o simplă parcurgere **DFS** / **BFS**. 
 + 
 +  * **complexitate temporală**:​ $T = O(n + m)\ sau\ O(|V| + |E|)$ 
 +    * Complexitatea dată de parcurgere. 
 +  * **complexitate spațială** : $S = O(1)$ 
 +    * Nu avem memorie spațială auxialiară. ATENȚIE! Vom aloca tabloul $d$, însă acesta nu este specific algoritmului. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 +Folosind diferite preprocesări,​ putem calcula distanța între oricare două noduri în $O(1)$. 
 + 
 +==== Shortest-paths:​ DAG - Topological Sort ==== 
 + 
 +Daca avem un **DAG** (graf orientat aciclic), o soluție optimă va folosi **Topological Sort**. 
 + 
 +<spoiler Detalii>​ 
 + 
 +Daca avem un **DAG** (graf orientat aciclic), putem să relaxăm muchiile nodurilor, parcurgându-le pe acestea în ordinea dată de sortarea topologică. 
 + 
 +  * **complexitate temporală**:​ $T = O(n + m)\ sau\ O(|V| + |E|)$ 
 +    * Complexitatea dată de parcurgere. 
 +  * **complexitate spațială** : $S = O(n)$ 
 +    * Stocăm vectorul cu sortarea topologică. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 +===== [Studiu de caz] k surse / destinații ===== 
 + 
 +Mai există o varianta a problemei pe care dorim să o menționăm. Avem **k** surse (sau destinații),​ unde **k << n ** (k mult mai mic decât n - de exemplu, $k = 10$ constant) și ne interesează să găsim distanța pentru fiecare nod din graf către cea mai apropiată sursă. 
 + 
 +O abordare naivă ar rula de **k** ori un algorthm de drumuri minime (de exemplu, Dijkstra) și pentru fiecare nod ar reține minimul dintre cele k distanțe calculate pentru un nod. Complexitatea este $O(k * complexitate\_algoritm$). 
 + 
 +O optimizare pe care o putem facem, este să adaugăm un nod fictiv $S$ și să îl unim cu fiecare dintre cele **k** noduri cu muchie de cost **0**. În noul graf format, dacă vom rula un algoritm să găsim toate distanțele de la nodul **S** la celelalte noduri din graf, rezolvăm și problema inițială. 
 + 
 +Dacă alegem să folosim Dijkstra, putem să nu modificăm graful. Dacă băgăm cele **k** surse în heap în etapa de inițializare,​ efectul este ca și cum s-ar fi scos nodul **S** și s-au relaxat toate muchiile care pornesc din acesta. 
 + 
 +===== Referințe ===== 
 + 
 +[0] Chapters **Single-Source Shortest Paths** / **All-Pairs Shortest Paths**, “Introduction to Algorithms”,​ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein. 
pa/laboratoare/shortest-paths-problem.1650409703.txt.gz · Last modified: 2022/04/20 02:08 by darius.neatu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0