- docs/SPEC.md sostituito da un file per argomento (indice in docs/README.md) - assunzioni A1-A24 con dove nel codice e cosa succede se false - formule in LaTeX corrette (nessuno spazio prima del dollaro di chiusura), simboli e chiavi in tabella - diagrammi Mermaid per il flusso degli algoritmi e le dipendenze dei moduli - figura dei domini sul seed 1 (docs/img/domini_esempio.png) - README ridotto a indice con avvio rapido; CLAUDE.md e docstring allineati Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
12 KiB
Algoritmi
Tutti i passi, nell'ordine in cui il programma li esegue. Le assunzioni richiamate (A1, A2, …) sono in assunzioni.md; le
chiavi di configurazione (in_questo_formato) in configurazione.md; il modulo che implementa ogni passo in
moduli.md.
Visione d'insieme
flowchart TD
CSV(["CSV in input/"]) --> P1
subgraph P1["PASSO 1 · Domini"]
direction LR
L["<b>1 · Lettura</b><br/>validazione"] --> S["<b>2 · Rumore</b><br/>stima di σ"] --> G["<b>3 · Gradini</b><br/>salti sopra soglia"] --> D["<b>4 · Domini</b><br/>divisione del tempo"]
end
P1 --> RIP["<b>Riposo</b>"]
P1 --> RIS["<b>Riscaldamento</b><br/>2–3 campioni"]
P1 --> INT["<b>Raffreddamenti intermedi</b><br/>tra due gradini, corti"]
P1 --> FIN["<b>Raffreddamento finale</b><br/>l'ultimo, il più lungo"]
subgraph P2["PASSO 2 · Equazioni"]
direction TB
F0["<b>5 · Fit</b><br/>costante, lineare,<br/>esponenziale"]
F1["<b>5 · Fit esponenziale</b><br/>c, A, τ liberi"]
F2["<b>5b · Fit esponenziale</b><br/>c e τ fissi, solo A libera"]
SALTO["<b>7 · Salto Δ</b><br/>descritto, non fittato"]
SC["<b>6 · Scelta del modello</b><br/>validi → adeguati → meno parametri"]
F0 --> SC
F1 --> SC
F2 --> SC
end
RIP --> F0
FIN --> F1
INT --> F2
RIS --> SALTO
F1 -. "passa c, τ" .-> F2
SC --> REP
SALTO --> REP
REP(["<b>PASSO 3</b> · Sovrapposizione e report<br/>dati grezzi contro equazioni<br/>report.md · grafici · risultati.json"])
classDef dato fill:#eceff1,stroke:#607d8b,color:#263238
classDef calcolo fill:#e3f2fd,stroke:#1a73e8,color:#0d47a1
classDef dominio fill:#fff8e1,stroke:#f9a825,color:#5d4037
classDef uscita fill:#e8f5e9,stroke:#2e7d32,color:#1b5e20
class CSV dato
class L,S,G,D,F0,F1,F2,SC,SALTO calcolo
class RIP,RIS,INT,FIN dominio
class REP uscita
linkStyle 15 stroke:#e65100,stroke-width:2px,color:#e65100
Come si legge: dall'alto in basso. I numeri nei riquadri sono i paragrafi di questo documento. Colori: grigio dati, azzurro calcoli,
giallo tipi di dominio, verde risultati. Il Passo 1 produce i domini; ogni tipo ha il suo trattamento nel Passo 2; la freccia
arancione tratteggiata indica che il raffreddamento finale passa c e \tau ai raffreddamenti intermedi (§5b), per questo si elabora per primo.
Il riscaldamento non si fitta: se ne riporta il salto (§7).
Simboli e chiavi di configurazione
Nelle formule si usano questi simboli; a destra la chiave di configurazione.md con il valore.
| Simbolo | Chiave | Significato |
|---|---|---|
\theta_g |
soglia_gradino_c |
salto positivo minimo che segna un gradino [°C] |
\theta_b |
soglia_bordo_sigma |
soglia, in multipli di \sigma_d, per estendere la salita ai campioni adiacenti |
\theta_\rho |
soglia_acf |
soglia di \rho_1 oltre la quale si allargano gli intervalli |
\kappa |
scala_perdita_sigma |
scala della perdita robusta, in multipli di \sigma |
\alpha_{\min},\ \alpha_{\max} |
tau_min_rel, tau_max_rel |
limiti di \tau come frazione di L |
\lambda |
rmse_vs_rumore_max |
un modello è «adeguato» se \mathrm{RMSE} \le \lambda\,\sigma |
\delta |
soglia_delta_aicc |
tolleranza su \Delta\mathrm{AICc} per preferire il modello più semplice |
L |
— | durata del dominio, t_\text{ultimo} - t_\text{primo} |
n, k |
— | campioni usati nel fit; parametri liberi del modello |
1. Lettura dei dati (dati.leggi_csv)
Legge l'intestazione, controlla che ci siano la colonna del tempo e tutte le serie (A2), converte il tempo in secondi (A3) e verifica che
sia strettamente crescente (A1). Restituisce t (array in secondi) e un dizionario serie {nome: array}.
2. Stima del rumore (domini.sigma_rumore)
Per un rumore bianco \varepsilon_i di deviazione \sigma, la derivata seconda discreta \Delta^2 y_i = y_{i+2} - 2y_{i+1} + y_i elimina
le componenti lisce (costante, lineare, e in buona parte l'esponenziale) e ha varianza 6\sigma^2. Per renderla robusta agli outlier si usa la
deviazione mediana assoluta:
\sigma = \frac{1.4826\,\mathrm{MAD}(\Delta^2 y)}{\sqrt{6}}, \qquad \mathrm{MAD}(x) = \mathrm{mediana}\,|x_i - \mathrm{mediana}(x)|
Il fattore 1.4826 rende la MAD uguale a \sigma per dati gaussiani. La stima si calcola per dominio (A13) sui campioni usati nel fit
e serve come scala della perdita robusta e come soglia di «adeguatezza» (§6). Ignora la deriva lenta (A14) e restituisce nan con meno
di 4 campioni.
3. Rilevamento dei gradini (domini.trova_gradini)
Sulla serie_riferimento:
- Candidati:
d_i = y_{i+1} - y_i; sono forti gli indici cond_i > \theta_g(solo salti positivi, A5, A12). - Raggruppamento: candidati a meno di
distanza_min_salti_campioniindici l'uno dall'altro appartengono allo stesso gradino (la salita si distribuisce su 2 campioni, ognuno con un salto grande). - Estensione ai bordi: il gruppo si estende all'indietro e in avanti ai campioni adiacenti ancora in salita, cioè finché
d_i > \theta_b\,\sigma_d, con\sigma_d = 1.4826\,\mathrm{MAD}(d)calcolata su tutti i salti (A6). Serve a non lasciare un campione a metà salita dentro il tratto vicino. - Ogni gradino diventa la coppia
(i_0, i_1):i_0è il primo campione già in salita ei_1il campione successivo all'ultimo in salita (estremo escluso). I campioni di salita sono quelli in[i_0, i_1).
4. Costruzione dei domini (domini.proponi)
Dati N gradini, in ordine di tempo:
riposo: dall'inizio al primo gradino (o tutto il segnale se non ci sono gradini);- per ogni gradino: un dominio
riscaldamentosui suoi campioni di salita, seguito da un dominioraffreddamentofino al gradino successivo (o alla fine). Un raffreddamento senza campioni (gradini adiacenti) non viene creato.
Con N gradini i domini sono quindi 1 + 2N. I domini sono contigui e coprono tutti i campioni. L'utente può sostituire la proposta con
domini.toml (A21), che viene validato: tipi ammessi, intervalli non vuoti, contiguità.
5. Fit (fit.adatta)
5.1 Modelli (modelli.MODELLI, t' = t - t_0)
| Modello | Equazione | Parametri | Dove si prova |
|---|---|---|---|
costante |
y = a |
a |
riposo |
lineare |
y = a + b\,t' |
a, b |
riposo |
esp_decad |
y = c + A\,e^{-t'/\tau} |
c, A, \tau |
riposo, raffreddamento |
Nel raffreddamento c è l'asintoto (≈ ambiente per T_C, ≈ 0 per dT_C), A l'ampiezza a t'=0 e \tau = 1/k la costante di tempo.
5.2 Partenza
- Polinomi (
costante,lineare): soluzione dei minimi quadrati lineari. esp_decad: proiezione delle variabili. Per\taufissato il modello è lineare in(c, A). Si provanon_griglia_tauvalori di\tausu una griglia logaritmica tra\alpha_{\min} Le\alpha_{\max} L, per ognuno si risolvono(c, A)in modo lineare e si tiene il\taucon\mathrm{RSS}minima. Poi il raffinamento non lineare parte da lì: nessuna partenza casuale (A22).- Se
ce\tausono fissi e soloAè libero:A = \sum (y - c)\,e^{-t'/\tau} \big/ \sum e^{-2t'/\tau}.
5.3 Minimizzazione
scipy.optimize.least_squares sui soli parametri liberi, con x_scale="jac", limiti \tau \in [\alpha_{\min} L,\ \alpha_{\max} L] e
perdita robusta (perdita, default soft_l1):
\min_p \sum_i \rho\!\left(\frac{r_i^2}{s^2}\right), \quad \rho(z) = 2\left(\sqrt{1+z}-1\right), \quad s = \kappa\,\sigma, \quad r_i = f(t'_i; p) - y_i
Per |r_i| \ll s si comporta come i minimi quadrati; per |r_i| \gg s cresce linearmente, così gli scarti casuali pesano molto meno (A14).
Se \sigma non è finita o è nulla la scala è 1 (A20).
5.4 Incertezze
s^2 = \frac{\mathrm{RSS}}{n-k}, \qquad \mathrm{cov}(p) = s^2\,(J^\top J)^{-1}, \qquad \mathrm{IC}_{95\%} = \pm 1.96\,\sqrt{\mathrm{diag}(\mathrm{cov})}\cdot f_\rho
k è il numero di parametri liberi, J lo jacobiano dei residui nella soluzione (con la pseudo-inversa di J^\top J), \mathrm{RSS} = \sum r_i^2 (A16).
Il fattore di autocorrelazione vale f_\rho = \sqrt{(1+\rho_1)/(1-\rho_1)} se correggi_autocorrelazione è attivo e \rho_1 > \theta_\rho, altrimenti 1 (A17).
Per i parametri fissi l'incertezza è 0 (A18).
5.5 Metriche
| Metrica | Definizione |
|---|---|
\mathrm{RMSE} |
\sqrt{\mathrm{RSS}/n} |
R^2 |
1 - \mathrm{RSS}/\mathrm{TSS}, con \mathrm{TSS} = \sum (y_i - \bar y)^2 |
\rho_1 |
autocorrelazione dei residui a lag 1: \sum_{i} \tilde r_{i+1}\tilde r_i \big/ \sum_i \tilde r_i^2, con \tilde r = r - \bar r |
\mathrm{AICc} |
n\ln(\mathrm{RSS}/n) + 2k + \dfrac{2k(k+1)}{n-k-1} (infinito se n-k-1 \le 0) |
\mathrm{BIC} |
n\ln(\mathrm{RSS}/n) + k\ln n |
| condizione | numero di condizione di J con le colonne normalizzate in norma euclidea |
AICc e BIC sono calcolati da \mathrm{RSS}, quindi senza peso robusto (A19).
5.6 Validità e identificabilità
Un fit è valido se converge, nessun parametro libero è sul limite (distanza dal limite inferiore a 10^{-3} volte il limite stesso: \tau al bordo della griglia),
il numero di condizione non supera soglia_condizione e l'AICc è finito. Un fit è non identificabile se la condizione supera la
soglia oppure un parametro libero diverso da a e c ha 1.96\,\sigma_p > |p| (intervallo che include lo zero: il parametro non
è distinguibile da 0).
5b. Costanti condivise (analisi.analizza_domini)
Per A8 i raffreddamenti hanno lo stesso \tau e lo stesso c. L'ordine di elaborazione è quindi:
- il raffreddamento finale (ultimo dominio di tipo
raffreddamento) si fitta per primo conc, A, \tauliberi; - se la scelta è valida, i valori di
ce\tau(parametri inraffreddamento_intermedio_fissa_da_finale) sono salvati per serie; - ogni raffreddamento intermedio si fitta con quei valori fissi, e solo
Alibera (k = 1).
Motivo: un intermedio ha 12–25 campioni con scarti casuali, e \tau da solo non è identificabile (su dati puliti lo sarebbe: i test lo
verificano). Se il finale non dà un fit valido o la lista è vuota gli intermedi restano liberi.
6. Scelta del modello (analisi.scegli)
Per ogni (dominio, serie) con più modelli candidati:
- Scarto: via i fit non validi (§5.6). Se non ne resta nessuno:
indeterminato. - Adeguatezza: sono adeguati i fit con
\mathrm{RMSE} \le \lambda\,\sigma. Se ce n'è almeno uno si sceglie tra questi, altrimenti tra tutti i validi (e il dominio è segnato non adeguato). - Parsimonia: tra i candidati con
\mathrm{AICc} \le \mathrm{AICc}_{\min} + \deltavince quello con meno parametri (a parità, AICc minore).
Un dominio con meno di n_min_punti campioni non viene fittato (indeterminato); un modello con più parametri di n - 2 non viene provato.
Con un solo modello candidato (raffreddamento) la scelta è lui, se valido: il flag adeguato resta informativo.
7. Riscaldamento come salto (analisi._gradino)
Il dominio di riscaldamento ha 2–3 campioni: nessun fit. Si riporta, per ogni serie, con i_0, i_1 gli estremi del dominio:
\Delta = y_{i_1-1} - y_{i_0-1}, \qquad \text{durata} = t_{i_1-1} - t_{i_0-1}
cioè il salto dal campione prima della salita all'ultimo campione di salita, e il tempo che separa i due (per 2 campioni di salita ≈ 2
intervalli, circa 300 ms). Poiché parte della salita può cadere sul campione precedente, \Delta è una stima per difetto dell'ampiezza del
gradino (A23). sigma vale null e fit è vuoto.
Esempio di calcolo completo (seed 1, T_C, raffreddamento finale)
n = 651campioni dat_0 = 22.12s (doposcarta_dopo_salto_n = 1, 650 usati nel fit);\sigma = 0.145°C.- Griglia su
\tau \in [0.05 L,\ 50 L]conL \approx 97.8s →\tau_0vicino a 16 s,c, Alineari. - Raffinamento
soft_l1con scala3\sigma = 0.44°C:c = 23.00 \pm 0.12,A = 179.6 \pm 0.48,\tau = 16.08 \pm 0.07s. - Metriche:
\mathrm{RMSE} = 0.356,\rho_1 = 0.71(> 0.3: intervalli moltiplicati per\sqrt{1.71/0.29} = 2.43),R^2 = 0.9999. \mathrm{RMSE} > 1.3 \cdot 0.145 = 0.189: non adeguato (residui autocorrelati per gli scarti casuali), ma unico modello valido → scelto.- Gli intermedi 3 e 5 usano
c = 23.00,\tau = 16.08e stimano soloA(84.3e148.3).