Analisi di un algoritmo

Slides:



Advertisements
Presentazioni simili
Puntatori Linguaggio C.
Advertisements

Strutture dati per insiemi disgiunti
Elementi di complessità
INFORMATICA Algoritmi fondamentali
1 Introduzione ai calcolatori Parte II Software di base.
Analisi della complessità degli algoritmi
Analisi della complessità degli algoritmi
Lez. 51 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Complessita'
Hash Tables Indirizzamento diretto Tabelle Hash Risoluzioni di collisioni Indirizzamento aperto.
Alberi binari di ricerca
1 Istruzioni, algoritmi, linguaggi. 2 Algoritmo per il calcolo delle radici reali di unequazione di 2 o grado Data lequazione ax 2 +bx+c=0, quali sono.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
Caratteri e stringhe di caratteri
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
Iterazione enumerativa (for)
Algoritmi e Strutture Dati Capitolo 2 Modelli di calcolo e metodologie di analisi.
Algoritmi Paralleli e Distribuiti a.a. 2008/09
2 Sistema composto da un numero elevato di componenti, in cui ogni componente svolge una sua funzione elaborazione dati memorizzazione dati trasferimento.
Informatica di base A.A. 2003/2004 Algoritmi e programmi
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Capitolo 1 Unintroduzione.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Algoritmi e Strutture Dati Capitolo 2 Modelli di calcolo e metodologie.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Capitolo 9 Il problema della gestione di insiemi disgiunti (Union-find) Algoritmi e Strutture Dati.
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Problemi e algoritmi Anno Accademico 2009/2010.
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
Algoritmi e Strutture Dati (Mod. A)
Algoritmi e Strutture Dati Introduzione. Gli argomenti di oggi Analisi della bontà degli algoritmi Modello Computazionale Tempo di esecuzione degli algoritmi.
Algoritmi e Strutture Dati Valutazione del tempo di esecuzione degli algoritmi.
Programmazione Un programma descrive al computer, in estremo dettaglio, la sequenza di passi necessari a svolgere un particolare compito L’attività di.
1 2. Analisi degli Algoritmi. 2 Algoritmi e strutture dati - Definizioni Struttura dati: organizzazione sistematica dei dati e del loro accesso Algoritmo:
Algoritmi di ordinamento
Introduzione1 Algoritmi e strutture dati - Definizioni Struttura dati: organizzazione sistematica dei dati e del loro accesso Algoritmo: procedura suddivisa.
07/04/2003Algoritmi Ricerca in una sequenza di elementi Data una sequenza di elementi, occorre verificare se un elemento fa parte della sequenza oppure.
Il Linguaggio Macchina
memoria gestita staticamente:
Notazioni Asintotiche e Ordini di Grandezza delle funzioni
Fondamenti di Informatica1 Ripetizioni di segmenti di codice Spesso è necessario ripetere più volte uno stesso segmento dell'algoritmo (e.g. I/O, elaborazioni.
Le funzioni.
Fibonacci Heaps e il loro utilizzo nell’algoritmo di Prim
1 Programmazione = decomposizione basata su astrazioni (con riferimento a Java)
Elementi di Informatica di base
Ordinamento dell’array
Esercizio 10.* Un cassiere vuole dare un resto di n centesimi di euro usando il minimo numero di monete. a) Descrivere un algoritmo goloso per fare ciò.
1 ListaDiElem Cancella( ListaDiElem lista, TipoElemento elem ) { ListaDiElem puntTemp; if( ! ListaVuota(lista) ) if( lista–>info == elem ) { puntTemp =
30 ottobre Mergesort F. Bombi 30 ottobre 2002.
Strutture dati per insiemi disgiunti
Un esempio: Calcolo della potenza n-esima di un numero reale
Unità Didattica 3 Linguaggio C
28 ottobre Mergesort F. Bombi 28 ottobre 2003.
I metodi F. Bombi Campi e metodi Abbiamo visto che una classe può contenere – Campi – Metodi stato I campi sono utilizzati per memorizzare.
Complessità di un algoritmo
Sistemi e Tecnologie Informatiche Ricorsione Umberto Ferraro Petrillo.
1 Record, tabelle, relazioni F. Bombi 1 novembre 2001.
Implementazione di dizionari Problema del dizionario dinamico Scegliere una struttura dati in cui memorizzare dei record con un campo key e alcuni altri.
R 255 G 211 B 8 R 255 G 175 B 0 R 127 G 16 B 162 R 163 G 166 B 173 R 104 G 113 B 122 R 234 G 234 B 234 R 175 G 0 B 51 R 0 G 0 B 0 R 255 G 255 B 255 Supporting.
La ricorsione.
Didattica e Fondamenti degli Algoritmi e della Calcolabilità Quarta giornata Risolvere efficientemente un problema in P: la sequenza di Fibonacci Guido.
Informatica Lezione 5 Scienze e tecniche psicologiche dello sviluppo e dell'educazione (laurea triennale) Anno accademico:
Calcolatori Elettronici Valutazione delle Prestazioni Francesco Lo Presti Rielaborate da Salvatore Tucci.
13 ottobre Decisioni F. Bombi 13 ottobre 2002.
ALLOCAZIONE STATICA: LIMITI Per quanto sappiamo finora, in C le variabili sono sempre dichiarate staticamente –la loro esistenza deve essere prevista e.
Esercizi.
Informatica 4 La ricorsione. Definizione di ricorsione Ricorsione è la proprietà di quei programmi che, all’interno delle istruzioni che li compongono,
Complessità Computazionale
Hardware Struttura fisica (architettura) del calcolatore formata da parti meccaniche, elettriche, elettroniche.
Sistemi e Tecnologie Informatiche Complessità di calcolo.
Informatica 3 V anno.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Capitolo 1 Un’introduzione.
Rudimenti di Complessità Corso di Programmazione II Prof. Dario Catalano.
Hardware Struttura fisica (architettura) del calcolatore formata da parti meccaniche, elettriche, elettroniche.
Transcript della presentazione:

Analisi di un algoritmo F. Bombi 17 novembre 2003 17.11.2003

Analisi delle risorse Per valutare la qualità di un algoritmo siamo interessati a valutare le risorse di cui ha bisogno un programma che lo realizzi Consideriamo i componenti principali di un calcolatore Unità centrale di elaborazione (CPU) Memoria centrale Dispositivi di memoria di massa Nella nostra trattazione elementare abbiamo studiato solo algoritmi che operano con i dati in memoria per cui analizzeremo solo l’utilizzo della CPU e della memoria centrale 17.11.2003

Utilizzo della memoria Nel nostro modello semplificato di calcolatore possiamo pensare che la memoria centrale sia divisa in tre aree distinte o segmenti Il segmento statico utilizzato per contenere il codice del programma e le costanti Il segmento dinamico (free store o heap) utilizzato per contenere gli oggetti creati dinamicamente e soggetto a garbage collection Lo stack (run time stack) utilizzato per l’allocazione delle variabili locali create all’interno di un blocco al momento della sua attivazione 17.11.2003

Il segmento statico Gli algoritmi elementari, oggetto del nostro corso, portano a programmi di modeste dimensioni per cui l’utilizzo di memoria per la parte statica può essere trascurato Non dobbiamo comunque dimenticare che è possibile aumentare la velocità di un programma trasformando un ciclo in una sequenza di istruzioni senza confronti e salti. In questo modo si risparmia sulla risorsa tempo a spese dell’impiego di memoria statica 17.11.2003

Memoria dinamica L’ingombro della memoria dinamica è invece un parametro che ci può aiutare a scegliere fra soluzioni diverse di un problema In certi casi infatti è possibile individuare soluzioni che richiedono un tempo minore a spese di un maggior utilizzo della memoria. Ad esempio: mergesort richiede uno spazio di memoria doppio, rispetto agli algoritmi elementari, per contenere una copia del vettore da ordinare un dizionario in una tabella, quando le chiavi sono sparse, richiede di utilizzare molto più spazio di una rappresentazione con una lista 17.11.2003

Utilizzo del run time stack Lo stack durante l’esecuzione di un programma contiene le variabili dichiarate all’interno del blocco che costituisce il corpo di ogni metodo Le variabili vengono allocate al momento dell’attivazione del blocco e rilasciate quando si esce dal blocco per cui occupano spazio solo durante le chiamate al metodo L’utilizzo dello stack può essere un fattore critico nei metodi ricorsivi in quanto un nuovo blocco viene creato ad ogni attivazione ricorsiva di un metodo senza rilasciare il blocco precedente Le dimensioni dello stack sono quindi proporzionali alla profondità di ricorsione che rappresenta di conseguenza un parametro importante per valutare la qualità della soluzione adottata 17.11.2003

Utilizzo della CPU: il tempo Nel nostro modello l’unità centrale di elaborazione esegue ciclicamente una istruzione alla volta, di conseguenza il tempo necessario alla soluzione di un dato problema è proporzionale al numero di cicli (inversamente proporzionale alla frequenza di clock del processore utilizzato e proporzionale al numero di istruzione eseguite) Il tempo necessario a risolvere un dato problema rappresenta spesso il parametro più importante nella valutazione della qualità di un algoritmo Infatti mentre possiamo immaginare di aumentare le dimensioni della memoria di una macchina a piacere, il tempo non è un bene replicabile Vedremo come anche aumentando la frequenza di clock algoritmi inefficienti non consentono di risolvere problemi di grandi dimensioni 17.11.2003

Il tempo Per valutare il tempo necessario alla soluzione di un dato problema sarebbe necessario stimare il numero di istruzioni in funzione delle dimensioni o taglia del problema La stima è impossibile quando si utilizzi un linguaggio ad alto livello in quanto il numero di istruzioni macchina corrispondente ad una istruzione nel linguaggio ad alto livello dipende dal compilatore impiegato È comunque significativo stimare quale sia il comportamento asintotico del numero di istruzioni necessario alla soluzione del problema in funzione della taglia, a meno di una costante Tale stima viene comunemente indicato come complessità temporale dell’algoritmo impiegato 17.11.2003

Comportamento asintotico Le funzioni che legano il numero di istruzioni necessarie alla soluzione di un problema alla sua taglia n non sono, come vedremo con qualche esempio, in genere continue e non ammettono un limite per n tendente all’infinito Per descrivere il comportamento asintotico ci dobbiamo accontentare di una stima del limite superiore utilizzando la notazione O-grande Indichiamo con O(g(n)) un insieme di funzioni I = {f’(n), f”(n), …} per ognuna delle quali esistono due costanti positive c e n0 tali per cui 0  f(n)  c•g(n) per ogni n  n0 per indicare che una funzione appartiene all’insieme si dice f(n) è O(g(n)) 17.11.2003

f(n) c•n f(n)= O(n) n n0 n 17.11.2003

Attenzione Fare attenzione che dalle definizioni date una funzione che è O(n) è anche O(n2) oppure O(n3) In genere nel valutare il comportamento asintotico si cercherà di trovare la funzione che cresce più lentamente e che quindi limita in modo più stretto il comportamento asintotico 17.11.2003

Esempio: ricerca in un vettore Rivediamo, come ripasso, l’analisi dell’algoritmo di ricerca di un elemento in un vettore, il metodo restituisce la posizione dell’elemento cercato se presente, -1 se non presente int scansione (Comparable x, Comparable[] v, int n) { for (int i = 0; i < n; i++) if (x.compareTo(v[i]) == 0) return i; return -1; } Per chiarezza conviene per prima cosa riscrivere il programma trasformando il ciclo for in un ciclo while equivalente 17.11.2003

Se supponiamo ora di conoscere il tempo necessario per eseguire int scansione (Comparable x, Comparable[] v, int n) { int i = 0; while (i < n) { if (x.compareTo(v[i]) == 0) return i; i++; } return -1; Se supponiamo ora di conoscere il tempo necessario per eseguire ciascuna istruzione siamo in grado di valutare il tempo necessario a risolvere il problema determinando quante volte ciascuna istruzione verrà eseguita in funzione dei dati in ingresso. Indichiamo con ki il tempo necessario all’esecuzione di ciascuna istruzione, l’unica cosa importante è essere sicuri che le costanti non dipendano dalla taglie del problema che nel nostro caso è la lunghezza n del vettore su cui si deve effettuare la ricerca 17.11.2003

k3 { if (x.compareTo(v[i]) == 0) k4 return i; k5 i++; } k6 return -1; k1 int i = 0; k2 while (i < n) k3 { if (x.compareTo(v[i]) == 0) k4 return i; k5 i++; } k6 return -1; 1 int i = 0; c+1-s while (i < n) c { if (x.compareTo(v[i]) == 0) s return i; c-s i++; } 1-s return -1; Il tempo complessivo necessario a ritrovare l’elemento cercato è dato da: t=f(n)=k1 +(c+1-s)k2 + ck3 + sk4 + (c-s)k5 + (1-s)k6 i = 0 while (i < n) if (x.compareTo(v[i]) == 0) return i i++ return -1 s = 1 successo c = posizione ---------------- s = 0 insuccesso c = n 17.11.2003

Il tempo complessivo necessario a ritrovare l’elemento cercato è dato da: t=f(n)= k1 + (c+1-s)k2 + ck3 + sk4 + (c-s)k5 + (1-s)k6 e quindi: t=f(n)= k1+k2+k6 + s(k4-k2-k5-k6) + c(k2+k3+k5) = a1 + a2 s + a3 c Se l’elemento cercato non è presente: s = 0, c = n t = a1 + a3 n Se l’elemento cercato è presente al posto c: s = 1 Caso migliore (c = 1) t = a1 + a2 + a3 Caso peggiore (c = n) t = a1 + a2 + a3n Caso medio (tutte le posizioni sono equiprobabili) t = a1 + a2 + a3(n+1)/2 17.11.2003

Conclusioni Le costanti k o a delle espressioni appena viste dipendono dal compilatore impiegato e dal processore In particolare sappiamo che sono (in prima approssimazione) inversamente proporzionali al clock della macchina impiegata Indipendentemente da questi parametri possiamo però dire che la ricerca richiede un tempo che è O(n) in caso di insuccesso e, in caso di successo, in media o nel caso peggiore. Il tempo richiesto è invece O(1) nel caso migliore 17.11.2003

Il paradosso del comportamento asintotico È ragionevole domandare perché siamo tanto preoccupati dal tempo impiegato da un algoritmo per risolvere un dato problema Sappiamo che ogni 18 mesi i microelettronici sfornano un nuovo processore che ha circa il doppio della potenza di calcolo del precedente, se un problema non è risolvibile con la tecnologia di oggi sarà risolvibile domani? Questo è vero solo se disponiamo di un algoritmo efficiente per la soluzione del problema e ce ne possiamo rendere conto osservando la seguente tabella 17.11.2003

Tempo in funzione di n 1 10 100 1000 log n 2 3  n 32 n n log n 200 2 3  n 32 n n log n 200 3000 n2 10000 1e6 n3 1e9 2n 1e3 1e30 1e300 17.11.2003

Dimensioni massime del problema risolvibile Nella prossima tabella consideriamo le dimensioni di un problema risolvibile in 1 secondo, 1 minuto, 1 ora o 1 giorno supponendo di utilizzare algoritmi che richiedono un tempo pari a 0.1f(n) secondi Possiamo notare che il passaggio dalla prima alla seconda colonna corrisponde all’utilizzo di un tempo 60 volte maggiore oppure, a parità di tempo, di un processore 60 volte maggiore (circa 9 anni di progresso tecnologico) 17.11.2003

Dimensioni in funzione del tempo 10 f(n) 1 sec 1 minuto 1 ora 1 giorno log n 100 6e3 1e36000 1e864000  n 3.6e5 1.3e9 7.5e11 n 10 600 3.6e4 8.6e5 n log n 250 9.1e3 1.65e5 n2 3 24 190 930 n3 2 8 33 95 2n 9 15 20 17.11.2003