• Non ci sono risultati.

cammini minimi da un vertice sorgente in un grafo orientato e pesato, senza cicli di peso negativo

N/A
N/A
Protected

Academic year: 2022

Condividi "cammini minimi da un vertice sorgente in un grafo orientato e pesato, senza cicli di peso negativo "

Copied!
24
0
0

Testo completo

(1)

Grafi (orientati): cammini minimi

Una presentazione alternativa (con ulteriori dettagli)

………..

(2)

Un algoritmo greedy per calcolare i

cammini minimi da un vertice sorgente in un grafo orientato e pesato, senza cicli di peso negativo

raggiungibili dal sorgente.

Definiamo “distanza” di un vertice u da un vertice v: δ(v, u), in un grafo orientato e pesato, il peso di un cammino di peso minimo tra tutti i cammini da v a u.

δ(v, u) = min {W(p) | p cammino da v a u}

dove W(p) è la somma dei pesi degli archi che formano il cammino.

N.B. δ(v, u) è ben definita solo se nessun cammino tra v e u contiene un ciclo di peso negativo

(3)

Per costruire un algoritmo greedy, dobbiamo individuare

l’ insieme di oggetti e definire per essi un grado di appetibilità.

Input: G = <V, E> grafo orientato e pesato,

w: E → R funzione peso, s ∈ V, G senza cicli di peso negativo raggiungibili da s

Output: ∀v ∈ V[G], l’attributo d[v] indica la “distanza” di v dal vertice sorgente: d[v] = δ(s, v)

Si può pensare ai vertici come agli oggetti tra i quali scegliere;

mantenendo per ogni vertice v, nell’attributo d[v] una stima (maggiore o uguale) della distanza di v da s.

Un vertice risulterà tanto più appetibile quanto minore è la stima della sua distanza dal sorgente stesso.

(4)

L’idea dell’algoritmo è la seguente:

Inizialmente si stima la distanza di ogni vertice da s uguale a ∞, tranne che per s stesso, di cui si conosce la distanza vera:

δ(s, s) = 0. Si definisce pertanto d[s] = 0

Si costruisce poi un albero, di radice s, in cui viene inserito un vertice per volta: il più appetibile.

L’albero è memorizzato implicitamente come l’insieme dei suoi archi < π[v], v>

Quando un vertice u è inserito nell’albero, si aggiornano le stime delle distanze dei vertici v ad esso adiacenti, in quanto potrebbe esitere un cammino da s a v, attraverso il vertice u, meno pesante del cammino da s a v considerato fino a quel momento.

(5)

Se il vertice sorgente è A, si ha inizialmente:

d[A] = 0, d[B] = d[C] = d[D] = d[E] = ∞ La strategia greedy sceglie percio’ il vertice A.

A B

D C

E 3 2

3 4

3 1

Da A sono raggiungibili con un arco i vertici B, C e D.

Si possono modificare pertanto le stime delle loro distanze da A.

d[B] = 3, d[C] = 2, d[D] = 4, mentre resta d[E] = ∞

Esempio

(6)

Scegliendo C si scopre il cammino A - C - D, ma d[D] non viene modificata in quanto il suo peso (5) è maggiore del peso del

cammino A - D (di peso 4).

A B

D C

E 3 2

3 4

3 1

La scelta è ora tra i vertici B, D ed E, con d[B] = 3, d[D] = 4, d[E] = ∞, e la stategia greedy impone di scegliere B.

Si scopre così il cammino A - B - E e diventa d[E] = 6.

La scelta di D permette infine di ottenere d[E] = 5, ed E sarà l’ultimo vertice scelto.

(7)

Usiamo il secondo schema greedy e scriviamo una prima approssimazione dell’algoritmo, dove S è l’insieme dei vertici già considerati:

Dijkstra (G, W, s) for ogni u ∈ V do

d[u] ← ∞ π[u] ← nil d[s] ← 0

S ← Φ

