ELEMENTE DE TEORIA
GRAFURILOR
În general, pentru situațiile care necesită la rezolvare un oarecare efort mintal (și un caz tipic este cel al celor din economie), se caută, în primul rând, o metodă de reprezentare a lor care să permită receptarea întregii probleme dintr-o privire (pe cât posibil) și prin care să se evidențieze cât mai clar toate aspectele acesteia.
În acest scop se folosesc imagini grafice gen diagrame, schițe, grafice etc. O reprezentare dintre cele mai utilizate este cea prin grafuri. Acestea sunt utilizate în special pentru vizualizarea sistemelor și situațiilor complexe. În general, vom reprezenta componentele acestora prin puncte în plan iar relațiile (legăturile, dependențele, influențele etc) dintre componente prin arce de curbă cu extremitățile în punctele corespunzătoare. Între două puncte pot exista unul sau mai multe segmente (în funcție de câte relații dintre acestea, care ne interesează, există) iar segmentelor li se pot asocia sau nu orientări (după cum se influențează cele două componente între ele), numere care să exprime intensitatea relațiilor dintre componente etc.
Este evident, totuși, că această metodă are limite, atât din punct de vedere uman (prea multe puncte și segmente vor face desenul atât de complicat încât se va pierde chiar scopul pentru care a fost creat claritatea și simplitatea reprezentării, aceasta devenind neinteligibilă) cât și din punct de vedere al tehnicii de calcul (un calculator nu poate "privi" un desen ca un om).
Din acest motiv, alături de expunerea naiv-intuitivă a ceea ce este un graf, dată mai sus, se impune atât o definiție riguroasă cât și alte modalități de reprezentare a acestora, adecvate în general rezolvărilor matematice.
Definiția 1 Se numește multigraf un triplet G = (X, A, f)
în care X și A sunt două mulțimi iar f este
o funcție, definită pe produsul vectorial al lui X cu el însuși (X2
= XŽX), care ia valori în mulțimea părților mulțimii A (notată P(A))
Mulțimea X se numește mulțimea nodurilor multigrafului și elementele sale se numesc noduri (sau vârfuri) ale multigrafului, iar A reprezintă mulțimea relațiilor (legăturilor) posibile între două noduri ale multigrafului.
Definiția 2 Se numește graf orientat un multigraf în care mulțimea A are un singur element: A = {a}.
În acest caz mulțimea părților mulțimii A are doar două elemente: mulțimea vidă Æ și întreaga mulțime A. Dacă unei perechi orientate (xi, xj) din X2 i se asociază prin funcția f mulțimea A atunci spunem ca există arc de la nodul xi la nodul xj iar perechea (xi,xj) se va numi arcul (xi,xj). Nodul xi se numește nod inițial sau extremitate inițială a arcului (xi,xj) iar nodul xj se numește nod final sau extremitate finală a arcului (xi,xj). Arcul (xi,xj) este incident spre interior vârfului xj și incident spre exterior vârfului xi. Dacă pentru un arc nodul inițial coincide cu nodul final atunci acesta se numește buclă. Nodurile xi și xj se vor numi adiacente dacă există cel puțin unul din arcele (xi,xj) și (xj,xi).
Dacă unei perechi orientate (xi, xj) din X2 i se asociază prin funcția f mulțimea vidă Æ atunci spunem că nu există arc de la nodul xi la nodul xj.
Este evident că a cunoaște un graf orientat este echivalent cu a cunoaște vârfurile și arcele sale. Din acest motiv putem defini un graf orientat prin perechea (X,U), unde X este mulțimea vârfurilor sale iar U mulțimea arcelor sale.
De asemenea, putem cunoaște un graf orientat cunoscând mulțimea nodurilor și, pentru fiecare nod, mulțimea arcelor incidente spre exterior. Din acest motiv putem defini un graf orientat ca o pereche (X,G) unde X este perechea nodurilor iar G este o funcție definită pe X cu valori în mulțimea părților lui X, valoarea acesteia într-un nod xi, G(xi) Í X fiind mulțimea nodurilor adiacente nodului xi, prin arce pentru care xi este extremitatea inițială.
Definiția 3 Se numește graf neorientat un multigraf în care mulțimea A are un singur element iar funcția f are proprietatea:
f[(xi,xj)] = f[(xj,xi)] , oricare ar fi nodurile xi și xj din X
În aceste condiții, dacă f[(xi,xj)] = f[(xj,xi)] = A atunci perechea neorientată {xi,xj} este o muchie iar dacă f[(xi,xj)] = f[(xj,xi)] = Æ spunem că nu există muchie între vârfurile xi și xj.
Deoarece, în cele mai multe din cazurile practice care vor fi analizate în acest capitol, situația este modelată matematic printr-un graf orientat, vom folosi, pentru simplificarea expunerii, denumirea de graf în locul celei de graf orientat iar în cazul în care graful este neorientat vom specifica acest fapt la momentul respectiv.
2. Moduri de reprezentare ale
unui graf
A. O primă modalitate de reprezentare este listarea efectivă a tuturor nodurilor și a arcelor sale.
B. Putem reprezenta graful dând pentru fiecare nod mulțimea nodurilor cu care formează arce în care el este pe prima poziție.
C. Putem reprezenta geometric graful, printr-un desen în plan, reprezentând fiecare nod printr-un punct(cerculeț) și fiecare arc printr-un segment de curbă care are ca extremități nodurile arcului și pe care este trecută o săgeată orientată de la nodul inițial spre cel final.
D. Putem folosi o reprezentare geometrică în care nodurile sunt reprezentate de două ori, în două șiruri paralele, de la fiecare nod din unul din șiruri plecând săgeți spre nodurile cu care formează arce în care el este pe prima poziție, de pe al doilea șir (reprezentarea prin corespondență).
E. Un graf poate fi reprezentat printr-o matrice pătratică booleană, de dimensiune egală cu numărul de noduri, în care o poziție aij va fi 1 dacă există arcul (xi,xj) și 0 în caz contrar, numită matricea adiacențelor directe.
F. Un graf poate fi reprezentat printr-o matrice pătratică latină, de dimensiune egală cu numărul de noduri, în care pe o poziție aij va fi xixj dacă există arcul (xi,xj) și 0 în caz contrar.
Exemplu: Dacă în reprezentarea A avem graful G = (X,U), unde X = {x1, x2, x3, x4, x5, x6} și U = {(x1,x1), (x1,x2), (x1,x4), (x1,x5), (x2,x3), (x2,x4), (x2,x6), (x3,x1), (x3,x2), (x4,x5), (x5,x2), (x6,x4)}, atunci în celelalte reprezentări vom avea:
B x1 ź {x1, x2, x4, x5} C
x2 ź {x3, x4, x6}
x3 ź {x1, x2}
x4 ź {x5}
x5 ź {x2}
x6 ź {x4}
D (reprezentarea prin corespondență)
x1 x2 x3 x4 x5 x6
x1 x2 x3 x4 x5 x6
x1 x2 x3 x4 x5 x6 x1 x1x1 x1x2 0 x1x4 x1x5 0 x2 0 0 x2x3 x2x4 0 x2x6 x3 x3x1 x3x2 0 0 0 0 x4 0 0 0 0 x4x5 0 x5 0 x5x2 0 0 0 0 x6 0 0 0 x6x4 0 0 x1 x2 x3 x4 x5 x6 x1 1 1 0 1 1 0 x2 0 0 1 1 0 1 x3 1 1 0 0 0 0 x4 0 0 0 0 1 0 x5 0 1 0 0 0 0 x6 0 0 0 1 0 0
E F
3. Concepte de bază în teoria
grafurilor
1. semigraf interior al unui nod xk: este mulțimea arcelor = {(xj,xk)/ (xj,xk) Î U} care sunt incidente spre interior nodului xk;
2. semigraf exterior al unui nod xk: este mulțimea arcelor = {(xk,xi)/ (xk,xi) Î U} care sunt incidente spre exterior nodului xk;
3. semigradul interior al unui nod xk: este numărul arcelor care sunt incidente spre interior nodului xk = cardinalul lui și se notează cu ;
4. semigradul exterior al unui nod xk: este numărul arcelor care sunt incidente spre exterior nodului xk = cardinalul lui și se notează cu ;
5. gradul unui nod xk: este suma semigradelor nodului xk: = + ;
6. nod izolat: este un nod cu gradul 0;
7. nod suspendat: este un nod cu gradul 1;
8. arce adiacente: arce care au o extremitate comună;
9. drum într-un graf: o mulțime ordonată de noduri ale grafului: (x1, x2, ..., xk), cu proprietatea că există în graf toate arcele de forma (xi,xi+1) i = 1,...,k-1;
10.
lungimea unui drum: este numărul arcelor care
îl formează;
11.
drum elementar: un drum în care fiecare nod
apare o singură dată;
12. drum simplu: un drum în care fiecare arc apare o singură dată;
13.
putere de atingere a unui nod xi Î X în graful G: numărul de noduri la care se poate ajunge din xi.
Puterea de atingere se notează cu p(xi), 1 £ i £ n și evident p(xi) ³ .
14.
drum hamiltonian: un drum elementar care trece
prin toate nodurile grafului;
15.
drum eulerian: un drum simplu care conține
toate arcele grafului;
16.
lanț: un drum în care arcele nu au neapărat
același sens de parcurgere;
17.
circuit: un drum în care nodul inițial coincide cu cel final;
18.
circuit elementar: un drum în care fiecare nod
apare o singură dată, cu excepția celui final, care coincide cu cel inițial;
19.
circuit simplu: un drum în care fiecare arc
apare o singură dată;
20.
circuit hamiltonian: un circuit care trece
prin toate nodurile grafului;
21.
ciclu: este un circuit în care arcele nu au
neapărat același sens de parcurgere;
22.
ciclu elementar: un ciclu în care fiecare nod
apare o singură dată, cu excepția celui final, care coincide cu cel inițial;
23.
ciclu simplu: un ciclu în care fiecare arc
apare o singură dată;
Observație: Într-un graf neorientat noțiunile de drum și lanț sunt echivalente și de asemenea cele de circuit și ciclu.
24.
graf parțial al unui graf G = (X,U): este un
graf G'(X,U') cu U' Ì U;
25.
subgraf al unui graf G = (X,G): este un graf G'(X',G') unde X' Ì X și G'(xi) = G(xi) Ç X' pentru
orice xi Î X';
26.
graf redus al unui graf G = (X,U): este un graf
G*(X*,U*) unde X* este formată din
mulțimile unei partiții de mulțimi nevide ale lui X, iar (,) există doar dacă i ¹ j și
există cel puțin un arc în U, de la un nod din la un nod din .
27.
graf tare conex: este un graf în care între
oricare două noduri există cel puțin un drum;
28.
graf simplu conex: este un graf în care între
oricare două noduri există cel puțin un lanț;
Observație: Pentru grafuri neorientat noțiunile de tare conex și simplu conex
sunt echivalente, graful numindu-se doar conex;
29.
componentă tare conexă a unui graf G = (X,U):
este un subgraf al lui G care este tare conex și nu este subgraful nici unui
alt subgraf tare conex al lui G (altfel spus, între oricare două noduri din
componentă există cel puțin un drum și nu mai există nici un nod în afara
componentei legat printr-un drum de un nod al componentei).
4. Găsirea drumurilor într-un
graf orientat
Pasul 1. Se construiește matricea booleană a adiacențelor directe corespunzătoare grafului, notată cu A. În aceasta se află, evident, toate drumurile de lungime 1.
Este interesant de văzut ce legătură există între această matrice și drumurile de lungime 2. Fie două noduri xi și xj oarecare din graf. Existența unui drum de lungime 2 între ele presupune existența unui nod xk, din graf, cu proprietatea că există atât arcul (xi,xk) cât și arcul (xi,xk). Pentru a vedea dacă acesta există, luăm pe rând fiecare nod al grafului și verificăm dacă există sau nu ambele arce ((xi,xk) și (xi,xk)). Aceasta este echivalent cu a verifica dacă, în matricea booleană a adiacențelor directe, există vreun indice k astfel încât elementul k al liniei i și elementul k al coloanei j să fie ambele egale cu 1. Dacă folosim operațiile algebrei booleene de adunare și înmulțire:
|
0 |
1 |
|
|
0 |
1 |
0 |
0 |
1 |
|
0 |
0 |
0 |
1 |
1 |
1 |
|
1 |
0 |
1 |
atunci verificările de mai sus sunt echivalente cu a verifica dacă elementul de pe poziția (i,j) din A2 este egal cu 1. Valoarea 1 spune doar că există cel puțin un drum de lungime 2 de la xi la xj. Dacă dorim să vedem și câte sunt, vom folosi regulile de înmulțire și adunare obișnuită.
De asemenea, se poate observa că existența unui drum de lungime 3 de la xi la xj presupune existența unui nod xk astfel încât să existe un drum de lungime 2 de la xi la xk și un arc de la xk la xj, care este echivalent cu a verifica dacă există vreun indice k astfel încât elementul k al liniei i din matricea A2 și elementul k al coloanei j din A sunt ambele egale cu 1 sau, mai simplu, dacă elementul (i,j) din A3 este 1.
Din cele de mai sus se observă că existența drumurilor de lungime k este dată de valorile matricei Ak, dacă s-au folosit regulile algebrei booleene și numărul lor este dat de Ak, dacă s-au folosit regulile obișnuite.
Pasul 2. Vom calcula succesiv puterile lui A până la puterea An-1
Dacă între nodurile xi și xj există un drum de lungime ³ n atunci el va conține un număr de noduri mai mare sau egal nu n+1 și, cum în graf sunt doar n vârfuri, este clar că cel puțin unul, să zicem xk, va apărea de două ori. Vom avea în acest caz un drum de la xi până la prima apariție a lui xk, și un drum de la ultima apariție a lui xk la xj. Eliminând toate nodurile dintre prima apariție a lui xk și ultima apariție a sa vom obține un drum de la xi la xj, în care xk apare o singură dată. Aplicând acest procedeu pentru toate nodurile care apar de mai multe ori pe drum, vom obține un drum de la xi la xj, în care fiecare nod apare o singură dată (deci un drum elementar), care are evident cel mult n-1 arce. În concluzie, dacă există vreun drum de la xi la xj atunci există și un drum elementar și, deci, va exista o putere a lui A, între A1 și An-1, în care poziția (i,j) este diferită de 0. Pentru deciderea existenței unui drum între oricare două noduri este suficientă, deci, calcularea doar a primelor n-1 puteri ale lui A.
Pasul 3. Se calculează matricea D = A + A2 + ... + An-1
Dacă ne interesează doar existența drumurilor dintre noduri, nu și numărul lor, vom folosi înmulțirea și adunarea booleană și conform observației de mai sus:
dij =
În acest caz, observând că:
AŚ(A + I)n2 = ŚA +ŚA2 + ŚA3 + ... + ŚAn1 = A + A2 + A3 + ... + An-1 = D
rezultă că e suficient să calculăm doar
puterea n-2 a matricei A + I și apoi s-o înmulțim cu A. Avantajul acestei
metode, în ceea ce privește economia de timp, este susținut și de următoarea
observație: dacă D conține toate perechile de arce între care există drum
atunci:
D = (A + A2 + ...
+ An-1) + An + An+1 + ... + An+k =
D oricare ar fi k ³ 0 Þ
Þ AŚ(A + I)n2+k = (A
+ A2 + ... + An-1) + An + An+1 +
... + An+k-1 = D = AŚ(A + I)n2
Û
ÛAŚ(A + I)n2+k = AŚ(A + I)n2
oricare ar fi k ³ 0
deci de la puterea k = n-2 toate matricile Ak
sunt egale. Putem, deci, calcula direct orice putere a lui A+I mai mare sau
egală cu n-1 (de exemplu calculând (A+I)2, (A+I)4, (A+I)8,
..., , r fiind prima putere a lui 2 pentru care 2r ³ n-2).
Procedeul de mai sus
nu asigură decât aflarea faptului dacă există sau nu drum între două noduri,
eventual ce lungime are și câte sunt de această lungime. Totuși, în problemele
practice cel mai important este să știm care sunt efectiv aceste drumuri.
Deoarece toate drumurile pot fi descompuse în drumuri elementare și în
problemele practice în general acestea sunt cele care interesează, pașii
următori ai algoritmului vor fi dedicați găsirii lor. Pentru găsirea acestora
se folosește reprezentarea grafului prin matricea latină de la cazul F.
Pasul 4. Construim matricea latină L asociată grafului, unde:
lij =
și matricea , definită prin:
=
numită matricea latină redusă.
Găsirea unui drum de lungime 2 de la xi la xj presupune găsirea unui nod cu proprietatea că există arcele (xi,xk) și (xk,xj) și memorarea vectorului (xi, xk, xj). Aceasta este echivalent cu a găsi un indice k astfel încât elementul de pe poziția k a liniei i, din matricea L, să fie xi,xk și elementul de pe poziția k al coloanei j, din matricea , să fie xj. Vom înmulți deci matricea L cu matricea , folosind însă niște reguli de calcul speciale, numite înmulțire și adunare latină.
Definiția 1: Se numește alfabet o mulțime de semne numite simboluri sau litere {si/iÎI} unde I este o mulțime oarecare de indici, finită sau nu.
Definiția 2: Se numește cuvânt un șir finit de simboluri notat .
Definiția 3: Se numește înmulțire latină o operație definită pe mulțimea cuvintelor unui alfabet, notată "", astfel:
=
(produsul a două cuvinte se obține prin concatenarea lor)
Înmulțirea latină este asociativă, are ca element neutru cuvântul vid, nu e comutativă și un element este inversabil doar dacă este cuvântul vid.
Definiția 3: Se numește adunare latină o funcție definită pe mulțimea cuvintelor unui alfabet cu valori în mulțimea parților mulțimi cuvintelor, notată "" astfel:
=
(suma a două cuvinte este mulțimea formată din cele două cuvinte)
Pasul 5. Se calculează succesiv matricile:
L2 = L , L3 = L2 , ... ,Lk+1 = Lk
folosind operațiile de înmulțire și adunare latină, alfabetul fiind mulțimea nodurilor grafului, unde operația de înmulțire este ușor modificată, produsul dintre două elemente ale matricilor fiind 0, dacă unul dintre ele este 0 sau au un nod comun și este produsul latin al lor, în caz contrar.
Din felul cum a fost construită, matricea Lk va conține toate drumurile elementare de lungime k. Cum un drum elementar poate avea cel mult n noduri (câte are graful cu totul) rezultă că:
- primele n-1 puteri ale lui L conțin toate drumurile elementare din graf;
- puterile lui L mai mari sau egale cu n au toate elementele egale cu 0;
- matricea Ln-1 conține toate drumurile hamiltoniene din graf (dacă există).
Observație: Deoarece obținerea matricii D prin metoda
de mai sus presupune un volum foarte mare de calcule (de exemplu, dacă graful
are 100 de noduri, ridicarea unei matrici de 100Ś100 la puterea 100) pentru
obținerea acesteia se poate aplica și următorul algoritm:
Pas 1. Se construiește matricea de
adiacență A;
Pas 2. Pentru fiecare linie i se
adună boolean la aceasta toate liniile j pentru care aij = 1.
Pas 3. Se reia pasul 2 până când,
după o aplicare a acestuia, matricea rămâne aceeași (nu mai apare nici un 1)
Ultima matrice obținută este
matricea drumurilor D numită și matricea conexiunilor totale.
Această metodă, deși mai
simplă nu spune însă și care sunt aceste drumuri, pentru găsirea lor
aplicându-se, de exemplu, înmulțirea latină
5. ARBORI. Problema arborelui de valoare optimă
În acest subcapitol grafurile vor fi considerate neorientate.
Un arbore este un graf neorientat, finit, conex și fără cicluri. Grafurile din fig. 4.1. sunt arbori.
Studiul arborilor este justificat de existența în practică a unui număr mare de probleme care pot fi modelate prin arbori. Dintre acestea amintim:
1. construirea unor rețele de aprovizionare cu apă potabilă (sau cu energie electrică sau termică etc) a unor puncte de consum, de la un punct central;
2. construirea unor căi de acces între mai multe puncte izolate;
3. desfășurarea unui joc strategic;
4. luarea deciziilor în mai multe etape (arbori decizionali);
5. evoluții posibile ale unui sistem pornind de la o stare inițială;
6. construirea unei rețele telefonice radiale, a unei rețele de relee electrice;
7. legarea într-o rețea a unui număr mare de calculatoare;
8. organigramele întreprinderilor;
9. studiul circuitelor electrice în electrotehnică (grafe de fluență etc);
10. schemele bloc ale programelor pentru calculatoare etc.
În toate problemele de mai sus se dorește ca, dintre muchiile unui graf neorientat, să se extragă arborele optim din mulțimea tuturor arborilor care pot fi extrași din graful dat.
Deoarece definiția arborelui este dificil de aplicat pentru deciderea faptului că un graf este arbore sau nu (și în special sunt greu de verificat conexitatea și mai ales existența ciclurilor) există mai multe caracterizări posibile ale unui arbore, acestea fiind date de teorema de mai jos:
Teoremă. Dacă H este un graf neorientat finit, atunci următoarele afirmații sunt echivalente:
1) H este arbore;
2) H nu conține cicluri și, dacă se unesc printr-o muchie două noduri neadiacente, se formează un ciclu (și numai unul). Arborele este, deci, pentru o mulțime de noduri dată, graful cu numărul maxim de arce astfel încât să se păstreze proprietatea că nu are cicluri);
3) H este conex și dacă i se suprimă o muchie se creează două componente conexe (arborele este graful conex cu numărul minim de arce);
4) H este conex și are n-1 muchii;
5) H este fără cicluri și are n-1 muchii;
6) Orice pereche de noduri este legată printr-un lanț și numai unul.
Demonstrație :
1)Þ 2). între cele două noduri adiacente noii muchii introduse exista deja un drum în fostul graf. Acest drum, împreună cu noul arc va forma evident un ciclu și afirmația 2) a fost demonstrată.
2)Þ3). Pentru oricare două vârfuri neunite printr-o muchie, adăugând muchia dintre cele două vârfuri s-ar crea, conform ipotezei, un ciclu care conține această muchie, deci două drumuri între cele două noduri, din care unul nu conține noua muchie, adică în graful inițial exista un drum între cele două noduri. Dacă nu există cicluri înseamnă că între oricare două noduri există un singur drum. Pentru două noduri unite printr-o muchie, aceasta este chiar drumul corespunzător celor două noduri. Dacă suprimăm această muchie între cele două noduri nu va mai exista nici un drum, formându-se două componente conexe.
3)Þ4). Demonstrația se face prin inducție după n = numărul de noduri ale grafului. Pentru n=2 este evident. Presupunem afirmația adevărată pentru toate grafurile cu cel mult n noduri. Dacă graful are n+1 noduri, prin suprimarea unei muchii se formează două componente conexe fiecare având cel mult n noduri (n1 £ n, n2 £ n și n1 + n2 = n+1) și deci au n1 1 respectiv n2 1 muchii. În concluzie graful inițial a avut (n1 1) + (n2 1) +1 = n1 + n2 1= (n+1)-1 muchii, ceea ce era de demonstrat.
4)Þ5). Dacă ar avea un ciclu atunci prin suprimarea unui arc al acestuia ar rămâne de asemenea conex. Eliminăm acest arc apoi repetăm procedeul pentru graful parțial rămas și tot așa până când nu mai rămâne nici un ciclu. În acest moment graful rămas este conex și nu are cicluri deci este arbore și deci are n-1 arce, în contradicție cu faptul că el avea n-1 arce înainte de a începe suprimarea arcelor;
5)Þ6). Dacă între două noduri ar exista două drumuri atunci acestea ar forma la un loc un ciclu. Deci între 2 noduri este cel mult un drum. Dacă între două noduri nu ar exista nici un drum ar fi cel puțin două componente conexe în graf, fiecare fiind arbore (pentru că nu există cicluri) și deci fiecare ar avea un număr de arce cu 1 mai mic decât numărul de noduri. Făcând adunarea, ar rezulta că în graf sunt strict mai puțin de n-1 arce.
6)Þ1). Dacă H ar avea un ciclu, între două noduri ale acestuia ar exista două lanțuri, în contradicție cu ipoteza.
Presupunem că avem un graf pentru care am verificat deja dacă este conex. Dacă nu este atunci acesta, evident, nu are nici un graf parțial care să fie arbore.
Presupunem de asemenea că fiecărei muchii îi este asociată o valoare reală.
5.2. Algoritmi pentru găsirea arborelui de valoare optimă
Vom da mai jos trei algoritmi pentru determinarea unui graf parțial al grafului, care să fie arbore și pentru care suma valorilor arcelor sale să fie minimă (sau maximă).
Toți algoritmii descriși în continuare extrag arborele prin colectarea una câte una a muchiilor acestuia.
Pasul 1. Dintre toate muchiile grafului se alege muchia de valoare minimă (maximă). Dacă minimul este multiplu se alege la întâmplare una din muchiile respective. Deoarece acest "la întâmplare" trebuie cumva tradus în limbajul calculatorului, în cazul implementării unui program bazat pe acest algoritm, vom perturba din start valorile muchiilor, la k muchii cu aceiași valoare V adunând respectiv valorile e, 2e, ... , ke, unde e este foarte mic (în orice caz, ke mai mic decât diferența dintre valoarea acestor arce si valoarea imediat superioară a unui arc), pozitiv.
Pasul 2. Dintre toate muchiile rămase, se alege cea de valoare minimă (maximă);
Pasul 3. Dintre toate muchiile rămase, se alege cea de valoare minimă (maximă), astfel încât să nu se formeze cicluri cu cele deja alese;
Pasul 4. Se reia algoritmul de la pasul 3 până se colectează n-1 muchii.
Deși s-a demonstrat că algoritmul găsește întotdeauna arborele optim, el are dezavantajul că este foarte laborios (de fiecare dată trebuie calculat minimul unei mulțimi mari sau foarte mari există situații în practică în care graful are sute de mii de arce) și, în plus, trebuie aplicat un algoritm special ca să respectăm condiția de a nu se forma cicluri, la alegerea unui nou arc.
O metodă posibilă este ca, după adăugarea fiecărui arc, să se împartă graful în componente conexe și să alegem apoi un arc care nu are ambele extremitățile în aceeași componentă conexă.
De asemenea este clar că, în cazul existenței arcelor de valori egale, deoarece se alege la întâmplare, există mai multe variante de evoluție a alegerii arcelor. Totuși, cu toate că pot fi mai multe grafuri la care se poate ajunge prin acest algoritm, ele vor avea toate aceeași valoare (minima (sau maxima) posibilă).
Pasul 1. Pentru fiecare nod se alege muchia adiacentă de valoare minimă (maximă).
Pasul 2. Se evidențiază componentele conexe, existente în graful parțial format din arcele alese până în acest moment.
Pasul 3. Pentru fiecare componentă conexă se alege muchia adiacentă de valoare minimă (maximă). Prin muchie adiacentă unei componente conexe înțelegem o muchie care are o singură extremitate printre nodurile componentei respective.
Pasul 4. Se reia algoritmul de la pasul 2 până rămâne o singură componentă conexă. Aceasta este arborele optim căutat.
Acest algoritm asigură de asemenea găsirea arborelui optim, necesită mult mai puține calcule (la fiecare alegere se calculează minimul doar pentru muchiile adiacente unui singur nod), evită automat formarea ciclurilor, dar, pentru grafuri foarte mari, la un moment dat pot exista atât de multe componente conexe care trebuie memorate succesiv, încât calculul devine greoi sau, pe calculator, depășește posibilitățile de memorare ale calculatorului.
Pasul
1. Dintre toate muchiile grafului se alege cea de valoare minimă (maximă);
Pasul
2. Dintre toate muchiile adiacente componentei conexe formată din arcele
alese până în acest moment, se alege cea de valoare minimă (maximă);
Pasul
3. Se reia pasul 2 până se colecționează n-1 muchii.
Algoritmul are toate avantajele algoritmului lui Sollin și, în plus, lucrează cu o singură componentă conexă, fiind mult mai ușor de implementat pe calculator și mult mai rapid în execuție.
Exemplu: Administrația unei localități montane a hotărât construirea unor linii de teleferic care să lege orașul de cele 8 puncte turistice importante din jurul acestuia. În urma unui studiu au fost puse în evidența toate posibilitățile și costurile de conectare a obiectivele turistice între ele și cu orașul, acestea fiind prezentate în figura 4.2.
Se cere găsirea variantei de construcție de cost minim, care să asigure accesul din oraș la oricare din obiectivele turistice.
Condiția de cost minim implică două obiective:
1. Să se construiască minimul de arce necesare;
2. Să se construiască cele mai ieftine legături.
Referitor la numărul de arce necesar, facem observația că, dacă din oraș se va putea ajunge la orice obiectiv turistic, atunci se va putea ajunge și de la orice stațiune la oricare alta (trecând prin oraș), deci trebuie ca arcele alese pentru construcție să formeze la un loc un graf conex.
În concluzie, căutăm un graf parțial conex cu un număr minim de arce, adică un arbore. În plus, suma costurilor arcelor sale trebuie să fie minimă. Vom aplica pe rând cei trei algoritmi pentru găsirea acestuia:
A. Kruskal
La primul pas poate fi ales unul din arcele OP3 sau OP7, ele având valoarea minimă 2. Putem alege oricum primul arc dintre cele două pentru că la al doilea pas va fi ales celălalt.
La pasul trei poate fi ales unul din arcele OP5, OP6 sau P1P6 care au valoarea minimă 3. Nici în acest caz nu are vre-o importanță ordinea alegerii, deoarece pot fi alese succesiv toate trei fără a se forma nici un ciclu.
Al șaselea arc poate fi ales dintre arcele P4P5 și P1P2, care au valoarea minimă 4. Nici în acest caz nu are vre-o importanță ordinea alegerii, deoarece pot fi alese succesiv ambele, fără a se forma nici un ciclu.
Următoarea valoare disponibilă a unui arc este 5, dar arcul opt nu poate fi ales dintre arcele OP1, P6P7, deși au valoarea minimă 5. Arcul OP1 nu poate fi ales deoarece s-ar forma ciclul OP1P6, iar P6P7 ar duce la ciclul OP6P7. Următoarea valoare minimă este 6, pentru arcul P5P7 dar nu poate fi ales deoarece se formează ciclul OP5P7.
Valoarea următoare, 7, o au arcele OP4, P2P3 și P5P8. OP4 nu poate fi ales deoarece s-ar forma ciclul OP5P4. Arcul P2P3 nu poate fi ales deoarece s-ar forma ciclul OP6P1P2P3. Arcul P5P8 nu formează nici un ciclu și el va fi al optulea arc ales. În acest caz, deoarece s-au adunat 8 arce într-un graf cu 9 noduri, am obținut graful căutat.
Acest arbore este reprezentat în figura 4.3.
B. Sollin
Vom alege: |
pentru nodul O |
ź |
arcul OP3 |
|
pentru
nodul P1 |
ź |
arcul P1P6 |
|
pentru nodul P2 |
ź |
arcul P1P2 |
|
pentru nodul P3 |
ź |
arcul OP3 |
|
pentru nodul P4 |
ź |
arcul P4P5 |
|
pentru nodul P5 |
ź |
arcul OP5 |
|
pentru nodul P6 |
ź |
arcul P1P6 |
|
pentru nodul P7 |
ź |
arcul OP7 |
|
pentru nodul P8 |
ź |
arcul P5P8 |
Rezultă graful parțial:
După cum se vede, s-au format două componente conexe: C1 = {P1,P2,P6}
C2 = {O,P3,P4,P5,P7,P8}.
Vom alege: pentru C1 ź arcul OP6
pentru C2 ź arcul OP6
și obținem o singură componentă conexă, care este arborele căutat.
C. Varianta algoritmului lui Kruskal
Succesiunea alegerii arcelor va fi:
1 |
ź |
OP3 |
2 |
ź |
OP7 |
3 |
ź |
OP6 |
4 |
ź |
OP5 |
5 |
ź |
P1P6 |
6 |
ź |
P1P2 |
7 |
ź |
P4P5 |
8 |
ź |
P5P8 |
6. Cuplajul a două mulțimi disjuncte Probleme de afectare (de repartiție)
În practica economică sunt foarte des întâlnite probleme în care se dorește asocierea optimă a elementelor unei mulțimi X = {x1, x2, ... , xn} cu elementele unei alte mulțimi Y = {y1, y2, ... , ym} în condițiile unor limitări existente (și cunoscute) ale posibilităților de asociere.
În general, fiecare asociere posibilă xi « yj aduce un anumit efect aij (profit, cost etc) care poate fi calculat și vom presupune că este cunoscut.
Limitările asupra asocierilor se traduc de obicei prin faptul că:
1. Un element xi poate fi asociat doar cu anumite elemente din Y și reciproc;
2. La sfârșit, fiecărui element din X i s-a asociat cel mult un element din Y și reciproc.
Asocierea optimă presupune, de obicei, două obiective:
1. Să se facă maximul de asocieri;
2. Suma efectelor asocierilor să fie maximă (sau minimă, în funcție de semnificația acestora).
Reprezentarea geometrică a situației de mai sus este un graf de forma:
numit graf bipartit.
Definiția 1: Se numește graf bipartit un graf G = (X, U) în care mulțimea nodurilor poate fi împărțită în două mulțimi disjuncte A și B astfel încât orice arc are extremitatea inițială în A și cea finală în B.
Definiția 2: Se numește cuplaj al unui graf bipartit o submulțime de arce W Í U cu proprietatea că nu există două arce adiacente (sau altfel spus, pentru orice nod există cel mult un arc incident acestuia).
Definiția 3: Se numește cuplaj maxim un cuplaj cu proprietatea că orice arc care nu face parte din cuplaj este adiacent cu un arc din cuplaj ( Û orice arc am adăuga, nu mai rămâne cuplaj Û nu există nici un cuplaj în care să se includă strict Û conține numărul maxim de arce neadiacente)
Este evident că numărul de arce ale unui cuplaj este mai mic sau egal cu numărul de elemente din fiecare din mulțimile A și B (£ min (½A½,½B½). Este interesant de văzut însă cât de mare este el efectiv și în ce condiții este egal chiar cu min (½A½,½B½).
Referitor la prima întrebare, în 1931 König a demonstrat o teoremă care permite stabilirea numărului de arce ale unui cuplaj maxim:
Teoremă: Numărul maxim de arce ale unui cuplaj într-un graf bipartit G = (AÈB, G) este egal cu
În ceea ce privește a doua problemă, observăm mai întâi că putem presupune că întotdeauna ½A½£½B½, în caz contrar inversând sensul tuturor arcelor grafului, problema rămânând aceeași.
În acest caz:
= ½A½ Û ½A½ = 0 Û = 0 Û
Û = 0 Û oricare ar fi C Í A
sau altfel spus, pentru orice submulțime C a lui A, mulțimea nodurilor atinse de arce care pleacă din nodurile sale, adică G(C), are cel puțin atâtea elemente cât C.
De exemplu, la repartizarea angajaților pe posturi, fiecare angajat poate obține un post dorit dacă și numai dacă oricare ar fi mulțimea de r angajați există cel puțin r posturi diferite din care pot alege.
Presupunem, în continuare, că s-a asociat fiecărui arc (xi,xj) o valoare vij.
Definiția 4: Se numește valoare a unui cuplaj suma valorilor arcelor care îl formează.
În acest moment putem spune că determinarea unei asocieri optime a mulțimilor X și Y de la început este echivalentă matematic cu determinarea unui cuplaj maxim de valoare optimă (minimă sau maximă) în graful bipartit asociat.
Dintre problemele întâlnite în practica economică, ce se reduc matematic la găsirea unui cuplaj maxim de valoare optimă, amintim:
1. Problema repartizării muncitorilor unei secții la utilajele acesteia în funcție de pregătirea și preferințele muncitorilor, complexitatea mașinilor etc;
2. transferarea unor informații într-un grup;
3. Repartizarea angajaților pe posturi;
4. Formarea grupelor de lucru după afinitățile dintre membrii colectivului.
În 1955, bazându-se pe teorema lui König, H.W. Kuhn a elaborat un algoritm, cunoscut în literatura de specialitate sub denumirea de algoritmul ungar, cu ajutorul căruia se poate determina un cuplaj maxim de valoare minimă într-un graf bipartit pentru care ½A½=½B½= n.
El se bazează pe observația că, dacă se adună (sau scade) aceeași număr la toate valorile arcelor, nu se modifică ierarhia cuplajelor maxime, în ceea ce privește valoarea lor.
Vom prezenta algoritmul concomitent cu rezolvarea unui caz particular, pentru o mai bună receptare a acestuia:
"Într-o secție produsele finite se obțin în urma efectuării succesive a 6 operații pe 6 mașini. În această secție sunt angajați 6 muncitori, fiecare fiind calificat pentru efectuarea oricărei din cele 6 operații. Pentru a optimiza activitatea în secție cei 6 muncitori au fost supuși la un test în care fiecare a prelucrat un număr de piese, pe toate cele șase mașini. În final, calculându-se timpul mediu în care muncitorul Mi efectuează operația Oj s-au obținut valorile (în ore) date în tabelul de mai jos:
|
M1 |
M2 |
M3 |
M4 |
M5 |
M6 |
O1 |
4 |
3 |
6 |
2 |
6 |
8 |
O2 |
5 |
4 |
8 |
3 |
8 |
9 |
O3 |
5 |
6 |
8 |
2 |
8 |
7 |
O4 |
4 |
5 |
7 |
2 |
7 |
8 |
O5 |
4 |
6 |
6 |
3 |
6 |
7 |
O6 |
6 |
6 |
8 |
3 |
8 |
9 |
Să se găsească acea repartiție a muncitorilor la mașini astfel încât timpul în care o piesă se prelucrează succesiv pe cele 6 mașini să fie minim."
Pasul 1. Se construiește matricea pătratică M care are elementele:
mij =
Pentru exemplul ales vom avea: M =
Pasul 2. Se scade din fiecare linie minimul acesteia apoi, în matricea obținută, din fiecare coloană minimul acesteia (se poate face și invers, rezultatul final va fi același). Pentru exemplul dat vom obține succesiv matricile:
M1 = și apoi M2 =
Ultima matrice este cea asupra căreia se aplică următoarele calcule. În acest moment pe fiecare linie și pe fiecare coloană se află cel puțin un 0, care corespunde celui mai mic timp. Se încearcă în continuare folosirea doar a acestor repartizări:
Pasul 3. În ordinea crescătoare a numărului de zerouri și de sus în jos (în cazul existenței mai multor linii cu același număr de zerouri ) se încadrează pentru fiecare linie zeroul a cărui coloană conține cele mai puține zerouri (primul de la stânga dintre acestea, în caz de egaliate) și se barează celelalte zerouri de pe linia și coloana acestuia. Pe parcursul algoritmului sunt luate în considerare la numărare doar zerourile neîncadrate și nebarate încă. În final, pe fiecare linie și pe fiecare coloană va fi cel mult un zero încadrat. Dacă în final sunt n (= dimensiunea matricei) zerouri, atunci arcele corespunzătoare formează cuplajul căutat. Dacă sunt mai puține se trece la pasul 4.
În exemplul nostru avem trei linii cu câte un zero (a 3-a, a 4-a și a 5-a) .Îl încadrăm pe cel de pe linia 3 (prima dintre ele) și barăm restul zerourilor de pe linia 3 și coloana 3, obținând:
În acest moment pe liniile 1 și 2 se află un zero. Se încadrează cel de pe linia 1 și se barează celelalte de pe linia 1 și coloana 2, obținând:
Ultima linie cu zerouri este linia 5 din care îl încadrăm pe primul și le barăm pe celelalte:
În total nu sunt 6 zerouri încadrate (sunt doar trei) și deci trecem la pasul 4.
Pasul 4. La acest pas se va stabili numărul minim posibil de linii și coloane care să conțină toate zerourile matricii. În acest sens vom proceda astfel:
a) se marchează liniile care nu au nici un zero încadrat;
b) se marchează coloanele care au un zero barat pe o linie marcată;
c) se marchează liniile care au un zero încadrat pe o linie marcată (dacă există);
Se repetă operațiile b) și c) până nu mai poate fi marcată nici o linie și nici o coloană.
În cazul nostru vom avea: a) ź se marchează liniile 2, 4 și 6;
b) ź se marchează coloanele 2 și 4;
c) ź se marchează liniile 1 și 3;
b) ź nu mai marcăm nici o coloană deoarece nu mai există nici un zero barat pe liniile 1 și 3, care să corespundă unei coloane nemarcate;
c) ź nu mai marcăm nici o linie, deoarece nu a mai apărut nici o coloană marcată.
Rezultă:
Pasul 5. Se taie liniile nemarcate și coloanele marcate:
Pasul 6. Se împart elementele matricei în trei grupe:
G1 = elemente aflate la intersecții de linii netăiate cu coloane netăiate;
G2 = elemente situate la intersecții de linii tăiate cu coloane netăiate sau de linii netăiate cu coloane tăiate;
G3 = elemente situate la intersecții de coloane tăiate cu linii tăiate
Pasul 7. Se găsește minimul grupei G1, care se scade din fiecare element al lui G1 și se adună la fiecare element al grupei G3. Elementele grupei G2 rămân neschimbate.
Pentru exemplul dat, minimul lui G1 este 1 și obținem noua matrice:
Pasul 8. Se reia algoritmul de la pasul 3.
Vom avea după marcare:
Deoarece avem 6 zerouri încadrate, am obținut cuplajul maxim de valoare minimă căutat, căruia îi va corespunde repartizarea muncitorilor pe operații de mai jos:
care duce la o durată totală a prelucrării unei piese de 6 + 4 + 7 + 6 + 3 = 26 ore
Observație: Deoarece regula de a alege de sus în jos la linii cu același număr de zerouri este arbitrară și de asemenea alegerea primului zero de la stânga, putem ajunge și la alte cuplaje maxime, dar toate vor avea aceeași valoare, cea minimă. De exemplu, un alt cuplaj optim este:
adică
care are de asemenea valoarea 26.
Observația 1. Dacă dorim un cuplaj de valoare maximă atunci vom calcula la pasul 1 matricea M astfel:
1. Construind matricea A de elemente:
aij =
2. Matricea M va avea componentele: mij =
apoi aplicăm în continuare algoritmul.
Observația 2. Dacă ½A½¹½B½ atunci aplicăm același algoritm cu singura diferență că ne vom opri când vom obține un număr de zerouri egal cu min (½A½,½B½).
7. Drumuri și
circuite hamiltoniene
Una dintre cele mai cunoscute probleme economice este problema comis voiajorului. Comis voiajorul este un individ care trebuie să prezinte s-au să distribuie marfa comandată la o serie de centre distribuite în general neliniar pe o anumită zonă teritorială (localitățile dintr-un județ, magazinele dintr-un cartier, persoanele dintr-un sat etc). Dacă numărul de obiective care trebuie vizitate este mare sau foarte mare iar timpul disponibil foarte limitat atunci devine vitală o asemenea organizare a trecerii pe la fiecare obiectiv încât să se efectueze în timpul minim posibil. Acest timp minim se traduce prin drumul cel mai scurt, iar cel mai scurt drum este evident cel în care se trece pe la fiecare obiectiv o singură dată. În plus, la sfârșit trebuie să se afle în punctul inițial, adică sediul firmei la care lucrează.
O reprezentare a regiunii aprovizionate, în care centrele pe la care se trece sunt vizualizate prin puncte iar căile de acces la acestea prin segmente de curbe, va fi evident un graf, problema reducându-se la a găsi circuitul hamiltonian de lungime minimă.
În timp, s-au evidențiat o multitudine de probleme reductibile la găsirea unui drum (sau circuit) hamiltonian într-un graf, cum ar fi:
1. Problema poștașului (găsirea traseului cel mai scurt care trece pe la toate locuințele ce aparțin de oficiul poștal la care lucrează acesta);
2. Problema adunării deșeurilor (cel mai scurt drum care trece pe la toate punctele de depozitate a deșeurilor);
3. Problema succesiunii operațiilor (executarea mai multor operații pe o mașină în acea ordine în care suma timpilor consumați cu pregătirea mașinii pentru trecerea de la o operație la următoarea să fie minim)
4. Ordinea lipirii unor componente electronice pe o placă, etc;
Determinarea
drumurilor hamiltoniene
Problema
determinării drumului (circuitului) hamiltonian de valoare optimă s-a dovedit
deosebit de dificilă, neexistând nici acum un algoritm care să rezolve problema
în timp polinomial și nici măcar o metodă simplă prin care să se decidă dacă
într-un graf dat există sau nu drumuri hamiltoniene.
Există însă mai mulți algoritmi, unii exacți alții heuristici, care reușesc, într-un caz sau altul, să rezolve problema satisfăcător și în timp util.
Pasul 1. Se scrie matricea
booleană A asociată grafului G.
Pasul 2. Se determină
matricea D a drumurilor grafului G prin procedeul expus la începutul
capitolului și apoi matricea M = I + D.
Pasul 3. Se împarte mulțimea
nodurilor grafului în submulțimi disjuncte astfel:
1.
Se consideră în matricea M liniile pline (cu toate
elementele 1). Nodurile ce corespund liniilor pline cu 1 formează submulțimea C1.
2.
Se elimină liniile și coloanele care corespund
nodurilor din submulțimea stabilită.
3.
Se reia raționamentul de la punctul 1 pe matricea
redusă obținută la punctul 2 obținându-se următoarea submulțime și în
continuare toate celelalte până se epuizează toate liniile matricei.
Pasul 4. Se construiește
graful G' în care:
1.
Nodurile care formează o submulțime sunt
reprezentate prin puncte în interiorul unui dreptunghi și între acestea se
trasează arcele existente în graful inițial G.
2.
Se trasează legăturile dintre submulțimi. Ele sunt
reprezentate prin arcele existente în graful inițial G între nodurile
submulțimii C1 și cele ale submulțimii C2, între nodurile
submulțimii C2 și cele ale submulțimii C3 etc.
Pasul 5. Se găsesc drumurile
hamiltoniene
Un drum hamiltonian
se găsește plecând de la un vârf din submulțimea C1, trecând prin
toate vârfurile acesteia cu un drum hamiltonian, din ultimul vârf la care se
ajunge în C1 trecând la un vârf din C2, parcurgând în
continuare un drum hamiltonian în a doua submulțime și tot așa, trecând prin
toate submulțimile și parcurgând, deci, toate nodurile grafului inițial, o
singură dată. Aplicând acest procedeu în toate modurile posibile se obțin toate
drumurile hamiltoniene din graful inițial G. (Observație: poate să nu existe nici un drum hamiltonian în graful
G, caz în care algoritmul se oprește deoarece la un anumit pas nu mai exista
nici o linie plina cu 1).
Observație. Algoritmul lui Foulkes reduce găsirea drumurilor hamiltoniene în graful inițial G (care în problemele practice este foarte mare) la găsirea mai multor drumuri hamiltoniene mai mici în componente tare conexe ale grafului. Dacă un graf are o singură componentă tare conexă, algoritmul lui Foulkes nu este eficient, în acest caz trebuind aplicați alți algoritmi cum ar fi cel bazat pe înmulțirea latină.
B. Algoritmul lui Chen pentru determinarea
drumurilor hamiltoniene
în
grafuri fără circuite
Fie G = (X,U) un
graf orientat fără circuite, cu n noduri: X = {x1, x2,
, xn}. Vom considera că am calculat matricea drumurilor D și
puterile de atingere ale tuturor nodurilor.
Dacă în graful G
există un drum de la nodul xi la nodul xj atunci evident
p(xi) > p(xj), deoarece în orice vârf în care se poate
ajunge din xj se poate ajunge și din xi dar din xj
nu se poate ajunge în xj pentru că nu există circuite.
Teorema 2.3 (Chen) Un graf cu n noduri, fără circuite conține un drum
hamiltonian dacă și numai dacă există relația:
Demonstrație
Þ Fie H
un drum hamiltonian și presupunem că nodurile grafului au fost notate în
ordinea în care apar în acest drum. Atunci din orice nod xi se poate
ajunge în toate nodurile cu indice mai mare și numai în acestea (altfel ar
exista circuite) și deci puterea unui nod xi este n i, de
unde:
= (n 1) + (n 2) +
+ 1 + 0
=
Ü Ordonând vârfurile în
ordinea descrescătoare a puterii lor de atingere (i > j Û p(xi) < p(xj))
și cum graful nu are circuite, vom obține o matrice D cu toate zerourile
deasupra diagonalei (evident pe o poziție (i,i) nu se află nici un 1 iar dacă
ar fi un 1 pe poziția (i,j) cu i > j ar însemna că din xi se
poate ajunge în xj, deci în toate nodurile în care se poate ajunge
din xj, iar din xj nu se poate ajunge în xi,
deci p(xi) > p(xj) în contradicție cu ipoteza de
ordonare a nodurilor). Cum deasupra diagonalei sunt poziții iar suma
puterilor vârfurilor este chiar rezultă că toate
pozițiile de deasupra diagonalei sunt 1. Aceasta înseamnă că există toate
arcele de forma (xi,xi+1) (altfel n-ar exista drum de la
xi la xi+1, deoarece toate drumurile au indicii nodurilor
în ordine descrescătoare) și deci drumul hamiltonian (x1, x2,
, xn) q.e.d.
Teorema 2.4 Dacă într-un graf
orientat fără circuite există un drum hamiltonian atunci acesta este unic.
Demonstrație Deoarece un drum
hamiltonian se identifică cu o permutare a nodurilor grafului, existența a două
drumuri hamiltoniene implică existența a două permutări distincte a nodurilor
grafului și cum două permutări distincte diferă prin cel puțin o inversiune vor
exista două noduri xi și xj în ordinea xi ź xj pe un drum și
invers pe celălalt, existând deci un drum atât de la xi la xj
cât și de la xj la xi, cele două formând împreună un
circuit, în contradicție cu ipoteza.
Pe aceste teoreme se
bazează algoritmul lui Chen de
determinare a drumului hamiltonian într-un graf orientat fără circuite:
Pasul1. Se scrie matricea de
adiacență A
Pasul2. Se calculează
matricea drumurilor D
Pasul3. Dacă există un
indice i cu dii = 1 atunci graful are circuite, nu se poate aplica
algoritmul lui Chen și algoritmul se oprește. Dacă nu, se trece la pasul 4.
Pasul4. Se calculează
puterile de atingere pentru fiecare nod.
Pasul5. Dacă nu se verifică
relația atunci graful nu
are drumuri hamiltoniene și algoritmul se oprește, altfel se trece la pasul 6.
Pasul6. Se ordonează
nodurile în ordinea descrescătoare a puterilor lor de atingere și obținem
drumul hamiltonian căutat.
Pasul 1. Construim matricea latină L asociată grafului, unde:
lij =
Pasul 2. Construim matricea , definită prin:
=
numită matricea latină redusă.
Pasul 3. Se calculează succesiv matricile:
L2 = L, L3 = L2, ..., Lk+1 = Lk, ...
folosind operațiile de înmulțire și adunare latină, alfabetul fiind mulțimea nodurilor grafului, unde operația de înmulțire este ușor modificată, produsul dintre două elemente ale matricilor fiind 0, dacă unul dintre ele este 0 sau au un nod comun, și este produsul latin al lor, în caz contrar.
Din felul cum a fost construită, matricea Lk va conține toate drumurile elementare de lungime k. Cum un drum elementar poate avea cel mult n noduri (câte are graful cu totul) rezultă că:
- primele n-1 puteri ale L conțin toate drumurile elementare din graf;
- puterile lui L mai mari sau egale cu n au toate elementele egale cu 0;
- matricea Ln-1 conține toate drumurile hamiltoniene din graf.
Pasul 4. Dacă se doresc și
circuitele atunci se verifică pentru fiecare drum hamiltonian dacă poate fi completat
până la un circuit (adică dacă există în graf arcul care unește nodul final cu
cel inițial);
Pasul 5. Dacă se dorește și
drumul (sau circuitul) de valoare optimă (maximă sau minimă) se calculează suma
valorilor pentru fiecare drum și/sau circuit și se alege cel cu valoarea
optimă.
În
concluzie, metoda înmulțirii latine (A. Kaufmann J. Melgrange) determină
toate drumurile elementare din graf, prin calcularea matricelor M(1),
M(2), M(3),
, M(n-1).
În
matricea M(n-1) se citesc drumurile hamiltoniene.
Această metodă a
înmulțirii latine (algoritmul lui Kaufmann) este utilă, mai ales, în cazul
grafurilor tare conexe, unde algoritmul lui Foulkes nu este eficient. Totuși,
metoda este greu de aplicat în grafuri cu un număr mare de noduri. În acest caz
este preferabil să se construiască graful condensat, să se determine drumurile
hamiltoniene în fiecare în parte cu algoritmul lui Kaufmann și apoi, ca la
algoritmul lui Foulkes, să se caute drumurile hamiltoniene în graful inițial.
D. Un
algoritm bazat pe algoritmul ungar
Fie G = (X,U) un graf
orientat cu n noduri X = {x1, x2,
, xn}.
Pasul 1. Se construiește
graful bipartit H = (AÈB,V) în care A = B =
X și V = U (adică am folosit pentru G reprezentarea prin corespondență).
Pasul 2. Se găsește pentru
graful H cuplajul maxim de valoare minimă.
Pasul 3. Se construiește
graful parțial al lui G format doar cu arcele cuplajului găsit. Este ușor de
demonstrat că, componentele tare conexe ale acestuia sunt toate niște circuite.
Dacă s-a format un singur circuit acesta este circuitul hamiltonian de valoare
minimă. Dacă s-au format mai multe se trece la pasul 4.
Pasul 4. Pentru fiecare arc
aflat pe circuitul de lungime minimă (dacă sunt mai multe se iau în considerare
arcele tuturor) se reia algoritmul de la pasul 1 pentru graful parțial rezultat
din G prin eliminarea acestui arc.
Pasul 5. Pentru fiecare graf
parțial se continuă procedeul până se ajunge la unul din cazurile:
Cazul1.
Cuplajului maxim găsit îi corespunde un singur
circuit. Dacă acest circuit este primul obținut atunci valoarea sa i se
atribuie unei variabile Z și circuitul este păstrat. Dacă nu este primul atunci
valoarea sa se compară cu Z și, dacă este mai mică, ea devine noua valoare a
lui Z și circuitul se păstrează, eliminându-l pe cel corespunzător fostei
valori a lui Z. În caz contrar se trece la alt graf parțial neanalizat încă.
Cazul2.
Cuplajul maxim are o valoare mai mare decât Z.
Pentru acest graf parțial se abandonează ramificarea.
Pasul 6. Se continuă analiza
grafurilor parțiale până sunt analizate toate ramificațiile. Valoarea Z finală
este valoarea circuitului de valoare minimă iar circuitul corespunzător este
cel optim.
Analiza de mai sus
poate fi schematizată printr-un arbore de tipul:
în care fiecare nod este un graf parțial de
analizat, iar pentru fiecare arc, nodul inferior este un graf parțial care
provine din graful corespunzător nodului superior, prin suprimarea unui arc de
pe circuitele de lungime minimă corespunzătoare cuplajului maxim de valoare
minimă al acestuia.
Observație: Algoritmul asigură găsirea circuitului de
valoare minimă iar în cazul în care algoritmul lui Foulkes nu funcționează este
o alternativă mai bună decât algoritmul lui Kaufmann. Totuși el nu lucrează în
timp polinomial și în unele cazuri (de exemplu cazuri în care se formează
foarte multe cicluri cu lungime minimă) necesită un număr imens de calcule.
În aceste cazuri se
pot folosi metode euristice prin care se elimină din start o serie de arce,
considerate a avea valori prea mari pentru a se putea afla pe circuitul
hamiltonian de valoare minimă, apoi se aplică în graful parțial rămas unul din
algoritmii de mai sus.
8.
Drumuri optime într-un graf
În marea majoritate a problemelor care pot fi
modelate prin grafuri nu ne interesează numai dacă există sau nu legături între
componentele reprezentate prin nodurile grafului ci și intensitatea acestora.
Această intensitate are semnificația unei valori numerice (pozitive sau
negative) asociate arcului corespunzător legăturii a cărei intensitate o
măsoară.
În aplicațiile economice
această valoare poate fi:
-
lungimea drumului dintre două localități;
-
costul parcurgerii rutei reprezentate prin arcul
corespunzător;
-
durata parcurgerii rutei respective;
-
cantitatea transportată pe ruta respectivă;
-
capacitatea maximă a rutei respective;
-
câștigul realizat prin trecerea de la o stare la alta
a sistemului;
-
consum de energie pentru efectuarea trecerii
respective;
-
punctaj realizat etc.
Una din problemele
care poate apărea în aceste situații este găsirea, pentru o anumită pereche de
noduri (sau mai multe perechi), a drumului optim între acestea.
Pentru formalizarea
problemei vom introduce noțiunea de valoare
a unui drum, care este egală
cu suma valorilor arcelor care îl compun. Vom nota în continuare valoarea unui
arc (xi,xj) cu v(xi,xj) sau cu vij.
În aceste condiții putem enunța problema drumului optim astfel:
"Dat un graf G = (X,U) și o
funcție care asociază fiecărui arc o valoare reală, să se găsească, pentru o
pereche dată de noduri, drumul (drumurile) de valoare optimă (minimă sau/și
maximă) între cele două noduri și valoarea acestuia (acestora)"
Deoarece este vorba
de găsirea minimului unei mulțimi de numere reale, prima întrebare care se pune
este dacă aceasta admite minim. Dacă mulțimea nodurilor grafului este infinită
atunci pot exista o infinitate de drumuri elementare distincte între cele două
noduri și mulțimea valorilor acestora poate avea orice formă (închisă sau nu,
mărginită sau nu) devenind foarte greu de caracterizat cazurile când minimul
dorit există. Deoarece totuși majoritatea covârșitoare a problemelor economice
se modelează prin grafuri cu număr finit de noduri, ne vom limita în continuare
doar la acestea.
Un număr finit
de noduri n atrage după sine existența unui număr finit de arce (cel
mult n2) și a unui număr finit de drumuri elementare ( cel mult nŚn!Ś). Deoarece oricărui drum d îi corespunde un drum
elementar de (obținut prin eliminarea tuturor
subcircuitelor lui d) putem calcula valoarea oricărui drum ca sumă între
valoarea drumului elementar corespunzător și valorile unor subcircuite ale sale, fiecare înmulțită cu
numărul de parcurgeri ale circuitului respectiv.
În concluzie, dacă
există un circuit de valoare negativă înseamnă că există drumuri de valoare
oricât de mică (cele care conțin acest circuit), obținută prin parcurgerea
acestuia de oricâte ori dorim) și, deci, mulțimea valorilor drumurilor este
nemărginită inferior, neexistând drum de valoare minimă. Dacă există un circuit
de valoare pozitivă atunci există drumuri de valoare oricât de mare și mulțimea
valorilor drumurilor este nemărginită superior, neexistând drum de valoare
maximă.
Dacă nu există
circuite de valoare negativă atunci valoarea oricărui drum este mai mare sau
egală cu a drumului elementar corespunzător, deci drumul de valoare minimă
(dacă există) va fi un drum elementar. Cum mulțimea drumurilor elementare este
finită (și deci și mulțimea valorilor lor) va avea minorant și am lămurit
problema compatibilității problemei. Analog, dacă nu există circuite de valoare
pozitivă atunci valoarea oricărui drum este mai mică sau egală cu a drumului
elementar corespunzător, deci drumul de valoare maximă (dacă există) va fi un
drum elementar. Cum mulțimea drumurilor elementare este finită (și deci și
mulțimea valorilor lor), va avea majorant.
Obs. 1. Dacă în graf nu există
decât arce de valoare pozitivă atunci există drum de valoare minimă.
Obs. 1. Dacă în graf nu există
decât arce de valoare negativă atunci există drum de valoare maximă.
Obs. 1. Dacă în graf nu există
circuite atunci există și drum de valoare minimă și drum de valoare maximă.
Deoarece din cele de
mai sus se sesizează importanța existenței circuitelor într-un graf vom da în
continuare un algoritm de depistare a
existenței circuitelor într-un graf:
Pasul 1. Se construiește
mulțimea A formată din nodurile pentru care toate arcele incidente sunt
incidente spre interior ( noduri în care toate arcele "intră" sau,
altfel spus, noduri din care nu "pleacă" nici un arc).
Pasul 2. Se găsesc toate
nodurile care nu sunt din A pentru care toate arcele incidente au cealaltă
extremitate în A (noduri din care se poate "ajunge" doar in A). Dacă
nu există nici un astfel de arc se trece la pasul 4.
Pasul 3. Se adaugă arcele
găsite la pasul 2 la mulțimea A apoi se reia algoritmul de la pasul 2, pentru
noua mulțime A.
Pasul 4. Dacă A conține
mulțimea tuturor nodurilor atunci graful nu conține circuite. Dacă au rămas
noduri în afara lui A atunci graful conține circuite.
Algoritmi
de găsire a drumului optim
Din cauza varietății
nelimitate a grafurilor posibile, nu există un algoritm care să rezolve orice
problemă în timp util, dar s-au elaborat o mulțime de algoritmi, fiecare fiind
cel mai eficace în anumite cazuri. Acești algoritmi pot fi grupați în cinci
categorii:
1.
Algoritmi prin calcul matricial (Bellman-Kalaba, I.
Tomescu, Bellman-Schimbell);
2.
Algoritmi prin ajustări succesive: (Ford);
3.
Algoritmi prin inducție (Dantzig);
4.
Algoritmi prin ordonare prealabilă a vârfurilor
grafului;
5.
Algoritmi prin extindere selectivă (Dijkstra).
În continuare vom
prezenta trei dintre acești algoritmi.
A. Algoritmul lui Bellman - Kalaba
Algoritmul se aplică
în grafuri finite care nu au circuite de valoare negativă (pentru o problemă de
minim) sau care nu au circuite de valoare pozitivă (într-o problemă de maxim)
și găsește drumurile de valoare minimă (maximă) de la toate nodurile grafului
la un nod oarecare, fixat. Dacă dorim să cunoaștem drumurile de valoare minimă
(maximă) între oricare două noduri vom aplica algoritmul, pe rând, pentru
fiecare nod al grafului.
Fie G = {x1,
x2, ... ,xn} un graf orientat finit. Presupunem (fără a
restrânge generalitatea, că am numerotat nodurile astfel încât nodul spre care
căutăm drumurile de valoare minimă (maximă) de la celelalte noduri să fie xn.
Pasul 1. Se construiește
matricea pătratică M cu dimensiunea egală cu numărul de noduri ale grafului ale
cărei elemente sunt:
mij =
Pasul 2. Se adaugă succesiv
liniile Li la matricea M, elementele acestora calculându-se prin
relațiile de recurență:
1. L1j = mjn j = 1,...,n
(prima linie este ultima coloană, transpusă, a matricii M)
2. Lij = min
(Li-1,j , (mjk + Li-1,k)) într-o problemă de minim
sau Lij
= max (Li-1,j , (mjk + Li-1,k)) într-o problemă de maxim
Pasul 3. După calcularea
fiecărei linii noi se compară elementele ei cu cele ale precedentei:
-
Dacă Lij = Li-1,j pentru orice
j = 1,...,n atunci se oprește recurența și ultima linie calculată conține
valorile minime ale drumurilor de la celelalte noduri la nodul xn.
-
Dacă există cel puțin un indice j cu Lij ¹ Li-1,j se trece
la calcularea noii linii Li+1
Pasul 4. Pentru găsirea drumului
care dă valoarea minimă de la un nod xj la nodul xn se
găsesc, începând înapoi de la ultima linie, pe care s-au obținut valorile
finale, notată Lf, nodurile ,, ..., care formează drumul căutat, unde = xj, = xn și fiecare alt indice ki+1 este
cel pentru care s-a obținut minimul(maximul) de pe poziția ki al
liniei Li.
Observație: Pentru grafuri
foarte mari, algoritmul necesită un volum mare de memorie, prin necesitatea
memorării matricei M, care este greu de manipulat. Chiar dacă din cele n2
arce posibile graful ar avea doar un procent foarte mic matricea grafului va
avea tot n2 poziții de memorat și analizat.
Exemplu: Presupunem dat
graful orientat de mai jos, în care se dorește găsirea drumului de valoare
minimă de la nodul x1 la nodul x9.
Matricea M va fi
iar după calcularea liniilor Li obținem:
|
x1 |
x2 |
x3 |
x4 |
x5 |
x6 |
x7 |
x8 |
x9 |
x1 |
0 |
4 |
¥ |
¥ |
5 |
¥ |
¥ |
¥ |
¥ |
x2 |
¥ |
0 |
7 |
9 |
¥ |
¥ |
¥ |
¥ |
¥ |
x3 |
¥ |
¥ |
0 |
3 |
¥ |
¥ |
¥ |
¥ |
9 |
x4 |
¥ |
¥ |
¥ |
0 |
¥ |
¥ |
¥ |
¥ |
3 |
x5 |
¥ |
8 |
2 |
7 |
0 |
3 |
2 |
9 |
¥ |
x6 |
¥ |
8 |
¥ |
¥ |
¥ |
0 |
5 |
¥ |
¥ |
x7 |
¥ |
¥ |
¥ |
¥ |
¥ |
¥ |
0 |
6 |
8 |
x8 |
¥ |
¥ |
¥ |
4 |
¥ |
¥ |
¥ |
0 |
7 |
x9 |
¥ |
¥ |
¥ |
¥ |
¥ |
¥ |
¥ |
¥ |
0 |
L1 |
¥ |
¥ |
9 |
3 |
¥ |
¥ |
8 |
7 |
0 |
L2 |
¥ |
12 |
6 |
3 |
10 |
13 |
8 |
7 |
0 |
L3 |
15 |
12 |
6 |
3 |
8 |
13 |
8 |
7 |
0 |
L4 |
13 |
12 |
6 |
3 |
8 |
13 |
8 |
7 |
0 |
L5 |
13 |
12 |
6 |
3 |
8 |
13 |
8 |
7 |
0 |
Deoarece L4
= L5 oprim calcularea liniilor după calcularea liniei 5. În această
linie se află valorile celor mai scurte de la toate nodurile la nodul x9.
Drumul dorit de noi (x1 ź x9) are
valoarea dată de prima poziție a liniei 5, fiind egal cu 13.
Pentru a găsi acest
drum, plecăm înapoi de la linia 4 și avem:
x1 |
|
|
|
x5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
= |
8 |
+ |
5 |
|
x3 |
|
|
|
|
ß |
|
|
|
|
|
|
|
|
8 |
= |
6 |
+ |
2 |
|
x4 |
|
|
|
|
ß |
|
|
|
|
|
|
|
|
6 |
= |
3 |
+ |
3 |
|
|
|
|
|
|
ß |
|
|
|
|
|
|
|
|
3 |
ź |
x9 |
B.
Algoritmul lui Ford simplificat
Algoritmul lui Ford
simplificat se aplică doar în grafuri care nu admit circuite. Cu ajutorul
lui se găsește drumul de valoare optimă între două noduri fixate xi
și xj. Printr-o eventuală renumerotare a nodurilor putem presupune
că nodul de la care pornește drumul este x1, care va fi numit nod
inițial, iar nodul la care se termină este xn, numit nod final.
Algoritmul este:
Pasul 1. I se dă vârfului
inițial valoarea 0 (zero): w(x0) = 0
Pasul 2. Se construiește
mulțimea A formată din nodul inițial: A = {x1}
Pasul 3. Se analizează
nodurile din afara mulțimii A.
-
Dacă există noduri în care se poate ajunge prin arce
directe doar de la nodurile mulțimii A, acestea se adaugă la mulțimea A, cu
valoarea:
w(xi) = , în problemele de minim
sau w(xi) = , în problemele de maxim
apoi se trece la pasul 4
-
Dacă nu există nici un nod de acest tip atunci nu
există nici un drum de la x1 la xn. STOP
Pasul 4. Se analizează
mulțimea A:
-
Dacă xn Î A atunci valoarea sa
reprezintă valoarea drumului de valoare optimă de la x1 la xn.
Pentru găsirea acestui drum se pornește înapoi de la nodul final xn
și se găsesc nodurile ,, ..., care formează drumul căutat, unde = xn, = x1 și fiecare alt indice ki+1 este
cel pentru care:
w() + v(,) = w() STOP
-
Dacă xn Ï A se reia algoritmul de la
pasul 3.
Exemplu: Pentru același graf și
aceeași pereche de noduri din exemplul rezolvat cu algoritmul lui
Bellman-Kalaba vom avea succesiv:
pas1:
w(x1) = 0
pas2:
A = {x1}
pas3: Nodurile în care se poate ajunge doar
din x1: {x5} ¹ Æ
w{x5) =
min( w(x1) + v(x1,x5)) = 0 + 5 = 5
pas4: x9 Ï A
pas3: A = {x1,x5} și
nodurile în care se poate ajunge prin arce directe doar din x1 și x5
sunt: {x6}¹ Æ
w{x6) =
min( w(x1) + v(x1,x6), w(x5) + v(x5,x6))
= min(0 + 3 , 5 + 3) = 3
pas4: x9 Ï A
pas3:
A = {x1,x5,x6} și nodurile în care se poate ajunge
prin arce directe doar din x1, x5 și x6 sunt:
{x2,x7} ¹ Æ
w{x2) =
min( w(x1) + v(x1,x2), w(x5) + v(x5,x2),
w(x6) + v(x6,x2)) = min(0 + 4,5 + 8,3 + 8) = 4
w{x7) =
min( w(x5) + v(x5,x7), w(x6) + v(x6,x7))
= min(5 + 2,3 + 5) = 7
pas4: x9 Ï A
pas3:
A = {x1,x2,x5,x6,x7} și
nodurile în care se poate ajunge prin arce directe doar din x1, x2,
x5, x6 și x7 sunt: {x3,x8}
¹ Æ
w{x3) =
min( w(x2) + v(x2,x3), w(x5) + v(x5,x3))
= min(4 + 7,5 + 2) = 7
w{x8) =
min( w(x5) + v(x5,x8), w(x7) + v(x7,x8))
= min(5 + 9,7 + 6) = 13
pas4: x9 Ï A
pas3:
A = {x1,x2,x3,x5,x6,x7,x8}
și nodurile în care se poate ajunge prin arce directe doar din x1, x2,x3,x5,
x6, x7 și x8 sunt: {x4} ¹ Æ
w{x4) =
min( w(x2) + v(x2,x4), w(x3) + v(x3,x4),w(x5)
+ v(x5,x4), w(x8) + v(x8,x4))
= min(4 + 9,7 + 3,5 + 7,13 + 4) = 10
pas4: x9 Ï A
pas3:
A = {x1,x2,x3,x4,x5,x6,x7,x8}
și nodurile în care se poate ajunge prin arce directe doar din x1, x2,
x3, x4, x5, x6, x7 și x8
sunt: {x9} ¹ Æ
w{x9) = min( w(x3) + v(x3,x9),
w(x4) + v(x4,x9), w(x7) + v(x7,x9),
w(x8) + v(x8,x9)) = min(7 + 9, 10 + 3, 7 + 8,
13 + 7) = 13
pas4: x9 Î A și urmează să găsim
drumul care are lungimea 13.
Avem succesiv:
w(x9) = w(x4)
+ v(x4,x9)
w(x4) = w(x3)
+ v(x3,x4)
w(x3) = w(x5)
+ v(x5,x3)
w(x5) = w(x1)
+ v(x1,x5)
deci drumul căutat este: x1
ź x5 ź x3 ź x4 ź x9
Observația 1. Dacă graful are un circuit atunci se
poate demonstra ușor că nu vom putea da valoare nici unui nod al acestuia și
dacă există vreun drum de la x1 la xn care trece prin
unul din nodurile circuitului nu vom putea da valoare nici lui xn,
cu toate că există drum de la x1 la xn.
Observația 2: Algoritmul necesită pentru memorare și
manipulare doar cunoașterea, pentru fiecare nod, a nodurilor spre care
"pleacă" arce din acesta și valorile acestor arce, fiind mult mai
ușor de aplicat sau implementat pe calculator. El are însă dezavantajul că se
poate aplica doar în grafuri fără circuite.
C. Algoritmul Ford generalizat
Algoritmul lui Ford
generalizat a fost creat cu scopul de a putea găsi drumul optim și în grafurile
care au circuite. Cu ajutorul lui se găsește drumul de valoare optimă între
două noduri fixate xi și xj. Printr-o eventuală
renumerotare a nodurilor putem presupune că nodul de la care pornește drumul
este x1, care va fi numit nod inițial, iar nodul la care se termină
este xn, numit nod final.
Algoritmul este:
Pasul 1. I se dă vârfului
inițial valoarea 0 (zero): w(x0) = 0 și tuturor celelalte valoarea +¥ (într-o problemă de minim)
sau -¥ (într-o problemă de
maxim).
Pasul 2. În ordinea
crescătoare a indicilor nodurilor se calculează pentru fiecare nod, pe bază
fostelor valori, noile valori cu formula:
w*(xi)
= în problemele de minim
sau w*(xi)
= în problemele de maxim
Pasul 3. Se compară noile
valori w*(xi) cu fostele valori w(xi):
-
Dacă w*(xi) = w(xi)
pentru orice nod xi atunci:
-
dacă w(xn) < ¥ (la problema de minim) sau
w(xn) > -¥ (la problema de
maxim), valoarea nodului xn reprezintă valoarea drumului de valoare
minimă(maximă) de la x1 la xn. Pentru găsirea acestui
drum se pornește înapoi de la nodul final xn și se găsesc nodurile ,, ..., care formează drumul căutat, unde = xn, = x1 și fiecare alt indice ki+1 este
cel pentru care:
w() + v(,) = w() STOP
-
dacă w(xn) = +¥ (-¥) atunci nu există nici un
drum de la x1 la xn. STOP
-
Dacă există cel puțin un nod pentru care w*(xi) < w(xi)
se reia algoritmul de la pasul 2 pentru noile valori ale vârfurilor.
Observație: Algoritmul poate găsi drumul și în grafuri
cu circuite dar este evident mult mai lent decât cel simplificat. Pentru
scurtarea duratei de execuție se poate modifica algoritmul în sensul că o
valoare nou calculată a unui vârf va fi folosită imediat ca atare la calculul
noilor valori ale celorlalte, nu doar după ce se calculează noile valori ale
tuturor vârfurilor.
În algoritmul Ford
simplificat, pentru a găsi valoarea nodului final, deci a drumului minim,
plecăm de la nodul inițial în toate direcțiile posibile, păstrând de fiecare
dată toate nodurile analizate. Acest fapt duce la un consum inutil de timp,
deoarece foarte multe din aceste noduri nu vor face parte din drumul optim.
Pentru a elimina acest neajuns, algoritmul lui Dijkstra încearcă să păstreze,
la fiecare iterație, mulțimea minimă de noduri care să le conțină pe toate cele
care vor forma efectiv drumul optim. În plus, algoritmul se poate aplica și în
drumuri cu circuite. Ca un minus este faptul că se aplică doar la probleme de
minim. Algoritmul are următorii pași:
Pasul 1. I se dă vârfului
inițial valoarea 0 (zero): w(x0) = 0
Pasul 2. Se construiește
mulțimea A formată din nodul inițial: A = {x1}
Pasul 3. Se analizează nodurile
din afara mulțimii A.
-
Dacă există noduri în care se poate ajunge prin arce
directe de la noduri din A (nu doar de la nodurile
mulțimii A, ca la algoritmul lui Ford simplificat) se calculează pentru toate
acestea:
w(xi) = în problemele de minim
dar, spre deosebire
de algoritmul lui Ford simplificat, se adaugă la mulțimea A doar cel pentru care se obține valoarea minimă, apoi
se trece la pasul 4.
-
Dacă nu există nici un nod de acest tip atunci nu
există nici un drum de la x1 la xn. STOP
Pasul 4. Se analizează
mulțimea A:
-
Dacă xn Î A atunci valoarea sa
reprezintă valoarea drumului de valoare optimă de la x1 la xn.
Pentru găsirea acestui drum se pornește înapoi de la nodul final xn
și se găsesc nodurile ,, ..., care formează drumul căutat, unde = xn, = x1 și fiecare alt indice ki+1 este
cel pentru care:
w() + v(,) = w() STOP
-
Dacă xn Ï A se reia algoritmul de la
pasul 3.
Exemplu Vom aplica
algoritmul la același graf folosit la ceilalți algoritmi, pentru a putea face
comparații:
pas1:
w(x1) = 0
pas2:
A = {x1}
pas3: Nodurile în care se poate ajunge și din
x1: {x2, x5, x6}
¹ Æ
w{x2) = min( w(x1) +
v(x1,x2)) = 0 + 4 = 4
w{x5) = min( w(x1) +
v(x1,x5)) = 0 + 5 = 5
w{x6) = min( w(x1) +
v(x1,x6)) = 0 + 3 = 3
min(w{x2),w{x5),w{x6))
= w{x6) = 3
pas4: x9 Ï A
pas3:
A = {x1,x6} și nodurile în care se poate ajunge prin arce
directe din x1 sau x6 sunt: {x2,x5,x7}¹Æ
w{x2) = min( w(x1) +
v(x1,x2), w(x6) + v(x6,x2))
= min(0 + 4 , 3 + 8) = 4
w{x5) = min( w(x1) +
v(x1,x5)) = min(0 + 5) = 5
w{x7) = min( w(x6) +
v(x6,x7)) = min(3 + 5) = 8
min(w{x2),w{x5),w{x7))
= w{x2) = 4
pas4: x9 Ï A
pas3:
A = {x1,x2,x6} și nodurile în care se poate
ajunge prin arce directe din x1, x2 sau x6
sunt: {x3,x4,x5,x7} ¹ Æ
w{x3) = min( w(x2) +
v(x2,x3)) = min(4 + 7) = 11
w{x4) = min( w(x2) +
v(x2,x4)) = min(2 + 9) = 11
w{x5) = min( w(x1) +
v(x1,x5)) = min(0 + 5) = 5
w{x7) = min( w(x6) +
v(x6,x7)) = min(3 + 5) = 0
min(w{x3),w{x4),w{x5),w{x7))
= w{x5) = 5
pas4: x9 Ï A
pas3:
A = {x1,x2,x5,x6} și nodurile în
care se poate ajunge prin arce directe din x1, x2, x5,
x6 și x7 sunt: {x3,x4,x7,x8}
¹ Æ
w{x3) = min( w(x2) +
v(x2,x3), w(x5) + v(x5,x3))
= min(4 + 7,5 + 2) = 7
w{x4) = min( w(x2) +
v(x2,x4), w(x5) + v(x5,x4))
= min(4 + 9,5 + 7) = 12
w{x7) = min( w(x5) +
v(x5,x7), w(x6) + v(x6,x7))
= min(5 + 2,3 + 5) = 7
w{x8) = min( w(x5) +
v(x5,x8)) = min(5 + 9) = 14
min(w{x3),w{x4),w{x7),w{x8))
= w{x3) = w{x7) = 7
pas4: x9 Ï A
pas3:
A = {x1,x2,x3,x5,x6,x7}
și nodurile în care se poate ajunge prin arce directe din x1, x2,
x3, x5, x6, și x7 sunt: {x4,x8,x9}
¹ Æ
w{x4) = min( w(x2) +
v(x2,x4), w(x3) + v(x3,x4),w(x5)
+ v(x5,x4)) = min(4 + 9,7 + 3,5 + 7) =10
w{x8) = min( w(x5) +
v(x5,x8), w(x7) + v(x7,x8))
= min(5 + 9,7 + 6) = 13
w{x9) = min( w(x3) +
v(x3,x9), w(x7) + v(x7,x9))
= min(7 + 9,7 + 8) = 15
min(w{x4),w{x8),w{x9))
= w{x4) = 10
pas4: x9 Ï A
pas3:
A = {x1,x2,x3,x4,x5,x6,x7}
și nodurile în care se poate ajunge prin arce directe din x1, x2,
x3, x4, x5, x6, și x7
sunt: {x8,x9} ¹ Æ
w{x9) = min( w(x3) +
v(x3,x9), w(x4) + v(x4,x9),
w(x7) + v(x7,x9)) = min(7 + 9,10 + 3,7+8)=13
w{x8) = min( w(x5) + v(x5,x8),
w(x7) + v(x7,x8)) = min(5 + 9,7 + 6) = 13
min(w{x8),w{x9)) = w{x8)
= w{x9) = 13
pas4: x9 Î A și urmează să
găsim drumul care are lungimea 13.
Avem succesiv:
w(x9) = w(x4)
+ v(x4,x9)
w(x4) = w(x3)
+ v(x3,x4)
w(x3) = w(x5)
+ v(x5,x3)
w(x5) = w(x1)
+ v(x1,x5)
deci drumul căutat este: x1
ź x5 ź x3 ź x4 ź x9
Pentru studiul matematic al acestei situații vom da definițiile matematice ale obiectelor implicate în problemă și ipotezele modelului.
Definiția 1: Se numește rețea de transport standard un graf finit, simplu, conex, fără bucle G = (X,U) care are următoarele proprietăți:
1. Există și este unic s a.î. Æ, Æ (din care doar "ies" arce), numit intrarea rețelei de transport;
2. Există și este unic t a.î. = Æ, ¹ Æ (în care doar "intră" arce) numit ieșirea rețelei de transport;
3. S-a definit o funcție c: U ź R+ care asociază fiecărui arc u un număr strict pozitiv cu numit capacitatea arcului.
Observație: Este clar că exemplele obișnuite au doar rareori o singură sursă și o singură destinație. Totuși, printr-o tehnică foarte simplă, orice rețea de transport se poate aduce la forma standard:
1. Dacă sunt mai multe surse se introduce un nod suplimentar din care "pleacă" câte un arc spre fiecare sursă (și numai spre acestea), iar capacitățile acestor arce vor fi egale cu disponibilurile surselor corespunzătoare;
2. Dacă sunt mai multe destinații se introduce un nod suplimentar spre care "pleacă" câte un arc din fiecare destinație (și numai din acestea), iar capacitățile acestor arce vor fi egale cu necesarurile destinațiilor corespunzătoare;
Definiția 2: Se numește flux într-o rețea de transport R = (X,U) o funcție j: U ź R+ care are următoarele proprietățile:
P1. 0 £ ju £ cu oricare ar fi u din U; valoarea ju se numește flux al arcului u
P2. oricare ar fi i ¹ s,t (suma fluxurilor arcelor care "intră" într-un nod i este egală cu suma fluxurilor arcelor care "ies" din acest nod, cu excepția nodului inițial și al celui final.
Definiția 3: Se numește valoare a fluxului suma fluxurilor arcelor care "pleacă" din nodul inițial s și se notează cu F.
Observație: Se poate demonstra ușor că această valoare este egală și cu suma fluxurilor arcelor care "intră" în nodul final t. În concluzie avem:
F =
Valoarea fluxului reprezintă cantitatea care se transportă efectiv pe rețea de la surse la destinații.
Definiția 4: Se numește flux de valoare maximă într-o rețea un flux j în această rețea, cu proprietatea că, pentru orice alt flux j' pe această rețea, avem F ³ F'.
Valoarea fluxului de valoare maximă reprezintă cea mai mare cantitate care se poate transporta efectiv pe rețea, de la surse la destinații.
Economic vorbind, ne interesează, referitor la o rețea, răspunsurile la următoarele întrebări:
1. Putem transporta întreaga cantitate necesară la destinații?
2. Dacă da, cum transportăm efectiv această cantitate de la surse la destinații?
3. Dacă nu, din ce motiv nu putem realiza acest transport?
4. Cum putem înlătura cu eforturi minime acest motiv?
Răspunsul la primele două întrebări se poate afla prin găsirea fluxului de valoare maximă și compararea valorii lui cu suma necesarurilor destinațiilor. În plus, valoarea acestuia pe un arc reprezintă cantitatea care trebuie transportată pe ruta respectivă, pentru a obține această valoare a fluxului.
Răspunsul la ultimele două întrebări pornește de la observația că cea mai mare cantitate care poate traversa rețeaua de la un cap la altul este egală cu dimensiunea celui mai îngust loc de trecere prin rețea. Dacă vrem, deci, să mărim fluxul va trebui să lărgim tocmai acest cel mai îngust loc de traversare al rețelei.
Pentru formalizarea considerațiilor de mai sus vom introduce noțiunea de tăietură într-o rețea:
Definiția 5: Dată o rețea de transport G(X,U) cu s = nodul inițial și t = nodul final, se numește tăietură în rețea o partiție a mulțimii vârfurilor rețelei de transport, formată din două submulțimi V și W (VÇW = Æ, VÈW = X) astfel încât s Î V și t Î W.
O tăietură poate fi privită, intuitiv, ca o secțiune a rețelei, care lasă nodul inițial cu o submulțime din noduri într-o parte, nodul final cu restul nodurilor în cealaltă parte și retează toate arcele care trec dintr-o parte în cealaltă.
A cunoaște o tăietură este echivalent cu a cunoaște care sunt elementele celor două mulțimi, V și W, care formează partiția.
Vom nota o tăietură prin T = (V,W), convenind ca mulțimea scrisă pe prima poziție să conțină nodul inițial s al rețelei iar cea scrisă pe a doua, nodul final t.
Definiția 6: Se numește capacitate a unei tăieturi T = (V,W) într-o rețea de transport G(X,U), notată C(T), suma capacităților tuturor arcelor care au extremitatea inițială în V și cea finală în W.
C(T) =
Pentru a nu exista nici o ambiguitate, insistăm asupra faptului că se vor lua în considerare doar arcele care trec de la mulțimea ce conține nodul inițial spre mulțimea care conține nodul final, adică în sensul normal de transport (surse ź destinație).
Definiția 7: Se numește tăietură de valoare minimă într-o rețea o tăietură T în această rețea, cu proprietatea că, pentru orice altă tăietură T' în această rețea, avem C(T) £ C(T').
Următoarele teoreme fac legătura matematică dintre fluxurile unei rețele și tăieturile sale:
Teorema 1. Dată o tăietură T = (V,W) și un flux j într-o rețea de transport avem:
F =
sau, altfel spus, valoarea unui flux oarecare este egală cu suma fluxurilor arcelor care trec de la V la W din care se scade suma fluxurilor arcelor care trec invers, de la W la V, oricare ar fi tăietura T = (V,W).
Demonstrație: Avem succesiv:
F = = + =
= + - =
Corolar: Într-o rețea de transport valoarea oricărui flux este mai mică sau egală decât valoa-rea oricărei tăieturi.
Demonstrație: Fie T o tăietură oarecare și j un flux oarecare. Avem succesiv:
F = £ £ = C(T)
Corolar: Într-o rețea de transport valoarea fluxului maxim este mai mică sau egală decât valoarea tăieturii minime.
Demonstrația e evidentă. În plus, din cele de mai sus se vede că egalitatea are loc numai dacă, pentru tăietura minimă, există un flux pentru care toate arcele de la V la W sunt folosite la maxim (fluxul e egal cu capacitatea arcelor) iar pe toate arcele de la W la V nu se transportă nimic.
Teorema lui Ford-Fulkerson Dacă fluxul j este maximal atunci există o tăietură de capacitate egală cu valoarea fluxului.
Demonstrație: Fie j un flux maximal. Introducem următorul procedeu de marcare a vârfurilor:
Pasul 1. Se marchează nodul inițial s cu 0(zero);
Pasul 2. Pentru fiecare vârf marcat xi se marchează cu:
· [+xi] toate vârfurile nemarcate xj pentru care există arcul (xi,xj) și j(xi,xj) < c(xi,xj) (adica nodurile spre care mai e loc pentru a se transporta ceva din xi);
· [xi] toate vârfurile nemarcate xj pentru care există arcul (xj,xi) și j(xj,xi) > 0 (adică toate nodurile spre care pleacă deja ceva din xi);
Pasul 3. Se repetă pasul 2 până nu mai poate fi marcat nici un vârf.
Dacă vârful final t ar fi marcat, atunci începând de la acesta, am putea construi lanțul ,, ..., unde = s, = t și marcajul oricărui vârf este +sau . Adăugând la fluxul fiecărui arc al lanțului de tipul (,) valoarea:
D = min(,)
și scăzând din fluxul fiecărui arc de tipul (,) aceeași valoare D, obținem un flux de valoare F + D, deci fluxul j nu ar fi maximal.
În concluzie vârful t nu va fi marcat. Fie tăietura T = (V,W), unde V este formată din mulțimea nodurilor marcate iar W din cele nemarcate. În acest caz, pentru fiecare arc (xi,xj) care "traversează" tăietura avem:
- dacă xi Î V atunci j(xi,xj) = c(xi,xj) deoarece nodul xj nu e marcat
- dacă xi Î W atunci j(xi,xj) = 0 deoarece nodul xi nu e marcat
În acest caz avem:
C(T) = = = F
și teorema e demonstrată.
Teorema lui Ford-Fulkerson poate stabili doar valoarea fluxului maxim dar nu dă o metodă de găsire a acestuia. Pentru a rezolva problema găsirii fluxului de valoare maximă se poate folosi algoritmul lui Ford-Fulkerson.
Pentru expunerea acestuia vom introduce și noțiunile de:
arc saturat = un arc pe care fluxul este egal cu capacitatea;
drum complet = un drum de la nodul inițial s la nodul final t care conține cel puțin un arc saturat;
flux complet = un flux pentru care orice drum de la nodul inițial s la nodul final t este complet.
ETAPA I Se determină un flux complet.
Pasul 1. Se numerotează nodurile rețelei de transport astfel încât x1 = s și xn = t;
Pasul 2. Se asociază grafului fluxul nul (ju = 0 pentru orice arc u din graf);
Pasul 3. În ordine lexicografică, se ia pe rând fiecare drum D de la nodul inițial la cel final, se calculează valoarea DD = și se adaugă la fluxul de pe fiecare arc al drumului. Arcul(arcele) unui drum D pentru care s-a obținut valoarea minimă DD va fi după această adăugare, în mod evident, saturat și deci drumul D va fi complet.
După epuizarea tuturor drumurilor se obține un flux complet, de valoare F = . Deoarece alegerea drumurilor în ordine lexicografică nu ține cont de structura rețelei, așa cum se poate vedea pe un exemplu, acest procedeu nu asigură întotdeauna găsirea fluxului maxim. Acest impediment poate fi depășit fie prin găsirea unei ordini de parcurgere a tuturor drumurilor, care să dea pentru fiecare rețea fluxul maxim, în urma procedeului de mai sus, fie prin redistribuirea judicioasă a fluxului găsit la etapa I. A doua variantă este cea care se aplică la etapa II.
ETAPA II Se determină fluxul maxim
Pasul 4. Se marchează nodul inițial s cu 0(zero);
Pasul 5. Pentru fiecare vârf marcat xi se marchează cu:
· [+xi] toate vârfurile nemarcate xj pentru care există arcul (xi,xj) și j(xi,xj) < c(xi,xj) (adica nodurile spre care mai e loc pentru a se transporta ceva din xi);
· [xi] toate vârfurile nemarcate xj pentru care există arcul (xj,xi) și j(xj,xi) > 0 (adică toate nodurile spre care pleacă deja ceva din xi);
Pasul 6. Se repetă pasul 5 până este marcat nodul final sau până când nu mai poate fi marcat nici un vârf;
Pasul 7. Dacă nodul final a fost marcat atunci fluxul este maxim și algoritmul se oprește, în caz contrar trecându-se la pasul 8;
Pasul 8. Construim un lanțul L = ,, ..., unde = s, = t și marcajul oricărui vârf este +sau . Se calculează:
DL = min(,)
care se adaugă la fluxul fiecărui arc al lanțului de tipul (,) și se scade din fluxul fiecărui arc de tipul (,).
Pasul 9. Se șterge marcajul și se reia algoritmul de la pasul 4.
În final, tăietura de valoare minimă este cea în care V = mulțimea nodurilor marcate iar W = mulțimea nodurilor nemarcate.
Observația 1. Algoritmul nu asigură întotdeauna găsirea fluxului maxim, deoarece se poate ca creșterea fluxului la fiecare iterație să se facă cu cantități din ce în ce mai mici astfel încât suma lor să nu atingă niciodată marginea superioară dată de valoarea tăieturii minime, algoritmul având o infinitate de pași. Teorema de mai jos dă o condiție suficientă pentru ca algoritmul să se termine într-un număr finit de pași:
Teoremă Dacă toate capacitățile rutelor rețelei sunt numere raționale atunci algoritmul lui Ford-Fulkerson are un număr finit de pași.
Demonstrație Prin înmulțirea tuturor acestor capacități cu cel mai mic multiplu comun al numitorilor se obține o rețea cu toate capacitățile numere naturale. Ținând cont de formula de calcul, la fiecare iterație cantitatea adăugată D va fi număr natural și cum valoarea fluxului maxim este mărginită de capacitatea tăieturii minime Cmin, care este de asemenea număr natural, algoritmul va avea nevoie de cel mult Cmin pași pentru a o atinge.
Observația 2. Teorema de mai sus asigură doar o limitare superioară a numărului de iterații ale algoritmului, față de capacitatea tăieturii minime. Această valoare poate fi însă, în anumite cazuri, foarte mare și, dacă nu se iau precauții suplimentare, algoritmul nu va da soluția în timp util. Depășirea acestei situații este asigurată de următoarea teoremă:
Teoremă Dacă la fiecare iterație se alege drumul (lanțul) de lungime minimă atunci algoritmul va avea cel mult ŚmŚn iterații, unde n = numărul de noduri iar m = numărul de muchii.
Observația 3. Există probleme în care se dorește găsirea fluxului minim într-o rețea, valorile fluxului pe arce fiind limitate inferior de capacitățile acestora. În acest caz se aplică de asemenea algoritmul lui Ford-Fulkerson astfel:
Pasul 1. Se calculează M = maximul capacităților arcelor
Pasul 2. Se construiește rețeaua R', care este fosta rețea, în care au fost modificate doar capacitățile arcelor, acestea devenind = M cu
Pasul 3. Se găsește cu algoritmul Ford-Fulkerson fluxul j, de valoare maximă, în această rețea
Pasul 4. Fluxul de valoare minimă în rețeaua inițială va avea valorile j' = M j
Observația 4. Există și alte tipuri de probleme asemănătoare celor de mai sus. Astfel, se poate pune problema:
- găsirii capacităților minime ale arcelor cu care se poate asigura transportarea întregii cantități de la surse la destinații
- fluxului minim(maxim) într-o rețea în care capacitățile rutelor sunt limitate atât superior cât și inferior;
- În cazul în care rutelor li se asociază și costuri unitare de parcurgere, putem căuta fluxul maxim de cost minim;