Sei sulla pagina 1di 8

Analisi e implementazione dell’algoritmo di Dijkstra (Parte 1)

Algoritmicamente August 1, 2009

http://algoritmicamente.wordpress.com/

1 Concetti fondamentali

Definizione 1

che connettono coppie di vertici distinti.

Un grafo `e un insieme di vertici pi`u un insieme di archi

Una definzione pi`u formale `e comunque necessaria in quanto all’interno di tale articolo essa sar`a spesso utilizzata:

Definizione 1.1

dove V `e l’insieme dei vertici ed E l’insieme degli archi .

Si dice grafo G una coppia ordina G=(V,E) di insiemi,

Definizione 1.2 Un vertice `e un punto terminale oppure un punto di intersezione di un grafo.

Definizione 1.3 Un arco `e una connessione tra due vertici. Esso viene indicato con la coppia ( i,j), dove i indica il vertice da cui parte l’arco (testa) e j indica il vertice in cui arriva (coda).

Per dare un’idea pi`u concreta di un grafo, viene mostrato un esempio di esso:

indica il vertice in cui arriva (coda). Per dare un’idea pi`u concreta di un grafo, viene

1

Come si pu`o notare l’insieme dei vertici V = { v 1 , v 2 , v 3 , v 4 , v 5 , v 6 } mentre l’insieme degli archi `e dato da tutte le coppie di vertici che vengono connessi tra loro, in questo caso:

G = {{v 1 , v 2 } , {v 1 , v 4 } , { v 1 , v 6 } , {v 3 , v 6 } , { v 5 , v 2 } , { v 5 , v 6 } , {v 2 , v 4 } , { v 4 , v 6 } , {v 5 , v 6 }}. Spesso (come nel caso trattato) ad ogni vertice o ad ogni arco viene associato un peso ossia un valore numerico che indica la distanza che intercor re da due vertici. Tale tipo di grafo prende il nome di grafo pesato del quale viene data una definizione pi`u formale.

Definizione 1.4 Un grafo pesato G `e definito come una terna G = ( V,E,P ). Dove V ed E indicano il grafo G’ = ( V,E ) e P indica una generica funzione che ad ogni vertice o ad ogni arco associa un valore numerico n ǫ [−∞, + ].

Definizione 1.5 Un cammino (p) in un grafo `e una sequenza di vertici nei quali ogni vertice successivo `e adiacente al precedent e nel cammino. Definizione 1.5.1 Un cammino semplice , `e un cammino dove tutti i vertici sono distinti. Definizione 1.5.2 Un ciclo `e un cammino semplice, eccetto che il vertice iniziale e finale rimangono invariati.

che il vertice iniziale e finale rimangono invariati. fig. 2 Grafo pesato fig. 3 Possibile cammino

fig. 2 Grafo pesato

iniziale e finale rimangono invariati. fig. 2 Grafo pesato fig. 3 Possibile cammino di un grafo

fig. 3 Possibile cammino di un grafo

Nella figura 3 `e possibile vedere il cammino p = {v 1 , v 2 , v 5 , v 3 , v 6 }

2 Cammini minimi

L’analisi dei cammini minimi `e il cuore di tale articolo, infatti l’algorito di Dijk- stra ha come scopo quello di trovare il cammino minimo all’interno di un grafo. Prima di tutto bisogna far chiarimento su cosa sia un cammino minimo

, v n }

il peso di un cammino ω (p ) `e la somma dei pesi degli archi che compongono

Definizione 2 Dato un grafo G=( V,E,P ) ed un cammino p = {v 1 , v 2 ,

tale cammino.

2

Dalla figura risulta che il peso del cammino in rosso `e dato da :

ω (p ) = (1 + 5 + 21 + 3) = 30. Detto ci`o `e possibile ora definire il cammino minimo di un generico grafo G.

Definizione 2.1 Dato un grafo G = ( V,E,P ) il cammino minimo di tale grafo `e il pi`u piccolo dei ω (p n ), dove p i 1 i n `e un generico cammino del grafo G.

Grazie a tale definizione appare pi`u chiaro lo scopo dell’algoritmo di Dijkstra, infatti mediante esso possiamo trovare IL cammino minimo all’interno di un grafo pesato G. Seguono dunque alcuni esempi per mostrare il cammino minimo all’interno di un grafo:

per mostrare il cammino minimo all’interno di un grafo: fig. 4 Cammino minimo corretto fig. 5

fig.

4 Cammino minimo corretto

all’interno di un grafo: fig. 4 Cammino minimo corretto fig. 5 Cammino minimo scorretto Come si

fig. 5 Cammino minimo scorretto

Come si pu`o dunque notare dalle due figure, il cammino minimo (per arrivare

dal vertice 1 al vertice 3) non `e quello “ pi`u breve” cio`e quello che percorre meno archi, ma, come detto nella definizione, `e quello la cui somma dei pesi degli archi

`e minima.

Tale problema non `e banale in quanto vi `e un’importante osservazione da fare:

