Tempo e spazio di calcolo

Documenti analoghi
Tempo e spazio di calcolo

Un algoritmo realizza una relazione funzionale tra i valori di input e quelli di output

Algoritmi e Strutture Dati

Divide et impera (Divide and Conquer) Dividi il problema in sottoproblemi piu` semplici e risolvili ricorsivamente

Per regnare occorre tenere divisi i nemici e trarne vantaggio. fai ad ogni passo la scelta più conveniente

Informatica II. Capitolo 2 Analisi di algoritmi. Valutare la complessità in tempo. Complessità in tempo: cosa serve?

Gli algoritmi e la loro complessità

Definizioni di base. Algoritmo: procedura computazionale ben definita che prende valori in input e produce valori in output.

Notazioni asintotiche. Martedì 30 settembre 2014

Algoritmi e Strutture Dati

Esercizi per il corso di Algoritmi

complessità degli algoritmi

Algoritmi e Strutture Dati. Capitolo 4 Ordinamento: Selection e Insertion Sort

Lezione 4 Ugo Vaccaro

Testo di riferimento. Problema delle 12 monete. Algoritmi. Complessità degli algoritmi (cenni) Dispense del Corso di Algoritmi e Strutture Dati

Complessità degli algoritmi (cenni)

Algoritmi e Strutture di Dati I 1. Algoritmi e Strutture di Dati I Massimo Franceschet

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati. Luciano Gualà

Tecniche di analisi degli algoritmi

Tecniche di analisi degli algoritmi

COMPLESSITÀ COMPUTAZIONALE DEGLI ALGORITMI

Di cosa parliamo oggi?

Appendice B. Algoritmi e Complessità

Un esempio di calcolo di complessità: insertion sort

Notazione asintotica. notazione Ω. notazione O. notazione o notazione ω. Marina Zanella Algoritmi e strutture dati Richiami matematici 1

Algoritmi e Strutture Dati

Tempo e spazio di calcolo (continua)

Tecniche di analisi degli algoritmi

Tempo e spazio di calcolo (continua)

complessità computazionale

Laboratorio di Algoritmi e Strutture Dati

Pensiero Algoritmico. Lezione 3 23 Novembre Ripasso. Anatomia di un programma. Anatomia di un programma. Ozalp Babaoglu Università di Bologna

ESERCITAZIONI DI INTRODUZIONE AGLI ALGORITMI (A.A. 08/09)

Algoritmi e Strutture Dati

Algoritmi e strutture dati. Analisi di algoritmi Funzioni di costo, notazione asintotica

Nozioni di base (II Parte)

Algoritmi e Strutture Dati

Algoritmi di ricerca. Per ricerca si intende qui il procedimento di localizzare una particolare informazione in un elenco di dati.

Problemi e algoritmi. Il che cosa ed il come. Il che cosa ed il come. Il che cosa e il come

Complessità computazionale

sono le risorse di calcolo necessarie per la sua l esecuzione di un metodo sono tipicamente:

Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base

Crescita funzioni. 20 novembre Come possiamo confrontare le funzioni di costo che abbiamo ottenuto finora?

Proprietà delle notazioni asintotiche

Problemi e algoritmi. Il che cosa e il come. F. Damiani - Alg. & Lab. 04/05 (da U. de' Liguoro - Alg. & Spe. 03/04)

Tecniche Algoritmiche: divide et impera

Nell' Informatica è importante porsi questa domanda: Questo è l'argomento che viene trattato nella Complessità Computazionale, e si articola in due

Fondamenti di Informatica II 9. Complessità computazionale

2. Analisi degli Algoritmi

Analisi asintotica. Astrazione: come il tempo di esecuzione cresce in funzione della taglia dell input asintoticamente.

Algoritmi e Strutture Dati

Laboratorio Algoritmi 2016

Fondamenti di Informatica

COMPLESSITÀ COMPUTAZIONALE DEGLI ALGORITMI

Esercizi riassuntivi (Fondamenti di Informatica 2 Walter Didimo) Soluzioni

Algoritmi e Strutture di Dati I 1. Algoritmi e Strutture di Dati I Massimo Franceschet francesc

Algoritmi e Strutture Dati. Capitolo 4 Ordinamento

Problemi di ordinamento

COMPLESSITÀ COMPUTAZIONALE. Fondamenti di Informatica A - Massimo Bertozzi

Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano. Usa la tecnica del divide et impera:

Ordinamenti e crescita della complessità

Quick Sort. PARTITION(A,p,r) risistema il sottoarray A[p...r] e riporta l indice q:

Esempio : i numeri di Fibonacci

Macchina RAM. Modelli di calcolo e metodologie di analisi. Linguaggio di una macchina RAM. Algoritmi e Strutture Dati. Istruzioni.

Ad ogni problema computazionale possiamo associare una misura della sua complessità.

In questa lezione. Il Mergesort: primo esempio di applicazione della tecnica divide et impera analisi tempo di esecuzione del Mergesort

Algoritmi di ordinamento (I parte)

Algoritmi e Strutture Dati

Tecniche di analisi degli algoritmi

Corso di Perfezionamento

Principali strumenti per lo sviluppo di algoritmi in pascal-like. concetti universali presenti in tutti i linguaggi di programmazione

Algoritmi e Strutture Dati. Capitolo 1 Un introduzione informale agli algoritmi

Programmazione dinamica Primi esempi

Appunti lezione Capitolo 2 Analisi delle funzioni di costo

COMPLESSITA COMPUTAZIONALE. Esercitazioni Tutor: Francesca Piersigilli

Analisi algoritmi ricorsivi e relazioni di ricorrenza

Sommario. Algoritmi di ordinamento lineari: CountingSort. BucketSort. RadixSort

Complessità computazionale concreta

Costo di esecuzione. Quanto costa? Spazio. Spazio e tempo. Università Roma La Sapienza Corsi di Laurea Informatica/Tecnologie Informatiche

Esercizio. 2 i=i*2) j=j*2)

Introduzione alla programmazione Algoritmi e diagrammi di flusso. Sviluppo del software

Algoritmi di Ordinamento

Silvia Rossi. Cenni sulla complessità. Informatica. Lezione n. Parole chiave: Corso di Laurea: Insegnamento: Programmazione I

Rappresentazione degli algoritmi

ALGORITMI Docente: Prof. Domenico Cantone

Algoritmo di ordinamento sul posto che ha tempo di esecuzione :

Esercizi per il corso di Algoritmi, anno accademico 2011/12

2.1 Computational Tractability. Chapter 2. Basics of Algorithm Analysis. Efficienza degli algoritmi. Efficienza degli algoritmi

Note per la Lezione 2 Ugo Vaccaro

Calcolare x n = x x x (n volte)

Algoritmi (e Complessità)

Albero di Riscorsione

Algoritmi di ordinamento

Informatica Teorica. Macchine a registri

Sommario. Un algoritmo di ordinamento di complessità lineare: CountingSort. [CLRS10] cap. 8 par.8.2

Esercitazioni di Algoritmi e Strutture Dati

Transcript:

Tempo e spazio di calcolo Modelli di calcolo e metodologie di analisi In quale modo stimiamo il tempo di calcolo? Possiamo considerare due approcci: Approccio empirico (a posteriori) Approccio teorico (a priori) SECONDO VOI QUALE STUDIEREMO IN QUESTO CORSO? SECONDO VOI QUALE E IL PIU UTILE IN PRATICA? Sviluppiamo una metodologia per l approccio teorico Per sviluppare la metodologia per stimare il tempo e lo spazio di calcolo dobbiamo precisare: 1. Linguaggio per descrivere gli algoritmi 2. Modello computazionale d esecuzione 3. Metrica per misurare il tempo di calcolo 4. Modo per caratterizzare il tempo di calcolo per gli algoritmi ricorsivi

1. Linguaggio per descrivere gli algoritmi Pseudo-codice Java-like: assegnazione: i j k equivale alla seq.: j k; i j espressioni: simboli matematici standard per espressioni numeriche e booleane commento: { } dichiarazione di metodo: nome (param 1, param 2,...) chiamata di un metodo: nome (param 1, param 2,...) ritorno da un metodo: return valore Pseudo-codice Java-like (continua): dati composti: i-esimo elemento array A: A[i] A[i.. j] <A[i], A[i+1],..., A[j]>, se i j sequenza vuota, se i > j i dati composti sono organizzati in oggetti, che sono strutturati in attributi o campi: ad es. length[a] una variabile che rappresenta un oggetto è un riferimento un riferimento che non si riferisce a nessun oggetto: nil parametri alle procedure passati per valore (per gli oggetti una copia del riferimento) Pseudo-codice Java-like (continua): struttura di blocco: spaziatura costrutti iterativi e condizionali : if condizione then azioni (else azioni) while condizione do azioni do azioni while condizione for variabile val-iniz. to val-fin. (incremento) do azioni for variabile val-iniz. downto val-fin. (decremento) do azioni

2. Il modello computazionale d esecuzione Consideriamo come operazioni primitive le seguenti operazioni : 1. assegnazione di un valore ad una variabile 2. chiamata di un metodo 3. eseguire un operazione aritmetica 4. confronto di due numeri 5. indicizzazione di un elemento in un array 6. riferimento a un oggetto 7. rientro da un metodo Assunzione implicita: il numero di operazioni primitive è proporzionale al tempo di esecuzione dell algoritmo Questo approccio dà origine al modello computazionale chiamato Random Access Machine (RAM): CPU connessa a un banco di celle di memoria ogni cella memorizza una parola (un numero, un carattere,... In generale: il valore di un tipo di base o un riferimento ad un oggetto) la CPU accede ad una cella di memoria arbitraria con una operazione primitiva (ogni operando e una cella di memoria) La quantità di tempo (e di spazio) consumato dall esecuzione di un programma RAM su un dato input può essere determinato essenzialmente usando due criteri: Criterio di costo uniforme: l esecuzione di un istruzione primitiva richiede un tempo indipendente dalla grandezza degli operandi (ricordate: un operando e o un valori di un tipo base o un riferimento ad un oggetto) Criterio di costo logaritmico: il tempo di calcolo richiesto da un istruzione primitiva dipende dal numero di bit necessari a rappresentare gli operandi

3. Metrica per misurare il tempo di calcolo Misureremo il tempo di calcolo contando le operazioni primitive Ad esempio: Massimo (A, n) current-max A[0] for i 1 to n-1 do if current-max < A[i] then current-max A[i] return current-max 2 1 + n Numero di operazioni primitive: t (n) = minimo 2 + 1 + n + 4*(n-1) + 1 = 5*n massimo 2 + 1 + n + 6*(n-1) + 1 = 7*n - 2 1 4*(n-1) 6 *(n-1) In generale, istanze diverse avranno tempi di calcolo diversi, ad esempio: tempo di calcolo 5 ms 3 ms tempo nel caso peggiore tempo nel caso migliore 1 ms A B C D E F G istanze in input Analisi del caso medio Il tempo di calcolo medio dell algoritmo definito come media dei tempi per tutti i possibili input Per poterlo calcolare si deve conoscere la distribuzione di probabilità sull insieme dei possibili input In generale si tratta di un compito non banale. In mancanza di informazioni si puo assumere una distribuzione uniforme, ma si tratta di un assunzione arbitraria!

Analisi del caso peggiore non richiede teoria probabilità caso peggiore quasi sempre facile da identificare se un algoritmo si comporta bene nel caso peggiore, si comporta bene su ogni input (fornisce una garanzia!) Analisi del caso ottimo non richiede teoria probabilità caso ottimo quasi sempre facile da identificare se un algoritmo si comporta male nel caso ottimo, si comporta male su ogni input 4. Modo per caratterizzare il tempo di calcolo degli algoritmi ricorsivi Equazione di ricorrenza: una funzione che esprime il numero di operazioni sull input di dimensione n in funzione del numero di operazioni su input di dimensione inferiore. Ad esempio: { n > 1} Massimo-ricorsivo (A, n) if n = 1 then return A[0] return max (Massimo-ricorsivo (A, n-1), A[n-1]) T(n) = 3 se n = 1 T(n-1) + k altrimenti T(n) = k*(n-1) + 3 ESEMPIO: tempo di calcolo della moltiplicazione per somme successive Moltiplicazione per somme successive y x2 45 19 44 19 43 19.. 4 19 3 19 2 19 1 19 855 moltiplicazione (x1, x2) y x1 prod 0 while y > 0 do prod prod + x2 y y - 1 return prod

ESEMPIO: tempo di calcolo della moltiplicazione alla russa Moltiplicazione alla russa y1 y2 45 19 19 22 38 --- 11 76 76 5 152 152 2 304 --- 1 608 608 855 molt-russa (x1, x2) y1 x1 y2 x2 prod 0 while y1 > 0 do if y1 is odd then prod prod + y2 y1 y1 div 2 y2 y2 + y2 return prod Moltiplicazione per somme successive vs moltiplicazione alla russa moltiplicazione (x1, x2) y x1 prod 0 while y > 0 do prod prod + x2 y y - 1 return prod molt-russa (x1, x2) y1 x1 y2 x2 prod 0 while y1 > 0 do if y1 is odd then prod prod + y2 y1 y1 div 2 y2 y2 + y2 return prod moltiplicazione molt-russa nel while 2 * x1 assegnazioni 3 * lg x1 assegnazioni x1 somme lg x1 divisioni x1 decrementi 2 * lg x1 somme x1+1 confronti 2 * lg x1 + 1 confronti 5 * x1+1 + 3 operazioni 8 lg x1+1 + 4 operazioni 60 f(m) = 5m + 4 g(m) = 8 lg m + 5 54 50 49 44 numero di operazioni 40 30 20 14 19 17,68 24 21 29 23,58 34 25,68 39 27,46 29 30,36 31,58 10 9 13 4 5 0 0 1 2 3 4 5 6 7 8 9 10 11 moltiplicatore

LA NOTAZIONE ASINTOTICA Introduciamo un ulteriore astrazione : tasso di crescita o ordine di grandezza del tempo di calcolo ogni passo nello pseudo-codice (e ogni statement in un linguaggio ad alto livello) corrisponde a un piccolo numero di operazioni primitive che non dipendono dalla dimensione dell input basta considerare il termine principale perchè i termini di ordine inferiore non sono significativi per n grande. L ordine di grandezza del tempo di calcolo fornisce una semplice caratterizzazione dell efficienza e consente di confrontare algoritmi alternativi. Efficienza asintotica degli algoritmi: come cresce il tempo di esecuzione con il crescere al limite della dimensione delle istanze in input Notazione asintotica Consideriamo funzioni dai naturali ai numeri reali non negativi Notazione O: O (g(n)) e l insieme di tutte le funzioni f(n) per cui esistono due costanti positive c ed n 0 tali che f(n) c g(n) per tutti gli n n 0 c g(n) tem po di run f(n) n 0 f(n) O (g(n)) n

Notazione Ω: Ω(g(n)) e l insieme di tutte le funzioni f(n) per cui esistono due costanti positive c ed n 0 tali che f(n) c g(n) per tutti gli n n 0 f(n) tem po di run c g(n) n 0 f(n) Ω (g(n)) n Notazione Θ: Θ(g(n)) e l insieme di tutte le funzioni f(n) per cui esistono tre costanti positive c 1, c 2 ed n 0 tali che c 1 g(n) f(n) c 2 g(n) per tutti gli n n 0 c 2 g(n) tem po di run f(n) c 1 g(n) n 0 f(n) Θ (g(n)) n Proprietà della notazione asintotica Transitiva: f(n) = Θ (g(n)) e g(n) = Θ (h(n)) f(n) = O (g(n)) e g(n) = O (h(n)) f(n) = Ω (g(n)) e g(n) = Ω (h(n)) f(n) = Θ (h(n)) f(n) = O (h(n)) f(n) = Ω (h(n)) Riflessiva: f(n) = Θ (f(n)) f(n) = O (f(n)) f(n) = Ω (f(n)) Simmetrica: f(n) = Θ (g(n)) g(n) = Θ (f(n)) Simmetrica trasposta: f(n) = O (g(n)) g(n) = Ω (f(n))

d(n) = O(f(n)) a. d(n) = O(f(n)), per ogni costante a > 0 d(n) = O(f(n)) & e(n) = O(g(n)) d(n) + e(n) = O(f(n) + g(n)) d(n) = O(f(n)) & e(n) = O(g(n)) d(n). e(n) = O(f(n). g(n)) f(n) funzione polinomiale di grado d: f(n) = a 0 + a 1 n +... + a d n d f(n) = O(n d ) Alcune classi di complessità trattabili non trattabili O(log n) O(n) O(n 2 ) O(n k ) (k 1) O(a n ) (a > 1) logaritmica lineare quadratica polinomiale esponenziale Alcune funzioni ordinate per velocità di crescita n log n n n n log n n 2 n 32 2 n 2 1 1,41 2 2 4 8 4 4 2 2 4 8 16 64 16 8 3 2,83 8 24 64 512 256 16 4 4 16 64 256 4.096 65.536 32 5 5,66 32 160 1.024 32.768 4.294.967.296 64 6 8 64 384 4.096 262.144 1,84 x 10 19 128 7 11,31 128 896 16.384 2.097.152 3,40 x 10 38 256 8 16 256 2.048 65.536 16.777.216 1,15 x 10 77 512 9 22,63 512 4.608 262.144 134.217.728 1,34 x 10 154 1.024 10 32 1.024 10.240 1.048.576 1.073.741.824 1,79 x 10 308

10 10 logn radn 9 9 9 n n logn 8 8 8 8 8 n^2 n^3 7 7 2^n 6 6 5 4,75 5 4 3 2 1 4 3 2 1,73 1,41 1,58 1 2 2 4 3,17 2,81 3 2,58 2,32 3 2,83 2,65 2,24 2,45 3,58 3,32 3,46 3,16 3,32 3,46 0 2 3 4 5 6 7 8 9 10 11 12 60 50 40 logn radn n n logn n^2 n^3 2^n 30 20 10 0 2 3 4 5 6 7 8 9 10 11 12 4500 4000 3500 3000 logn radn n n logn n^2 n^3 2^n 2500 2000 1500 1000 500 0 2 3 4 5 6 7 8 9 10 11 12

ESEMPIO: tempo di calcolo dell algoritmo di ordinamento per inserzione Problema: ordinamento di numeri. Input: una sequenza di n numeri <a 1, a 2,,a n >. Output: una permutazione <a 1, a 2,,a n > della sequenza di input tale che a 1 a 2 a n. 1 2 3 4 5 3 5 1 8 2 key = 5 1 2 3 4 5 3 5 1 8 2 key = 1 1 2 3 4 5 1 3 5 8 2 3 5 5 8 2 1 3 5 8 2 3 3 5 8 2 key = 8 1 2 3 4 5 1 3 5 8 2 key = 2 1 3 5 8 8 1 3 5 5 8 1 3 3 5 8 1 2 3 5 8 Insertion-sort (A) num. volte j 2 1 1 forj 2 to length[a] do n 2 key A[j] n 1 3 {inserisci A[j] nella sequenza A[1..j-1] } NON E UN INVARIANTE! spostando a destra gli elementi > di A[j]} 4 i j 1 n 1 5 while i > 0 and A[i] > key do Σ t j ( j=2..n) 6 A[i+1] A[i] Σ(t j 1) ( j=2..n) 7 i i 1 Σ(t j 1) ( j=2..n) 8 A[i+1] key n 1 j j+1 n 1 T(n) = 1 + a*n + b*(n-1) + c*σ t j + d*σ(t j 1) = = (a + b)*n + (1 b) + c*σ t j + d*σ(t j 1)

T(n) = 1 + a*n + b*(n 1) + c*σ t j + d*σ(t j 1) = = (a + b) *n + (1 b) + (c+d)* Σ t j n + 1 = = (a + b 1)*n + (2 b) + (c+d)* Σ t j = = e*n + f + g* Σ t j Caso migliore: A è ordinato T(n) è una funzione lineare di n. Caso peggiore: A è ordinato in ordine inverso T(n) è una funzione quadratica di n. Caso medio (considerando ogni permutazione è ugualmente probabile) T(n) è una funzione quadratica di n. ESEMPIO: il problema della valutazione di un polinomio Input: una sequenza di n+1 numeri reali A = <a 0, a 1,,a n > e il valore della variabile x Output: il valore del polinomio di grado n: P(x) = a 0 +a 1 x+ + a n x n Un algoritmo che risolve il problema: Poly-eval (A, x, n) 1 y 1 2 result A[0] 3 fori 1 to n do 4 y y x 5 result result +A[i] y {y = x i } 6 return result L algoritmo esegue 2*n moltiplicazioni n somme e 2*n assegnazioni. Ma si può fare meglio La regola di Horner: P(x) = a 0 +x (a 1 + +x (a n-1 + x a n )) ) Un algoritmo basato sulla regola di Horner: Horner (A, x, n) 1 result A[n] 2 fori n - 1 downto 0 do 3 result result x+ A[i] 4 return result L algoritmo esegue n somme, n moltiplicazioni e n assegnazioni.

Poly-eval (A, x, n) 1 y 1 2 result A[0] 3 fori 1 to n do 4 y y x 5 result result +A[i] y 6 return result Horner (A, x, n) 1 result A[n] 2 fori n - 1 downto 0 do 3 result result x+ A[i] 4 return result fuori dal for confronti nel for Poly-eval Horner 5 4 n + 1 n + 1 8*n 6*n Poly-eval: 9*n + 6 Horner: 7*n + 5 1200 1000 800 600 400 200 0 1005 915 825 735 782 645 712 555 642 572 465 502 375 432 285 362 292 195 222 82 152 12 105 15 1 11 21 31 41 51 61 71 81 91 101 111 T(n) = 9 n + 6 T(n) = 7 n + 5 L algoritmo Horner è sicuramente migliore dell algoritmo Poly-eval L analisi asintotica non distingue però tra i due algoritmi: per entrambi si ottiene Θ(n)

RIEPILOGO Una metodologia per l approccio teorico alla stima del tempo di calcolo Analisi dei casi medio, peggiore, ottimo Efficienza asintotica degli algoritmi Risposta ad alcune domande lasciate in sospeso durante le lezioni precedenti. ESERCIZIO: Rispondete alle seguenti domande. Quali domande restano ancora in sospeso? Adesso abbiamo gli strumenti per rispondere a qualcuna di esse? Se si, quali sono le risposte? UN ALTRO ESERCIZIO La correttezza degli algoritmi considerati nei lucidi precedenti (o di loro minime varianti) e stata dimostrata (nelle lezioni precedenti) con il metodo delle asserzioni. ANNOTATE (SCRIVENDO SULLA STAMPA DEI LUCIDI) IL CODICE CON LE ASSERZIONI CHE NE DIMOSTRANO LA CORRETTEZZA. In questo modo vi sara piu facile seguire il ragionamento sulla loro complessita!!!