ELAI S.r.l.

Tutti i dati arrivano. Ma l’AI sta decidendo sul passato?

Tutti i dati arrivano. Ma l’AI sta decidendo sul passato? Un esempio svolto chiarisce metodo, ipotesi e limiti.

Tutti i dati arrivano. Ma l’AI sta decidendo sul passato?

Il dato arriva, ma racconta un istante lontano

Un sistema AI riceve misure di umidità e deve decidere sullo stato attuale di una serra. Nessun messaggio viene perso: il servizio li elabora tutti in ordine. Eppure la decisione può diventare sempre più vecchia, perché la coda conserva un passato che cresce più velocemente di quanto il server riesca a smaltire. Contare messaggi completati non basta a misurare la freschezza. Studieremo l’età dell’informazione con una traccia deterministica che possiamo controllare evento per evento.

Tre tempi che non coincidono

Ogni misura ha un istante di generazione g e un istante di consegna d. Il tempo di sistema di quel messaggio è d−g. A un istante di osservazione t, invece, interessa l’istante u(t) della misura più recente già consegnata: l’età è Δ(t)=t−u(t). Tutti i tempi sono in secondi sullo stesso orologio ideale, senza deriva né ritardi di rete aggiunti. Una consegna non azzera necessariamente l’età: se il dato ha già tre secondi, l’età scende a tre, non a zero.

u(t) = max { g_i : d_i ≤ t }; Δ(t) = t − u(t)

La definizione richiede almeno un aggiornamento consegnato, o uno stato iniziale dichiarato. Per evitare un’inizializzazione artificiosa, misureremo la media soltanto da t=3, quando entrambe le politiche hanno consegnato il primo campione, fino a t=15. Prima della prima consegna non attribuiamo al sistema una freschezza mai osservata. Se arrivassero messaggi fuori ordine, il massimo su g impedirebbe a un pacchetto vecchio di far regredire u(t).

La stessa macchina, due regole di coda

Generiamo dieci misure ai tempi 0,1,…,9; ogni elaborazione dura esattamente tre secondi. La politica FIFO, primo arrivato primo servito, conserva tutto: genera consegne a 3,6,9,12,15,…,30 per le misure 0,1,2,3,4,…,9. Non c’è parallelismo o interruzione del lavoro. A t=15 ha appena consegnato il dato generato a 4: età 11 secondi. Il servizio sta lavorando continuamente, ma il suo lavoro completato descrive un istante sempre più lontano.

La seconda politica conserva soltanto l’aggiornamento più recente fra quelli in attesa; quello già in esecuzione non viene interrotto. Fissiamo anche i pareggi: una misura generata nell’istante di fine servizio è disponibile prima della scelta successiva. Si elaborano allora le generazioni 0,3,6,9, consegnate a 3,6,9,12. Le altre sei vengono sostituite mentre aspettano. A t=15 l’ultima generazione disponibile è 9: età 6 secondi. Non è un guadagno gratuito: abbiamo rinunciato a conservare ogni misura.

Calcolare la media senza cancellare i salti

La media temporale è l’area sotto Δ(t) divisa per la durata osservata. Fra due consegne, u resta costante e l’età cresce con pendenza uno. Per un intervallo [a, b) l’integrale è (b²−a²)/2−u(b−a). Il codice somma queste aree esattamente fra i tempi di evento; non usa la media delle età dei soli messaggi consegnati, che risponderebbe a una domanda diversa. Anche la media dei punti del grafico sarebbe un’approssimazione, non la definizione.

mean_age_[3,15] = (1/12) ∫_(3..15) [t−u(t)] dt

FIFO produce quattro aree di 13,5, 19,5, 25,5 e 31,5 secondi quadrati: somma 90, divisa per 12 secondi dà 7,5 secondi. La politica più recente produce quattro aree di 13,5, somma 54, media 4,5 secondi. Un salto esattamente a t=15 cambia l’età istantanea ma non l’integrale: un singolo punto ha durata nulla. È per questo che possiamo confrontare la media e l’età a 15 senza aspettarci la stessa differenza numerica.