Come si pu`o notare in entrambe le figure (fig.4, fig5) il cammino minimo non

inizia affatto con l’arco di peso minore, anzi, in questo caso il cammino minimo

`e

quello che ha come arco di partenza, quello con il peso magg iore (gli altri sono

E

1 = { v 1 , v 6 } il quale ha peso 2, e E 2 = {v 1 , v 4 } il quale ha peso 1). Ci`o ci da la

dimostrazione che il cammino minimo `e dato da una somma, e in quanto somma si deve tener conto degli addendi che la compongono (in questo caso i pesi). In- oltre, dalla definizione 1.4 si evince che i pesi possono anche essere negativi, dunque per quanto possa essere grande il peso del primo arco di un percorso, il peso di un cammino potr`a essere “ diminuito” a causa di un cammino di valore negativo .

3

3 Algoritmo di Dijkstra

L’algoritmo di Dijkstra permette di poter calcolare i cammini minimi all’interno

di

un grafo, la forza di tale algoritmo `e la semplicit`a del codice e soprattutto

la

sua efficienza, infatti la complessit`a nel caso peggiore di tale algoritmo `e :

O(|E |+ |V|log |V |) . Esso possiede inoltre delle propriet`a particolari :

Propriet`a 3 L’algoritmo di Dijkstra risolve i problemi di cammino min- imo,da un vertice di partenza ad un vertice di arrivo, nei grafi che non hanno pesi negativi.

Propriet`a 3.1 Con L’algoritmo di Dijkstra possiano trovare ogni SPT in una grafo denso in un tempo lineare.

La propriet`a 3.1 viene data solo a scopo informativo, non `e interesse di tale

articolo trattare argomenti non inerenti con l’analisi di tale algoritmo, mentre

la propriet`a 3 pu`o essere dimostrata, tale dimostrazione verr`a trattata in se-

guito.

Il funzionamento `e molto semplice, dato un grafo e un vertice di partenza,

l’algoritmo mostra tutti i cammini minimi per raggiungere g li altri nodi, per poter meglio comprendere tale algoritmo viene mostrato inizialmente il suo pseu- docodice completo.

function Dijkstra(Graph, source ):

for each vertex v in Graph :

dist[v ] := infinity previous[v ] := undefined dist[source ] := 0 Q := the set of all nodes in Graph while Q is not empty:

u := vertex in Q with smallest dist[] 8

if dist[u ] = infinity:9

break 10 remove u from Q 11 for each neighbor v of u : 12 alt := dist[u ] + dist between(u, v ) 13

if alt < dist[v ]: 14

dist[v ] := alt 15 previous[v ] := u 16 return previous

La I riga non `e altro che il prototipo della funzione, la quale (come gi`a detto) accetta in input un grafo e un vertice sorgente. Possiamo dividere tale algoritmo in due parti, l’inizializzazione del grafo dato

in input, e l’algoritmo vero e proprio.

4

Per quanto riguarda l’inizializzazione, essa `e effettuata dalle righe 2,3,4,5,6 nelle quali vengono effettuate le inizializzazioni per tutti i nodi, pi`u nello specifico,

le righe 3,4 settano le distanze dal vertice sorgente agli altri nodi a , la riga

5 setta la distanza del vertice sorgente a 0, e infine la riga 6 c rea l’insieme Q il quale contiene tutti i nodi del grafo dato in input. Per chiarire meglio quanto mostriamo un esempio.

in input. Per chiarire meglio quanto mostriamo un esempio. fig. 6 Grafo dato in input fig.

fig. 6 Grafo dato in input

quanto mostriamo un esempio. fig. 6 Grafo dato in input fig. 7 Grafo inzializzato L’esempio mostrato

fig. 7 Grafo inzializzato

L’esempio mostrato accetta in input il grafo di fig. 6 e si prende come ver- tice sorgente v1. Le righe 3,4, come gi`a detto, settano le distanze di tutti i vertici al vertice sorgente ad , tale distanza viene indicata ponendo vicino al

vertice interessato il suo valore, mentre la riga 5 setta la distanza del vertice sorgente a 0. Infine vi `e la riga 6, la quale crea l’insieme di tutti i vertici del grafo Q, nel caso dai noi analizzato, al momento dell’inizia lizzazione, l’insieme

Q = { v 1 , v 2 , v 3 , v 4 , v 5 , v 6 } .

La seconda parte dell’algoritmo analizza il grafo per estra rne i cammini minimi, essa va dalla riga 7 alla riga 16. Possiamo subito notare che essa `e composta da un ciclo princ ipale (while Q is not empty:) dal quale poi si diramano gli altri cicli, tale ciclo termina ovvia- mente quanto l’insieme Q `e vuoto. La riga 8 prende dall’insieme Q il vertice che ha distanza minore, poiche tutti

i vertici eccetto v 1 hanno distanza infinita, verr`a selezionato v 1 dall’insieme Q. La riga 9 consiste in un if, il quale in tal caso non verr`a preso in considerazione