while S ≠ V[G] do

u ← “vertice con d minore tra quelli non ancora scelti”

S ← S ∪ {u}

for ogni v ∈ ADJ[u] do

if v ∉ S and d[v] > d[u] + W(u, v) then d[v] ← d[u] + W(u, v)

π[v] ← u

{valuta le appetibilità iniziali dei vertici}

{ci sono elementi da scegliere}

{scegli il vertice più appetibile}

{aggiorna le appetibilità dei vertici}

(8)

A B

D C

E 5 2

2 3

-3 1

Ad esempio:

Ma δ(A, E) = 2, mentre d[E] = 4

Se il vertice sorgente è A, dopo le opportune modifiche alle stime delle distanze, vengono scelti, nell’ordine:

A (quando: d[A] = 0, d[B] = d[C] = d[D] = d[E] = ∞) C (quando: d[B] = 5, d[C] = 2, d[D] = 3, d[E] = ∞) D (quando: d[B] = 5, d[D] = 3, d[E] = ∞)

E (quando: d[B] = 5, d[E] = 4) B (quando: d[B] = 5)

Non sempre la strategia funziona!

(9)

Riscriviamo l’algoritmo di Dijkstra aggiungendo come

precondizione la richiesta che la funzione peso non assuma valori negativi.

Nell’esempio considerato è facile capire che il non corretto comportamento è dovuto alla presenza dell’arco <B, E>, il cui peso è negativo.

Allora, se la strategia greedy funziona, essa funziona solo in assenza di archi di peso negativo.

{G = <V, E> grafo orientato e pesato & s∈V &

& W: E → ℜ+ ∪{0}}

(10)

Dijkstra (G, W, s) for ogni u ∈ V do

d[u] ← ∞ π[u] ← nil d[s] ← 0

S ← Φ

while S ≠ V[G] do

u ← “vertice con d minore tra quelli non ancora scelti”

S ← S ∪ {u}

for ogni v ∈ ADJ[u] do

if v ∉ S and d[v] > d[u] + W(u, v) then d[v] ← d[u] + W(u, v)

π[v] ← u

{G = <V, E> grafo orientato e pesato & s∈V &

& W: E → ℜ+ ∪{0}}

Usiamo una coda con priorità

(11)

Dijkstra (G, W, s)

for ogni u ∈ V do d[u] ← ∞ π[u] ← nil d[s] ← 0

S ← Φ

while S ≠ V[G] do

u ← “vertice con d minore tra quelli non ancora scelti”

S ← S ∪ {u}

for ogni v ∈ ADJ[u] do

if v ∉ S and d[v] > d[u] + W(u, v) then d[v] ← d[u] + W(u, v)

π[v] ← u Q ← V[G]

vertice con d minima Q ≠ Φ

v ∈ Q

Extract-min (Q)

{G = <V, E> grafo orientato e pesato & s∈V &

& W: E → ℜ +∪{0}}

(12)

Ricorda un altro algoritmo che conosciamo L’algoritmo di

PRIM

(13)

MST-Prim (G, W, r)

for ogni u ∈ Q do key[u] ← ∞ π[r] ← nil

key[r] ← 0 Q ← V[G]

while Q ≠ Φ do

u ← Extract-min(Q)

for ogni v ∈ Adj[u] do

if v ∈ Q e W(u, v) < key[v]

then key[v] ← W(u, v) π[v] ← u

MST-Prim (G, W, r)

for ogni u ∈ Q do key[u] ← ∞ π[u] ← nil key[r] ← 0

S ← Φ Q ← V[G]

while Q ≠ Φ do

u ← Extract-min(Q) S ← S ∪ {u}

for ogni v ∈ Adj[u] do

if v ∈ Q e W(u, v) < key[v]

then key[v] ← W(u, v) π[v] ← u

(14)

MST-Prim (G, W, r)

for ogni u ∈ Q do key[u] ← ∞ π[u] ← nil key[r] ← 0

