ELAI S.r.l.

Il giro più corto arriva tardi: che cosa deve ottimizzare un pianificatore di consegne?

Tre clienti, sei rotte e una scadenza: un caso completo distingue distanza minima, tempi di servizio e fattibilità, senza promettere risparmi non misurati.

Il giro più corto arriva tardi: che cosa deve ottimizzare un pianificatore di consegne?

La promessa al cliente non si misura in chilometri

Un’impresa vuole pianificare tre consegne con un solo veicolo. Un cliente deve essere raggiunto entro un orario preciso; dagli altri lo scarico richiede tempi diversi. Se chiediamo a un pianificatore AI soltanto il percorso più corto, può restituire una soluzione perfetta per la distanza e inutilizzabile per il servizio. Il problema non è necessariamente l’algoritmo: potremmo avergli chiesto di risolvere il problema sbagliato.

La domanda centrale è quale differenza faccia imporre una scadenza come vincolo invece di sperare che emerga dalla minimizzazione dei chilometri. Costruiamo un caso piccolo che possiamo risolvere per enumerazione completa: tutte le sei permutazioni dei tre clienti. Non usiamo traffico reale, un motore di mappe o dati di clienti EL-AI. Il caso è sintetico e serve a capire come obiettivo e fattibilità cambino una decisione aziendale.

Ipotesi, coordinate e orologio

Il deposito D è in (0,0) km, A in (1,0), B in (4,0) e C in (4,3). La distanza fra due punti è euclidea, cioè quella di un segmento rettilineo; non rappresenta una strada. La velocità costante ipotizzata è 1 km/min, equivalente a 60 km/h. Non ci sono attese, traffico o restrizioni stradali. Partiamo al minuto zero, visitiamo ciascun cliente una volta e torniamo al deposito.

Il servizio presso A dura 10 minuti, presso B e C un minuto ciascuno. B richiede arrivo entro il minuto 6 incluso: il requisito riguarda l’arrivo, non il completamento dello scarico. Ogni cliente riceve una cassa, tutte caricate inizialmente; la capacità del veicolo è tre casse. I tempi di servizio fanno parte dell’orologio ma non aggiungono chilometri. Specificare questo dettaglio evita di confrontare quantità con unità diverse o di dimenticare il tempo trascorso a veicolo fermo.

La ricorrenza che trasforma un giro in un programma

Indichiamo con d(i, j) la distanza in km, con v la velocità in km/min, con s_i il servizio in minuti e con a_i l’istante di arrivo in minuti. Dopo essere arrivati in i, prima completiamo il servizio e poi viaggiamo verso j. Perciò l’arrivo successivo è il precedente più servizio e tempo di viaggio. Il deposito iniziale ha a_D=0 e s_D=0. È una formula semplice, ma rende visibile perché ordinare i clienti cambia gli arrivi pur conservando gli stessi servizi totali.

d(i,j) = sqrt((x_i-x_j)^2 + (y_i-y_j)^2) a_j = a_i + s_i + d(i,j)/v minimise L(pi) = sum_(consecutive i,j in D,pi,D) d(i,j) subject to a_B <= 6 min; initial load = 3 crates <= Q

pi è l’ordine dei tre clienti, L la lunghezza totale e Q la capacità. Il criterio di minimizzazione si applica soltanto alle rotte ammissibili. Non sottraiamo “minuti” a “chilometri” in un punteggio privo di significato fisico. Un obiettivo con penalità per ritardo sarebbe possibile, ma richiederebbe un costo per minuto e una decisione esplicita su quanto ritardo sia negoziabile. Il nostro requisito è invece rigido.

Due giri quasi uguali, due esiti diversi

Nel giro D-A-B-C-D percorriamo 1+3+3+5=12 km. Arriviamo ad A al minuto 1, finiamo il servizio al minuto 11 e raggiungiamo B al minuto 14. Il giro è corto ma B è in ritardo di 8 minuti. Invertire il giro non basta: D-C-B-A-D resta lungo 12 km, ma C viene raggiunto al minuto 5, il suo servizio termina al minuto 6 e B viene raggiunto al minuto 9. Entrambi i minimi della distanza violano la scadenza.

Nel giro D-B-C-A-D raggiungiamo invece B al minuto 4, entro il limite. Dopo un minuto di servizio raggiungiamo C al minuto 8; terminato quel servizio, il tratto C-A di lunghezza √18 km porta l’arrivo ad A a circa 13,2426 minuti. Dieci minuti di servizio e un chilometro di ritorno chiudono il giro a circa 24,2426 minuti. La distanza totale è 8+√18≈12,2426 km. Percorriamo circa 0,2426 km in più per soddisfare il requisito; non stiamo finendo l’intero giro prima dei giri da 12 km, che terminano al minuto 24.

