Sei sulla pagina 1di 26

Fondamenti di Informatica B

II Facolt di Ingegneria - Cesena a.a 2011/2012

COMPLESSIT COMPUTAZIONALE

TEMPO e MEMORIA Quando si esegue un programma si spesso interessati a stimare il tempo di calcolo e l'occupazione di memoria. Esempi:
Ordinamento di vettori Ricerca di un elemento in una lista Soluzione di un problema combinatorio (e.g., orari, turni di lavoro, allineamento di sequenze di DNA)

ESEMPIO Si supponga di avere un vettore A di n interi positivi; si vuole sapere se gli n numeri sono tutti distinti. Formalmente:
Input: A (di dimensione n) Output: YES/NO (i.e., tutti distinti/almeno due uguali)

ESEMPIO: soluzione 1 Una prima soluzione:


per ogni intero del vettore, scandire il vettore per verificare se esiste un altro intero uguale e, quando ci si verifica, stampare NO e fermarsi; altrimenti, se si giunge alla fine del ciclo, stampare YES

Algoritmo scan fori 1ton1do forj i+1tondo ifA(i)=A(j) thenoutput'NO'; exit output'YES'

Programma scan.c
#include<stdio.h> #defineN12 intmain(){ intA[N]={86,63,39,98,96,38,68,88,66,83,81,87}; inti,j; for(i=0;i<N1;++i){ for(j=i+1;j<N;++j){ if(A[i]==A[j]){ printf("NO\n"); return0; } } } printf("YES\n"); return0; }

Memoria occupata dal programma Una stima della memoria occupata data dallo spazio allocato (su stack e heap) per le strutture dati:
vettore: n * sizeof(int) variabili indice: 2 * sizeof(int) totale: (n+2)*sizeof(int)

Spesso si fornisce la stima omettendo la dimensione dell'unit di memoria

Tempo di esecuzione del programma Il tempo effettivo dipende da n e dalle caratteristiche dell'istanza Per esempio, se i numeri sono tutti distinti si uscir dal programma dopo avere controllato tutti gli interi; se, invece, il vettore inizia con due interi uguali, ci si arresta al primo controllo Occorre quindi chiarire l'oggetto della stima.

Complessit temporale Caso peggiore (worst case): stima del tempo richiesto per risolvere l'istanza nel caso pi sfortunato. Caso medio (average case): stima del tempo richiesto per risolvere l'istanza nella media dei casi. Caso tipico (typical case): stima sperimentale (statistica) del tempo di esecuzione necessario per risolvere un dato insieme di istanze.

Stima del tempo nel caso peggiore Si supponga che le istruzioni richiedano tutte lo stesso tempo di esecuzione Stimiamo con una costante b il tempo richiesto per eseguire il controllo e le istruzioni del blocco relativo tempo(scan) b (n-1 + n-2 + n-3 + ... + 1) = 2 = b n(n-1)/2 = b(n - n)/2

Stima del tempo nel caso peggiore Stima asintotica: per prescindere dalla specifica implementazione delle istruzioni, si considera solo l'ordine di grandezza e si stima come il tempo di calcolo dipenda da n, per n Quindi: tempo(scan) n2

Notazione O grande Una funzione f(n) si dice essere un O grande di una funzione g(n) se esistono un intero N e una costante c tali che f(n) cg(n), per n N e si scrive: f(n) = O(g(n)) Se anche g(n) = O(f(n)), allora si dice che le due funzioni hanno lo stesso ordine di grandezza

Complessit di scan nel caso peggiore

L'algoritmo scan ha complessit temporale nel caso peggiore pari a: Tw(n) = O(n2) e complessit spaziale: Sw(n) = O(n)

ESEMPIO: soluzione 2 Una soluzione alternativa:


Scandire A e memorizzarne ogni elemento in un nuovo vettore B, inizialmente con elementi a zero, con la seguente regola: B(A(i)) = 1 Se si trova B(A(i)) 0, allora stampare 'NO' e terminare altrimenti, se si giunge alla fine del ciclo, stampare 'YES'

Algoritmo store fori 1tomdo


B(i) 0

fori 1tondo ifB(A(i))0 thenoutput'NO'; exit elseB(A(i)) 1 output'YES'

Programma store.c
#include<stdio.h> #defineN12 #defineM100 intmain(){ inta[N]={86,63,39,98,96,38,68,88,66,83,81,83}; intb[M]; inti; for(i=0;i<M;++i)b[i]=0; for(i=0;i<N;++i){ if(b[a[i]]!=0){ printf("NO\n"); return0; } elseb[a[i]]=1; } printf("YES\n"); return0;}

Osservazioni La lunghezza di B deve essere almeno pari al massimo intero contenuto in A, che indichiamo con m La tecnica di memorizzazione dei dati usata nell'esempio alla base delle strutture dati hash Tramite opportuna procedura di allocazione di B, possibile evitare il ciclo di azzeramento. In C, si pu usare la procedura calloc()

Complessit nel caso peggiore Tw(n,m) = O(n+m), oppure, se il tempo per l'azzeramento trascurabile, Tw(n) = O(n) Sw(n,m) = O(n+m)

Confronto: n vs n

Complessit: note
Se lo spazio richiesto non esorbitante, il requisito principale relativo al tempo di calcolo Per alcuni problemi possibile dimostrare che l'algoritmo pi efficiente ha una certa complessit temporale nel caso peggiore (e si dice che il problema ha quella complessit) ordinamento: O(n log n) fondamentale considerare anche la complessit tipica, stimata empiricamente, spesso notevolmente inferiore a quella nel caso peggiore

Complessit: ambiti di applicazione


Strutture dati (operazioni di accesso, rimozione, aggiunta, spostamento, etc.) Interrogazioni basi di dati Risoluzione di problemi di ottimizzazione combinatoria e soddisfacimento di vincoli (Cammino minimo su grafo, Problema del commesso viaggiatore, Colorazione di grafi, Problema di soddisfacibilit, etc.)

Classi di complessit
Problemi trattabili -> risolvibili con algoritmi di complessit polinomiale. Problemi difficili (intrattabili) -> gli algoritmi disponibili hanno complessit almeno esponenziale. Per alcuni problemi stato dimostrato che non pu esistere un algoritmo a complessit polinomiale.

Esempi di problemi polinomiali


Ordinamento Cammino minimo tra due nodi su un grafo Risoluzione sistemi di equazioni lineari

Esempi di problemi difficili


Nota: per i problemi sotto elencati non stato trovato ancora un algoritmo polinomiale e si ipotizza che non esista. Esistono, comunque, classi di problemi di complessit, dimostrata, ancora maggiore. Soddisfacimento di formule logiche (SAT) Problema della colorazione di grafi Problema del commesso viaggiatore

Affrontare problemi difficili


Il fatto che un problema abbia una complessit esponenziale nel caso peggiore non significa che sue istanze di interesse pratico non possano essere risolte efficientemente. Due possibilit: Usare un algoritmo a complessit esponenziale, ma limitarsi a istanze mediamente risolte in tempo polinomiale nella pratica. Usare algoritmi a complessit (peggiore) polinomiale, i quali non garantiscono che la soluzione trovata sia ottima.

Esempio: SAT
SAT: data una formula logica, trovare un assegnamento di verit alla variabili per cui la formula risulti vera. Per esempio: F = (A or B) and (A or not B or C) Caso peggiore: enumerazione di 2n possibili assegnamenti Nella pratica, risolte istanze con milioni di variabili e clausole.