S ← Φ Q ← V[G]

while Q ≠ Φ do

u ← Extract-min(Q) S ← S ∪ {u}

for ogni v ∈ Adj[u] do

if v ∈ Q e W(u, v) < key[v]

then key[v] ← W(u, v) π[v] ← u

Dijkstra (G, W, s)

for ogni u ∈ Q do d[u] ← ∞ π[u] ← nil d[r] ← 0

S ← Φ Q ← V[G]

while Q ≠ Φ do

u ← Extract-min(Q) S ← S ∪ {u}

for ogni v ∈ ADJ[u] do

if v ∈ Q and d[u] + W(u, v) < d[v]

then d[v] ← d[u] + W(u, v) π[v] ← u

(15)

La complessità dell’algoritmo di Dijkstra è pertanto la stessa dell’algoritmo di Prim:

• coda realizzata con heap binario:

O(E logV)

• coda realizzata con un heap di Fibonacci:

O(E + V logV)

Dobbiamo ancora dimostrare che l’algoritmo è corretto

(16)

Dijkstra (G, W, s)

for ogni u ∈ V do d[u] ← ∞ π[u] ← nil d[s] ← 0

Q ← V[G]

S ← Φ

while Q ≠ Φ do

u ← Extract-min (Q) S ← S ∪ {u}

for ogni v ∈ ADJ[u] do

if v ∈ Q and d[u] + W(u, v) < d[v]

then d[v] ← d[u] + W(u, v) π[v] ← u

{G = <V, E> grafo orientato e pesato & s∈V &

& W: E → ℜ+∪{0}}

{∀t ∈ V[G] : d[t] = δ(s, t)}

{∀t ∈ S: d[t] = δ(s, t) & S ∪ Q = V[G] & S ∩ Q = Φ}

(17)

Un sottocammino di un cammino minimo è minimo.

Proprietà 1.

Dimostazione.

Siano x e y due vertici qualunque in un cammino minimo p da u a v:

u x y v = p1 p2 p3 p =

W(p) = W(p1) + W(p2) + W(p3)

Se il sottocammino p2 da x a y non fosse minimo, ne esisterebbe un altro p2’ di peso inferiore. In tal caso il cammino p’ = p1 p2’ p3 sarebbe un cammino da u a v con W(p’) < W(p). Assurdo.

p1 p2 p3

(18)

Le seguenti asserzioni:

2.1 ∀v ∈ V[G]: v ∈ S ⇒ d[v] non viene modificata 2.2 ∀v ∈ Q: π[v] ≠ nil ⇒ π[v] ∈ S

2.3 ∀v ∈ V[G] - {s}: d[v] ≠ ∞ ⇔ π[v] ≠ nil

2.4 ∀v ∈ V[G] - {s}: d[v] ≠ ∞ ⇒ d[v] = d[π[v]] + W(π[v], v) sono invarianti del ciclo while.

Proprieta` 2.

u ← Extract-min (Q) S ← S ∪ {u}

for ogni v ∈ ADJ[u] do

if v ∈ Q and d[u] + W(u, v) < d[v]

then d[v] ← d[u] + W(u, v) π[v] ← u

Dimostrazione. Ovvia esaminando il corpo del while.

(19)

Proprieta` 3.

Dimostrazione.

(⇒) Supponiamo l’asserzione vera e dimostriamo che,

se per il vertice u estratto dalla coda d[u] ≠ ∞, il cammino esiste.

Per ipotesi induttiva esiste un cammino da s a π[u]. Allora il cammino da s a π[u] piu` l’arco < π[u], u>

costituisce un cammino da s a u.

La seguente asserzione:

∀v ∈ S: d[v] ≠ ∞ ⇔ esiste un cammino da s a v in G e` invariante del ciclo while.

(⇐) Se u viene estratto da Q con d[u] = ∞, allora (*) tutti i vertici t in Q hanno d[t] = ∞. Supponiamo che tra s e u vi sia almeno un cammino:

