Un insieme di Mandelbrot
fatto in casa
Prima di spingerci oltre nell'esplorazione di M,
cerchiamo di capire meglio come si ottengono questi disegni.
Vi sembrerà strano, ma è possibile generarli con
un programma di poche righe!
Iniziamo ricordando qualche formula matematica
(chiedo venia):
Somma di due numeri complessi: (a + ib) + (c +
id) = (a + c) + i(b + d)
Modulo di un numero complesso (ovvero distanza
di un punto del piano dall'origine degli assi): mod(a + ib) = sqrt(a*a
+ b*b)
Quadrato di un numero complesso: (a + ib)2 = (a*a
- b*b) + 2abi
Associamo ad ogni pixel un punto del piano complesso
e determiniamo se esso appartiene all'insieme:
in caso affermativo lo coloriamo in bianco, altrimenti
in nero.
Abbiamo così ottenuto una rappresentazione in 2
colori dell'insieme.
Per rendere la cosa più gradevole dal punto di
vista estetico, e per meglio comprendere il comportamento dei vari
punti del piano rispetto alla legge di Mandelbrot, conviene usare
più colori.
Si può allora decidere di indicare con colori diversi
la velocità con cui la successione diverge:
ad esempio, si colorano in blu i punti in cui la
successione diverge alla prima iterazione,
in verde quelli in cui diverge alla seconda, ecc.
Ma come si fa a stabilire se la successione diverge
o no?
Guardiamo più attentamente la legge di Mandelbrot:
In essa compare il quadrato di z.
Ebbene, secondo una proprietà dei numeri complessi,
se un numero z ha modulo >=2, il suo quadrato avrà modulo ancora
maggiore e quindi la successione sarà divergente.
Se invece la successione, dopo un certo numero
massimo di iterazioni, non accenna a divergere, si dà per scontato
che non divergerà mai, e si accetta il punto che la origina come
membro dell'insieme.
La cosa non è corretta dal punto di vista teorico,
ma, se il numero di iterazioni è abbastanza alto, la probabilità
di commettere errori di attribuzione è ragionevolmente limitata.
Per quanto detto finora, l'algoritmo opera nel seguente
modo: viene calcolato ripetutamente il valore di z mediante la formula
sopra indicata, e, ogni volta, il modulo di z viene confrontato
col valore 2.
Il procedimento si arresta quando la successione
mostra di essere divergente (mod(z)>=2) oppure quando si giunge
al numero massimo di iterazioni.
Infine viene attribuito il colore opportuno al
pixel corrispondente al punto c considerato e si passa al punto,
e al pixel, successivi.
Quanto appena detto è alla base delle poche righe
di codice in linguaggio C,
Pascal
e QBasic
che ho approntato.
Per velocizzare l'elaborazione ho adottato due semplici
ma importanti accorgimenti.
Il primo è nella condizione di uscita del ciclo
WHILE che applica iterativamente la legge di Mandelbrot: il numero
complesso in esame (e cioè il modulo del valore corrente di z, pari
a sqrt(a*a+b*b)) viene confrontato senza la radice con il valore
4 (anziché 2), risparmiando alla macchina l'inutile e dispendiosa
operazione di radice.
Il secondo accorgimento si basa sulla constatazione
che, per colorare un pixel appartenente all'insieme, è necessario
un numero di calcoli molto maggiore che per gli altri pixel in quanto
il ciclo WHILE viene eseguito MAXCONT volte (dove MAXCONT è il numero
massimo di iterazioni prefissato).
Ho pensato, quindi, di individuare (per via empirica)
un rettangolo di piano complesso tutto appartenente all'insieme:
in questo modo è possibile evitare l'esecuzione del ciclo per tutti
i pixel di questo rettangolo, che verranno immediatamente attribuiti
all'insieme senza ulteriori calcoli.
L'istruzione IF..THEN posta subito prima del WHILE
si occupa proprio di questo.
Per velocizzare ulteriormente il programma si potrebbe
sfruttare la simmetria dell'insieme rispetto all'asse delle ascisse,
ma ho preferito non seguire questa strada per non appesantire eccessivamente
il listato.
In alternativa si potrebbe ridurre ulteriormente
il valore della costante MAXCONT, ma questo andrebbe a scapito della
precisione del disegno (il valore attuale è già molto basso).
Per "zoomare" su un particolare della figura basta
modificare le costanti INFX, SUPX, INFY, SUPY e rilanciare il programma;
queste costanti, infatti, definiscono il rettangolo di piano che
deve essere visualizzato sullo schermo (sono le coordinate del primo
e del quarto vertice).
Se i valori attribuiti a tali costanti sono tali
che INFX>SUPX si ottiene un'immagine ribaltata attorno all'asse
delle ordinate.
La capacità di ingrandimento del programma è limitata
unicamente dalla precisione del tipo di dato in virgola mobile utilizzato.
|