Semplici modelli matematici con chatGPT
Grazie ai modelli generativi del linguaggio (LLM) come chatGPT è possibile sviluppare in tempi rapidi dei semplici modelli matematici che permettono di simulare certi eventi o l’evoluzione di un sistema reale e rappresentare i risultati graficamente.
In questo breve articolo useremo chatGPT per simulare la crescita della popolazione giovane rispetto a quella vecchia in funzione del tasso annuo di natalità.
Ci sono molti modi per avviare una conversazione con la chat che ci conduce all’obiettivo. Uno di questi potrebbe essere quello di fornirle un’istruzione come la seguente:
“Crea un modello usando python che descriva il comportamento di un sistema interessato da flussi di elementi (persone) in ingresso ed in uscita che rispetta le seguenti regole:
In ingresso ci sono solo elementi giovani, in uscita solo vecchi. Ad un certo punto, dopo 60 anni gli elementi giovani diventano vecchi. il numero di elementi in generale non viene conservato. I vecchi escono gradualmente in modo proporzionale tra 60 e 100 anni di età. Mostra come varia nel tempo la popolazione giovane e vecchia in base all’incremento di giovani in ingresso. Rappresenta mediante un grafico la popolazione totale, vecchia e giovane. Il modello deve prendere avvio da una distribuzione iniziale della popolazione in ragione dell’età che si ispira ai dati percentuali indicati nella tabella.”
La tabella potrebbe essere la seguente

Meglio fornire alla chat l’immagine delle due colonne utili per definire una distribuzione iniziale della popolazione in ragione delle fasce d’età.
Ecco uno schema del lavoro che il codice dovrà svolgere:
Importazione delle librerie
Definizione delle percentuali della popolazione
Normalizzazione della popolazione per età
Definizione delle fasce d’età
- Calcolo delle età rappresentative
Regressione polinomiale
- Definizione del grado del polinomio
- Esecuzione della regressione
- Generazione di valori continui di età
- Calcolo dei valori della popolazione stimata
Visualizzazione della regressione
- Creazione del grafico scatter
- Configurazione e visualizzazione del grafico
Definizione della funzione di mortalità
Normalizzazione delle popolazioni giovane e anziana
- Calcolo della popolazione giovane
- Calcolo della popolazione anziana
Simulazione della popolazione
- Definizione degli anni da simulare
- Inizializzazione delle liste di storia
- Definizione della funzione per i nuovi giovani
Loop di simulazione per ogni anno
- Calcolo dei nuovi giovani
- Invecchiamento della popolazione giovane
- Aggiunta dei nuovi giovani
- Applicazione della mortalità agli anziani
- Invecchiamento della popolazione anziana
- Aggiunta dei nuovi anziani
- Aggiornamento delle liste di storia
Calcolo della popolazione totale
Visualizzazione della simulazione
- Creazione del grafico delle popolazioni nel tempo
- Configurazione e visualizzazione del grafico
Stampa dei risultati finali
- Calcolo dei valori finali
- Calcolo delle percentuali
- Stampa dei risultati
Visualizziamo la prima parte del codice che si occupa di effettuare una regressione polinomiale a partire dalle percentuali della popolazione (variabile dipendente) in corrispondenza delle fasce d’età (variabile indipendente). Il codice genera anche il grafico.
import numpy as np
from numpy.polynomial.polynomial import Polynomial
import matplotlib.pyplot as plt
# Percentuali della popolazione per fascia d'età (dati di esempio)
percentuali_popolazione = [3.5, 4.2, 4.7, 4.9, 5.0, 5.1, 5.5, 5.7, 6.4, 7.6, 8.1, 8.2, 7.1, 6.1, 5.6, 4.7, 3.8, 2.4, 1.1, 0.3, 0.0]
popolazione_normalizzata_per_eta = [p / 100 * 1000 for p in percentuali_popolazione]
# Definizione delle fasce di età
eta = [2] + [np.mean([int(i.split('-')[0]), int(i.split('-')[1])]) for i in
["5-9", "10-14", "15-19", "20-24", "25-29", "30-34", "35-39",
"40-44", "45-49", "50-54", "55-59", "60-64", "65-69", "70-74",
"75-79", "80-84", "85-89", "90-94", "95-99"]] + [100]
popolazione = popolazione_normalizzata_per_eta
# Regressione polinomiale
grado_polinomio = 6
p_fit = Polynomial.fit(eta, popolazione, grado_polinomio)
eta_valori_continui = np.linspace(0, 100, 400)
popolazione_fit = p_fit(eta_valori_continui)
plt.figure(figsize=(10, 6))
plt.scatter(eta, popolazione, color='blue', label='Dati Originali', alpha=0.6)
plt.plot(eta_valori_continui, popolazione_fit, color='red', label=f'Polinomio di Grado {grado_polinomio}')
plt.title('Regressione Polinomiale della Distribuzione della Popolazione per Età')
plt.xlabel('Età')
plt.ylabel('Popolazione Normalizzata')
plt.legend()
plt.grid(True)
plt.show()

