Corso di Algoritmi e Strutture Dati
Prima Esercitazione in Laboratorio
28/04/2004
Questa esercitazione ha come obiettivo lo studio della complessità computazionale di un
semplice algoritmo ricorsivo, che chiameremo mistero. In particolare, si vuole determinare
l’equazione di ricorrenza di mistero e la si vuole risolvere con il metodo della
sostituzione. Per congetturare una soluzione dell’equazione di ricorrenza, analizzeremo
sperimentalmente l’andamento delle prestazioni di mistero al variare della dimensione
dell’input, e confronteremo tale andamento con quello di alcune funzioni matematiche.
L’esercitazione è suddivisa in 5 fasi, ad ognuna delle quali dedicheremo un tempo ben
definito. Allo scadere del tempo, forniremo la soluzione della fase appena conclusa.
Fase 1 (5 min.)
Scrivere l’equazione di ricorrenza del costo di un’attivazione ricorsiva di mistero.
Fase 2 (20 min.)
Scrivere un metodo fase2 che compia alcuni esperimenti. Ogni esperimento consiste
nella misura del tempo impiegato da mistero per processare un input di dimensione n
(n>=2).
Il metodo fase2 dovrà:

generare un array di dimensione n>=2 riempito di valori casuali; n è un valore
significativo (è possibile generare l’array invocando il metodo
Eserc1.generaArrayCasuale());

invocare il metodo mistero sull’array appena generato, e misurare il tempo
impiegato da mistero. Suggerimento: è possibile leggere l’ora di sistema tramite
la classe java.util.Date, e in particolare il suo metodo getTime();

stampare su una riga la dimensione dell’input n e il tempo misurato. Suggerimento:
separare i due valori stampati con il carattere di tabulazione ‘\t’.

ripetere l’esperimento con altri valori significativi di n. Suggerimento: scegliere,
come valori di n, le potenze di 2.
Fase 3 (15 min.)
Scrivere un metodo fase3, modificando fase2 in modo tale che, per ogni esperimento
(ossia per ogni valore di n), venga stampato il rapporto tra il costo di mistero M(n) (cioè
il tempo misurato) e alcune funzioni di n:
M(n)/log n
M(n)/sqrt(n) M(n)/n
M(n)/(n log n)
M(n)/n2
M(n)/2n
Osservare se, per valori grandi di n, uno di questi rapporti converge ad un valore costante.
Se questo avviene possiamo congetturare un andamento asintotico per M(n).
Suggerimenti:

Usare il carattere di tabulazione ‘\t’ per stampare su un’unica riga i 6 rapporti
relativi allo stesso esperimento; poi andare a capo.

È possibile usare i metodi della classe java.lang.Math, in particolare log
(logaritmo), sqrt (radice quadrata) e pow (elevamento a potenza).

L’output è difficilmente leggibile da schermo. È possibile redirigere l’output su un file
aggiungendo > nome_del_file alla linea di comando. Per esempio, se la classe
java contenente il metodo main si chiama Main, il comando:
java Main > output.txt
redirige l’output su un file chiamato output.txt.
Fase 4 (10 min.)
Risolvere l’equazione di ricorrenza scritta nella Fase 1: tramite il metodo della sostituzione
verificare che la congettura avanzata nella Fase 3 è corretta.
Fase 5 (15 min.)
Misurare in un altro modo l’andamento asintotico della complessità di mistero:
individuare un’operazione dominante e contare il numero M’(n) di volte che l’istruzione
dominante è eseguita in una esecuzione di mistero.
Studiare l’andamento asintotico di M’(n), in modo analogo a quanto visto nella Fase 3.
Suggerimento: inserire nella classe Eserc1 una variabile statica contatore; inizializzarla
a 0 prima di eseguire un esperimento, e incrementarla quando viene eseguita l’operazione
dominante.
…a proposito, che cosa calcola mistero?