Differences

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

Link to this comparison view

pa:laboratoare:laborator-11 [2017/05/14 22:45]
david_traian.iancu [Probleme]
pa:laboratoare:laborator-11 [2023/03/15 16:58] (current)
radu.nichita
Line 1: Line 1:
-====== Laborator 11 : Algoritmi euristici ​de explorare a grafurilor. A* ======+====== Laborator 11: Flux maxim în rețele ​de transport ​====== 
 + 
 + 
 +{{:​pa:​new_pa:​partners:​bitdefender-logo.png?​190 |}} Bitdefender provides cybersecurity solutions with leading security efficacy, performance and ease of use to small and medium businesses, mid-market enterprises and consumers. Guided by a vision to be the world’s most trusted cybersecurity solutions provider, Bitdefender is committed to defending organizations and individuals around the globe against cyberattacks to transform and improve their digital experience.
  
 ===== Obiective laborator ===== ===== Obiective laborator =====
  
-In cadrul acestui ​laborator ​se va discuta despre modelarea problemelor sub forma grafurilor de stari si despre ​algoritmi ​specializati in gasirea solutiilor pentru acest tip de grafuri. De asemenea, se vor discuta modalitatile ​care pot fi folosite in analiza complexitatii si pe baza acestor metode se vor prezenta avantajele si limitarile acestei clase de algoritmi.+În acest laborator ​vom introduce contextul pentru **maximum flow problem** și vom studia ​algoritmi care pot rezolva această problemă.
  
-===== Importanţă – aplicaţii practice =====+  * Prezentarea noțiunii de rețea de transport și a termenilor asociați. 
 +  * Prezentarea problemei (diverse variante). 
 +  * Prezentarea algoritmilor pentru calcul unui flux maxim într-o rețea de transport.
  
-Algoritmii de cautare euristica sunt folositi in cazurile care implica gasirea unor solutii pentru probleme pentru care fie nu exista un model matematic de rezolvare directa, fie acest model este prea complicat pentru a fi implementat. In acest caz e necesara o explorare a spatiului starilor problemei pentru gasirea unui raspuns. Intrucat o mare parte dintre problemele din viata reala pornesc de la aceste premise, gama de aplicatii a algoritmilor euristici este destul de larga. Proiectarea agentilor inteligenti [1], probleme de planificare,​ proiectare circuitelor VLSI [3], robotica, cautare web, algoritmi de aproximare pentru probleme NP-Complete [10], teoria jocurilor ​ sunt doar cateva dintre domeniile in care cautarea informata este utilizata.+===== Maximum flow problem =====
  