s → v1 → v2 → . . . → vk-1→ vk ≡ u.

Allora, tutti i vertici vi sul cammino devono avere d[vi] = ∞ (se vl avesse d[vl] ≠ ∞, allora per (*) vl∈ S, quindi anche vi+1 avrebbre d[vi+1] ≠ ∞).

Ma questo è assurdo perché d[s] = 0.

(20)

Dimostriamo ora che il predicato

Per ipotesi induttiva ∀t ∈ S: d[t] = δ(s, t).

∀t ∈ S: d[t] = δ(s, t) & S ∪ Q = V[G] & S ∩ Q = Φ è un invariante del ciclo while.

• Il predicato è vero all’inizio poichè S è vuoto e Q = V[G].

• Supponiamo che sia vero quando l’albero è stato costruito

parzialmente, e dimostriamo che per il nuovo vertice u estratto da Q, d[u] = δ(s, u).

s r

x

(21)

Sia u il vertice estratto da Q.

1. d[u] ≠ ∞

Sia π[u] = r (proprietà 2.3 ). Sappiamo allora (proprietà 2.2) che r ∈ S, cioè all’albero e che (proprietà 2.4) d[u] = d[r] + W(r, u).

Supponiamo che tra s e u esista un cammino di peso minore di d[u]; esso deve contenere un arco tra un vertice in S e uno in Q: <x, y>.

Si hanno due casi:

u

s r

x

y

(22)

W(s x y u) = W(s x y) + W(y u)

= d[y] + W(y u)

≥ d[y] (W(y u) ≥ 0 perchè la funzione peso non può assumere valori negativi)

≥ d[u] ( perchè u è il vertice estratto da Q) d[u] = δ(s, u)

Questo cammino tra s e u può allora essere visto come la concatenazione di tre cammini

s x y u

Se s x y u è minimo, anche s x y è minimo (proprietà 1), quindi d[y], che è il suo peso, è uguale a δ(s, y).

(23)

∀t ∈ (S {u}): d[t] = δ(s, t)

&

(S {u}) ∪ (Q - {u}) = V[G]

&

(S {u}) ∩ (Q - {u}) = Φ 2. d[u] = ∞

Se il vertice u viene estratto quando d[u] = ∞ allora non esiste nessun cammino tra s e u (proprietà 3), cioè

d[u] = ∞ = δ(s, u)

(24)

Riepilogo

• Algoritmo di Dijkstra per il calcolo di cammini

minimi a sorgente singola, in un grafo orientato senza pesi negativi.

• Relazione con l’algoritmo di Prim per il calcolo del

minimo albero ricoprente in un grafo non orientato.

Riferimenti

Documenti correlati

Dichiarazioni sulla insussistenza di cause di inconferibilità o incompatibilità' di incarichi presso le pubbliche amministrazioni del DIRETTORE

Partendo dal vertice C congiungi i punti in modo da formare il poligono CANE e coloralo di AZZURRO.. Quali sono i vertici

Prendo la variabile fuori base con coefficiente di costo ridotto pi` u piccolo (quindi la x 32 ) e aggiungo il relativo arco all’albero di supporto (vedi Figura 2). Non esistono

La base ´e ammissibile ma non ottima per il problema di I fase (vi sono coefficienti di costo ridotto positivi nella riga t).. Applicando le regole viste a lezione il cardine si

liste di adiacenza: una lista di tutti i nodi e, per ciascuno di essi, una lista dei nodi

Grafo particolare è quello &#34;euleriano&#34;, dal matematico Eulero, che nel 1736 lo utilizzò per risolvere il problema dei ponti di Königsberg: un cammino o percorso è detto di

Un albero ` e un grafo connesso in cui non ci sono cammini chiusi Quindi in un albero si pu` o andare da un vertice a un altro in un solo

Allora esiste una funzione lineare a z per cui ˆz