PoliticaEtà media 3–15 sEtà a 15 s
17.511
24.56
Seguire l’età, non il numero di messaggi: ogni consegna aggiorna il tempo della misura più recente. Traccia deterministica; medie calcolate integrando esattamente fra i salti.
Seguire l’età, non il numero di messaggi: ogni consegna aggiorna il tempo della misura più recente. Traccia deterministica; medie calcolate integrando esattamente fra i salti.

Quando scartare sarebbe la decisione sbagliata

Una misura di stato può diventare meno utile quando ne esiste una nuova; un evento contabile o un allarme isolato può invece essere irripetibile. Se lo scopo è ricostruire una sequenza completa, scartare è inaccettabile anche con età media migliore. Nel nostro esempio il flusso finisce a 9: dopo l’ultima consegna l’età cresce comunque perché non esistono nuovi campioni. La politica non può creare aggiornamenti che la sorgente non ha prodotto. Non abbiamo dimostrato ottimalità per reti, carichi casuali o più sensori.

Il lavoro di Yates e coautori del 2021 definisce la metrica e sviluppa metodi di analisi; usiamo la sezione II come fondamento, non ne riproduciamo un benchmark. La traccia qui è una costruzione deterministica eseguita in Python. In un impianto reale vanno sincronizzati i tempi, definite le fonti e misurate perdite, errori e conseguenze delle decisioni. Freschezza non significa accuratezza: una misura appena arrivata può essere sbagliata. Non attribuiamo il test a un’installazione EL-AI.

Il servizio che elabora tutto può quindi decidere su dati vecchi. Per scegliere una coda servono due requisiti separati: quanto della storia dobbiamo conservare e quanto recente deve essere lo stato usato. Misurare entrambi rende visibile un compromesso che una percentuale di messaggi consegnati, da sola, nasconde.

Yates et al. (2021) — Age of Information, Section II.

import json,sys
from pathlib import Path
arrivals=list(range(10));service=3
fifo=[dict(generated=g,delivered=3*(g+1)) for g in arrivals]
# Arrivals at completion time are eligible before selecting the next job.
latest=[dict(generated=g,delivered=g+3) for g in [0,3,6,9]]
def age(events,t):return t-max(e['generated'] for e in events if e['delivered']<=t)
def mean_age(events,a=3,b=15):
 points=sorted({a,b}|{e['delivered'] for e in events if a<e['delivered']<b});total=0
 for x,y in zip(points,points[1:]):
  u=max(e['generated'] for e in events if e['delivered']<=x);total+=(y*y-x*x)/2-u*(y-x)
 return total/(b-a)
times=[3+i/20 for i in range(241)]
r=dict(python=sys.version.split()[0],seed=None,scope='Deterministic finite queue simulation, no network or sensor measurements',arrivalSeconds=arrivals,serviceSeconds=service,tieRule='Arrival at t is available when service completing at t selects next waiting update',FIFO=fifo,latestWaiting=latest,times=times,fifoAge=[age(fifo,t) for t in times],latestAge=[age(latest,t) for t in times],fifoMean=mean_age(fifo),latestMean=mean_age(latest),fifoAt15=age(fifo,15),latestAt15=age(latest,15))
assert r['fifoMean']==7.5 and r['latestMean']==4.5 and r['fifoAt15']==11 and r['latestAt15']==6
Path(__file__).with_name('results.json').write_text(json.dumps(r,indent=2),encoding='utf8')

Codice, dati e istruzioni · JSON. Calcoli didattici eseguiti con Python 3.14.0; figure con Matplotlib 3.11.2. Analisi con assistenza AI, senza dichiarare peer review o revisione umana. Copertina originale ImageGen, illustrativa: non documenta persone, sedi o installazioni EL-AI. Fonti consultate il 25 ottobre 2026.