670 likes | 993 Views
Grafi. Definizioni/1. Struttura dati per la rappresentazione di relazioni binarie G=(V,E), |V|=n, |E|=m V: insieme di Vertici E={(v i , v j ): v i , v j V} : insieme di Archi (v i , v j ) = (v j , v i ) = {v j , v i } Grafo semplice (v i , v j ) ≠ (v j , v i ) Grafo diretto.
E N D
Definizioni/1 • Struttura dati per la rappresentazione di relazioni binarie • G=(V,E), |V|=n, |E|=m • V: insieme di Vertici • E={(vi, vj): vi, vj V} : insieme di Archi • (vi, vj) = (vj, vi) = {vj, vi} Grafo semplice • (vi, vj) ≠ (vj, vi) Grafo diretto notazione impropria ASD - Grafi
Esempi • Relazioni di parentela • Alberi genealogici • Relazioni tra classi nei linguaggi OO • Grafo del Web • Assetti societari • Reti di trasporto • ................ ASD - Grafi
Definizioni/2 • Multigrafo: E è un multi-insieme • Pseudografo: E contiene anche coppie (vi, vi), dette cappi • Cammino (di lunghezza k) in un grafo:v1, v2,….., vk: (vi, vi+1) E • Circuito in un grafo: cammino con v1 = vk • Ciclo in un grafo: circuito con vi ≠ vj • Grafo pesato: valore reale wk associato ad ogni arco ek ASD - Grafi
Definizioni/3 • Kn: Grafo semplice con n nodi in cui sono presenti tutti gli archi, detto grafo completo • Numero di archi in Kn : n(n-1)/2 • G’ = (V’, E’) sottografo di G = (V, E) se e solo se V’ V ed E’ E • grado(v): #di archi incidenti in v • (vi, vj) E: vi adiacente a vj ASD - Grafi
Esempi di grafi: (a-d) grafi semplici; (c) un grafo completo K4; (e) un multigrafo; (f) uno pseudografo; (g) un circuito in un grafo orientato; (h) un ciclo nel grafo orientato ASD - Grafi
Rappresentazioni • Liste di adiacenza: ad ogni vertice è associata la lista dei vertici adiacenti • può essere una tabella o una lista concatenata • Matrice di adiacenza: aih = 1 se (vi, vh) E, aih = 0 altrimenti • Matrice di incidenza: aih = 1 se vieh, aih = 0 altrimenti ASD - Grafi
Rappresentazioni di grafi. Un grafo (a) rappresentato con una lista di adiacenze (b-c), ASD - Grafi
Rappresentazioni di grafi. Un grafo (a) rappresentato come una matrice di adiacenze (d) e come una matrice d’incidenza (e) ASD - Grafi
Vantaggi e Svantaggi • Lista di adiacenza: memoria O(m) Vantaggi: permette di scorrere i nodi adiacenti a v in O(grado(v)) Svantaggi: inserimenti e cancellazioni su liste concatenate in O(grado(v)) • Matrice di adiacenza: memoria O(n2) Vantaggi: Inserimenti e cancellazioni in O(1) Svantaggi: permette di scorrere i nodi adiacenti a v in O(n) • D.: matrice di incidenza ? ASD - Grafi
Visita di un Grafo • Obiettivo: visitare una sola volta tutti i nodi del grafo. • Es.: visitare un porzione del grafo del Web • Difficoltà: • Presenza di cicli: marcare i nodi visitati • Presenza di nodi isolati: la visita termina quando sono state considerate tutte le componenti isolate del grafo ASD - Grafi
Visita in profondità - DFS • La visita procede da ogni nodo finché tutti gli archi adiacenti non sono stati percorsi. • Se tutti i nodi adiacenti sono stati visitati allora si torna al nodo “predecessore”. • Una volta tornati al nodo di partenza si prosegue da un nodo qualsiasi non visitato. • I nodi vengono numerati secondo l’ordine di visita. ASD - Grafi
Esempio di applicazione dell’algoritmo depthFirstSearch ad un grafo ASD - Grafi
L’algoritmo depthFirstSearch applicato ad un grafo orientato ASD - Grafi
Implementazione della DFS/1 • I nodi sono inizialmente marcati con 0 • Si inizializza i=0 • Assumendo che la visita sia arrivata ad un nodo v, essa prosegue attraverso un nodo u adiacente a v, se marcato 0. • Se nessun nodo adiacente marcato 0 è disponibile si torna al nodo da cui si è raggiunto v, oppure si termina se v è il nodo iniziale. • Ogni volta che viene raggiunto un nodo mai visitato, questo viene marcato con i++ • Viene marcato sia l’inizio che la fine della visita di un nodo v, risp. num(v) e fin(v) ASD - Grafi
Implementazione della DFS/2 depthFirstSearch() { for (tutti i vertici v) num(v) = fin(v) = 0; /* Vedi slide seg. */ edges = {}; // insieme vuoto i = j = 1; /* per aggiornare num(v) e fin(v) */ /* main loop */ while (<esiste vertice v con num(v)=0>) DFS(v); <visualizza edges> } ASD - Grafi
Implementazione della DFS/3 DFS(v) { num(v) = i++; // num(v): prima volta che si visita v for (<tutti i vertici u adiacenti a v>) if (num(u) == 0) { edges = edges {(v, u)}; DFS(u); } fin(v) = j++; // fin(v): ultima volta che si visita v } ASD - Grafi
DFS iterativa • L’implementazione iterativa della DFS utilizza una pila per memorizzare gli archi uscenti da un nodo visitato. • Ad ogni passo si estrae l’arco (w,v) sulla cima della pila. • La visita prosegue su un nodo u adiacente a v (solo se marcato 0). • La numerazione fin(v) viene assegnata quando si estrae un arco (w,v) con num(w) < num(v) ASD - Grafi
DFS iterativa void iterativeDFS(v) { pila.push((v,v)); // arco fittizio while(!pila.isEmpty()) { (w,v) = pila.pop(); // arco w -> v if (num(v) == 0) { num(v) = i++; edges = edges {(w, v)}; pila.push((w,v)); // prepariamo la II marcatura for (<tutti i vertici u adiacenti a v>) if (num(u) == 0) pila.push((v, u)); } else if (fin(v) == 0) fin(v) = j++;//test inutile? } } ASD - Grafi
proprietà della DFS • l’algoritmo DFS visita l’intera componente del grafo raggiungibile dal nodo di partenza • se collezioniamo gli archi (edges) che portano alla scoperta di nuovi nodi, otteniamo una collezione di alberi che coprono l’intero grafo • un arco viene seguito solo se il nodo adiacente non è mai stato raggiunto. • gli archi seguiti connettono un nodo con marca inferiore ad un nodo con marca superiore (forward edges) • gli archi che non vengono seguiti al contrario connettono nodi con marca superiore a nodi con marca inferiore (back edges) ASD - Grafi
Complessità della DFS • O(n) per inizializzare marcatura dei nodi. • Test degli archi uscenti da un nodo v: • O(grado(v)) nella rappresentazione con lista di adiacenza. • O(n) nella rappresentazione con matrice di adiacenza. • Ogni arco viene testato al più due volte, una volta per ogni estremo • Complessivamente O(n + m), O(n2) (grafo denso) ASD - Grafi
Ordinamento parziale • Ordinamento parziale di un insieme A: relazione d'ordine parziale (transitiva) sugli elementi di A • possono esistere coppie tra le quali non è definito alcun ordine • Un grafo diretto aciclico (DAG) rappresenta un ordinamento parziale: l'insieme dei vertici è l'insieme A ed esiste un arco (u, v) sse u < v secondo l'ordine parziale • Se esiste un ciclo il grafo non può rappresentare un ordine parziale: perché? ASD - Grafi
esempio l'introduzione/eliminazione di archi transitivi non modifica l'ordine parziale descritto chiusura transitiva = aggiunta di tutti gli archi transitivi riduzione transitiva = eliminazione di tutti gli archi transitivi ASD - Grafi
Applicazione ordini parziali • Ereditarietà tra classi in linguaggi OO • Vincoli di precedenza in progetti complessi • Contenimento insiemistico • Studio di proprietà geometriche • ... ASD - Grafi
esempio slip orologio scarpe pantaloni calzini giacca camicia cintura cravatta ASD - Grafi
Ordinamento Topologico/1 • Un ordinamento topologico di un DAG è un ordinamento lineare dei suoi vertici che soddisfa la seguente condizione: per ogni arco (u, v) del grafo, u precede v nell’ordinamento • a ciascun vertice u si assegna un intero p(u) in modo tale che, se esiste l'arco (u, v), allora p(u) < p(v) • di conseguenza, se esiste un cammino da u a w, allora p(u) < p(w): ogni nodo nell’ordine è seguito da tutti i suoi successori • è sempre possibile determinare un ordinamento topologico di un DAG ASD - Grafi
Ordinamento Topologico/2 • In altre parole si vuole determinare un ordine totale consistente con l'ordine parziale (ce ne possono essere molti!) • spesso si usano algoritmi che determinano un ordinamento inverso all'ordinamento topologico • per semplicità, consideriamo anch'essi "topological sorter" • Un vertice pozzo è un vertice che non ha archi uscenti. In un DAG esiste sempre almeno un pozzo: perché? ASD - Grafi
Ordinamento Topologico/3 TopologicalSort() { for(i = 1; i <= n; i++) { <trova un vertice pozzo v> num(v) = i; <elimina dal DAG tutti gli archi incidenti in v> } } sfruttiamo la proprietà che un sottografo di un DAG è un DAG num(·) fornisce la numerazione cercata (inversa) ASD - Grafi
Ordinamento topologico: g,e,b,f,d,c,a ASD - Grafi
Ordinamento Topologico/4 • In pratica un ordinamento topologico (inverso) si ottiene se nella sequenza ogni nodo è seguito dai suoi predecessori (e da altri eventuali nodi) • Si esegue una DFS e si ordinano i vertici secondo il valore fin(v). • il valore fin(v) è inferiore a quello dei suoi predecessori • L’ordinamento topologico si ottiene dalla sequenza ordinata secondo fin(v) scandita in ordine inverso. Come si dimostra? ASD - Grafi
Ordinamento Topologico/5 TS(v) num(v) = i++; for(<tutti i vertici u adiacenti a v>) if (num(u) == 0) TS(u); else if (fin(u) == 0) errore; // identificato un ciclo /* siamo tornati ad u visitando i successori di u */ /* dopo avere esaminato tutti i predecessori, assegna a v un numero maggiore di quelli assegnati a qualsiasi predecessore */ fin(v) = j++; ASD - Grafi
Ordinamento Topologico/6 topologicalSorting(digraph) for(<tutti i vertici v>) num(v) = fin(v) = 0; i = j = 1; while (<esiste v tale che num(v) == 0>) TS(v); <Visualizza i vertici in ordine inverso secondo fin(v)> /* conviene "organizzarsi" in anticipo per non dover pagare il costo di un ordinamento */ ASD - Grafi
Connettività in Grafi diretti • Due nodi u,v sono connessi in un grafo orientato se esiste un cammino diretto che collega u a v. • Un grafo diretto è fortemente connesso se per ogni coppia u,v, esiste un cammino da u a v. • Un grafo è debolmente connesso se ogni coppia di nodi è connessa da un cammino quando gli archi orientati si sostituiscono con archi non orientati. ASD - Grafi
Componenti fortemente connesse - SCC/1 • Un grafo diretto può essere decomposto in componenti fortemente connesse, V1 , V2 ,… , Vk, tale che • V = V1 V2 ... Vk • u, v Vj: u connesso a v, v connesso ad u • Vj è un insieme massimale • Vi Vj = Ø • GT = (V, ET): (u, v) E (v, u) ET ASD - Grafi
SCC / 2 StronglyConnectedComponent(G) Esegui DFS(G) per calcolare fin(v) per ogni vertice v; Calcola GT; Calcola DFS(GT) considerando i nodi nel "main loop" in ordine decrescente secondo fin(v); Output ogni albero di DFS(GT) come una componente fortemente connessa separata ASD - Grafi
G GT a b c d a b c d 8/6 6/8 1/5 5/4 2 1 4 5 Esempio di esecuzione dell’algoritmo per SCC e f g h e f g h 7/7 3/1 2/3 4/2 3 7 6 8 num/fin num Radici Alberi DFS: b, c, g, h SCC: {a,b,e} {c,d} {f,g} {h} ASD - Grafi
Visita in ampiezza - BFS • La visita in ampiezza fa uso di una coda per memorizzare tutti gli archi incidenti nel nodo v visitato che portano ad un nodo marcato 0. • I nodi raggiungibili non marcati vengono quindi marcati. • La visita procede dall’arco (v,u) in testa alla coda. ASD - Grafi
Implementazione della BFS breadthFirstSearch() { for (tutti i vertici v) num(v) = 0; edges = {}; // empty set i = 1; while (<esiste vertice v tale che num(v) == 0>) { num(v) = i++; enqueue(v); while (<la coda non è vuota>) { v = dequeue(); for (<tutti i vertici u adiacenti a v>) if (num(u) == 0) { num(u) = i++; enqueue(u); edges = edges {(v, u)} } } } <visualizza edges> } ASD - Grafi
Un esempio di applicazione dell’algoritmo breadthFirstSearch ad un grafo ASD - Grafi
Applicazione dell’algoritmo breadthFirstSearch ad un grafo orientato ASD - Grafi
Il Problema dei Cammini Minimi • G=(V,E) è un grafo pesato sugli archi • d(u,v), (u,v) E: peso sull’arco (u,v) • Cammino dal nodo s al nodo t: v1, v2,….., vk: (vi, vi+1) E, v1= s, vk=t • Lunghezza del cammino: • Il cammino di lunghezza minima non contiene cicli ……se le distanze sugli archi sono positive. Come si dimostra? ASD - Grafi
Il problema dei Cammini Minimi/2 • Determinare il cammino di lunghezza minima • dal nodo s al nodo t • dal nodo s a tutti gli altri nodi V (SSSP) • tra tutte le coppie di nodi del grafo (APSP) • Numerose applicazioni: reti stradali, reti di comunicazione, scheduling di progetti, progetto di circuiti,…. ASD - Grafi
Single Source Shortest Paths/1 • Consideriamo un grafo pesato con pesi non negativi. • Determinare il cammino minimo da un nodo s a tutti i nodi V del grafo • Ogni sottocammino di un cammino minimo è esso stesso un cammino minimo. • Ex: s,…,i,…j,…,v: cammino minimo da s a v i,…,j è un cammino minimo da i a j. Come si dimostra? ASD - Grafi
Single Source Shortest Paths/2 • La collezione dei cammini minimi da s a tutti i nodi V forma un albero. Come si dimostra? • Algoritmi per SSSP mantengono ad ogni istante delle etichette sui nodi. • Etichette rappresentano delle approssimazioni delle distanze dalla sorgente. • Vi sono algoritmi che ad ogni passo fissano alcune etichette ai loro valori finali, ex Dijkstra. • Altri algoritmi, ex: Bellmann & Ford, possono modificare tutte le etichette lungo l’intera esecuzione dell’algoritmo. ASD - Grafi
Dijkstra/1 • Due insiemi di nodi Q ed R. • Inizialmente Q= {}, R={1,..,n} • Ad ogni passo estrai il nodo v in R con min dist(v) ed inserisci v in Q • Per ogni u adiacente a v aggiorna la distanza da s ad u attraverso nodi in Q: ASD - Grafi
Un’esecuzione diDijkstraAlgorithm ASD - Grafi
Dijkstra/2 • Ad ogni passo si determina la distanza minima di un nodo v in R. Il nodo viene inserito in Q. • Dijkstra termina in n passi. • Ad ogni passo occorre determinare il nodo v in R con minimo valore dist(v), O(log n) usando un heap per la coda di priorità. • Occorre poi eseguire il rilassamento per ogni adiacente u di v, O(grado(u)) vertici, ed eventualmente aggiornare la priorità. Complessivamente O(m log n) • Complessità di Dikstra O((n + m )log n). ASD - Grafi
Dijkstra/3 • Correttezza: Dimostrare che dist(v) è la distanza minima d(v) da v ad s quando v è incluso in Q. • Per assurdo, considera il primo nodo inserito in Q per cui • Esiste un cammino alternativo più breve che contiene almeno un nodo in R. • Sia v’ l’ultimo nodo in R sul cammino da v a s. • v’ è connesso ad s con un cammino formato di soli nodi in Q con dist(v’)<dist(v). • Una contraddizione poiché v’ sarebbe stato selezionato in luogo di v. ASD - Grafi
Dijkstra/4 DijkstraAlg(grafo digraph, vertice source) for tutti i vertici v dist(v)= ; dist(source)=0; R = tutti i vertici; while R!=0 v = vertice in R con minimo dist(v); for tutti i vertici u in R adiacenti a v if dist(u)>dist(u)+d(v,u) dist(u)= dist(u)+d(v,u; pred(u) = v; ASD - Grafi
Dijkstra/5 • La collezione dei pred(u) forma l’albero dei cammini minimi con sorgente s. • Si può risolvere il problema APSP eseguento n volte Dijkstra a partire da n sorgenti. Complessità:O(nlog n(m +n)). ASD - Grafi