-===== Descrierea problemei şi a rezolvărilor =====+Vă rugăm să parcugeț[[https://​ocw.cs.pub.ro/​courses/​pa/​laboratoare/​maximum-flow-problem|Maximum flow problem]] pentru ​vă familiariza cu contextul, problema și notațiile folosite.
  
-==== Prezentare generală a problemei ====+Concepte necesare:
  
-Primul pas in rezolvarea unei probleme folosind algoritmi euristici ​de explorare este definirea exacta ​problemei, prin tuplul (Si, O, Sf) – stare initiala, operatori, stari finale. Incercam sa cunoastem urmatorii parametri:+  * **rețea ​de transport** / **flow network** 
 +  * **flux** / **flow** 
 +  * **flux maxim** / **maximum flow** 
 +  * **capacitate reziduală** / **residual capacity** 
 +  * **rețea reziduală** / **residual network** 
 +  * **drum de ameliorare** / **augmenting path** 
 +  * **capacitate reziduală ​unui drum de ameliorare** / **residual capacity of augmenting path**
  
-  ***Starea initiala a problemei** – reprezinta configuratia de plecare. +===== Algoritmi =====
-  ***Functie de expandare a nodurilor** – in cazul general este o lista de perechi (actiune, stare_rezultat). Astfel, pentru fiecare stare se enumera toate actiunile posibile precum si starea care va rezulta in urma aplicarii respectivei actiuni.  +
-  ***Predicat pentru starea finala** – functie care intoarce adevarat daca o stare este stare scop si fals altfel +
-  ***Functie de cost** – atribuie o valoare numerica fiecarei cai generate in procesul de explorare. De obicei se foloseste o functie de cost pentru fiecare actiune/​tranzitie,​ atribuind, astfel, o valoare fiecarui arc din graful starilor.+
  
-In functie de reprezentarea problemeisarcina algoritmilor de cautare este de a gasi o cale din starea initiala intr-o stare scop. Daca algoritmul gaseste o solutie atunci cand multimea solutiilor este nevida spunem ca algoritmul este complet. Daca algoritmul gaseste si calea de cost minim catre starea finala spunem ca algoritmul este optim.+Pentru **maximum flow problem** există mai mulți algoritmidintre care amintim:
  
-In principiuorice algoritm pe grafuri discutat in laboratoarele si cursurile ​anterioare ​poate fi utilizat pentru gasirea solutiei unei probleme astfel definiteIn practica, insamulti dintre acesti algoritmi nu sunt utilizati in acest context, fie pentru ​ca exploreaza mult prea multe noduri, fie pentru ca nu garanteaza o solutie pentru grafuri definite implicit ​(prin stare initiala si functie de expandare).+  * **Ford–Fulkerson**:​ Este o metodă (nu un algorithm concret)a cărui complexitate este direct proporțională cu valoarea fluxului maxim - $O(m * f_{max})$. [1] 
 +  * **Edmonds-Karp**:​ Este o implementare concretă / optimizare a metodei ​anterioare ​- $O(n * m^2)$[2] 
 +  * **Dinic**: O optimizare bazată pe construirea progresivă a unui graf folosind BFS. În fiecare etapă se poate afla fluxul în $O(n * m)$iar în total sunt $n -1$ etape. Complexitate finală $O(n^2 * m)$. [3] 
 +  * **Preflow-push / push-relabel**:​ Un algoritm care poate fi optimizat ​pentru ​a obține complexitate $O(n^3)$ sau $O(n^2 * m)$.
  
-Algoritmii euristici de cautare sunt algoritmi ​care lucreaza pe grafuri definite ca mai sus si care folosesc o informatie suplimentara,​ necontinuta in definirea problemei, prin care se accelereaza procesul de gasirea a unei solutii. +Puteți consulta capitolul **Maximum Flow** din **Introduction to Algorithms** [0] pentru mai multe detalii despre acești ​algoritmi.
-In cadrul explorarii starilor fiecare algoritm genereaza un arbore, care in radacina va contine starea initialaFiecare nod al arborelui va contine urmatorele informatii:+
  
-  - **Starea continuta** - stare(nod) +În acest laborator vom studia și analiza ​**metoda Ford-Fulkerson**, apoi vom implementa ​**algoritmul Edmonds-Karp** (care este o optimizare peste Ford-Fulkerson).
-  - **Parintele nodului** – π(nod) +
-  ​- **Cost cale** – costul drumului de la starea initiala pana la nod – g(nod)+
  
-De asemenea, pentru fiecare nod definim si o functie de evaluare **f** care indica cat de promitator este un nod in perspectiva gasirii unui drum catre solutie. (De obicei, cu cat **f** este mai mic, cu atat nodul este mai promitator). +===== Ford-Fulkerson =====
-Am mentionat mai sus ca algoritmii de cautare euristica utilizeaza o informatie suplimentara referitoare la gasirea solutiei problemei. Aceasta informatie este reprezentata de o functie **h**, unde h(nod) reprezinta drumul estimat de la nod la cea mai apropiata stare solutie. Functia h poate fi definita in orice mod, existand o singura constrangere:​+
  
- h(n)=0 pt ∀n,solutie(n)=adevarat  +Algoritmul lui [[https://​en.wikipedia.org/​wiki/​L._R._Ford_Jr.|Lester Randolph **Ford** Jr. ]] și [[https://​en.wikipedia.org/​wiki/​D._R._Fulkerson|Delbert Ray **Fulkerson**]]cunoscut ca și algoritmul / metoda [[https://​en.wikipedia.org/​wiki/​Ford%E2%80%93Fulkerson_algorithm|Ford-Fulkerson]] este un algoritm **greedy** pentru calcularea fluxului maxim într-o rețea ​de transport.
-  +
-==== Algoritmi ​de cautare informata ====+
  
-Intrucat functioneaza prin alegerea, la fiecare pas, a nodului pentru care f(nodeste minimalgoritmii prezentati ​mai jos fac parte din clasa algoritmilor de cautare informata (nodul cel mai promitator este explorat mereu primul)Best-First tine cont doar de istoric (informatii sigure)pe cand A* estimeaza costul pana la gasirea unei solutii. +Atât timp cât în graf încă există drumuri de ameliorare ​(augmenting paths), înseamnă că mai putem adauga flux in rețea prin acele drumuriLa fiecare pas alegem un drum de ameliorareprin care adăugăm cantitatea maximă posibilă de flux.
-De notat ca BFS si DFS sunt particularizari ale Best-First: ​+
  
-  *pentru BFS: f = adancime (S) +<spoiler Ford-Fulkerson - Pseudocod>​
-  *pentru DFS: f = adancime (S)+
  
-Vom prezenta ​in continuare cativa dintre cei mai importanti algoritmi de cautare euristica. Vom folosi pentru exemplificareurmatoarea problemadata fiind o harta rutiera a Romanieisa se gaseasca o cale (de preferinta de cost minimintre Arad si Bucuresti. ​+<code cpp> 
 +// apply Ford-Fulkerson'​s algorithm for computing maximum flow in network G 
 +// 
 +// nodes     = list of all nodes from G 
 +// edges     = the list of all edges in G 
 +//             ​example:​ edge (nodeneigh, capacity) 
 +// S         = source in network G 
 +// T         = sink in network G 
 +// 
 +// returnsmaxFlow (maximum flow in G from S to T) 
 +// 
 +Ford-Fulkerson(G=(nodesedges), S, T) { 
 +  // STEP 0: initialize 
 +  // * flow in network 
 +  foreach ​((u, v) in edges
 +      f[u][v] = 0; 
 +  } 
 +  // * maximum total flow 
 +  totalFlow = 0;
  
-Pentru aceasta problema starea initiala indica faptul ca ne aflam in orasul Arad, starea finala este data de predicatul Oras_curent == Bucuresti, functia de expandare intoarce toate orasele in care putem ajunge dintr-un oras dat, iar functia de cost indica numarul de km al fiecarui drum intre doua orase, presupunand ca viteza de deplasare este constanta. Ca euristica vom utiliza pentru fiecare oras distanta geometrica(in linie dreaptapana la Bucuresti.+  while (exists augmenting path p in G
 +      augment flow f along p; 
 +      update totalFlow;​ 
 +  }
  
-{{ :​pa:​laboratoare:​111.png?​400 |}}+  return totalFlow;​ 
 +}
  
-==== Greedy Best-First ====+// Usage example: 
 +maxFlow ​Ford-Fulkerson(G=(nodes, edges), S, T); 
 +// Use maxFlow. 
 +</​code>​ 
 +După cum se observă, metoda Ford-Fulkerson descrie care este abordarea generală, însă nu ne spune concret cum să găsim drumurile de ameliorare și cum să creștem fluxul pe ele.
  
-In cazul acestui algoritm se considera ca nodul care merita sa fie expandat in pasul urmator este cel mai apropiat ​de solutieDeciin acest cazavem: +Putem să alegem drumurile la întâmplare. Vom obține un rezultat corect (nu vom demonstra). 
-  + 
- f(n= h(n), ptoricare n+Din punct de vedere al performanței,​ în cel mai rău caz, pornind o parcurgere oarecare vom găsi în $O(n + m)$ un drum de ameliorare pe care vom putea crește cu exact o unitate cantitatea de fluxAceastă abordare duce la o complexitate de $O((n + m) * |f_{max}|)$ - adică un timp de execuție proporțional cu cantitea de flux pompată. Abordarea este ineficientă. 
 + 
 +</​spoiler>​ \\ 
 + 
 + 
 +În practică **NU** vom folosi direct metoda Ford-Fulkersonci **vom folosi algoritmul Edmonds-Karp**pe care îl vom analiza în secțiunea următoare. 
 + 
 +===== Edmonds-Karp ===== 
 + 
 +Algoritmul lui [[https://​en.wikipedia.org/​wiki/​Jack_Edmonds|Jack **Edmonds**]] și [[https://​en.wikipedia.org/​wiki/​Richard_M._Karp|Richard M. **Karp**]], cunoscut ca și algoritmul [[https://​en.wikipedia.org/​wiki/​Edmonds%E2%80%93Karp_algorithm|Edmonds-Karp]] reprezintă o implementare concretă a metodei Ford-Fulkerson. Acest algoritm rezolvă problema drumurilor de ameliorare folosind **BFS** - adică drumul cel mai scurt (ca și număr de arce), pe care se poate merge ținând cont de restricția de capacitate ​($f(u, v\lt c(uv)$). 
 + 
 +==== Edmonds-Karp - pseudocod ====
  
- Pseudocodul acestui algoritm: 
 <code cpp> <code cpp>
 +// apply Edmonds-Karp'​s algorithm for computing maximum flow in network G
 +//
 +// nodes     = list of all nodes from G
 +// adj[node] = the adjacency list of node
 +//             ​example:​ adj[node] = {..., neigh, ...} => edge (node, neigh)
 +// S         = source in network G
 +// T         = sink in network G
 +// f         = flow in network G
 +// c         = capacity in network G
 +//
 +// returns: maxFlow (maximum flow in G from S to T)
 +//
 +Edmonds-Karp(G=(nodes,​ adj), S, T) {
 +  // STEP 0: initialize
 +  // * flow in network
 +  foreach (u in nodes) {
 +      foreach(v in nodes) {
 +          f[u][v] = 0;
 +      }
 +  }
 +  // * maximum total flow
 +  totalFlow = 0;
 +
 +  // STEP 1: Start BFS for finding augmenting path(s).
 +  while (BFS finds at least one augmenting path in G) {
 +    // STEP 2.1: Compute residual capacity of augmenting path.
 +    rc = +oo; // residual capacity
 +    foreach ((u, v) in path) {
 +        rc = min(rc, c[ u ][ v ] - f[ u ][ v ]);
 +    }
 +
 +    // STEP 2.2: Update flow on path with rc.
 +    foreach ((u, v) in path) {
 +        f[ u ][ v ] += rc;      // Increase on edge (u, v).
 +        f[ v ][ u ] -= rc;      // Decrease on edge (v, u).
 +    }
 +
 +    // STEP 2.3: Update total flow.
 +    totalFlow += rc;
 +  }
 +
 +  return totalFlow;
 +}
  
-Greedy Best-First(sinitial , expand, h, solution) +// Usage example: 
-    closed ← {} +maxFlow ​Edmonds-Karp(G=(nodes, adj), S, T); 
-    n ← new-node() +// Use maxFlow.
-    state(n) ← sinitial +
-    π(n) ← nil +
-    open ← { n } +
-    ​// Bucla principala +
-    ​repeat +
-        if open Ø then return failure +
-        n ← get_best(open) with f(n) h(n= min +
-        open ← open - {n} +
-        if solution(state(n)) then return build-path(n+
-        else if n not in closed then +
-            closed ← closed U {n} +
-            for each s in expand(n) +
-                n' ← new-node() +
-                state(n'​) ← s +
-                π(n') ← n +
-                open ← open U {n'} +
-            end-for +
-    end-repeat+
 </​code>​ </​code>​
 +Algoritmul Edmons-Karp pornește o parcurgere BFS la fiecare pas. Pentru un drum de ameliorare găsit, calculează capacitatea reziduală a acestuia, apoi crește corespunzător fluxul pe acesta.
  
-In cadrul algoritmului se folosesc doua multimi: closed – indica nodurile deja explorate si expandate si open – nodurile descoperite dar neexpandate. Open este intializata cu nodul corespunzator starii intiale. ​La fiecare pas al algoritmului este ales din open nodul cu valoarea ​   f(n) = h(n) cea mai mica (din acest motiv e de preferat ca open  sa fie implementata ca coada cu prioritati). Daca nodul se dovedeste a fi o solutie a problemei atunci este intoarsa ca rezultat calea de la starea initiala pana la nod (mergand recursiv din parinte in parinte). Daca nodul nu a fost deja explorat atunci se expandeaza iar nodurile corespunzatoare starilor rezultate sunt introduse in multimea open. Daca multimea open ramane fara elemente atunci nu exista niciun drum catre solutie si algoritmul intoarce esec.+La **fiecare** pas, atunci când se crește fluxul pe un arc, se scade fluxul pe arcul invers ​(vom demonstra într-subsecțiune viitoare necesitatea acestui pas pentru corectitudinea algoritmului).
  
-Greedy Best-First urmareste mereu solutia care pare cea mai aproape de sursa. Din acest motiv nu se vor analiza stari care desi par mai departate ​de solutie produc o cale catre solutie mai scurta (vezi exemplul de rulare)De asemenea, intrucat nodurile din closed nu sunt niciodata reexplorate se va gasi calea cea mai scurta catre scop doar daca se intampla ca aceasta cale sa fie analizata inaintea altor cai catre aceiasi stare scop. Din acest motiv, algoritmul nu este optim. De asemenea, pentru grafuri infinite e posibil ca algoritmul sa ruleze la infinit chiar daca exista o solutie. Rezulta ca algoritmul nu indeplineste nici conditia de completitudine.+Algoritmul se oprește când nu mai există drumuri ​de ameliorareFluxul pompat până atunci în rețea ​este maxim.
  
-In figura de mai jos se prezinta rularea algoritmului Greedy Best-First pe exemplul dat mai sus. In primul pas algoritmul expandeaza nodul Arad, iar ca nod urmator de explorat se alege Sibiu, intrucat are valoarea h(n) minima. Se alege in contiuare Fagaras dupa care urmeaza Bucuresti, care este un nod final. Se observa insa ca acest drum nu este minimal. Desi Fagaras este mai aproape ca distanta geometrica de Bucuresti, in momentul in care starea curenta este Sibiu alegerea optimala este Ramnicu-Valcea. In continuare ar fi urmat Pitesti si apoi Bucuresti obtinandu-se un drum cu 32 km mai scurt.+==== Exemple ====
  
- ​{{ ​:pa:​laboratoare:​112.png?​400 |}}+=== Edmonds-Karpexemplu rezultat ===
  
 +{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab12-edmonds-karp-example.png?​512| Exemplu Edmonds-Karp}}
  
-==== A(A star) ====+Fluxul maxim calculat cu Edmonds-Karp pentru rețeaua atașată este: **2**.
  
-A* reprezinta cel mai cunoscut algoritm ​de cautare euristica. El foloseste, de asemenea o politica Best-First, insa nu sufera de aceleasi defecte pe care le are Greedy Best-First definit mai sus. Acest lucru este realizat prin definirea functiei de evaluare astfel:+Drumurile ​de ameliorare folosite sunt:
  
- f(n= g(n) h(n, pt. oricare n ∈ Noduri+  * $1 - 2 - 4 - 6$ (capacitate reziduală **+1**) 
 +  * $1 - 3 - 5 - 6$ (capacitate reziduală **+1**)
  
-A* evalueaza nodurile combinand distanta deja parcursa pana la nod cu distanta estimata pana la cea mai apropiata stare scop. Cu alte cuvinte, pentru un nod n oarecare, **f(n) reprezinta costul estimat al celei mai bune solutii care trece prin n**. Aceasta strategie se dovedeste a fi completa si optimala daca euristica h(n) este admisibila:+=== Exemplu Edmonds-Karpexemplu simplu pas cu pas ===
  
- 0 ≤ h(n) ≤ h*(n) , ptoricare n ∈ Noduri+În această secțiune vom exemplifica de ce doar simpla incrementare a fluxului pe arcele directe nu este suficientă pentru a găsi fluxul maxim în rețea. Următoarea secțiunea conține soluția.
  
-unde h*(n) este distanta exacta de la nodul n la cea mai apropiata solutie. Cu alte cuvinte A* intoarce mereu solutia optima daca o solutie exista atat timp cat ramanem optimisti si nu supraestimam distanta pana la solutie. Daca h(n) nu este admisibila o solutie va fi in continuare gasita, dar nu se garanteaza optimalitatea. De asemenea, pentru a ne asigura ca vom gasi drumul optim catre o solutie chiar daca acest drum nu este analizat primul, A* permite scoaterea nodurilor din closed si reintroducerea lor in open daca o cale mai buna pentru un nod din closed (g(n) mai mic) a fost gasita.+<spoiler Exemplu>
  
-Algoritmul evolueaza in felul urmator: initial se introduce in multimea open (organizata ca o coada de prioritati dupa f(n)) nodul corespunzator starii initiale. **La fiecare pas se extrage ​din open nodul cu f(n) minim**. Daca se dovedeste ca nodul n contine chiar o stare scop atunci se intoarce calea de la starea initiala pana la nodul n. Altfel, daca nodul nu a fost explorat deja se expandeaza. Pentru fiecare stare rezultata, daca nu a fost generata de alt nod inca (nu este nici in open nici in closed) atunci se introduce in open. Daca exista un nod corespunzator starii generate in open sau closed se verifica daca nu cumva nodul curent produce o cale mai scurta catre s. Daca acest lucru se intampla se seteaza nodul curent ca parinte al nodului starii s si **se corecteaza distanta g**. Aceasta corectare implica reevaluarea tuturor cailor care trec prin nodul lui s, deci acest nod va trebui reintrodus in open in cazul in care era inclus in closed. ​+Pornim ​de la rețeaua ​din figura următoare:
  
-Pseudocodul pentru A* este prezentat in continuare:+{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab12-edmonds-karp-example.png?​512| Exemplu Edmonds-Karp}}
  
-<code cpp> +  * ''​%%n = 6%%'',​ ''​%%m = 7%%''​ 
-A-Star(s initial ​expand, h, solution) +  * Sursa este ''​%%S = 1%%''​iar terminalul este ''​%%T = 6%%''​. 
- //​initializari +  * Funcția de capacitate ''​%%c%%''​ are valorile din figură.
-    closed ← {} +
-    n ← new-node() +
-    state(n) ← s initial +
-    g(n) ← 0 +
-    π(n) ← nil +
-    open ← { n }+
  
-    //Bucla principala +Dacă rulăm Edmonds-Karpo posibilă succesiune de stări pentru rețea este cea din figura următoare:
-    repeat +
-        if open = Ø then return failure +
-        n ← get_best(open) with f(n) = g(n)+h(n) = min +
-        open ← open {n} +
-        if solution(state(n)) then return build-path(n) +
-        else if n not in closed then +
-            closed ← closed U {n} +
-            for each s in expand(n) +
-                cost_from_n ← g(n) + cost(state(n)s) +
-                if not (s in closed U open) then +
-                    n' ← new-node() +
-                    state(n'​) ← s +
-                    π(n') ← n +
-                    g(n') ← cost_from_n +
-                    open ← open U { n'} +
-                else +
-                    n' ← get(closed U open, s) +
-                    if cost_from_n < g(n') then +
-                        π(n') ← n +
-                        g(n') ← cost_from_n +
-                        if n' in closed then +
-                            closed ← closed – { n'} +
-                            open ← open U { n'} +
-     end-for +
-    end-repeat +
-</​code>​+
  
-Algoritmul prezentat mai sus va intoarce calea optima catre solutie, daca o solutie existaSingurul incovenient fata de Greedy Best-First este ca sunt necesare reevaluarile nodurilor din closedSi aceasta problema poate fi rezolvata daca impunem o conditie mai tare asupra euristicii h, si anume ca euristica sa fie **consistenta** (sau **monotona**):​+{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab12-edmonds-karp-basic-example-01.png?512| Exemplu Edmonds-Karp}}
  
- h(n) ≤ h(n') + cost(n,​n'​) , pt. oricare n' ∈ expand(n) +  * Inițial fluxul în rețea este zero. 
-  +  ​Se vor găsi 2 drumuri ​de ameliorare $1 - 2 - 4 - 6$ și $ 1 - 3 - 5 - 6$Pe fiecare drum se pompează câte unitate de flux. 
-Daca o functie este consistenta atunci ​ea este si admisibilaDaca euristica h indeplineste si aceasta conditie atunci algoritmul Aeste asemanator cu Greedy Best-First cu modificarea ca functia de evaluare este f = + h, in loc de f = h. +  * În rețeaua reziduală obținută se observă că nu se mai poate ajunge de la S la T
-In imaginea de mai jos se prezinta rularea algoritmului pe exemplul laboratorului. Se observa ca euristica aleasa (distanta in linie dreapta) este consistenta si deci admisibila. Se observa ca in pasul (e), dupa expandarea nodului Fagaras desi exista ​solutie in multimea open aceasta nu este aleasa pentru explorareSe va alege Pitesti, intrucat f(nod(Bucuresti)) = 450 > f(nod(Pitesti)) = 417, semnificatia acestei ​ inegalitati fiindca e posibil sa existe prin Pitesti un drum mai bun catre Bucuresti decat cel descoperit pana acum+  * Prin urmare fluxul obținut este maxim și are valoare $1 + 1 = 2$.
-  +
-{{ :​pa:​laboratoare:​113.png?400 |}}+
  
-==== Complexitate algoritmului A* ==== 
  
-Pe langa proprietatile de completitudine si optimalitate A* mai are o calitate care il face atragator: pentru o euristica data orice algoritm de cautare complet si optim va explora cel putin la fel de multe noduri ca A*, ceea ce inseamna ca A* este optimal din punctul de vedere al eficientei. In practica, insa, A* poate fi de multe ori imposibil de rulat datorita dimensiunii prea mari a spatiului de cautare. Singura modalitate prin care spatiul de cautare poate fi redus este prin gasirea unei euristici foarte bune – cu cat euristica este mai apropiata de distanta reala fata de stare solutie cu atat spatiul de cautare este mai strans (vezi figura de mai jos). S-a demonstrat ca spatiul de cautare incepe sa creasca exponential daca eroarea euristicii fata de distanta reala pana la solutie nu are o crestere subexponentiala:​+<note warning>
  
- |h(n) - h*(n)| ≤ O(logh*(n))+NU avem control asupra drumurilor găsite de BFS, adică ordinea în care acestea vor fi alese, ci știm doar că se va alege cele mai scurte drumuri.
  
-Din pacate, in majoritatea cazurilor, eroarea creste liniar cu distanta pana la solutie ceea ce face ca A* sa devina un algoritm mare consumator de timp, dar mai ales de memorie. Intrucat in procesul de cautare se retin toate nodurile deja explorate (multimea closed), in cazul unei dimensiuni mari a spatiului de cautare cantitatea de memorie alocata cautarii este in cele din urma epuizata. Pentru acest incovenient au fost gasite mai multe solutii. Una dintre acestea este utilizarea unor euristici care sunt mai stranse de distanta reala pana la starea scop, desi nu sunt admisibile. Se obtin solutii mai rapid, dar nu se mai garanteaza optimalitatea acestora. Folosim aceasta metoda cand ne intereseaza mai mult sa gasim o solutie repede, indiferent de optimalitatea ei. +</​note>​
  
-{{ :pa:​laboratoare:​114.png?​400 |}}+O altă succesiune posibilă și corectă de stări pentru rețea se găsește în figura următoare:
  
-Volumul spatiului de cautare in functie de euristica aleasa+{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab12-edmonds-karp-basic-example-02.png?​512| Exemplu Edmonds-Karp}}
  
-Alte abordari presupun sacrificarea timpului ​de executie pentru a margini spatiul ​de memorie utilizat [3]Aceste alternative sunt prezentate in continuare.+  * Inițial fluxul în rețea este zero. 
 +  * Se găsește drumul ​de ameliorare $1 - 2 - 5 - 6$ (tot de lungime ​arce) cu capacitatea reziduală 1. Se pompează această unitate de flux. 
 +  * În rețeaua reziduală obținută se observă că nu se mai poate ajunge de la S la T. 
 +  * Fluxul total obținut este **1**, care **NU** este maxim.
  
-==== IDA*, RBFS, MA* ====+Prin urmare ajungem într-un punct în care algoritmul a greșit și nu mai poate pompa flux în plus. Parcugeți următorul exemplu pentru a vedea concret cum se rezolvă această problemă.
  
-=== IDA* ===+</​spoiler>​ \\
  
-Iterative deepening A* [5] utilizeaza conceptul de adancire iterativa[1][8] in procesul de explorare a nodurilor – la un anumit pas se vor explora doar noduri pentru care functia de evaluare are o valoare mai mica decat o limita data, limita care este incrementata treptat pana se gaseste o solutie. IDA* nu mai necesita utilizarea unor multimi pentru retinerea nodurilor explorate si se comporta bine in cazul in care toate actiunile au acelasi cost. Din pacate, devine ineficient in momentul in care costurile sunt variabile. 
  
-=== RBFS ===+=== Exemplu Edmonds-Karp:​ exemplu detaliat cu flux pe arce inverse ​===
  
-Recursive Best-First Search [6] functioneaza intr-un mod asemanator cu DFS, explorand la fiecare ​pas nodul cel mai promitator fara a retine informatii despre nodurile deja explorate. Spre deosebire de DFS, **se retine in orice moment cea mai buna alternativa sub forma unui pointer catre un nod neexplorat**. Daca valoarea functiei de evaluare (f = g + h) pentru nodul curent devine mai mare decat valoarea caii alternative,​ drumul curent este abandonat si se incepe explorarea nodului retinut ca alternativa. RBFS are avantajul ca spatiul de memorie creste doar liniar in raport ​cu lungimea caii analizate. Marele dezavantaj este ca se ajunge de cele mai multe ori la reexpandari si reexplorari repetate ale acelorasi noduri, lucru care poate fi dezavantajos mai ales daca exista multe cai prin care se ajunge la aceiasi stare sau functia expand este costisitoare computational (vezi problema deplasarii unui robot intr-un mediu real). RBFS este optimal daca euristica folosita este admisibila.+În această secțiune vom arăta ce face algoritmul ​pas cu pas și vom observa necesitatea și corectitudinea scăderii fluxului pe arcele inverse.
  
-=== MA* ===+Pornim de la rețeaua din figura următoare:
  
-Memory-bounded A* este o varianta a A* in care se limiteaza cantitatea de memorie folosita pentru retinerea nodurilorExista doua versiuni – MA* [7]si SMA* [4] (Simple Memory-Bounded A*), ambele bazandu-se pe acelasi principiuSMA* ruleaza similar cu A* pana in momentul in care cantitatea de memorie devine insuficienta. In acest moment spatiul de memorie necesar adaugarii unui nod nou este obtinut prin stergerea celui mai putin promitator nod deja explorat. In cazul in care exista o egalitate in privinta valorii functiei de evaluare se sterge nodul cel mai vechi. Pentru a evita posibilitatea in care nodul sters este totusi un nod care conduce la o cale optimala catre solutie valoarea f a nodului sters este retinuta la nodul parinte intr-un mod asemanator felului in care in RBFS se retine cea mai buna alternativa la nodul curent. Si in acest caz vor exista reexplorari de noduri, dar acest lucru se va intampla doar cand toate caile mai promitatoare vor esua. Desi exista probleme in care aceste regenerari de noduri au o frecventa care face ca algoritmul sa devina intractabil,​ MA* si SMA* asigura un compromis bun intre timpul de executie si limitarile de memorie.+{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab12-edmonds-karp-negative-flow-01.png?512| Exemplu Edmonds-Karp}}
  
-===== Concluzii ​și observații =====+  * ''​%%n ​6%%'',​ ''​%%m ​7%%''​ 
 +  * Sursa este ''​%%S ​1%%'',​ iar terminalul este ''​%%T ​6%%''​. 
 +  * Funcția de capacitate ''​%%c%%''​ are valorile din figură. 
 +  * Observăm că pentru fiecare arc $(u, v)$ am dus un arc imaginar $(v, u)$ de capacitate **0**. Aceste arce fictive reprezintă cheia funcționării algoritmului Edmonds-Karp:​ de fiecare dată când vom pompa (adăuga) flux pe un arc $(u, v)$, vom scădea cu aceeași valoare fluxul pe arcul $(v, u)$.
  
-Deseori singura modalitate de rezolvare a problemelor dificile este de e explora graful starilor acelei probleme. Algoritmii clasici pe grafuri nu sunt intotdeauna potriviti pentru cautarea in aceste grafuri fie pentru ca nu garanteaza un rezultat fie pentru ca sunt ineficienti.  +Să vedem în continuare ​la ce ne ajută dacă alegem din noughinionistdrumul ​de amelioarare $1 - 2 - 5 - 6$ și dacă de data aceasta putem corectaVom face acțiunile marcate în figura următoare:
-Algoritmii euristici sunt algoritmi care exploreaza astfel de grafuri folosindu-se de o informatie suplimentara despre modul in care se poate ajunge ​la o stare scop mai rapid. A* esteteoreticcel mai eficient algoritm ​de explorare euristica. In practica, insa, pentru probleme foarte dificile, A* implica un consum prea mare de memorie. In acest caz se folosesc variante de algoritmi care incearca sa minimizeze consumul de memorie in defavoarea timpului ​de executie+
  
-===== Referinte =====+{{https://​ocw.cs.pub.ro/​courses/​_media/​pa/​new_pa/​lab12-edmonds-karp-negative-flow-02.png?​512| Exemplu Edmonds-Karp}}
  
-[1] SRusselPNorvig ​Artificial Intelligence:​ A Modern Approach - Prentice Hall2nd Edition – cap4+  * Se pompează o unitate de flux pe drumul $- 2 - 5 - 6$Prin urmare pe arcele marcate cu verde creștem fluxul cu **+1** unități de fluxiar pe arcele marcate cu roșu scădem (**-1** unități de flux). 
 +  * La pasul următor, se pornește BFS din 1 și se înaintează folosind aceeași condiție ​se poate merge pe o muchie $(uv)$ dacă $f(u, v) \lt c(u, v)$. De data aceasta, această condiție se îndeplinește și pentru unele dintre muchiile inverse - cele cu **-1/0**.
  
-[2] C.A Giumale – Introducere in Analiza Algoritmilor,​ cap. 7+Vom face acțiunile marcate în figura următoare:
  
-[3] [[http://www.cs.cmu.edu/afs/cs/project/pscico-guyb/294/class-notes/​all/​18.ps|Mehul Shah - Algorithms in the real world (Course Notes) ​ ​Introduction to VLSI routing]]+{{https://ocw.cs.pub.ro/courses/_media/pa/new_pa/lab12-edmonds-karp-negative-flow-03.png?512Exemplu Edmonds-Karp}}
  
-[4] [[http://​citeseerx.ist.psu.edu/​viewdoc/​download?​doi=10.1.1.54.6489&​rep=rep1&​type=pdf|S. Russel - Efficient memory-bounded search methods]]+  * Drumul de ameliorare găsit este $1 - 3 - 5 - 2 - - 6$, care are capacitatea reziduală **1**Se pompează **+1** pe acest drum (arcele cu verde), se scade în sens invers (arcele cu roșu). 
 +  * La următoarea incercare de apelare BFS, nu se mai poate ajunge de la S la T, prin urmare algoritmul se oprește! 
 +  * Fluxul găsit este **1 + 1 = 2**, care este maxim!
  
-[5] R. Korf - Depth-first iterative-deepening:​ an optimal admissible tree search 
  
-[6] [[http://​www.ailab.si/​gregorl/​Students/​mui/​Recursive%20Best-First%20Search.ppt|Recursive Best-First Search - Prezentare]]+<note warning>
  
-[7] P. Chakrabati, ​S. GhoshA. Acharya, SDeSarkar – Heuristic search in restricted memory+Să observăm că starea finală a rețelei conține 2 unități de fluxDacă ne uităm cu atențieobservăm că avem o unitate de flux pe drumul $1 - 2 - 4 - 6$ și alta pe $1 - 3 - 5 - 6$.
  
-[8] [[http://​en.wikipedia.org/​wiki/​Iterative_deepening_depth-first_search|Wikipedia ​Iterative deepening]]+Deși Edmonds-Karp nu a ales inițial aceste 2 drumuri, s-a corectat pe parcurs, iar în final, dacă fluxul maxim trebuia să treacă pe aici, rețeaua reziduală a fost actualizată ​corectată până s-a întâmplat acest lucru!
  
-[9] [[http://​dli.iiit.ac.in/​ijcai/​IJCAI-91-VOL2/​PDF/​017.pdf|A. E. Prieditis - Machine Discovery of Effective Admissible Heuristics]]+Semnificația înaintării pe un arc fictiv este că defapt cautăm să deviem fluxul de pe un drum ales anterior (de exemplu, $1 5 - 6$), pe o altă cale (de exemplu, porțiunea $1 - 2$ să se continue cu $2 - 4 - 6$), astfel încât să putem folosi partea eliberată (de exemplu, $5 - 6$), în construcția unui nou drum la pasul curent.
  
-[10] [[http://​en.wikipedia.org/​wiki/​Travelling_salesman_problem#​Heuristic_and_approximation_algorithms|Wikipedia - Travelling salesman problem - Heuristic and approximation algorithms]]+</note>
  
-[11] [[http://​en.wikipedia.org/​wiki/​A*_search_algorithm|Wikipedia – A*]]+==== Complexitate ====
  
-[12] [[http://​www.policyalmanac.org/​games/​aStarTutorial.htm|Tutorial A*]]+  * **complexitate temporală**$T = O(n * m^2)\ sau\ O(|V| * |E|^2)$ 
 +  * **complexitate spațială** : $S = O(n)\ sau \ O(|V|)$
  
-[13] [[http://​aaaipress.org/​Papers/​AAAI/​1994/​AAAI94-209.pdf|H. Kaindl, A. Khorsand - Memory Bounded Bidirectional Search, AAAI-94 Proceedings]]+<spoiler Detalii (analiză + optimizări)>​
  
 +  * **complexitate temporală**:​ Demonstrația se găsește în **Introduction to Algorithms**. Ideea de bază este că de fiecare dată când creștem fluxul pe un drum de ameliorare, o muchie devine saturată. Dacă vreodată această muchie va mai fi folosită în alt drum de ameliorare (în cazul unei corecții), aceasta va fi folosită într-un drum mai lung. Respectivele distanțe sunt monotone și limitate de $O(|V|)$.
 +  * **complexitate spațială** : Stocăm o coadă pentru algoritmul BFS. De asemenea, în implementare vom stoca și un vector de părinți pentru a putea parcurge un drum de ameliorare de la T la S (sens invers).
  
-===== Probleme =====+</​spoiler>​ \\
  
 +
 +===== TLDR =====
 +
 +  * Ford-Fulkerson este un tipar general, **în practică** vom folosi doar algoritmul Edmonds-Karp.
 +    * Algoritmul de bazează pe pomparea fluxului pe arcele directe și scăderea pe arcele inverse.
 +    * Ordinea în care drumurile de amelioare sunt găsite nu contează. Este un algoritm greedy de tip constructiv care își corectează deciziile pe parcurs. În final mereu găsește fluxul maxim!
 +  * Dacă în plus avem și costuri pe arce, putem determina flux maxim de cost minim cu Edmonds-Karp înlocuind BFS cu Dijkstra pentru găsirea drumurilor de ameliorare.
 +
 +===== Exerciții =====
 +
 +
 +<​note>​
 +
 +Scheletul de laborator se găsește pe pagina [[https://​github.com/​acs-pa/​pa-lab/​tree/​main/​skel/​lab12|pa-lab::​skel/​lab12]].
 +
 +</​note>​
 <note warning> <note warning>
-După rezolvarea problemelortoți studenții trebuie să încarce o arhivă cu sursele rezolvării pe Moodle (click ​[[http://cs.curs.pub.ro/2016/mod/assign/​view.php?​id=5901|aici]]) pentru a li se puncta laboratorul.+ 
 +Înainte de a rezolva exercițiileasigurați-vă că ați citit și înțeles toate precizările din secțiunea ​[[https://ocw.cs.pub.ro/courses/pa/skel_graph ​Precizari laboratoare 07-12]]. 
 + 
 +Prin citirea acestor precizări vă asigurați că: 
 + 
 +  * știți **convențiile** folosite 
 +  * evitați **buguri** 
 +  * evitați **depunctări** la lab/​teme/​test 
 + 
 </​note>​ </​note>​
-==== Labirint ==== 
  
-Fie un labirint dat sub forma unei matrici în care 0 înseamnă obstacol şi 1 înseamnă liber. Se cere să se determine un drum între două poziţii din labirint folosind algoritmi de căutare informată. Să se implementeze algoritmul A* pentru rezolvarea problemei folosind o euristică admisibilă. [4 pct] +==== Edmonds-Karp ​====
-==== Problema misionarilor şi a canibalilor ​====+
  
-Trei misionari şi trei canibali ajung la malul estic al unui râu. Aici se află o barcă cu două locuri cu care se poate traversa râul (râul nu se poate traversa înot)Dacă pe unul dintre maluri numărul de canibali este mai mare decât numărul de misionari, atunci misionarii de pe acel mal vor fi mâncaţi de canibali. Se cere sa determinaţi cum pot trece toţi râul fără ca misionarii să fie mâncaţi de canibali.+Se dă un graf orientat ​cu n noduri și m arceGraful are pe arce **capacitati pozitive**.
  
-Să se rezolve această problemă folosind algoritmul A* cu:+Folosiși Edmonds-Karp pentru a găsi fluxul maxim între nodul sursă 1 și nodul destinație n în graful dat.
  
-a) O euristica care nu este admisibilă [2 pct] 
  
-<hidden+<note warning
-h(S) nE(S) + 
-</hidden>+Restricții și precizări:​ 
 + 
 +  * $ n <10^3 $ 
 +  * $ m <= 5 * 10^3 $ 
 +  * $ 1 <= c <= 110.000$, unde c este capacitatea unui arc 
 +  * Nu există arce de la n la 1. 
 +  * timp de execuție 
 +    * C++: ''​%%1s%%''​ 
 +    * Java: ''​%%2s%%''​ 
 + 
 + 
 +</note> 
 +<​note>​ 
 + 
 +Rezultatul se va returna sub forma unui singur număr, reprezentând fluxul maxim ce poate fi trimis prin rețea. 
 + 
 +</​note>​ 
 + 
 +==== BONUS ====
  
-b) Doua euristici admisibile [3 pct]+La acest laborator, asistentul va alege 1-2 probleme din secțiunea extra.
  
-<​hidden>​ +==== Extra ====
-h1(S) nE(S)/2+
  
-h2(S) =+  * [[https://​infoarena.ro/​problema/​cuplaj|infoarena/​cuplaj]] 
 +  * [[https://​infoarena.ro/​problema/​fmcm|infoarena/​fcmm]] 
 +  * [[https://​infoarena.ro/​problema/​drumuri2|infoarena/​drumuri2]] 
 +  * [[https://​infoarena.ro/​problema/​joc4|inforena/​joc4]] 
 +  * [[https://​acm.timus.ru/​problem.aspx?​space=1&​num=1533|acm/​fat-hobbits]]
  
-* nE(S) + 1 daca barca pe malul vestic si nE(S) diferit de 0+===== Referințe =====
  
-* nE(S) - 1 daca barca pe malul estic si nE(S) diferit de 0+[0] Chapter **Maximum Flow**, “Introduction to Algorithms”,​ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein.
  
-* 0 altfel+[1] [[http://​www.cs.yale.edu/​homes/​lans/​readings/​routing/​ford-max_flow-1956.pdf|Maximal flow through a network]], L.R. Ford, D.R. Fulkerson
  
-nE numar oameni est+[2] [[http://​www.eecs.umich.edu/​~pettie/​matching/​Edmonds-Karp-network-flow.pdf|Theoretical improvements in algorithmic efficiency for network flow problems]], Edmonds, Jack; Karp, Richard M.
  
-</hidden>+[3] [[https://​www.cs.bgu.ac.il/​~dinitz/​Papers/​Dinitz_alg.pdf|Dinitz Algorithm]],​ Yefim Dinitz
  
-Comparati numarul de pasi necesar pentru a ajunge la solutie in functie de euristica [1 pct] 
pa/laboratoare/laborator-11.1494791142.txt.gz · Last modified: 2017/05/14 22:45 by david_traian.iancu
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