La seguente parte definisce la funzione di mortalità e normalizza i dati della popolazione in modo che gli individui formino 1000 unità di partenza. Viene impostato il periodo della simulazione e sono stampati i dati di partenza.
# Funzione di mortalità
def probabilita_morte(eta):
if eta < 60:
return 0
elif eta <= 100:
return (eta - 60) / 40 # Lineare da 0 a 1 tra 60 e 100 anni
else:
return 1
# Normalizzazione delle popolazioni giovane e anziana
eta_separazione = 60
young_population = np.array([p_fit(i)/5 for i in range(eta_separazione)])
old_population = np.array([p_fit(i + eta_separazione)/5 for i in range(40)])
# Simulazione della popolazione per un certo numero di anni
years_to_simulate = 200
young_start=np.sum(young_population)
old_start=np.sum(old_population)
totale=young_start+old_start
tassoy1=(young_start/totale)*100
tassoo1=(old_start/totale)*100
print("\n giovani")
print(round(young_start, 0))
print(round(tassoy1, 0))
print("\n vecchi")
print(round(old_start, 0))
print(round(tassoo1, 0))
print("\n totale")
print(round(totale, 0))
total_young_history = []
total_old_history = []
La funzione della probabilità di morte è il risultato di un’assunzione semplificatoria

L’ultima parte costituisce il cuore dell’algoritmo. Si imposta l‘incremento annuo di individui (nascite) assumendo l’attuale tasso di natalità dello 0,7% e si avvia il ciclo annuale di nascita, invecchiamento e morte degli individui secondo le regole impostate. Infine si traccia il grafico dello sviluppo della popolazione totale, giovane e vecchia e si stampano i dati finali.
Variando il tasso annuo di nascite per 1000 individui (incr) si possono ottenere scenari diversi e interessanti. Si può impostare una funzione new_youngs_per_year(year) in grado di mutare il tasso di natalità ogni anno secondo un certo modello previsionale:
def new_youngs_per_year(year):
incr = 7 # Nascite (su 1000 individui)
return incr
for year in range(years_to_simulate):
current_new_youngs = new_youngs_per_year(year)
new_old = young_population[-1] # Giovani che diventano vecchi
young_population[1:] = young_population[:-1] # Invecchiamento dei giovani
young_population[0] = current_new_youngs # Nuovi giovani entrano
# Applicazione della mortalità agli anziani
for i in range(len(old_population)):
old_population[i] *= (1 - probabilita_morte(eta_separazione + i))
old_population[1:] = old_population[:-1] # Invecchiamento degli anziani
old_population[0] = new_old # Aggiunta dei nuovi anziani
total_young_history.append(np.sum(young_population))
total_old_history.append(np.sum(old_population))
total = [y + o for y, o in zip(total_young_history, total_old_history)]
# Plotting dei risultati
plt.figure(figsize=(10, 6))
plt.plot(total_young_history, label='Popolazione Giovane')
plt.plot(total_old_history, label='Popolazione Vecchia')
plt.plot(total, label='Popolazione totale')
plt.title('Simulazione della Popolazione Giovane e Vecchia nel Tempo')
plt.xlabel('Anni')
plt.ylabel('Popolazione Totale')
plt.legend()
plt.grid(True)
plt.show()
# Stampa dei risultati finali
ultimoy = total_young_history[-1]
ultimoo = total_old_history[-1]
ultimot = total[-1]
tassoy2 = (ultimoy / ultimot) * 100
tassoo2 = (ultimoo / ultimot) * 100
print("\n alla fine...")
print("\n giovani")
print(round(ultimoy, 0))
print(round(tassoy2, 0))
print("\n vecchi")
print(round(ultimoo, 0))
print(round(tassoo2, 0))
print("\n totale")
print(round(ultimot, 0))


Altri modelli
Esistono molti tipi di modelli che si possono realizzare con l’aiuto della chat. Per esempio modelli per studiare la diffusione di malattie infettive in una popolazione. Il modello SIR (Susceptible-Infected-Recovered) divide la popolazione in tre categorie, mentre il modello SIS (Susceptible-Infected-Susceptible) considera la possibilità di reinfezione.
Modelli che descrivono come una nuova tecnologia o prodotto si diffonde all’interno di una popolazione.
Modelli che descrivono le interazioni tra due specie, una preda e un predatore, e come queste interazioni influenzano le loro popolazioni nel tempo.
Simulazione della crescita economica di un paese o di una regione considerando variabili come capitale, lavoro, tecnologia e politiche governative.
Modelli per analizzare e prevedere il traffico e l’uso dei trasporti pubblici in una città, considerando fattori come crescita della popolazione, cambiamenti infrastrutturali e politiche di trasporto.
Simulazione del consumo di energia in una regione o un settore industriale, considerando fattori come la crescita economica, cambiamenti tecnologici e politiche energetiche.
Modelli per valutare il rischio di credito di individui o aziende, utilizzato da banche e istituzioni finanziarie per determinare la probabilità di default.