Capitolo 13 Grafi e modelli su grafi In questo capitolo introduciamo la nozione di grafo ed alcune definizioni ad essa collegate. I grafi sono una struttura matematica molto usata nelle applicazioni e si prestano a rappresentare problemi apparentemente molto diversi tra di loro con un linguaggio semplice ed unificato. Questo spiega la loro importanza nella matematica applicata e, in particolare, nella Ricerca Operativa. 13.1 Definizioni fondamentali Un grafo non orientato G = (V, E) è definito da un insieme finito V (G) = {v1 , . . . , vn } di elementi detti nodi o vertici e da un insieme E(G) = {e1 , . . . , em } ⊆ V × V di coppie non ordinate di nodi dette archi o spigoli. Dato l’arco e = (v, w) = (w, v), i nodi v e w sono detti estremi di e, e si dice che l’arco e incide su u e v. Una comoda rappresentazione del grafo viene mostrata in figura 13.1a. I nodi sono rappresentati da cerchi, mentre gli archi sono tratti di curva congiungenti i due estremi. Per il grafo G = (V, E) rappresentato in figura si ha V = {v1 , v2 , v3 , v4 , v5 } E = {e1 , e2 , e3 , e4 , e5 , e6 } = {(v1 , v2 ), (v2 , v3 ), (v1 , v5 ), (v3 , v5 ), (v3 , v4 ), (v4 , v5 )}. Se gli estremi di un arco coincidono, l’arco è detto loop (Fig. 13.1b). I grafi di cui ci occuperemo nel seguito non conterranno loop, a meno che non sia altrimenti specificato. Due nodi u, v sono detti adiacenti (reciprocamente) se l’arco (u, v) appartiene ad E. Nella figura sono adiacenti, per esempio, i nodi v1 e v2 . Due archi sono detti adiacenti se hanno un estremo in comune, come gli archi e2 ed e4 in figura. Si definisce intorno di un nodo v in G, indicato con ω(v), l’insieme dei nodi adiacenti a v. Nella figura ω(v5 ) = {v1 , v3 , v4 }. Un nodo v si dice isolato se ω(v) = ∅. Si definisce stella di v in G, indicata con δ(v), l’insieme degli archi incidenti su v. Nella figura δ(v5 ) = {e3 , e4 , e6 }. Si definisce sottografo di G = (V, E) un grafo H = (W, F ) tale che W ⊆ V e F ⊆ E. Si definisce sottografo indotto da W ⊆ V in G = (V, E) il grafo H = (W, F ), ove l’insieme degli archi F è tale che l’arco (u, v) appartiene a F se e solo se: (u, v) ∈ W e (u, v) ∈ E. Informalmente possiamo dire che il sottografo H eredita tutti gli archi di G i cui estremi sono entrambi contenuti nel sottoinsieme W . In figura 13.2 vengono mostrati due sottografi del grafo 179 v2 v3 e2 e5 e1 e6 e3 v1 e v4 e4 v v5 b) a) Figura 13.1: a) Grafo non-orientato b) Loop di figura 13.1. Il primo non è un sottografo indotto (”manca” l’arco e4 ), mentre il secondo è indotto in G dall’insieme di nodi {v2 , v3 , v4 , v5 }. v2 e2 v3 v2 v3 e2 e5 v1 v4 e4 e1 e3 e6 v5 v5 b) a) Figura 13.2: a) Sottografo b) Sottografo indotto Un grafo orientato G = (V, E) è definito da un insieme finito V (G) = {v1 , . . . , vn } di elementi detti nodi e da un insieme E(G) = {e1 , . . . , em } ⊆ V × V di coppie ordinate di nodi dette archi. L’arco e = (v, u), si dice orientato dal nodo v al nodo u. I nodi v e u sono detti estremi di e, e si dice che l’arco e incide su v e u. Notiamo che a differenza del caso non orientato, l’arco (v, u) è distinto dall’arco (u, v). Una rappresentazione del grafo orientato viene mostrata in figura 13.3. L’unica differenza con la rappresentazione del grafo non orientato sta nella presenza sull’arco di una freccia che indica l’orientamento dell’arco stesso. Analogamente al caso non-orientato, si definisce stella di v in G, indicata con δ(v), l’insieme degli archi incidenti su v. In figura 13.3, ω(v1 ) = {e1 , e2 , e5 }. La stella δ(v) può essere partizionata in stella entrante δ e (v), cioè l’insieme degli archi entranti in v, e in stella uscente δ u (v), l’insieme degli archi uscenti da v. Nell’esempio, δ e (v1 ) = {e2 }, mentre δ u (v1 ) = {e1 , e5 }. Analogamente l’intorno ω(v) può essere partizionato in ω e (v) = {w : (w, v) ∈ δ e (v)} e ω u (v) = {w : (w, v) ∈ δ u (v)}. Sottografi e sottografi indotti sono definiti come per il caso non orientato. 180 v2 v3 e3 e6 testa v4 e2 e1 v1 v e4 v5 e5 coda u b) a) Figura 13.3: a) Grafo orientato b) Arco orientato Cammini, Cammini Orientati, Cicli. Dato un grafo G = (V, E) (indifferentemente orientato o non orientato), ove V = {v1 , . . . , vn } e E = {e1 , . . . , em } diremo cammino in (di) G, un insieme ordinato P = {vj0 , eh1 , vj1 , eh2 , . . . , vjp−1 , ehp , vjp } con: jk ∈ {1, . . . , n}, hi ∈ {1, . . . , m}, per k = 0, . . . , p e i = 1, . . . , p, e con l’arco ehi incidente sui nodi vji−1 e vji .1 Notiamo che nel caso del grafo orientato, l’orientamento degli archi del cammino è indifferente. Si richiede semplicemente che l’arco ehi incida sui nodi vji−1 e vji . I nodi vj0 e vjp sono detti estremi del cammino P . Un cammino è detto semplice se gli archi e i nodi che lo definiscono sono tutti distinti. v2 e2 v2 v3 e3 v3 e5 v1 e2 v4 e1 e3 v1 v5 e5 v5 b) a) Figura 13.4: Cammini semplici In figura 13.4a è mostrato un cammino semplice del grafo non orientato di figura 13.1, P = {v5 , e3 , v1 , e1 , v2 , e2 , v3 , e5 , v4 }, mentre in figura 13.4b è mostrato il cammino semplice del grafo orientato di figura 13.3, P = {v5 , e5 , v1 , e2 , v2 , e3 , v3 }. In figura 13.5a è mostrato il cammino (non semplice) del grafo non orientato di figura 13.1, P = {v1 , e1 , v2 , e2 , v3 , e5 , v4 , e6 , v5 , e4 , v3 , e5 , v4 }. Notiamo che se in un grafo esiste un cammino fra i nodi u e v, esisterà un cammino semplice fra u e v. 1 Spesso, quando non c’è possibilità di ambiguità, un cammino viene indicato indicando la sequenza dei soli nodi o quella dei soli archi 181 In un grafo orientato, chiameremo cammino orientato un cammino P = {vj0 , eh1 , vj1 , . . . , ehp , vjp } tale che ehi = (vji−1 , vji ). Nel cammino orientato è dunque importante anche l’orientamento degli archi. In figura 13.5b è mostrato il cammino orientato del grafo orientato di figura 13.3, P = {v1 , e1 , v2 , e3 , v3 , e4 , v5 }. Se u e v sono, rispettivamente, il primo e l’ultimo nodo di un cammino orientato P , si dirà che P va da u a v.2 v2 v3 e2 v2 v3 e5 v3 e5 e1 e3 e4 v4 v4 e4 e1 e6 v5 v1 v5 v1 a) b) Figura 13.5: a) Cammino (non semplice) b) Cammino orientato Un cammino è detto chiuso se i suoi estremi coincidono. Definiremo ciclo un cammino chiuso C = {vj0 , eh1 , vj1 , . . . , vhp−1 , vhp−1 , ehp , vj0 }, tale che {vj0 , eh1 , vj1 , . . . , ehp−1 , vhp−1 } è un cammino semplice. Il cammino chiuso P = {v1 , e1 , v2 , e2 , v3 , e3 , v4 , e4 , v2 , e5 , v5 , e6 , v1 } di figura 13.6a non è un ciclo perchè il cammino P = {v1 , e1 , v2 , e2 , v3 , e3 , v4 , e4 , v2 , e5 , v5 } non è semplice (il nodo v2 è contenuto due volte). In figura 13.6b è mostrato un ciclo. Notiamo che ancora una volta l’orientamento degli archi nei grafi orientati è indifferente. Per i grafi orientati si definisce ciclo orientato un camino orientato chiuso C = {vj0 , eh1 , vj1 , . . . , ehp−1 , vhp−1 , ehp , vj0 }, tale che {vj0 , eh1 , vj1 , . . . , ehp−1 , vhp−1 } è un cammino orientato semplice (Fig. 13.6c) e6 v1 v5 e5 e1 e4 v2 v4 e2 e3 v3 a) b) Figura 13.6: a) Cammino chiuso b) Ciclo 2 c) c) Ciclo orientato Spesso, quando si tratta di grafi orientati e non ci sia possibilità di ambiguità, si indica col nome di cammino quello che più propriamente dovrebbe essere chiamato cammino orientato 182 Alberi. Dato un grafo G = (V, E) (orientato o non orientato), un nodo v ∈ V si dice connesso a un nodo u ∈ V se esiste un cammino (non necessariamente orientato) tra v e u. Un grafo (orientato o non orientato) è detto aciclico se non contiene cicli (non necessariamente orientati) come sottografi. Si dice albero un grafo aciclico e connesso. Ogni grafo aciclico è l’unione di uno o più alberi e viene detto foresta. In figura 13.7a è mostrato un albero, in figura 13.7b una foresta. v1 v1 v6 v2 v3 v2 v3 v5 v4 v5 v6 v4 v7 a) b) Figura 13.7: a) Albero b) Foresta Grafi bipartiti Un grafo G = (V, E) non orientato è detto bipartito se è possibile trovare una partizione V1 , V2 dei suoi nodi 3 tale che gli estremi di ogni arco appartengono uno a V1 e uno a V2 . Nella figura 13.8 è riportato un esempio di grafo bipartito. Figura 13.8: Grafo bipartito Spesso un grafo bipartito viene indicato, mettendo in evidenza la partizione dell’insieme dei nodi, come G = (V1 , V2 , E). 3 Deve risultare, cioè, V1 ∪ V2 = V e V1 ∩ V2 = ∅ 183 13.2 Rappresentazioni di un grafo Un grafo G(V,E) può essere rappresentato in molti modi diversi. Nelle pagine precedenti abbiamo gia incontrato due modi diversi: la rappresentazione estensiva e quella grafica. Nella rappresentazione estensiva vengono elencati tutti gli elementi dell’insieme V e tutti quelli dell’insieme E, nella rappresentazione grafica, invece, il grafo viene rappresentato mediante un disegno in cui ai nodi si fanno corrispondere piccoli cerchi e agli archi tratti di curva congiungenti i cerchi. Già da questi due esempi si capisce che, benché concettualmente equivalenti, questi modi diversi di rappresentare un grafo possano avere caratteristiche molto differenti. Per esempio, la rappresentazione grafica è molto immediata e ci dà subito una visione intuitiva delle caratteristiche del grafo, e molta della terminologia introdotta finora è ispirata proprio dalla rappresentazione grafica. Tuttavia, se, come spesso accade nella pratica, il grafo ha moltissimi nodi (per esempio migliaia) si capisce subito che la rappresentazione grafica non è più di pratica utilità. Allora è utile avere a disposizione diversi modi di rappresentare un grafo. La decisione di scegliere una rappresentazione piuttosto che un’altra andrà poi fatta di volta in volta in base al problema che si vuole risolvere, alle dimensioni del grafo, alle sue caratteristiche etc. Nel seguito consideriamo la rappresentazione di un grafo tramite la matrice di incidenza. Tale rappresentazione è preferibile in alcune applicazioni della Ricerca Operativa per la sua corrispondenza ad alcune formulazioni standard di modelli di ottimizzazione e la conseguente maggior facilità di analisi del modello. La matrice di incidenza è una matrice n × m. La matrice ha quindi un numero di righe pari al numero di nodi e un numero di colonne pari al numero di archi. Nel caso di grafi non orientati, il generico elemento ai,j della matrice sarà ½ aij = 1 se arco j incide su nodo i 0 altrimenti Nel caso di grafi orientati, il generico elemento ai,j della matrice sarà pari a −1 se l’arco j-esimo esce dal nodo i, sarà pari a 1 se l’arco j-esimo entra nel nodo i, sarà pari a 0 se l’arco j-esimo non incide sul nodo i, ovvero −1 se arco j esce dal nodo i 1 se arco j entra nel nodo i 0 altrimenti Nella matrice di incidenza ogni colonna ha esattamente due elementi diversi da zero; essi sono in corrispondenza delle due righe della matrice relative ai due nodi estremi dell’arco. aij = Osservazione 13.2.1 La matrice di incidenza di un grafo orientato è totalmente unimodulare. Infatti la condizione del Teorema 12.4.6 è soddisfatta ponendo tutti gli indici di riga in uno dei due insiemi (ad es. Q1 = {1, . . . , n}, Q2 = ∅). Esercizio 13.2.2 Dato il grafo G mostrato in Figura 13.9, scrivere la corrispondente matrice d’incidenza nodi-archi. Soluzione. 184 4 2 5 7 1 6 3 Figura 13.9: Esercizio 13.2.2 Per scrivere la matrice d’incidenza nodi-archi, dobbiamo innanzitutto numerare arbitrariamente gli archi. In particolare, scegliamo e1 = (1, 2), e2 = (1, 3), e3 = (2, 4), e4 = (2, 5), e5 = (3, 2), e6 = (3, 5), e7 = (3, 6), e8 = (4, 5), e9 = (5, 6), e10 = (5, 7), e11 = (6, 2), e12 = (7, 6), la corrispondente matrice d’incidenza sarà: 1 2 3 4 5 6 7 e1 13.3 -1 1 0 0 0 0 0 e2 -1 0 1 0 0 0 0 e3 0 -1 0 1 0 0 0 e4 0 -1 0 0 1 0 0 e5 0 1 -1 0 0 0 0 e6 0 0 -1 0 1 0 0 e7 0 0 -1 0 0 1 0 e8 0 0 0 -1 1 0 0 e9 0 0 0 0 -1 1 0 e10 0 0 0 0 -1 0 1 e11 0 1 0 0 0 -1 0 e12 0 0 0 0 0 1 -1 Alcuni esempi di problemi su grafo In questa ultima sezione verranno formulati alcuni problemi utilizzando il formalismo dei grafi. Scopo di questi esempi non è quello di dare una panoramica completa di quei problemi la cui formulazione (e risoluzione) è basata sui grafi (non sarebbe sufficiente un intero corso dedicato a questo tema!). Piuttosto vogliamo mostrare come problemi molto diversi tra loro possano essere formulati (e risolti) usando una rappresentazione basata sui grafi, che spesso contribuisce a rendere chiari problemi apparentemente molto intricati, dando cosı̀, inoltre, una prova dell’importanza della scelta di un buon modello nella risoluzione di un problema e della necessità di disporre di un ampio spettro di modelli per poter adeguatamente modellare problemi pratici. 185 13.3.1 Modelli di distribuzione di flusso a costo minimo Modelli di distribuzione di flusso a costo minimo nascono naturalmente quando si voglia determinare il modo più economico di trasportare merci da alcune origini a delle destinazioni attraverso una rete fisica. Per formulare questo problema consideriamo una rete orientata G = (V, E) con associato ad ogni arco (i, j) ∈ E un costo cij (negativo, positivo o nullo), una capacità uij ≥ 0 ed un limite inferiore lij , con 0 ≤ lij ≤ uij . Supponiamo inoltre che a ciascun nodo i di V sia associato un numero intero b(i), con la convenzione che: - b(i) > 0 indica la presenza di offerta (il nodo i viene detto origine); - b(i) < 0 indica la presenza di domanda (il nodo i viene detto destinazione); - b(i) = 0 indica l’assenza di offerta e di domanda (il nodo i viene detto di trasferimento). Nel seguito supporremo valida la seguente ipotesi: Ipotesi di ammissibilità. L’offerta totale uguaglia la domanda totale; ovvero, formalmente: X b(i) = 0. (13.1) i∈V Definizione 13.3.1 Un flusso ammissibile in una rete G è un vettore non negativo x ∈ IR|E| che soddisfa i seguenti vincoli: – vincoli di capacità: per ogni arco (ij) ∈ E: lij ≤ xij ≤ uij . – vincoli di bilanciamento della massa: per ogni nodo k ∈ V X (jk)∈ω − (k) X xjk − xki = b(k). (ki)∈ω + (k) Il costo di un flusso è definito come la somma X cij xij . (ij)∈E Il problema del flusso a costo minimo, si può enunciare come segue: trovare una distribuzione ammissibile di flusso sulla rete G tale in modo da minimizzare il costo totale. Se si indica con AG la matrice d’incidenza della rete, con b = (b(1), . . . , b(n))T il vettore m della domanda/offerta, con c ∈ IRm il vettore dei costi e con l ∈ IRm + ed u ∈ IR+ i vettori le cui componenti rappresentano il limite inferiore e la capacità dell’arco corrispondente, il problema di flusso a costo minimo può essere scritto nel seguente modo: min cT x AG x = b l≤x≤u 186 (PC ) Nel caso di rete non capacitata, cioè quando si abbia lij = 0 e uij = ∞, allora il problema di flusso a costo minimo si scrive: min cT x AG x = b x≥0 (Q). In questo caso il problema è anche noto in letteratura come problema di trasferimento (transhipment problem). Osservazione 1 Questa formulazione richiede n vincoli di bilanciamento ed m vincoli di non negatività. In realtà però, sommando i vincoli di bilanciamento si ottiene: n X X akj xij = k=1 (ij)∈E n X b(k). k=1 Pn In effetti, poiché per ipotesi si ha k=1 b(k) = 0, e inoltre la somma delle righe della matrice d’incidenza è uguale alla riga nulla (vedi Teorema ??), si ottiene l’identità 0 = 0. Quindi, in realtà un’equazione dei vincoli di bilanciamento si può ottenere come combinazione lineare delle altre ed è quindi ridondante. Osservazione 2 L’ipotesi di ammissibilità consente di assicurare l’esistenza di una soluzione ammissibile per il problema di trasferimento (P̃ ). Si ha infatti, il seguente teorema: Teorema 13.3.2 (Ipotesi di ammissibilità) Condizione necessaria e sufficiente per l’esistenza di una soluzione ammissibile per problema di trasferimento (Q) è cha valga (13.1). Teorema 13.3.3 (Proprietà di interezza) Dato un problema di flusso a costo minimo che soddisfa l’ipotesi di ammissibilità, se i vettori l, u e b sono interi non negativi, se il problema ha una soluzione ottima, allora ha una soluzione intera dello stesso valore. Grazie a quest’ultima proprietà, è possibile costruire algoritmi polinomiali che consentano di trascurare eventuali vincoli di interezza sulle variabili, riducendo cosı̀ un problema di ottimizzazione combinatoria in un problema di ottimizzazione continua. Alcuni problemi classici di ottimizzazione su reti possono essere formulati come problemi di flusso a costo minimo. Nei prossimi paragrafi analizzeremo alcuni modelli su reti che sono una particolarizzazione dei modelli di flusso a costo minimo. Esempio 13.3.4 (Modello di flusso a costo minimo) Una unità portarei navale deve compiere una missione di tre giorni in oceano. Sono noti i seguenti fabbrisogni giornalieri di aerei necessari per portare a termine la missione: Aerei 1o giorno 40 2o giorno 70 È noto inoltre che 187 3o giorno 60 - non sono possibili rifornimenti in oceano; - non si può usare un aereo dopo una giornata di missione se non dopo una revisione; - le revisioni possono essere fatte di giorno o di notte con costi diversi; in particolare, revisionare di giorno costa £8, revisionare di notte costa £15; - un aereo nuovo costa £20; - le squadre di revisione sono in grado di revisionare quanti aerei si desidera. Formulare il problema di PL per decidere quanti aerei nuovi imbarcare e quanti aerei (e quando) revisionare per portare a termine la missione a costo minimo. Analisi del problema Si tratta di un problema di flusso a costo minimo su reti spazio-temporali. Formulazione Per determinare quali sono le variabili di decisione si devono individuare le possibilità di acquisto e/o di revisione nei tre giorni di missione. Distinguiamo i seguenti intervalli temporali: T1 : primo giorno; si possono utilizzare solo aerei nuovi. Indichiamo questa quantità con x100 . T2 : notte tra il primo ed il secondo giorno; si possono revisionare gli aerei usati il primo giorno; T3 : il secondo giorno; si possono utilizzare aerei nuovi ed aerei revisionati nel periodo T2 . Indichiamo rispettivamente con x200 e x212 queste quantità. Si possono inoltre revisionare aerei usati il primo giorno. T4 : notte tra il secondo ed il terzo giorno; si possono revisionare aerei usati il primo o il secondo giorno. T5 : terzo giorno; si possono utilizzare aerei nuovi oppure aerei utilizzati il primo giorno e revisionati nel periodo T2 , T3 o T4 oppure aerei utilizzati il secondo giorno e revisionati nel periodo T4 . Indichiamo queste quantità rispettivamente con x300 , x312 , x313 , x314 , x324 . – Variabili. Le variabili di decisione sono quindi le quantità di aerei utilizzati, cioè: xkij dove l’apice k = 1, 2, 3 indica il giorno. I pedici ij indicano rispettivamente il giorno in cui gli aerei sono stati usati ed il periodo in cui sono stati revisionati. Osserviamo che non ha alcun senso revisionare aerei usati il secondo giorno nel periodo T5 perché non potrebbero essere mai utilizzati. L’indice i vale 1, 2, l’indice j vale 2, 3, 4 (con riferimento all’intervallo temporale Tj .) Questa situazione è schematizzata nella seguente tabella: nuovi revisionati T2 T3 T4 1o giorno x100 - – Vincoli. Per quanto riguarda i vincoli abbiamo: 188 2o giorno x200 x212 - 3o giorno x300 x312 x313 3 x14 x324 • vincoli di non negatività: si tratta di quantità di aerei utilizzati, quindi: xkij ≥ 0 ∀k, i, j • vincoli di interezza: si tratta di quantità indivisibili xkij ∈ Z; • vincoli di domanda: sono noti i fabbisogni giornalieri di aerei. Il primo giorno dobbiamo avere 40 aerei, quindi : x100 = 40. Il secondo giorno gli aerei utilizzati devono essere pari a: x200 + x212 = 70. Analogamente per il terzo giorno x300 + x312 + x313 + x314 + x324 = 60 • vincoli di continuità: la quantità di aerei revisionati nel periodo Tj non può superare la quantità di aerei disponibile in quel periodo: x212 + x312 + x313 + x314 ≤ x100 x324 ≤ 70. Inoltre la quantità totale di aerei usata non può superare la quantità totale di aerei che è stata acquistata; supponendo che gli aerei usati vadano ad un deposito finale, si ha che il primo giorno vengono mandati al deposito finale gli aerei usati che non sono più revisionati, cioè: x100 − (x212 + x312 + x313 + x314 ) analogamente il secondo giorno: 70 − x324 ed il terzo giorno tutti gli aerei usati vanno al deposito, cioè 60. La quantità di aerei nuovi è pari a x100 +x200 +x300 , quindi complessivamente dovremo avere: x100 + x200 + x300 = 40 − x212 − x312 − x313 − x314 + 70 − x324 + 60, cioè x200 + x300 + x212 + x312 + x313 + x314 + x324 = 130 189 (13.2) – Funzione obiettivo. La funzione obiettivo è il costo totale dovuto all’acquisto e alla revisione dergli aerei. Gli aerei nuovi costano £20 e corrispondono ai valori di i = j = 0, quindi il costo totale di acquisto è 20 3 X xk00 = 20(x300 + x200 + x300 ). k=1 Gli aerei revisionati di giorno (corrispondono al periodo T3 ) costano £8, quindi: 8 X xki3 = 8x313 k,i Gli aerei revisionati di notte (corrispondono ai periodi T2 , T4 ) costano £15 quindi: 15 X X xkij = 15(x212 + x312 ) + 15(x314 + x324 ). k,i j=2,4 Complessivamente, il problema si scrive: minx 20(x300 + x200 + x300 ) + 8x313 + 15(x212 + x312 + x314 + x324 ) x100 = 40 x2 + x2 = 70 00 12 3 3 3 3 3 x00 + x12 + x13 + x14 + x24 = 60 x2 + x3 + x3 + x3 ≤ x1 12 12 13 14 00 3 ≤ 70 x 24 x200 + x300 + x212 + x312 + x313 + x314 + x324 = 130 xkij ≥ 0 ∀ k, i, j k xij ∈ Z Vediamo come questo problema può essere interpretato come un modello di flusso a costo minimo. Si tratta di definire una rete in cui archi e/o nodi corrispondono ad aerei usati e/o revisionati in intervalli di tempo diversi. Costruiamo una rete orientata in questo modo: introduciamo un nodo sorgente s che rappresenta lo stato iniziale, ovvero il deposito da cui si possono acquistare arei nuovi. Siano 1, 2, 3 tre nodi che rappresentano l’inizio rispettivamente del primo, secondo e terzo giorno. Avremo gli archi (s, 1), (s, 2), (s, 3) con un flusso su di essi che rappresenta il numero di aerei nuovi acquistati il primo, secondo e terzo giorno. Introduciamo anche un nodo pozzo t che rappresenta lo stato finale, ovvero il deposito degli aerei usati. Siano 10 , 20 , 30 tre nodi che rappresentano la fine rispettivamente del primo, secondo e terzo giorno. Avremo gli archi (10 , t), (20 , t), (30 , t) con un flusso su di essi che rappresenta il numero di aerei usati il primo, secondo e terzo giorno e che non sono più revisionati. Inoltre ci saranno gli archi (1, 10 ), (2, 20 ), (3, 30 ) con un flusso su di essi che rappresenta il numero di aerei utilizzati durante il primo, secondo, terzo giorno. Ovviamente questo flusso è fissato e noto (sono i fabbrisogni giornalieri). Introduciamo poi altri tre nodi 4, 5, 6 che corrispondono agli intervalli di tempo T2 , T3 , T4 , cioè esiste l’arco (i0 , j) con i0 = 10 , 20 , 30 e j = 4, 5, 6 se è possibile revisionare gli aerei usati nel giorno i durante l’intervallo di tempo corrispondente a j. In particolare avremo gli archi: 0 (1 , 4) 0 aerei (1 , 5) aerei 0 (1 , 6) aerei (20 , 6) aerei usati usati usati usati il il il il 1◦ 1◦ 1◦ 2◦ 190 giorno giorno giorno giorno revisionati revisionati revisionati revisionati T2 T3 T4 T4 Non ci sono archi di questo tipo uscenti da 30 . Ci sono anche archi del tipo (j, i) con j = 4, 5, 6 e i = 1, 2, 3 se è possibile utilizzare aerei revisionati nel periodo corrispondente a j il giorno i. In particolare avremo gli archi: (4, 2) (4, 3) aerei aerei (5, 3) aerei (6, 3) aerei revisionati revisionati revisionati revisionati T2 T2 T3 T4 usati usati usati usati il il il il 2◦ 3◦ 3◦ 3◦ giorno giorno giorno giorno Non ci sono archi di questo tipo entranti in 1. Complessivamente la rete è riportata in Figura 13.10 1 40 1' 4 S 2 70 T 2' 5 3 60 3' 6 Figura 13.10: Rete relativa all’Esercizio 13.3.4 Osservazione Notiamo che si tratta di determinare il flusso a costo minimo su una rete (non capacitata) con alcuni valori di flusso assegnati. Il nodo s è il nodo origine con b(s) = −(x100 + x200 + x300 ) < 0. Il nodo t è il nodo destinazione con b(t) > 0. tutti gli altri nodi sono di trasferimento con b(i) = 0. Il vincolo (13.2) corrisponde all’ipotesi di ammissibilità. Mentre gli altri vincoli di continuità sono i vincoli di conservazione ai nodi di trasferimento 10 e 20 . I vincoli di domanda sono i vincoli di conservazione negli altri nodi di trasferimento. Validazione del modello Si può osservare che si possono eliminare alcuni archi dalla rete del modello e quindi alcune variabili. In particolare, si può eliminare l’arco (4, 3) perché non conviene revisionare di notte aerei che potrebbero essere revisionati il giorno successivo (non ci sono limitazioni sul numero di aerei che si possono revisionare). Inoltre si può eliminare l’arco (10 , t) perché il primo giorno conviene revisionare quanti più aerei possibile piuttosto che comperarne di nuovi. Con lo stesso ragionamento si può eliminare l’arco (s, 3) cioè non comperare aerei nuovi il terzo giorno, ma usare solo aerei revisionati, poiché la quantità di aerei necessaria è inferiore al numero di aerei usati il secondo giorno. Questo corrisponde ad eliminare le variabili x300 , x312 . Quindi, il vincolo (13.2) diventa: x200 + x100 = 70 − x324 + 60 191 Con queste considerazioni si ottiene il seguente modello: min 20(x200 + x100 ) + 8x313 + 15(x212 + x314 + x324 ) x100 = 40 x200 + x212 = 70 x3 + x3 + x3 = 60 13 14 24 x212 + x313 + x314 = 40 x324 ≤ 70 x200 + x324 = 90 xk ≥ 0 ∀ k, i, j ij Modelli di trasporto. Il problema di trasporto definito nel paragrafo 3.3.2, può essere formulato come problema di flusso a costo minimo su una rete non capacitata in cui non ci sono nodi di trasferimento. Infatti, possiamo associare a questo problema un grafo bipartito G = (X, Y, E); l’insieme X rappresenta i nodi origini ed i nodi di Y sono i nodi destinazione. L’insieme dei nodi è V = X ∪ Y (|V | = n + m). Esiste un arco per ogni coppia ij con i ∈ X e j ∈ Y (|E| = nm). A ciascun arco (ij) è associato un costo. Per ogni (i, j) ∈ E, lij = 0 e uij = ∞. Infine, per ogni nodo i ∈ X, si pone b(i) = ai , mentre per ogni nodo i ∈ Y , si pone b(i) = −bj . L’ipotesi (3.10) corrisponde all’ipotesi di ammissibilità. Una rete corrispondente a un problema di trasporto viene detta rete di trasporto. Il problema di trasporto, come caso particolare del problema di flusso a costo minimo, gode ancora della proprietà espressa dal Teorema di interezza. Quindi, se nel problema dei trasporti ai , i = 1, . . . , m e bj , j = 1, . . . , n sono interi e se il problema ammette soluzione ottima, allora ha una soluzione ottima intera. Modelli di assegnamento I problemi di assegnamento sono un caso particolare del problema di trasporti in cui si ha lo stesso numero di origini e di destinazioni. Un generico problema di assegnamento consiste nel determinare il modo ottimale di assegnare lavori a persone o, più in generale, di assegnare mezzi (persone, macchine, etc. ) ad attività. Supponiamo che n persone P1 ,. . . ,Pn , debbano svolgere n lavori L1 ,. . . , Ln ; ciascun lavoro deve essere svolto esattamente da una persona e ciascuna persona deve svolgere un lavoro. Naturalmente le persone hanno diversi livelli di esperienza, competenza ed abilità e quindi si può introdurre un costo dell’assegnamento della persona i al lavoro j; indichiamo tale costo con cij e supponiamo che sia noto. Questo costo può, ad esempio, essere interpretato come tempo medio impiegato dalla persona i ad eseguire il lavoro j. Il problema consiste, quindi, nell’assegnare i lavori alle persone minimizzando il costo totale di realizzazione di tutti i lavori. Questo tipo di problemi sorge in molte situazioni pratiche: esempi tipici sono i problemi di assegnamento del personale all’interno di una azienda e i problemi di assegnare determinati mezzi di trasporto ad alcune particolari linee. Esempi di questo tipo verranno esaminati in dettaglio nel seguito. Se indichiamo con X l’insieme delle persone (|X| = n), con Y l’insieme dei lavori (|Y | = n) e con E l’insieme degli assegnamenti possibili, cioè delle possibili coppie (ij) con i ∈ X e j ∈ Y, 192 allora il problema di assegnamento è un problema di flusso a costo minimo su una rete di trasporto rappresentata da un grafo bipartito con V = X ∪ Y e b(i) = 1 per ogni i ∈ X e b(j) = −1 per ogni j ∈ Y. Inoltre per ogni (ij) si ha lij = 0 e uij = 1. Esempio 13.3.5 Assegnazione delle aule. In una facoltà universitaria vi sono nello stesso orario n corsi e m aule disponibili. Per ragioni di capienza delle aule e di attrezzature disponibili, ogni corso può essere tenuto solo in alcune delle aule. Il problema è quello di stabilire quale è il numero massimo di corsi che è possibile tenere nell’orario considerato. Il problema può essere scritto come problema su grafi nel seguente modo: sia G(V, E) un grafo bipartito in cui l’insieme di nodi V = V1 ∪ V2 in cui l’insieme V1 corrisponde ai corsi, l’insieme di nodi V2 corrisponde alle aule ed esiste un arco fra due nodi i e j (con i appartenente ad V1 e j appartenente a V2 ) se (e solo se) il corso i può essere tenuto nell’aula j. Il problema di stabilire qual è il numero massimo di corsi che è possibile tenere nell’orario considerato può ora essere formulato come il problema di scegliere sul grafo il massimo numero di archi (corrispondenti ad assegnazioni di corsi ad aule) tali che due archi scelti non siano mai adiacenti. Infatti se due archi fossero adiacenti in un nodo dell’insieme V1 , allora vorrebbe dire che uno stesso corso si tiene contemporaneamente in due aule diverse. Se due archi fossero adiacenti in un nodo dell’insieme V2 , allora vorrebbe dire che in una stessa aula si tengono contemporaneamente due corsi. In entrambi i casi le assegnazioni di aule non sono ovviamente ammissibili. Questo problema è detto di accoppiamento bipartito. Esempio 13.3.6 In un Dipartimento universitario, sono attivati cinque corsi diversi che possono essere tenuti da cinque professori. Ogni professore esprime delle preferenze sul corso che vorrebbe tenere, indicando un punteggio. A preferenza più alta corrisponde un punteggio più alto. I punteggi sono riportati nella seguente tabella: insegnante1 insegnante2 insegnante3 insegnante4 insegnante5 corso1 7 7 4 5 4 corso2 5 9 6 4 5 corso3 4 7 5 5 5 corso4 4 9 8 7 8 corso5 5 4 5 4 9 Si vuole assegnare ciascun professore ad un corso cercando di massimizzare il valore medio inteso come media delle preferenze. Analisi Si tratta di un problema di assegnamento in cui i lavori sono i corsi. Indichiamo con cij il punteggio assegnato dal professore i al corso j. Formulazione – Variabili. Le variabili di decisione sono le variabili booleane: ½ xij = 1 se l’insegnante i è assegnata al corso j 0 altrimenti. i, j = 1, . . . , 5. – Funzione obiettivo. Indicando con cij il punteggio assegnato dall’insegnante i alla corso j, la funzione obiettivo è il valore medio delle preferenze: 193 5 X 5 1X cij xij . 5 i=1 j=1 – Vincoli. I vincoli di assegnamento sono: x11 + x12 + x13 + x14 + x15 x21 + x22 + x23 + x24 + x25 x31 + x32 + x33 + x34 + x35 x41 + x42 + x43 + x44 + x45 x51 + x52 + x53 + x54 + x55 x11 + x21 + x31 + x41 + x51 x12 + x22 + x32 + x42 + x52 x13 + x23 + x33 + x43 + x53 x14 + x24 + x34 + x44 + x54 x15 + x25 + x35 + x45 + x55 =1 =1 =1 =1 =1 =1 =1 =1 =1 =1 Quindi, complessivamente il problema si scrive: P P min 5i=1 5j=1 cij xij x11 + x12 + x13 + x14 + x15 x 21 + x22 + x23 + x24 + x25 x31 + x32 + x33 + x34 + x35 x41 + x42 + x43 + x44 + x45 x51 + x52 + x53 + x54 + x55 x11 + x21 + x31 + x41 + x51 x12 + x22 + x32 + x42 + x52 x13 + x23 + x33 + x43 + x53 x14 + x24 + x34 + x44 + x54 x15 + x25 + x35 + x45 + x55 xij ≥ 0 =1 =1 =1 =1 =1 =1 =1 =1 =1 =1 Colorazione di una carta geografica. Il problema è quello di stabilire il numero minimo di colori necessario per colorare una carta geografica, assegnando colori alle varie nazioni rappresentate sulla carta, in modo che due nazioni adiacenti (che quindi abbiano un tratto di frontiera in comune) siano sempre colorate in modo diverso. Si suppone che ogni nazione sia formata da una unica regione connessa e che nazioni adiacenti abbiano una linea di confine in comune di lunghezza maggiore di zero (e non quindi solo un singolo punto in comune). Assegnando ad ogni nazione un nodo di un grafo e collegando due nodi se e solo se le due nazioni corrispondenti sono adiacenti, si ottiene un grafo (che viene detto planare). La famosa “congettura dei quattro colori”, ormai da chiamare “teorema dei quattro colori”, afferma che ogni carta geografica è colorabile utilizzando al più quattro colori. Questa congettura era già nota nel 1840. Nel corso di oltre un secolo sono state fornite dimostrazioni per molti casi particolari del problema (oltre a molte dimostrazioni della congettura, poi rivelatesi sbagliate o 194 valide per particolari classi di grafi). Solo nel 1976 la congettura è stata dimostrata in tutta la sua generalità usando gli strumenti della teoria dei grafi. Attraversamento di un fiume Su di una riva di un fiume vi è un pastore con un cane lupo, un agnello e un cesto di cavoli. Per attraversare il fiume il pastore dispone di una piccola barca che permette di trasportare, oltre al pastore, un solo altro passeggero (il cane lupo, l’agnello o il cesto di cavoli). Se su di una riva restano soli il cane lupo e l’agnello, il cane lupo puo uccidere l’agnello. Se restano soli l’agnello e il cesto di cavoli, l’agnello puo mangiare i cavoli. Il problema è quello di stabilire se è possibile trasferire tutto sull’altra riva del fiume senza mai lasciare soli cane lupo e agnello o agnello e cesto di cavoli. Il problema puo essere facilmente formulato come problema di esistenza di un cammino su di un opportuno grafo. Sia dato il grafo G = (V, E) dove i nodi corrispondono a tutti i possibili stati ammissibili del sistema pastore-lupo-agnello-cavoli. I possibili stati ammissibili del sistema sono i seguenti: PLAC pastore, lupo,agnello e cavoli sulla riva di partenza nessuno sulla riva di arrivo PLC pastore, lupo e cavoli sulla riva di partenza agnello sulla riva di arrivo PAC pastore, agnello e cavoli sulla riva di partenza lupo sulla riva di arrivo PLA pastore,lupo e agnello sulla riva di partenza cavoli sulla riva di arrivo PA pastore e agnello sulla riva di partenza lupo e cavoli sulla riva di arrivo LC lupo e cavoli sulla riva di partenza pastore e agnello sulla riva di arrivo A agnello sulla riva di partenza pastore lupo,e cavoli sulla riva di arrivo L lupo sulla riva di partenza pastore,agnello e cavoli sulla riva di arrivo C cavoli sulla riva di partenza pastore,lupo e agnello sulla riva di arrivo ∅ nessuno sulla riva di partenza pastore,lupo,agnello e cavoli sulla riva di arrivo Altri stati del sistema non sono ammissibili; per esempio non è ammissibile lo stato PL in quanto lascerebbe agnello e cavoli soli sulla riva di arrivo. Nel grafo G esiste un arco tra due nodi se è possibile passare da uno all’altro dei due stati corrispondenti con un solo viaggio in barca. Il grafo associato al problema viene riportato in figura 13.11. Si noti che in questo caso il grafo è simmetrico in quanto, se è possibile passare dal nodo A al nodo B, allora è anche possibile passare da B a A; per semplicità quindi il grafo viene riportato come grafo non orientato. L’esistenza di una soluzione equivale all’esistenza di un cammino tra il nodo PLAC e il nodo ∅. Il numero minimo di viaggi necessario per compiere l’operazione è pari a 7 e corrisponde al cammino con il minimo numero di archi tra il nodo PLAC e il nodo ∅. Si noti che esistono due possibili cammini semplici tra i due nodi, entrambi con 7 archi. 195 LC PLAC PLC L C PLA PAC A PA Ø Figura 13.11: Esistenza tra un cammino tra due nodi 13.4 Il problema del cammino minimo 13.4.1 Definizione del problema Dato un grafo orientato G = (V, E), associamo a ciascun arco e = (u, v) ∈ E un numero reale le , detto peso dell’arco. Per ogni cammino orientato P = {v1 , e1 , . . . , ep , vp }, denotiamo con l(P ) il peso di P , ossia la somma dei pesi degli archi di P . Il problema del cammino minimo può essere enunciato nel modo seguente: dati due nodi s ∈ V e t ∈ V , trovare un cammino orientato P ∗ in G da s a t di peso minimo. Si osservi che (i) se non esiste un cammino orientato da s a t in G, il problema non ha soluzioni ammissibili; (ii) se esiste un ciclo orientato in G di peso negativo la soluzione del problema è illimitata (poiché conterrà tale ciclo ripetuto un numero illimitato di volte). In Figura 13.12 è mostrato un grafo orientato contenente un ciclo orientato di peso negativo. I pesi degli archi sono mostrati in figura in prossimità di ciascun arco. Un cammino minimo conterrà i nodi e gli archi del ciclo un numero illimitato di volte. 1 1 t 2 s 2 2 2 -5 Figura 13.12: Grafo con ciclo di peso negativo Il problema del cammino minimo dal nodo s al nodo t, può essere formulato come problema di flusso a costo minimo, fatte le seguenti assunzioni: 196 • la rete sia non-capacitata; • per ogni nodo i ∈ V − {s, t}, si ponga b(i) = 0; • si ponga b(s) = 1 e b(t) = −1. È facile vedere che ogni flusso ammissibile corrisponde a inviare un flusso unitario dal nodo s al nodo t; utilizzando l’ipotesi di interezza del flusso su ogni arco, un flusso unitario corrisponde a un cammino diretto da s a t (formato dagli archi il cui flusso corrispondente è uguale a uno). Dunque, il flusso di costo minimo corrisponderà al cammino di costo minimo da s a t. È possibile formulare il problema del cammino minimo come problema di Programmazione Lineare associando una variabile booleana xij con ogni arco (i, j) ∈ E. In particolare un modello lineare può essere cosı̀ costruito: – Variabili. Si definiscono le variabili booleane ½ 1 se (i, j) ∈ P 0 altrimenti m Il vettore x ∈ R si chiama vettore di incidenza del cammino P. – Funzione obiettivo. La funzione obiettivo è il peso del cammino: xij = X cij xij . (i,j)∈E – Vincoli. I vincoli devono imporre che si abbia effettivamente un cammino semplice da s a t, cioè: • in ciascun nodo k che non sia s o t incidono esattamente due archi del cammino, uno entrante e l’altro uscente. Questo si esprime con i vincolo: X xik − (ik)∈ω − (k) X xkj = 0 ∀k ∈ V − {s, t} (kj)∈ω + (k) • dalla sorgente s esce esattamente un arco e nel pozzo t entra esattamente un arco; cioè: P P x − (tj)∈ω+ (t) xtj = 1 − P(it)∈ω (t) it P (is)∈ω − (s) xis − (sj)∈ω + (s) xsj = −1 Se poniamo b = (1 − 1 0 . . . 0)T , e consideramo la matrice di incidenza A della rete G, allora questi vincoli si possono esprimere in forma matriciale come: Ax = b. 13.5 Cammini minimi e massimi su grafi aciclici Una classe di grafi orientati di particolare interesse in campo applicativo è la classe di grafi aciclici. Per esempio il grafo di attività di un progetto con vincoli di precedenza fra le attività è aciclico (vedi il capitolo “Tecniche reticolari di programmazione delle attività”). La ricerca di cammini minimi o massimi su tali grafi è uno strumento di progetto di notevole importanza. 197 Come si vedrà nel seguito, i due problemi di minimo e di massimo sono, in questo caso particolare, risolti da due algoritmi identici eccetto che per la sostituzione di un massimo a un minimo nella formula ricorsiva alla base del procedimento. Nel seguito verrà prima considerato il caso di un problema di cammino minimo. Per poter procedere con la descrizione dell’algoritmo, è necessario studiare prima una particolare tecnica di numerazione dei nodi di un grafo aciclico. 13.5.1 Numerazione topologica dei nodi di un grafo Una caratteristica peculiare dei grafi aciclici (sia G = (V, E) il grafo, con|V | = n e |E| = m) consiste nella possibilità di numerare i nodi del grafo con i numeri 1,2,3,....,n-1,n in modo tale che: se esiste un arco dal nodo i al nodo j allora j > i Tale numerazione viene detta numerazione topologica dei nodi del grafo e non è in generale unica. Non tutti i grafi possono essere numerati topologicamente. In effetti l’esistenza di una numerazione topologica dei nodi di un grafo caratterizza esattamente la classe dei grafi aciclici. Vale infatti il seguente teorema. Teorema 13.5.1 Un grafo è aciclico se e solo se esiste una numerazione topologica dei suoi nodi. Dimostrazione. Sufficienza. Supponiamo che esista una numerazione topologica dei nodi e facciamo vedere che l’ esistenza di un ciclo porterebbe ad una contraddizione. Possiamo assumere che i nodi siano numerati topologicamente, indicheremo l’i-esimo nodo di questa particolare numerazione, come vi . Se esiste un ciclo (orientato) vuol dire che esiste una successione di nodi (vi , vj , vk , . . . , vr , vs ) tali che - esistono gli archi (vi , vj ), (vj , vk ), . . ., (vr , vs ); - vi = vs . Ma allora, da una parte, siccome la numerazione è topologica abbiamo i < j < k < . . . < r < s, cioè i < s, mentre dall’altra, poiché vi = vs abbiamo i = s. Questa è una contraddizione e cosı̀ il grafo deve essere aciclico. Necessità. Supponiamo che il grafo sia aciclico e mostriamo che deve esistere almeno una numerazione topologica. La dimostrazione è costruttiva, faremo cioè vedere che esiste una numerazione topologica costruendone una. Come primo passo osserviamo che se il grafo è aciclico, deve esistere almeno un nodo che non abbia archi entranti. Infatti, se ciò non fosse vero, potremmo ragionare nel modo seguente. Prendiamo un nodo qualunque, chiamiamolo v1 . Siccome tutti i nodi hanno archi entranti esiste un nodo predecessore di v1 , indichiamolo con v2 ; notiamo che per come abbiamo scelto v2 esiste l’arco (v2 , v1 ) (attenzione, questa è una numerazione non topologica). Possiamo ripetere il ragionamento con v2 e trovare un nodo v3 tale che esista l’ arco (v3 , v2 ). Siccome stiamo supponendo, per assurdo, che tutti gli archi abbiano degli archi entranti, possiamo ripetere il ragionamento quante volte vogliamo. Notiamo che ogni nodo generato deve essere diverso dai precedenti, altrimenti avremmo trovato un ciclo, contraddicendo l’aciclicità del grafo. D’altra 198 parte, arrivati a vn i nodi del grafo sono “finiti” e quindi il predecessore di vn che stiamo supponendo esistente per assurdo, deve per forza essere uno dei nodi già esaminati. Cosı̀ si viene a formare un ciclo. Quindi dato un grafo aciclico deve per forza esistere almeno un nodo che non ha archi entranti. Prendiamo uno di questi nodi e numeriamolo con il numero 1. Eliminiamo dal grafo il nodo 1 e tutti gli archi uscenti da esso. Il nuovo grafo che otteniamo è ovviamente ancora un grafo aciclico. Quindi per lo stesso ragionamento fatto prima deve esistere almeno un nodo che non ha archi entranti. Prendiamo uno di questi nodi e numeriamolo con il numero 2. Notiamo che ovviamente se consideriamo il grafo originario il nodo 2 può avere archi entranti, ma solo provenienti dal nodo 1 e quindi la condizione i < j è rispettata. Possiamo ora ripetere il procedimento n volte (quanti sono i nodi) ed ottenere cosı̀ una numerazione topologica del grafo. 2 Il precedente teorema è importante, anche perché nella dimostrazione della necessità è sostanzialmente dato un algoritmo per numerare topologicamente i nodi di un grafo. Riesponiamo qui l’algoritmo per chiarezza. - Siccome il grafo è aciclico, deve esistere almeno un nodo con solo archi uscenti; - individuiamo uno di questi nodi e attribuiamogli il numero 1; - cancelliamo il nodo numerato e tutti gli archi adiacenti, nel nuovo grafo ridotto individuiamo un nodo con soli archi uscenti e attribuiamogli il numero 2, e cosı̀ via fino ad aver numerato tutti i nodi La correttezza e validità di questa procedura è stata provata nella dimostrazione della necessità del Teorema 13.5.1. Notiamo che se ad un certo punto dell’applicazione della procedura non possiamo procedere, se succede cioè che ad un determinato passo non riusciamo a trovare un nodo senza archi entranti, questo vuol dire che il grafo considerato contiene un ciclo. Quindi la procedura per la numerazione topologica di un grafo può anche essere utilizzata per determinare se un grafo è aciclico o meno. Come esempio consideriamo il grafo di figura 13.13. B D A C Figura 13.13: Numerazione dei nodi di un grafo 199 Si tratta di decidere se il grafo è aciclico e, in caso, numerare i nodi topologicamente. I vari passi dell’algoritmo sono riportati qui di seguito Passo 1 2 3 4 Nodo senza archi entranti A B C D Nodi non ancora numerati B,C,D C,D D ∅ Numerazione A=1 B=2 C=3 D=4 Il procedimento è terminato con la numerazione di tutti i nodi. Il grafo è dunque aciclico e la numerazione trovata è topologica. Supponiamo ora che nel precedente grafo l’arco (B, D) sia orientato da D a B. Ovviamente si verrebbe a creare un ciclo. Se proviamo ad applicare la procedura per la determinazione di una numerazione topologica possiamo iniziare numerando il nodo A come nodo 1. Ma dopo non possiamo più procedere perché eliminato il nodo A e gli archi da esso uscenti ((A,B) e (A,C)) non è più possibile individuare un nodo che non abbia archi entranti. 13.5.2 Un algoritmo per il cammino minimo su grafi aciclici La numerazione dei nodi di un grafo aciclico descritta nella sezione precedente consente di costruire un algoritmo di soluzione per il problema di cammino minimo particolarmente semplice. Infatti, nella ricerca di un cammino tra una qualsiasi coppia di nodi i e j del grafo, a causa della numerazione attribuita ai nodi, si può affermare che: se j < i allora non esistono cammini da i a j; se j > i allora gli unici nodi che è necessario considerare nella ricerca del cammino da i a j sono i nodi con indice k tale che i < k < j. Infatti, se il cammino passasse per un nodo h > j, allora non potrebbe tornare su j, a causa della mancanza di archi che collegano nodi con indice maggiore a nodi con indice minore; se passasse per un nodo h < i, allora dovrebbe esistere un cammino da i a h, il che comporterebbe l’esistenza di archi che collegano nodi con indice maggiore a nodi con indice minore. Sulla base di queste considerazioni, è possibile impostare un algoritmo per il calcolo dell’albero dei cammini minimi tra un nodo del grafo (per esempio il nodo 1) e tutti i nodi con indice superiore (per quelli con indice inferiore non esiste sicuramente un cammino; ovviamente, se il nodo di partenza è quello contrassegnato con l’indice 1, allora si tratta di calcolare l’albero dei cammini minimi tra il nodo 1 e tutti gli altri). L’algoritmo per il calcolo dell’albero dei cammini minimi dal nodo 1 a tutti gli altri nodi si basa sul calcolo in sequenza dei cammini minimi dal nodo 1 al nodo 2, dal nodo 1 al nodo 3, dal nodo 1 al nodo 4, e cosı́ via. Indichiamo con: - pi,j il peso dell’arco (i, j) che parte dal nodo i e arriva al nodo j; - ω e (i) l’insieme dei nodi predecessori del nodo i; - d∗ (i) il valore del cammino minimo dal nodo 1 al nodo i; 200 - J(i) il nodo che precede i su tale cammino (nel caso il cammino minimo non sia unico, allora se ne sceglie uno qualsiasi fra quelli minimi). Possiamo allora illustrare l’algoritmo per il calcolo dei percorsi minimi. - d∗ (1) := 0; J(1) := 1; - per j = 2, 3, 4, . . . , n − 1, n ripeti la seguente serie di operazioni d∗ (j) := mini∈ωe (j) {d∗ (i) + pi,j }; J(j) := valore di i per cui si è verificato il minimo; Si noti che una volta assegnato un peso d∗ (i) a un nodo (cioè un valore del cammino minimo dal nodo 1 al nodo considerato), tale peso non viene più modificato nel corso dell’algoritmo, ma indica in modo definitivo il valore del cammino. Questo è dovuto al fatto, già citato, che tutti i nodi successivi non devono essere considerati per il calcolo del percorso dal nodo 1 al nodo i. Inoltre dai valori J(i) è possibile ricostruire in modo immediato l’albero (o uno dei possibili alberi) dei cammini minimi. La dimostrazione della correttezza della procedura segue immediatamente dal Teorema ??. Esempio 13.5.2 Come esempio consideriamo il grafo di figura 13.14. 2 3 1 1 1 3 4 1 3 Figura 13.14: Percorso minimo su grafi aciclici Si tratta di determinare l’albero dei cammini minimi tra il nodo 1 e tutti gli altri nodi. I vari passi dell’algoritmo, corrispondenti alla successione di nodi visitati, (si osservi che in questo caso particolare l’indice del passo coincide con l’indice del nodo visitato) portano alla seguente successione di valori d∗ (i) e J(i) Passo 1 2 3 4 Valore di d∗ (i) d∗ (1) = 0 d∗ (2) = 1 d∗ (3) = min{3, 1 + 1} = 2 d∗ (4) = min{1 + 3, 2 + 1} = 3 201 Valore di J(i) J(1) = 1 J(2) = 1 J(3) = 2 J(4) = 3 2 1 1 1 4 1 3 Figura 13.15: Albero dei cammini minimi Il corrispondente albero dei cammini minimi è riportato in figura 13.15 Esempio 13.5.3 Sia dato il grafo di Figura 13.16. Determinare l’albero dei cammini minimi, 1 B 3 4 2 A E 4 5 10 C F 3 3 2 D 3 2 G Figura 13.16: Grafo Esercizio 13.5.3 utilizzando l’algoritmo per grafi aciclici. Soluzione. Si deve prima numerare topologicamente il grafo. I passi sono riportati nella seguente tabella ed il grafo risultante in Figura 13.17 Passo 1 2 3 4 5 6 7 Nodo senza archi entranti A BoD B C EoG G F Nodi non ancora numerati B,C,D,E,F,G B,C,E,F,G C,E,F,G E,F,G F,G F ∅ 202 Numerazione A=1 D =2 B=3 C=4 E=5 G=6 F=7 Osserviamo che la numerazione topologica in questo esempio non é unica; infatti ai passi 2 e 5 potevamo scegliere tra due nodi. Applichiamo ora l’algoritmo. I passi sono riportati nella 1 3 3 4 2 1 5 4 5 10 4 7 3 3 2 2 3 2 6 Figura 13.17: Numerazione topologica del grafo di Figura 13.16 seguente tabella Passo 1 2 3 4 5 4 4 Valore di d∗ (i) d∗ (1) = 0 d∗ (2) = 3 d∗ (3) = 4 d∗ (4) = min{0 + 2, 3 + 2, 4 + 3} = 2 d∗ (5) = min{4 + 1, 2 + 5} = 5 d∗ (6) = min{3 + 2, 2 + 3} = 5 d∗ (7) = min{2 + 10, 5 + 4, 5 + 3} = 8 Valore di J(i) J(1) = 1 J(2) = 1 J(3) = 1 J(4) = 1 J(5) = 3 J(6) = 4 J(7) = 6 Il corrispondente albero dei cammini minimi è riportato in figura 13.18. 13.5.3 Un algoritmo per il cammino massimo su grafi aciclici Se il problema di ottimo è quello della determinazione del cammino di peso massimo sul grafo, allora è facile convincersi che basta sostituire nella formula ricorsiva al min un max e tutte le considerazioni fatta continuano, in questo caso particolare di grafi aciclici, a essere valide. L’algoritmo per il calcolo dei cammini massimi su grafici aciclici è allora il seguente - f (1) := 0; J(1) := 1; - per j = 2, 3, 4, . . . , n − 1, n ripeti la seguente serie di operazioni f (j) := maxi∈ωe (j) {f (i) + pi,j }; J(i) := valore di i per cui si è verificato il massimo; Come esempio consideriamo sempre il grafo di figura 13.14 Si tratta di determinare l’albero dei cammini massimi tra il nodo 1 e tutti gli altri nodi. I vari passi dell’algoritmo portano alla seguente successione di valori f (i) e J(i) 203 4 5 3 5 1 7 4 8 2 2 6 3 5 Figura 13.18: Albero dei cammini minimi Passo 1 2 3 4 Valore di f (i) f (1) = 0 f (2) = 1 f (3) = max{3, 1 + 1} = 3 f (4) = max{1 + 3, 3 + 1} = 4 204 Valore di J(i) J(1) = 1 J(2) = 1 J(3) = 1 J(4) = 2 (oppure J(4) = 3)