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?