Programmazione scientifica, una prima introduzione
Lo scopo di questo corso è fornire un'introduzione all'uso dei computer per il calcolo scientifico. Vedremo perché è necessario ricorrere ai computer nella scienza moderna, quali sono le loro potenzialità e quali problemi possono introdurre. Useremo due linguaggi, C e Python, per costruire una prima cassetta degli attrezzi di programmazione scientifica.
Obiettivi formativi
Al termine di questo modulo dovresti essere in grado di:
- Distinguere algoritmo, programma e linguaggio di programmazione.
- Spiegare i principali ruoli dei computer nella ricerca scientifica.
- Descrivere, a livello introduttivo, limiti e assunzioni del calcolo numerico.
Il corso di programmazione scientifica
L'informatica è ormai una scienza matura e molto ampia. Fornire anche solo un'infarinatura dei concetti generali richiederebbe molto tempo, senza permetterci di raggiungere gli aspetti pratici della programmazione in ambito scientifico che più ci interessano. Abbiamo quindi operato alcune scelte sul materiale da includere nel corso. Durante questo semestre vedremo in particolare:
- Concetti base di informatica: algoritmi.
- Concetti base sui computer: architettura di Von Neumann, rappresentazione binaria dei dati.
- Usare un sistema Linux.
- Introduzione alla programmazione in C e Python; librerie utili di Python.
- Alcuni cenni di ingegneria del software: scrivere codici leggibili e affidabili.
Il corso proseguirà in parallelo con una parte teorica e una pratica. All'inizio useremo Python in modo superficiale per implementare i concetti visti nel punto 1. Passeremo poi al linguaggio C quando descriveremo il funzionamento della macchina di Von Neumann, la rappresentazione dei dati, ecc. Alla fine del corso torneremo su Python in modo più approfondito.
Non riusciremo a coprire alcuni aspetti teorici, pur fondamentali, come la teoria degli algoritmi e delle strutture dati avanzate o la teoria della computazione. Di questi temi forniremo solo alcuni cenni.
Cos'è un computer
Nell'accezione moderna, un computer (o calcolatore elettronico) è una macchina digitale programmabile, in grado di eseguire compiti diversi seguendo sequenze di istruzioni precise (algoritmi) codificate tramite programmi in un linguaggio di programmazione. Un computer è inoltre in grado di ricevere dati e istruzioni dall'esterno (input), restituire i risultati all'esterno (output) e mantenere dati e programmi in memoria.
Esercizio
Quali sono 3 esempi di computer con cui interagiamo nella vita quotidiana?
Soluzione
- computer portatile
- smartphone
- sistema infotainment di un'automobile
- lavatrice programmabile
I computer hanno permeato tutti gli aspetti del lavoro e della società che hanno a che fare con l'elaborazione delle informazioni, per esempio:
- a. La scrittura di documenti.
- b. La gestione di archivi di informazioni (database), rendendone più facile l'accesso.
- c. Le comunicazioni (email, video, messaggistica, social networking, internet).
- d. Sistemi di matching chiave-valore o chiave-permesso: ad esempio quelli che associano un conto corrente a un bancomat e permettono di effettuare una transazione.
- e. Sistemi di raccomandazione basati su machine learning (es.: algoritmi per feed social network, motori di ricerca, ecc.).
Tutti questi esempi sono importanti anche per il lavoro di uno scienziato, ma sono più generici e in genere oggetto di corsi dedicati di informatica o ingegneria dell'informazione. Il punto e. viene trattato nei corsi di machine learning, come "Introduzione alla data science per fisici" del terzo anno. Durante questo corso toccheremo brevemente il punto d. per quanto riguarda la costruzione di filtri che agiscono sui dati.
Algoritmi, programmi, programmazione
Le istruzioni fornite ai computer devono essere perfettamente deterministiche, come vedremo meglio in seguito. Queste sono espresse tramite algoritmi, che specificano ogni passo di un compito da eseguire senza margini di interpretazione. Gli algoritmi esistono da molto prima dei computer, almeno dall'antica Grecia. I procedimenti che usiamo per sommare, sottrarre, moltiplicare, dividere, trovare il minimo comune multiplo o il massimo comun divisore di due numeri sono tutti esempi di algoritmi.
I computer lavorano in base a un loro linguaggio, il linguaggio macchina, tramite il quale vengono espressi gli algoritmi da eseguire. Programmare un computer vuol dire scrivere algoritmi in modo che possano essere tradotti in linguaggio macchina ed eseguiti. Il linguaggio macchina, però, è molto lontano dal modo in cui esprimiamo concetti e istruzioni nel quotidiano; per questo nel corso dei decenni sono stati creati diversi linguaggi di programmazione che permettono di scrivere programmi in modo più agile.
Esistono centinaia di linguaggi di programmazione diversi, ognuno con un suo scopo. Ci sono linguaggi più generici per scrivere algoritmi, linguaggi progettati per facilitare la gestione di grandi moli di dati organizzati (database), linguaggi pensati per creare siti web, per fare matematica, o usati spesso nella programmazione scientifica e nelle simulazioni, come Fortran, Matlab e Julia.
Esercizio
Qual è la differenza tra algoritmo e programma? Prova a rispondere in due frasi.
Soluzione
Un algoritmo è una sequenza di istruzioni ben definite per risolvere un problema o eseguire un compito. Un programma è l'implementazione concreta di uno o più algoritmi in un linguaggio di programmazione, che può essere eseguito da un computer. Lo stesso algoritmo può essere implementato in diversi programmi, usando linguaggi di programmazione diversi.
Esercizio
Scegli un'operazione quotidiana (esempio: preparare il caffè) e descrivila in 6-8 passi deterministici. Attenzione, i passi devono essere chiari e non ambigui, in modo che chiunque possa seguirli senza interpretazioni ma allo stesso tempo non devono contenere dettagli superflui (esempio: "prendere la tazza" è un passo, "prendere la tazza rossa" è un dettaglio superfluo. A meno che il colore della tazza non sia fondamentale per l'operazione (e.g. stai preparando il caffè di Natale) ).
Cos'è la programmazione scientifica
Con programmazione scientifica intendiamo quegli aspetti della programmazione che hanno più a che vedere con le necessità della ricerca scientifica. In fisica, in particolare, i computer si usano per le seguenti operazioni.
- Calcoli numerici: logaritmi, funzioni trigonometriche, integrali e derivate numerici, ecc.
- Effettuare in modo automatico prese dati sperimentali (l'esempio più famoso è il CERN, ma vale per qualunque esperimento).
- Archiviazione e analisi di dati, sia sperimentali che da simulazioni.
- Simulazioni numeriche di sistemi complessi (sistemi con grande numero di gradi di libertà, sistemi caotici).
- Calcolo simbolico (soluzione di equazioni differenziali e integrali, es. Mathematica).
Con l'arrivo delle tecniche di machine learning e, in particolare, dei large language model e dei modelli generativi, i computer stanno trovando spazio anche nella ricerca induttiva di ipotesi e nella generazione assistita di codice e testo. Si tratta di strumenti potenti, ma con comportamento non pienamente deterministico per l'utente e spesso opaco nei dettagli interni. Nel corso dedicheremo alcuni momenti a un uso consapevole di questi strumenti a supporto dell'apprendimento.
Calcoli numerici
Il primo utilizzo dei computer riguarda il calcolo di quantità numeriche, in particolare funzioni come seni, coseni e logaritmi, il cui valore si ottiene applicando algoritmi. Prima dell'avvento dei computer, questi calcoli venivano eseguiti da persone chiamate calcolatori. I risultati venivano spesso salvati in tavole dei logaritmi e delle funzioni trigonometriche. Uno dei problemi maggiori era che errori banali, come copiare male un numero, potevano ripercuotersi su molti risultati, rendendo le tavole poco affidabili. Errori presenti nelle tavole influenzavano poi molti aspetti della scienza e della tecnologia, dalla precisione dei tiri di artiglieria alla navigazione oceanica.

Un esempio di tavola dei logaritmi del XIX secolo. Queste tavole erano di importanza fondamentale perché i logaritmi permettono di trasformare moltiplicazioni in somme, molto più facili da calcolare rapidamente.
L'utilizzo dei computer come banali calcolatori è ormai talmente naturale per noi che neppure ci pensiamo. Per calcolare ad esempio \(\sin(0.012)\) basta usare uno smartphone, una calcolatrice, o collegarsi a internet. Ma quello che viene fatto dietro le quinte è applicare un algoritmo che in ultima istanza è basato sull'espansione in serie della funzione seno.
Esercizio
Perché un calcolo numerico può introdurre errore anche quando la formula matematica è corretta?
Soluzione
I calcoli numerici sono approssimati per definizione, perché i computer hanno memoria finita e rappresentano i numeri con precisione limitata. Lo stesso accade anche con i calcoli svolti a mano. Se volessimo calcolare il perimetro di un cerchio con raggio 1, dovremmo usare la formula \(P=2\pi r\), ma \(\pi\) è un numero irrazionale e non può essere rappresentato esattamente. Potremmo per esempio usare l'approssimazione 3.14, ma questo introdurrebbe un errore nel risultato. In generale, ogni calcolo numerico introduce errori di approssimazione, che, se non controllati, possono essere amplificati da operazioni successive.
Acquisizione di dati sperimentali e analisi dati
I moderni esperimenti in fisica, così come in altre discipline scientifiche, fanno un uso esteso di computer. Questo non solo per aumentare la rapidità e la mole di dati acquisibili, ma anche per ridurre gli errori nell'acquisizione. L'acquisizione manuale dei dati, infatti, porta inevitabilmente la possibilità di un'errata trascrizione o di un errore procedurale. Anche i sistemi automatici possono sbagliare, ma quando la procedura è codificata l'errore tende a essere sistematico e quindi più facile da individuare.

Alcuni esempi di esperimenti in cui i computer svolgono un ruolo essenziale.
L'immagine precedente riporta alcuni esempi di acquisizione dati fortemente computerizzata: l'esperimento CMS al CERN, nel quale fasci di protoni vengono fatti collidere per investigare la fisica delle particelle fondamentali; l'individuazione di palladio in sostanze polimeriche tramite microscopio elettronico a trasmissione (TEM); la spettroscopia Raman per studiare la composizione di materiali geologici.
In tutti e tre i casi precedenti i computer gestiscono tutte le fasi della misura:
- La sorgente che interagisce con il materiale nel caso del TEM e del Raman, oppure le caratteristiche e la generazione del fascio al CERN.
- La rilevazione dei segnali generati (spettro di emissione per il Raman, caratteristiche degli elettroni per il TEM, particelle emesse per CMS).
- La pulizia dei segnali, eliminando ad esempio il rumore ambientale.
Esercizio
Considerando le esperienze in programma nel corso di laboratorio, quali parti ritenete necessitino un computer, o si possano automatizzare?
Una volta acquisiti i dati grezzi, questi vanno analizzati. Il grafico della collisione di protoni riportato nella figura precedente è già il risultato di una lunga analisi: i prodotti della collisione vengono identificati e poi rappresentati in modo opportuno, condensando un'enorme mole di informazioni in un'unica immagine. Nella figura sull'identificazione del palladio, due misure diverse vengono combinate per ottenere una terza immagine, in falsi colori, nella quale il palladio è chiaramente identificabile. Questo passaggio richiede una lunga serie di calcoli al computer.
Un terzo esempio di processo altamente computerizzato è la determinazione della struttura tridimensionale delle proteine. Le proteine sono macromolecole essenziali per la vita e svolgono sia ruoli strutturali sia ruoli chimici. Questi ruoli sono possibili grazie al fatto che ogni proteina assume una struttura tridimensionale molto precisa, sulla scala dell'angstrom. Tramite scattering dei raggi X si ottengono mappe 2D da cui ricostruire una struttura 3D. La prima struttura proteica fu ricostruita a mano negli anni Sessanta e richiese circa due anni di lavoro. Oggi questa procedura avviene al computer nell'arco di ore. Le strutture ottenute vengono poi caricate in database globali, utili sia alla ricerca di base sia all'addestramento di modelli di deep learning.
Esercizio
Disegna una pipeline minima di analisi dati con quattro blocchi: acquisizione, pulizia, analisi, visualizzazione. Per ogni blocco indica un possibile errore.
Soluzione
graph LR
A[<b>Acquisizione</b><br>Il macchinario non è calibrato correttamente] --> B[<b>Pulizia</b><br>I filtri eliminano anche dati validi]
B --> C[<b>Analisi</b><br>Utilizzo un fit con tanti parametri quanti sono i dati]
C --> D[<b>Visualizzazione</b><br>Il grafico è disegnato in modo da enfatizzare un risultato particolare]
Simulazioni

Alcuni esempi di simulazioni numeriche di fenomeni fisici.
Forse l'esempio più noto di utilizzo dei computer in fisica è dato dalle simulazioni numeriche. Partendo dalle equazioni del moto di Newton, o da quelle della meccanica relativistica di Einstein, è possibile simulare sistemi estremamente complessi su molte scale, dalle galassie fino alle proteine. A scale più piccole si simulano sistemi quantistici, come gli elettroni in un metallo o le particelle in collisioni ad alta energia. In molti casi si usano anche approcci multi-scala, combinando descrizioni classiche e quantistiche.
Restando, per semplicità, nel caso della dinamica molecolare classica, partiamo dall'equazione differenziale:
Per risolverla al computer, discretizziamo il tempo in passi \(\Delta t\) e usiamo uno schema numerico, ad esempio Eulero esplicito:
Questa ricetta sostituisce il problema continuo con una sequenza finita di aggiornamenti. La scelta di \(\Delta t\) è cruciale: se troppo grande, la simulazione può essere instabile o imprecisa; se troppo piccolo, il costo computazionale cresce molto. In pratica si cerca un compromesso tra accuratezza e tempo di calcolo.
Esercizio
Perché la scelta del passo temporale \(\Delta t\) influenza sia la precisione sia il costo della simulazione?
micro-esercizio
Consideriamo un semplice moto rettilineo uniformemente accelerato in 1D con $\(\begin{align}m=1kg,\ F=1N,\ x_0=0m,\ v_0=0 \frac{m}{s}\end{align}\)$. Sappiamo che dopo \(3s\) la posizione esatta è \(x(3)=\frac{1}{2}\frac{F}{m}t^2=4.5m\).
Prova ora a calcolare a mano (o con un computer se te la senti) la posizione dopo \(3s\) usando lo schema di Eulero con \(\Delta t=3s\), \(\Delta t=1s\) e \(\Delta t=0.5s\). Come cambia l'errore rispetto alla soluzione esatta nei tre casi? Qual è il valore più preciso? Cosa ti aspetti succeda scegliendo un \(\Delta t\) ancora più piccolo?
Calcoli simbolici
Molti calcoli simbolici, come derivazione e integrazione, si basano su tecniche che possono essere rese in modo algoritmico. Le operazioni algebriche possono essere espresse tramite regole ben definite, quindi tramite un numero finito di istruzioni. Lo sviluppo dell'informatica moderna è strettamente legato a questi temi matematici, in particolare attraverso la macchina di Turing, con la quale si pongono le basi per distinguere problemi computabili e non computabili.
In ambito moderno, pacchetti software come Mathematica permettono di eseguire facilmente operazioni simboliche molto complesse.
Esercizio
Considerando i corsi di analisi e geometria, quali sono dei semplici algoritmi di calcolo simbolico?
Soluzione
- Derivazione: regole di derivazione (somma, prodotto, catena, ecc.)
- Metodo di bisezione per trovare radici di funzioni
- Metodo di Gauss per risolvere sistemi di equazioni lineari
- Calcolo di autovettori, autovalori e diagonalizzazione di una matrice
- ecc.
Esercizio
Scrivi in pseudocodice una regola di derivazione per la potenza: \(f(x)=x^n\).
Soluzione
Come si inserisce il computer nel metodo scientifico
Sebbene tutti gli strumenti dell'informatica vengano usati in ambito scientifico, con "programmazione scientifica" intendiamo l'uso dei computer in parti ben determinate del processo di ricerca. Gli esempi visti sopra si inseriscono in una rappresentazione semplificata del metodo scientifico: osservazione, formulazione di ipotesi, deduzione delle conseguenze, verifica sperimentale. In quest'ottica, l'acquisizione dati rientra soprattutto nella fase osservativa, mentre calcoli numerici e simbolici aiutano nella deduzione delle conseguenze di un'ipotesi e nella progettazione di nuovi esperimenti in silico.
Nella programmazione scientifica l'accento è posto su esigenze in parte diverse rispetto ad altri settori dell'informatica. Per un sito web sono centrali sicurezza e usabilità; in ambito scientifico ci concentriamo soprattutto su efficienza, riproducibilità e correttezza.
Nei casi di acquisizione dati, analisi e simulazione, i codici scientifici sono spesso funzioni matematiche che trasformano dati in ingresso in risultati in uscita.
Un computer rappresenta dati e operazioni in modo finito: memoria finita, tempo finito, precisione finita. Per esempio, i numeri irrazionali vengono rappresentati solo tramite approssimazioni. Per questo i codici scientifici introducono assunzioni aggiuntive nei ragionamenti, e tali assunzioni vanno controllate.
In forma semplificata, la verifica di un'ipotesi può essere vista come aggiornamento della fiducia alla luce dei dati:
Qui \(H\) è l'ipotesi e \(D\) sono i dati. Anche quando un risultato sembra sorprendente, è necessario valutare in modo critico errori sistematici, incertezze sperimentali e scelte di analisi. Un caso didatticamente famoso è l'episodio iniziale dei neutrini superluminali (OPERA), poi ricondotto a problemi strumentali.
Esercizio
Perché la riproducibilità è un requisito centrale in un codice scientifico?
Soluzione
La riproducibilità è fondamentale perché permette ad altri ricercatori di verificare i risultati ottenuti, identificare eventuali errori e costruire su quei risultati per ulteriori ricerche. Un codice non riproducibile rischia di essere poco affidabile e di non contribuire in modo significativo alla comunità scientifica. In modo analogo, è necessario che il codice non sia solo riproducibile, ma anche ben documentato e leggibile, in modo che altri possano capire come funziona e quali sono le assunzioni implicite.
Esercizio
Elenca tre possibili fonti di errore in una simulazione numerica (una legata al modello, una al metodo numerico, una all'implementazione).
Soluzione
- Modello: il modello fisico scelto non cattura tutti i fenomeni rilevanti (es. non include attriti, forze di attrazione, ecc.).
- Metodo numerico: la scelta del passo temporale \(\Delta t\) è troppo grande, portando a instabilità o imprecisioni.
- Implementazione: errori di programmazione, per esempio un errore di segno in una formula, o un errore di indice in un ciclo.
La scelta dei linguaggi: perché C e Python
Ci si può chiedere perché introduciamo due linguaggi anziché uno solo, e perché non scegliamo un linguaggio specialistico per il calcolo numerico. La risposta è che C e Python hanno punti di forza complementari.
Grazie all'enorme ecosistema di librerie già sviluppate a disposizione, Python è un linguaggio mirato alla facilità d'uso e alla rapidità di sviluppo. Questa sua rapidità di sviluppo lo rende particolarmente adatto per l'analisi dati, la prototipazione rapida di algoritmi e la visualizzazione. Questa facilità d'uso deriva dalla presenza di un interprete, un programma che astrae il processo di esecuzione del codice e cerca di compiere scelte al posto dell'utente. Nel momento in cui le scelte dell'interprete non coincidono con quelle dell'utente, però, si possono introdurre errori difficili da individuare.
Il vantaggio fondamentale di Python è che, se sapete usarne una minima parte, questa vi permette di svolgere agilmente la maggior parte delle analisi dati di cui ha normalmente bisogno un fisico.
Il C, invece, è un linguaggio essenziale: fornisce pochi elementi, ma proprio per questo aiuta a capire bene tipi di dato, programmazione imperativa e gestione della memoria. Grazie al suo essere vicino all'hardware, i programmi in C sono molto efficienti e possono essere usati in ambito embedded, dove è necessario un controllo diretto sull'hardware. Molti programmi ad alte prestazioni (tra cui l'intero sistema operativo Linux e l'interprete Python) sono scritti in C.
Dal punto di vista didattico, Python ci permette di sperimentare subito alcuni algoritmi, mentre C aiuta a capire cosa succede "sotto il cofano". Insieme, offrono una base solida per proseguire verso strumenti e linguaggi più avanzati.
In generale, conviene utilizzare Python per analisi dati e prototipazione rapida, e C per implementazioni ad alte prestazioni o quando è necessario un controllo più fine sull'hardware.
Esercizio
In quali casi pratici useresti C invece di Python, e viceversa? Scrivi due mini-scenari reali (3-4 righe ciascuno): uno in cui C è la scelta migliore, uno in cui Python è la scelta migliore.
Soluzione
- Ho sviluppato un piccolo modello di dinamica molecolare in Python, ma la simulazione è troppo lenta per essere eseguita in tempi ragionevoli. Decido di riscrivere il codice in C per sfruttare la maggiore efficienza. I dati generati dalla simulazione sono pochi, decido di analizzarli e visualizzarli in Python, usando librerie come NumPy e Matplotlib per facilitare l'analisi e la creazione di grafici.
- Sto sviluppando un componente hardware per il CERN che richiede di analizzare i dati in tempo reale per identificare eventi rari. La velocità di elaborazione è cruciale, quindi scelgo di implementare il codice in C per avere un controllo diretto sull'hardware e massimizzare le prestazioni. Per testarlo ho bisogno di pochi dati, quindi posso scrivere un semplice script Python per generarli e inviarli al componente, sfruttando la facilità di sviluppo di Python per questa fase di test.
Una situazione particolare: machine learning e AI
I modelli di machine learning e i modelli generativi sono strumenti utili anche nel lavoro scientifico: possono aiutare nell'esplorazione dei dati, nella generazione di bozze di codice e nella sintesi di letteratura. Tuttavia non sostituiscono il ragionamento fisico e il controllo sperimentale.
In questo corso li useremo con tre regole operative:
- Verificare sempre i risultati con test, conti indipendenti o fonti affidabili.
- Distinguere chiaramente tra suggerimento automatico e conclusione scientifica.
- Rendere il processo riproducibile, documentando prompt, parametri e passaggi di validazione.
Esercizio
Qual è un rischio concreto nell'uso di modelli generativi per scrivere codice scientifico?
Soluzione
Il modello generativo potrebbe fare assunzioni non valide nel nostro caso particolare portando a codice che sembra corretto ma produce risultati errati. Ad esempio, potrebbe supporre che la nostra matrice sia sempre quadrata o che gli errori siano distribuiti normalmente, quando in realtà non è così. Se non verifichiamo i risultati con test o conti indipendenti, potremmo finire per accettare risultati errati come validi, compromettendo la qualità della nostra ricerca. Inoltre, i modelli generativi producono risultati affidabili solo quando hanno incontrato un problema simile durante l'addestramento. Se il nostro caso è molto specifico o complesso, il modello potrebbe non avere abbastanza informazioni per generare un codice corretto ed allucinare funzioni non esistenti o con comportamento errato.
Riepilogo
In questa introduzione abbiamo visto che:
- I computer sono strumenti centrali nella ricerca moderna.
- La programmazione scientifica copre calcolo numerico, acquisizione/analisi dati, simulazioni e calcolo simbolico.
- Ogni risultato computazionale va interpretato alla luce di approssimazioni e incertezze.
- C e Python svolgono ruoli complementari nella formazione e nella pratica.
- Anche gli strumenti di AI possono essere utili, ma solo con validazione rigorosa.