Il computer non gioca a dadi: la casualità

Creato il 01 dicembre 2012 da Hnikarr

Oggi tornerò a dedicarmi a uno di quegli argomenti che soltanto io posso trovare interessanti: come forse si sarà capito dal titolo, mi riferisco alla casualità o, più precisamente, alla casualità nei computer. È un argomento molto più importante di quanto potrebbe sembrare di primo acchito, perché in un computer sono parecchie le attività che dipendono dalla casualità, in un modo o nell'altro  le chiavi crittografiche, ad esempio, ma anche le simulazioni, la creazione di modelli per previsioni, la manipolazione di insiemi di dati e, ultimi ma non meno fondamentali, i giochi. Più o meno qualunque tipo di gioco dipende da un generatore di casualità, che può essere un mazzo di carte da mescolare, un dado da lanciare, qualcosa da pescare “a caso”, eccetera. Se per una persona tutto ciò può sembrare molto semplice, per non dire banale (chi non è capace di pescare una carta o lanciare un dado?), per un computer il discorso si fa molto complicato, perché un computer non è capace di agire “a caso”. Si può però sopperire a questa lacuna e adesso vedremo come. Prima di tutto, cosa è la casualità? Qui si potrebbe aprire un lungo dibattito filosofico, diviso tra amici e nemici del determinismo, ma finiremmo decisamente fuori argomento. Per l’occasione, utilizzeremo una definizione molto semplice di casualità: casuale è un evento di cui, sulla base delle nostre attuali competenze, non sappiamo prevedere il verificarsi o le conseguenze del suo verificarsi. Siccome non sappiamo con esattezza che risultato otterremo, lanciando un dado (a meno che il dado non sia truccato, è ovvio), possiamo considerare casuale il risultato di un dado, proprio come possiamo considerare casuale la pesca di una carta da un mazzo, se non conosciamo l’ordine in cui sono disposte. E fin qui nulla di strano. Il discorso cambia quando arriviamo ai computer. Il computer è uno strumento in cui nulla è casuale, ma tutto è strettamente determinato (almeno i computer attuali, in futuro si vedrà): se un computer non è guasto, possiamo sempre prevedere il risultato di ogni sua azione, conoscendone tutte le premesse. Se vogliamo inserire un elemento di casualità all'interno di una sequenza di azioni eseguite da un computer, dovremo simulare questo elemento casuale utilizzando un elemento predeterminato, che dia però all’utente l’impressione di essere casuale. Avremo dunque bisogno di un generatore di numero (pseudo)casuali. Un esempio che dovrebbe essere conosciuto a tutti è la funzione “random”, che si trova in molti lettori musicali e che permette di eseguire brani scelti “casualmente” tra tutti quelli disponibili sul lettore, invece di eseguirli nella sequenza in cui si trovano, come avviene di consueto. In questa funzione, come praticamente in tutti gli altri casi in cui si parla di casualità e di scelte “random”, la casualità è simulata attraverso un generatore di numeri pseudocasuali, il quale produrrà una lunga sequenza di numeri, distribuiti in modo da sembrare casuali. Il programma poi percorrerà questa sequenza in ordine, dal primo numero in avanti, riproducendo di volta in volta il brano musicale che corrisponde a ogni numero. Come si genera una sequenza di numeri pseudocasuali? Attraverso appositi algoritmi, che partono da un determinato numero (chiamato “seme”) e lo sottopongono a una serie preordinata di operazioni matematiche, per ricavarne una sequenza di numeri. All'interno di questa sequenza, i numeri avranno una distribuzione che sembra casuale e, nella maggior parte dei casi, sarà sufficiente per sostituire una casualità vera, senza che l’utente si accorga della differenza. Di casuale, però, non c’è alcunché: la sequenza è predeterminata dal primo all’ultimo numero e lo stesso seme ci darà sempre la stessa sequenza, dato che i calcoli per ricavare una sequenza da un numero non cambiano mai. Facciamo un esempio. Immaginiamo di voler simulare il lancio di un normale dado a sei facce: avremo dunque bisogno di una sequenza di numeri da 1 a 6, corrispondente ai risultati che posso ottenere lanciando un dado reale. Noi passiamo al programma il numero 5783, da utilizzare come seme per il suo generatore di numeri pseudocasuali, e il programma genererà una sequenza del tipo 3, 5, 2, 6, 1, 3, 1, 4, 2, 6, 2, 5, eccetera. Se adesso vogliamo utilizzare questo simulatore di dado a sei facce, al primo lancio otterremo come risultato 3, ossia il primo numero della sequenza; al secondo lancio otterremo 5, ossia il secondo numero della sequenza; e così via. Una volta che la sequenza è giunta alla fine, si riparte dal primo numero. Possiamo già vedere che di casualità reale ce n’è ben poca. Inoltre, se passiamo di nuovo il numero 5783 come seme per la generazione di numero pseudocasuali, otterremo di nuovo la stessa sequenza, identica dal primo all’ultimo numero. Una discussione su quali siano gli algoritmi utilizzati per generare sequenze di numeri pseudocasuali, cioè quali siano le operazioni a cui sono sottoposti i semi, richiederebbe troppo spazio e troppa matematica per i miei gusti: giusto per dare una idea, i numeri casuali occupano la prima metà del secondo volume della monumentale opera The art of computer programming, di Donald E. Knuth, che rappresenta più o meno la “Bibbia” dei programmatori. Se vi interessa approfondire il discorso, quello è un ottimo punto di partenza, ma non illudetevi che sarà una lettura leggera e rilassante. A ogni modo, qualunque sia l’algoritmo (e dunque la sequenza di operazioni a cui sottoporre il seme), lo schema generale è sempre lo stesso: si parte da un seme e, sulla base di quel seme, si genera una sequenza di numeri compresi tra gli estremi che ci interessano. I numeri sono distribuiti all’interno della sequenza in modo più o meno omogeneo (in una sequenza da 1 a 6, ad esempio, ogni numero occuperà circa un sesto delle posizioni totali) e possono essere riprodotti con assoluta precisione, conoscendo il seme e l’algoritmo utilizzato. In alternativa ai numeri pseudocasuali, è anche possibile utilizzare i cosiddetti “veri numeri casuali”, ossia numeri ricavati non da una fonte predeterminata, come può essere un algoritmo o un generale una qualsiasi funzione matematica (che darà sempre lo stesso risultato, utilizzando gli stessi numeri), ma da qualcosa che è percepito come “veramente” casuale (ammesso e non concesso che esista davvero qualcosa di veramente casuale). Ritornando all'esempio del dado a sei facce, nel caso di un generatore di veri numeri casuali noi non utilizzeremo una formula matematica, per produrre la sequenza di numeri partendo da un determinato seme, ma lanceremo realmente il dado un certo numero di volte, segnando in sequenza i risultati ottenuti. Alla fine, otterremo una sequenza che non è determinata e non può essere predetta sulla base di un seme. Come è ovvio, un generatore di veri numeri casuali utilizza strumenti un po’ più efficienti di un dado, per generare i propri numeri: tipiche sorgenti di casualità sono, ad esempio, i rumori di sottofondo di un ambiente (purché non siano regolari e ripetitivi: una catena di montaggio è una pessima scelta, l’atrio di una stazione ferroviaria va invece benissimo), piccoli frammenti di lava, condizioni meteo, eccetera. Se avete in casa una buona quantità di elementi radioattivi, e ancora non siete morti, potete utilizzare il decadimento dei loro atomi come ottima sorgente di veri numeri casuali: Schrödinger apprezzerà il vostro gesto. Qualunque sia la sorgente, il principio resta lo stesso: i numeri casuali sono ottenuti identificando i più piccoli cambiamenti nella sorgente che abbiamo utilizzato. Come è facile da immaginare, i veri numeri casuali sono sì nondeterministici, ma anche spaventosamente lenti da ottenere: se un buon generatore di numeri pseudocasuali può produrre una sequenza in frazioni impercettibili di secondo, un generatore di veri numeri casuali impiegherà molto di più. Di conseguenza, risultano una ottima scelta quando il tempo non è un fattore determinante, ma lo è la sicurezza: la crittografia, per esempio. Se invece abbiamo bisogno di macinare numeri su numeri, e di farlo ad alta velocità (come nelle simulazioni), utilizzare un generatore di veri numeri casuali è una pessima idea, sia per la lentezza, sia perché i veri numeri casuali non sono ripetibili, a differenza dei numero pseudocasuali. Se qualcosa è andato storto nella prima simulazione, non potrete ripeterla in modo esatto dopo aver corretto gli errori, se utilizzate veri numeri casuali; coi numeri pseudocasuali, invece, potrete ripetere lo stesso esperimento tutte le volte che vorrete, purché utilizziate sempre lo stesso seme.

Potrebbero interessarti anche :

Possono interessarti anche questi articoli :