ELEMENTE DE TEORIA GRAFURILOR

 

1.      Noțiuni generale

 

Î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(x) ³ .

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

 

Dacă privim graful ca imagine a unui sistem, nodurile reprezentând componentele sistemu­lui, atunci o interpretare imediată a unui arc (xi,xj) este că, componenta xi influențează direct componenta xj. Dacă nodurile au semnificația de stări posibile ale unui sistem atunci un arc (xi,xj) semnifică faptul că sistemul poate trece direct din starea xi în starea xj. În ambele cazuri se vede că avem de-a face doar cu informații despre legături directe; totuși, chiar dacă o componentă xi nu influențează direct componenta xj ea o poate influența prin intermediul altor componente, existând un șir de componente intermediare: x1 x2 ,..., xk, fiecare influențând-o direct pe următoarea și xi direct pe x1 iar xk direct pe xj. Astfel, dacă dintr-o stare xi nu se poate trece direct într-o stare xj s-ar putea totuși în mai multe etape, prin alte stări intermediare. Deoarece găsirea acestor influențe sau treceri posibile este de obicei foarte importantă iar pentru un sistem cu mii sau zeci de mii de componente acest lucru nu mai poate fi făcut "din ochi", este necesară formalizarea noțiunii de "influențe" și "treceri" posibile, nu neapărat directe. Acest lucru a și fost făcut mai sus, deoarece este evident că "xi influențează xj" sau "din starea xi se poate trece în starea xj" este echivalent cu existența în graf a unui drum de la nodul xi la nodul x­j.

În continuare vom da un algoritm prin care putem găsi toate drumurile dintr-un graf orientat cu un număr finit de noduri.

 

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țe­lor 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)n–2 = ŚA +ŚA2 + ŚA3 + ... + ŚAn–1 = 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)n–2+k = (A + A2 + ... + An-1) + An + An+1 + ... + An+k-1 = D = AŚ(A + I)n–2 Û

ÛAŚ(A + I)n–2+k = AŚ(A + I)n–2 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.

 

5.1. Noțiunea de arbore

 

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.

 

 A. Algoritmul lui Kruskal

 

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ă).

 

 

B. Algoritmul lui  Sollin

 

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.

 

 

C.  O variantă a algoritmului lui Kruskal

 

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.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Rezolvare

 

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.

 

A.   Algoritmul lui Foulkes

 

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 x­j 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.

 

 

 

C. Algoritmul lui Kaufmann

 

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(x­i,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 L­i+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.

 

 

D.  Algoritmul lui Dijkstra

 

Î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


9.  Rețele de transport

 

Într-o mare varietate de situații concrete din practica economică se pune problema deplasării unei cantități de materie, energie, informație etc, din anumite locuri, numite surse, în alte locuri, numite destinații. Pentru realizarea acestui transport se folosesc o serie de trasee, numite rute de legătură. Unitățile indivizibile ale cantității Q, care se deplasează de-a lungul rutelor între surse și destinații, se numesc unități de flux, iar ansamblul rutelor, surselor, destinațiilor și, eventual, a altor puncte intermediare se numește rețea de transport.

Situația de mai sus poate fi reprezentată geometric printr-un graf finit, conex și fără bucle.

Pentru ca o astfel de problemă să fie suficient de complexă pentru a necesita un studiu matematic riguros, trebuie ca fiecare sursă să poată aproviziona mai multe destinații și orice destinație să poată fi aprovizionată de mai multe surse.

Aprovizionarea destinațiilor se poate face direct de la surse sau prin intermediul altor puncte, numite puncte intermediare. În cazul cel mai general pot exista de asemenea legături între surse și/sau legături între destinații.

Așa cum s-a văzut și la problema de transport, situația de mai sus este un cadru extrem de larg, care permite existența unui număr foarte mare de tipuri de probleme posibile, diferite între ele prin informațiile suplimentare pe care le avem despre rețea și prin obiectivele urmărite.

Una dintre acestea este problema determinării cantității maxime (minime) care poate fi transportată de la surse la destinații, în situația în care sursele dispun de cantități limitate (inferior sau superior), destinațiile au un necesar sau o putere de absorbție limitată inferior sau superior iar pe fiecare rută se poate transporta doar o cantitate cuprinsă între anumite limite.

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 x­i);

·        [–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 x);

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 fie­că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.

 

Algoritmul lui Ford-Fulkerson

 

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 x­i);

·        [–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 x);

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;