in quanto dist[v 1 ] = 0 = . La riga 11 eliminer`a in vertice v 1 dall’insieme Q

il quale ora diventer`a Q = {v 2 , v 3 , v 4 , v 5 , v 6 } . La riga 12 da origine ad un altro ciclo, il quale analizza i pesi degli archi che connettono i vertici, tale ciclo prende

in analisi tutti i vertici che sono collegati direttamente a v 1 e ne analizza il peso

degli archi che li uniscono, viene quindi preso in considera zione v 2 il quale ha una distanza (peso dell’arco) 3 con v 1 , a tal proposito nella riga 13 viene creata

una variabile temporale alt la quale sommer`a il peso dell’a rco che unisce i vertici con la distanza del vertice preso in considerazione poich`e la distanza {v 1 v, 2 } =

3, e poich`e v 1 ha in origine distanza = 0, alt = 0 + 3 = 3. Una volta calcolata

tale distanza, se tale distanza `e minore di quella presente nel vertice vicino a

5

v 1 (riga 14) cio`e la distanza di v 2 allora il vertice v 2 assume distanza uguale ad alt (riga 15), dunque poiche alt < v 2 = , allora v 2 = alt = 3, nella riga 16 viene creato un array nel quale viene aggiunto il vertice v 2 e cos`ı via per gli altri vertici vicino ad v . Per chiarire le idee viene dato un esempio pratico di quanto detto.

le idee viene dato un esempio pratico di quanto detto. fig. 8 v1 viene preso dall’insieme

fig. 8 v1 viene preso dall’insieme Q

di quanto detto. fig. 8 v1 viene preso dall’insieme Q fig. 9 uno dei “vicini” di

fig. 9 uno dei “vicini” di v 1 viene selezionato

Viene selezionato v 1 perch`e dell’insieme Q esso `e quello che ha come distanza minore (8) e viene tolto dall’insieme Q (11), viene poi selez ionato un vicino di v 1 (12), in questo caso v 2 , e poich`e 0+3 = 3 < (13,14), la sua distanza viene posta uguale a 3 (15), viene aggiunto v 2 all’array previous. Poiche v 1 ha ancora altri “ vicini ”, vengono selezionati anch’essi nel for dunque avremo:

vengono selezionati anch’essi nel for dunque avremo: fig. 10 Completamente del ciclo for Anche gli altri

fig. 10 Completamente del ciclo for

Anche gli altri vertici vicini a v 1 vengono selezionati e viene calcolata la distanza mediante l’analisi dei pesi degli archi che li uniscono. Una volta effettuata tale operazione, il processo inizia nuovamente, il ciclo while

6

esegue un’altra iterazione e si passa alla linea 8, la quale s cegliera il vertice con

la distanza pi`u piccolo all’interno dell’insieme Q, `e da r icordare che la linea 11

aveva modificato il contenuto di Q, dunque ora verr`a selezio nato come vertice

da analizzare, v 4 , poich`e esso ha la distanza minore tra tutti i vertici di Q. Le linee 9,10 anche in questo caso non vengono prese in cosidera zione poich`e v 4

= 1 = , dunque la linea 11 eliminera l’elemento v 4 dall’insieme Q, il quale

ora risulta essere composto da Q = {v 2 , v 3 , v 5 , v 6 }. Una volta effettuata tale operazione si entra nel ciclo for, il quale andra ad analizzare (come gi`a visto per v 1 ) tutti i vertici ad esso collegati, nell’esempio mostrato l’unico ad essere vicino a v 4 `e v 6 , la riga 13 crea la variabile alt = 1 + 13 = 14, la riga 14 indica che se la distanza di v 6 > alt allora tale distanza deve essere sovrascritta con il valore di alt , dunque poich`e 30 > 14 ne segue che il valore delle distanza di v 6 , viene settato a 14 (riga 15), infine la riga 16 aggiunge all’a rray il vertice v 4 , il quale conter`a ora previous[] = {v 1 , v 4 } , viene mostrato graficamente quanto descritto.

v 4 } , viene mostrato graficamente quanto descritto. fig. 11 v 4 `e il vertice

fig. 11 v 4 `e il vertice con distanza minore

fig. 11 v 4 `e il vertice con distanza minore fig. 12 viene calcolata la distanza

fig. 12 viene calcolata la distanza di v 6

Come si pu`o notare dalla fig. 11 tra tutti i vertici, v 4 `e quello con distanza minore, e poich`e esso ha come unico vicino v 6 , verr`a calcolata la sua distanza basandosi sul peso dell’arco che li unisce, poiche tale distanza `e uguale a 14, mentre la distanza precedente `e uguale a 30, tale distanza v iene aggiornata mettendo il valore minore dei due.

Tale processo continua per tutti i vertici rimanenti fino a quando essi non ver- ranno esaminati tutti, cio`e quando l’insieme Q che contiene tutti i vertici `e vuolo

Q = { φ} . Alla fine di tale processo il grafo apparir`a come in figura.

7

fig. 13 fine dell’algoritmo con le distanza minime 8

fig. 13 fine dell’algoritmo con le distanza minime

8