OrdineDistanza kmArrivo B minFine min
ABC12.000014.000024.0000
ACB12.242619.242624.2426
BAC16.24264.000028.2426
BCA12.24264.000024.2426
CAB16.242623.242628.2426
CBA12.00009.000024.0000

Ogni riga include implicitamente partenza e ritorno a D. I numeri della tabella sono arrotondati a quattro decimali soltanto per la lettura; il codice conserva i risultati completi. Le uniche rotte che rispettano l’arrivo a B sono BAC e BCA. Fra esse BCA è la più corta. Poiché tutte le sei alternative consentite dal modello sono state valutate, questa è una soluzione ottima per quel modello finito, non soltanto la migliore rotta trovata da un’euristica. Non è una prova di ottimalità per una città reale.

Mappa sintetica in km e confronto fra distanza totale e arrivo a B. La linea tratteggiata indica il minuto 6; i punti verdi soddisfano il requisito. La mappa mostra segmenti euclidei, non strade o misure di traffico.
Mappa sintetica in km e confronto fra distanza totale e arrivo a B. La linea tratteggiata indica il minuto 6; i punti verdi soddisfano il requisito. La mappa mostra segmenti euclidei, non strade o misure di traffico.

Le ipotesi cambiano la risposta

Un controllo di sensibilità incluso nel codice varia il servizio ad A fra 0, 1, 2, 5 e 10 minuti e il limite di B fra 4, 6, 10 e 14 minuti. Non sono previsioni: ricalcoliamo le stesse sei rotte cambiando un requisito alla volta. Per esempio, con servizio A nullo e scadenza 6, ABC arriva a B al minuto 4 e torna ammissibile; con servizio A di 10 minuti e scadenza 14, ABC torna ammissibile pur mantenendo gli stessi chilometri. La durata dello scarico non è un dettaglio da aggiungere dopo l’ottimizzazione.

Anche la capacità può rendere vuoto l’insieme delle soluzioni. Se il veicolo porta due casse ma deve partire con tutte e tre per un unico viaggio, nessuna delle sei rotte è ammissibile. Cambiare l’ordine non crea spazio. Il codice verifica questo caso senza inventare un risultato: non abbiamo risolto il problema con ricariche, viaggi multipli o un secondo veicolo, perché sarebbero problemi diversi da modellare. Dichiarare “nessuna soluzione sotto queste ipotesi” è un esito informativo.

Dal giocattolo verificabile a un sistema operativo

Enumerare n clienti richiede n! ordini e, valutandoli direttamente, circa n operazioni per ordine. Con tre clienti è trasparente; con molti clienti la crescita rende questo metodo inadeguato. Solutori dedicati, euristiche e metodi appresi possono cercare soluzioni più grandi, ma devono condividere lo stesso contratto di tempi, capacità e obiettivi. Un algoritmo AI può aiutare a stimare tempi di viaggio; la previsione non sostituisce la verifica dei vincoli e porta con sé incertezza. Non abbiamo confrontato solutori o addestrato un modello di traffico.

La guida primaria OR-Tools sul Vehicle Routing Problem with Time Windows è stata letta nelle sezioni dati, callback dei tempi e vincoli sulla dimensione temporale. Mostra come separare costi di percorrenza e finestre ammesse; il nostro caso non ne copia la matrice né esegue OR-Tools. Un sistema reale richiederebbe rete stradale, tempi di servizio verificati, regole di carico, tolleranze e protocollo di valutazione. Questo articolo non dimostra che EL-AI abbia installato un pianificatore logistico o ottenuto risparmi presso clienti.

La risposta: ottimizzare soltanto ciò che possiamo accettare

Il giro più corto non è sbagliato in assoluto: risolve un obiettivo incompleto per la nostra impresa. Nel caso svolto passare da 12 a circa 12,2426 km permette di rispettare B; non rende più breve la giornata né prova un guadagno economico generale. La lezione è rendere misurabile l’impegno verso il cliente, trasformarlo in un vincolo e soltanto dopo ottimizzare la distanza fra le alternative ammissibili. Prima di chiedere quanto sia intelligente il pianificatore, dobbiamo verificare quale problema gli abbiamo consegnato.

Fonte e riproducibilità

Google OR-Tools — Vehicle Routing Problem with Time Windows.

import math
points={'D':(0,0),'A':(1,0),'B':(4,0),'C':(4,3)}
service={'D':0,'A':10,'B':1,'C':1}
for order in ['ABC','BCA']:
    time=distance=0.0;current='D';arrivals={}
    for node in [*order,'D']:
        leg=math.dist(points[current],points[node])
        distance+=leg;time+=leg  # synthetic speed: 1 km/min
        arrivals[node]=time;time+=service[node];current=node
    print(order,distance,arrivals['B'],time)

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 21 ottobre 2026.