Prof. Alberto Postiglione Concetti di Base su Algoritmi, Strutture Dati e Programmazione Capitolo 4. Le prestazioni degli algoritmi 4.1. Valutazione delle prestazioni di un algoritmo 4.1.1. Un problema e due algoritmi Consideriamo il problema della somma dei primi 100 numeri interi positivi, cioè 1+2+3+...+ 99+100 e diamo il programma che implementa l’algoritmo diretto (quello che effettua una per una tutte le somme): program somma_1; Var somma, i : integer; begin somma := 0; i := 0; while i<100 do begin i := i + 1; somma := somma + i; end; writeln (somma); readln; end. Oppure utilizziamo la formula di Gauss secondo la quale 1+2+3+...+ 99+100 = (100*101)/2, e diamone l’algoritmo10: program somma_2; Var somma : real; begin somma := (100*101)/2; writeln (somma:5:0); readln; end. I due diversi procedimenti per ottenere la somma sono un esempio di due algoritmi differenti che risolvono lo stesso problema. Volendo generalizzare e risolvere il problema del calcolo della somma dei primi N numeri interi, i due algoritmi diventano: program somma_N; Var somma, i, N : integer; begin read (N); 1 somma := 0; 2 i := 0; 3 while i<N do begin 4 i := i + 1; 5 somma := somma + i; end; writeln (somma); readln; end. program somma_N_2; Var somma : real; N : integer; begin read (N); 1 somma := (N*(N+1))/2; writeln (somma:5:0); 10 Si noti che questo è un esempio di problema computazionale che ammette più di un algoritmo. Pagina:30 – Bozza del 10/05/2010 Prof. Alberto Postiglione Concetti di Base su Algoritmi, Strutture Dati e Programmazione readln; end. Ci sembra chiaro che il primo algoritmo richiede più operazioni del secondo. Cerchiamo di capire quante in più, calcolando quante operazioni effettuano i due algoritmi. Il primo algoritmo richiede (escludendo le istruzioni di Lettura/Scrittura): 2 operazioni di inizializzazione (istruzioni 1 e 2), N confronti (confronto nella istruzione 3, ripetuto N volte), 2*N somme (istruzioni 5 e 6 ripetute N volte l’una) Possiamo quindi affermare che il primo algoritmo per N=100 effettua complessivamente 2+100+200 = 302 operazioni per N=200 effettua complessivamente 2+200+400 = 602 operazioni, cioè quasi il doppio delle operazioni richieste per N=100. e cioè che il numero delle operazioni che esegue il primo algoritmo è praticamente proporzionale al valore N letto in input. Il secondo algoritmo richiede (escludendo le istruzioni di Lettura/Scrittura) sempre 3 operazioni aritmetiche: una somma, una moltiplicazione e una divisione (istruzione 1), Possiamo quindi affermare che il numero delle operazioni che esegue il secondo algoritmo è indipendente dal valore N letto in input, anzi esso esegue sempre lo stesso numero di operazioni, cioè 3. Diremo che il primo algoritmo ha un tempo di esecuzione proporzionale al numero di addendi da sommare, mentre il secondo algoritmo ha un tempo di esecuzione costante perché il numero di operazioni è sempre lo stesso, indipendentemente dal numero di elementi da sommare. Il primo algoritmo è quindi più costoso in termini di numero di operazioni rispetto al secondo. Inoltre, il primo algoritmo è tanto più costoso quanto più è grande il numero N input, mentre il secondo algoritmo ha un tempo di esecuzione che è indipendente dal valore di N, e quindi la differenza tra i due algoritmi è tanto più a vantaggio del secondo quanto più è grande N. 4.1.2. Valutazione “quantitativa” di un algoritmo Per poter stabilire quanto sia “veloce” un algoritmo ed eventualmente confrontarlo con altri algoritmi che risolvono lo stesso problema, bisognerebbe poterlo “valutare quantitativamente” e ci aspettiamo che questa valutazione sia dipendente dalla “dimensione” dei dati input (a meno di casi molto particolari) è ragionevole, infatti, aspettarsi che un algoritmo che elabora 1.000 dati input sia più veloce dello stesso algoritmo quando elabora 1.000.000 dati input. indipendente dalla velocità del singolo computer sul quale l’algoritmo verrà implementato. Noi vogliamo sapere quanto è “veloce” una soluzione, non quanti millisecondi impiega sul mio computer anche perché questo valore cambia da computer a computer e dipende, sullo stesso computer, da fattori contingenti, quali il carico globale del sistema. Vogliamo, cioè, una valutazione parametrica della velocità dell’algoritmo, legata solo al numero di operazioni che esso effettua. La teoria degli algoritmi mette a disposizione un insieme di strumenti per poter valutare un algoritmo in base ai seguenti criteri “quantitativi”: il tempo impiegato calcolato come il numero di operazioni elementari che esso fa sui dati input, mettendosi nella ipotesi del caso peggiore (Worst Case Analysis). lo spazio di memoria occupato valutato come la quantità di dati che esso ha bisogno di “vedere” contemporaneamente durante la computazione, mettendosi nella ipotesi del caso peggiore (Worst Case Analysis). Questi criteri permettono di ottenere una buona valutazione delle prestazioni di un algoritmo. Inoltre tale valutazione, essendo espressa come una funzione della dimensione dell’input, tende ad aumentare al crescere del numero dei dati in ingresso. Calcolando il numero di operazioni elementari e non l’effettivo tempo di esecuzione, si riesce a stimare, parametricamente, il tempo impiegato da un algoritmo svincolandosi dai Pagina:31 – Bozza del 10/05/2010 Prof. Alberto Postiglione Concetti di Base su Algoritmi, Strutture Dati e Programmazione valori tecnologici prestazionali del singolo computer. Il tempo effettivo di esecuzione dell’algoritmo dipende poi dal tempo che il singolo computer impiega per eseguire tali operazioni elementari. Sono requisiti “qualitativi” di un algoritmo (molto meno importanti di quelli “quantitativi”) 4.1.3. Adattabilità dell’algoritmo a situazioni diverse Semplicità Modularità Eleganza Analisi del Caso Peggiore (Worst Case Analysis) Perché analizzare il caso peggiore? Perché spesso il caso migliore non è significativo e perché, in situazioni pratiche, dobbiamo garantirci che la computazione termini comunque entro un tempo massimo, e questo è possibile valutarlo solo considerando la situazione più sfortunata (e quindi più lenta) possibile. Ad esempio, se devo valutare un algoritmo per la ricerca di una scheda in uno schedario, il caso migliore è sempre 1 (cioè trovo subito la mia scheda), indipendentemente da quante schede contiene lo schedario (10, 1.000 o 1.000.000.000), mentre la vera “velocità” dell’algoritmo la si può valutare calcolando il tempo che esso impiega quando la scheda non è presente nello schedario (che equivale al caso peggiore). In particolare, in un prossimo capitolo, analizzeremo due algoritmi che risolvono tale problema e che impiegano, nel caso peggiore e in presenza di 1.000.000.000 di schede, 1.000.000.000 di operazioni il primo e solo 30 operazioni il secondo. Pagina:32 – Bozza del 10/05/2010