![](https://i0.wp.com/www.raucci.net/wp-content/uploads/2023/06/Stanislaw_Ulam-706x1024.jpg?resize=257%2C373&ssl=1)
Uno dei modi più affascinanti di esplorare la bellezza intrinseca dei numeri primi è attraverso la Spirale di Ulam. Questa particolare disposizione dei numeri rivela una struttura nascosta tra i numeri primi che altrimenti potrebbe passare inosservata.
![](https://i0.wp.com/www.raucci.net/wp-content/uploads/2023/06/Schermata-2023-06-25-alle-19.22.07.png?resize=489%2C228&ssl=1)
La Spirale di Ulam è una matrice quadrata che inizia con il numero 1 al centro e procede verso l’esterno in senso orario, numerando sequenzialmente ogni cella lungo la spirale. Quando si evidenziano i numeri primi all’interno di questa spirale, emergono sorprendenti modelli a forma di diagonale. Questo fenomeno, scoperto dall’inventore e matematico Stanislaw Ulam nel 1963, è ancora oggetto di studio e di dibattito tra i matematici.
La generazione di una Spirale di Ulam può essere un ottimo esercizio per imparare a manipolare gli array in Python e per visualizzare dati con Matplotlib. Ecco un esempio di come farlo:
import numpy as np # Importa la libreria numpy per la manipolazione di array
import matplotlib.pyplot as plt # Importa la libreria matplotlib per la creazione di grafici
import matplotlib.cm as cm # Importa il modulo cm da matplotlib per la gestione dei colori
def make_spiral(arr):
nrows, ncols= arr.shape # Ottiene il numero di righe e colonne dell'array
idx = np.arange(nrows*ncols).reshape(nrows,ncols)[::-1] # Crea un array di indici e lo inverte
spiral_idx = [] # Inizializza una lista vuota per gli indici della spirale
while idx.size: # Mentre ci sono ancora elementi in idx
spiral_idx.append(idx[0]) # Aggiunge la prima riga di idx a spiral_idx
# Rimuove la prima riga (quella che abbiamo appena aggiunto a spiral).
idx = idx[1:]
# Ruota il resto dell'array in senso antiorario
idx = idx.T[::-1]
# Crea un array piatto di indici che formano una spirale nell'array.
spiral_idx = np.hstack(spiral_idx)
# Index into a flattened version of our target array with spiral indices.
spiral = np.empty_like(arr) # Crea un nuovo array vuoto con la stessa forma di arr
spiral.flat[spiral_idx] = arr.flat[::-1] # Assegna i valori di arr a spiral secondo l'ordine degli indici nella spirale
return spiral
# Dimensione del lato dell'array quadrato.
w = 251
# Numeri primi fino a e compreso w**2.
primes = np.array([n for n in range(2,w**2+1) if all(
(n % m) != 0 for m in range(2,int(np.sqrt(n))+1))])
# Crea un array di valori booleani: 1 per i numeri primi, 0 per i numeri composti
arr = np.zeros(w**2, dtype='u1')
arr[primes-1] = 1
# Spiraleggia i valori in senso orario partendo dal centro
arr = make_spiral(arr.reshape((w,w)))
plt.matshow(arr, cmap=cm.binary) # Crea una visualizzazione della matrice usando una colormap binaria
plt.axis('off') # Nasconde gli assi
plt.show() # Mostra il grafico
In questo script Python, iniziamo importando le librerie necessarie: numpy
per la manipolazione degli array, matplotlib.pyplot
per la creazione dei grafici e matplotlib.cm
per la gestione dei colori.
La funzione make_spiral
prende un array e lo trasforma in un array a spirale. Per fare questo, genera prima un array di indici idx
e poi crea una lista spiral_idx
per contenere gli indici nell’ordine in cui dovrebbero apparire nella spirale. Questa lista viene poi utilizzata per riordinare l’array originale in un ordine a spirale.
Successivamente, definiamo la dimensione w
del lato della nostra matrice quadrata e generiamo un array di numeri primi fino a w**2
. Questo array di numeri primi viene utilizzato per creare un array di zeri e uni, dove gli uni rappresentano i numeri primi.
Infine, trasformiamo il nostro array in una spirale con la funzione make_spiral
e visualizziamo il risultato con plt.matshow
, utilizzando una colormap binaria per distinguere i numeri primi (rappresentati in bianco) dai numeri non primi (rappresentati in nero). Il risultato è una bella rappresentazione della Spirale di Ulam, che evidenzia la misteriosa struttura dei numeri primi.
![](https://i0.wp.com/www.raucci.net/wp-content/uploads/2023/06/Figure_1.png?resize=480%2C480&ssl=1)
Nella figura, i numeri primi sembrano concentrarsi lungo certe linee diagonali. Nella spirale di Ulam di dimensione 250×250 mostrata sopra, le linee diagonali sono chiaramente visibili, confermando che il modello continua. Sono evidenti anche linee orizzontali e verticali con un’alta densità di numeri primi, sebbene meno evidenti.
# Creiamo una nuova colormap personalizzata.
# I colori sono specificati in formato RGBA; (0, 0, 0, 1) è nero e (0, 1, 0, 1) è verde.
cmap = ListedColormap([(0, 0, 0, 1), (0, 1, 0, 1)])
plt.matshow(arr, cmap=cmap) # Usiamo la nostra nuova colormap
plt.axis('off')
plt.show()
Qui, di seguito, con la piccola modifica allo script sopra indicata, si ottiene una visualizzazione più contrastata della spirale di Ulam
![](https://i0.wp.com/www.raucci.net/wp-content/uploads/2023/06/Figure_1-1.png?resize=480%2C480&ssl=1)
La Spirale di Ulam è un perfetto esempio di come la matematica possa rivelare pattern nascosti nel caos apparente. Con poche linee di codice Python, possiamo esplorare queste meravigliose strutture e forse avvicinarci un po’ di più alla comprensione del mistero dei numeri primi.