Semplici modelli matematici con chatGPT

Semplici modelli matematici con chatGPT

Condividi con i tuoi amici...

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.