Sei sulla pagina 1di 26

Fondamenti di Informatica B

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

COMPLESSITÀ

COMPUTAZIONALE

TEMPOTEMPO ee MEMORIAMEMORIA

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)

ESEMPIOESEMPIO

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:ESEMPIO: soluzionesoluzione 11

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

AlgoritmoAlgoritmo scanscan

for i 1 to n­1 do for j i+1 to n do if A(i) = A(j) then output 'NO'; exit output 'YES'

ProgrammaProgramma scan.cscan.c

#include <stdio.h>

#define N 12

int main() {

int A[N] = {86,63,39,98,96,38,68,88,66,83,81,87};

int i,j;

for (i = 0; i < N­1; ++i) { for (j = i+1; j < N; ++j) { if (A[i] == A[j]) { printf("NO\n"); return 0;

}

}

}

printf("YES\n");

return 0;

}

MemoriaMemoria occupataoccupata daldal programmaprogramma

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

TempoTempo didi esecuzioneesecuzione deldel programmaprogramma

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àComplessità temporaletemporale

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.

StimaStima deldel tempotempo nelnel casocaso peggiorepeggiore

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 + = b n(n-1)/2 = b(n 2 - n)/2

+ 1) =

StimaStima deldel tempotempo nelnel casocaso peggiorepeggiore

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) n 2

NotazioneNotazione OO grande”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àComplessità didi scanscan nelnel casocaso peggiorepeggiore

L'algoritmo scan ha complessità temporale nel caso peggiore pari a:

T w (n) = O(n 2 )

e complessità spaziale:

S w (n) = O(n)

ESEMPIO:ESEMPIO: soluzionesoluzione 22

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'

AlgoritmoAlgoritmo storestore

for i 1 to m do

B(i) 0

for i 1 to n do if B(A(i)) 0 then output 'NO'; exit else B(A(i)) 1 output 'YES'

ProgrammaProgramma store.cstore.c

#include <stdio.h>

#define N 12

#define M 100

int main(){

int a[N] = {86,63,39,98,96,38,68,88,66,83,81,83};

int b[M];

int i;

for (i = 0; i < M; ++i) b[i] = 0;

for (i = 0; i < N; ++i) { if (b[a[i]] != 0) { printf("NO\n"); return 0;

}

else b[a[i]] = 1;

}

printf("YES\n");

OsservazioniOsservazioni

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àComplessità nelnel casocaso peggiorepeggiore

T w (n,m) = O(n+m), oppure, se il tempo per l'azzeramento è trascurabile, T w (n) = O(n)

S w (n,m) = O(n+m)

Confronto:Confronto: nn vsvs nn 22

Confronto: Confronto: n n vs vs n n 2 2

Complessità:Complessità: notenote

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à:Complessità: ambitiambiti didi applicazioneapplicazione

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.)

ClassiClassi didi complessità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.

EsempiEsempi didi problemiproblemi polinomialipolinomiali

Ordinamento

Cammino minimo tra due nodi su un grafo

Risoluzione sistemi di equazioni lineari

EsempiEsempi didi problemiproblemi difficilidifficili

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

AffrontareAffrontare problemiproblemi difficilidifficili

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:Esempio: SATSAT

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 2 n possibili assegnamenti

Nella pratica, risolte istanze con milioni di variabili e clausole.