00:28 Introduzione
00:43 Robert A. Heinlein
03:03 La storia finora
06:52 Una selezione di paradigmi
08:20 Analisi statica
18:26 Programmazione array
28:08 Miscibilità hardware
35:38 Programmazione probabilistica
40:53 Programmazione differenziabile
55:12 Versionamento di codice e dati
01:00:01 Programmazione sicura
01:05:37 In conclusione, la strumentazione conta anche nella Supply Chain
01:06:40 Prossima lezione e domande del pubblico

Descrizione

Mentre la teoria della Supply Chain mainstream fatica a prevalere nelle aziende in generale, un unico strumento, vale a dire Microsoft Excel, ha riscosso un notevole successo operativo. Re-implementare le ricette numeriche della [teoria della Supply Chain] mainstream tramite fogli di calcolo è banale, eppure, questo non è ciò che è accaduto nella pratica nonostante la consapevolezza della teoria. Dimostriamo che i fogli di calcolo hanno avuto successo adottando i paradigmi di programmazione che si sono dimostrati superiori nel fornire risultati per la Supply Chain.

Trascrizione integrale

Slide 1

Ciao a tutti, benvenuti a questa serie di lezioni sulla Supply Chain. Io sono Joannes Vermorel, e oggi presenterò la mia quarta lezione: Paradigmi di programmazione per la Supply Chain.

Slide 2

Quindi, quando mi viene chiesto, “Signor Vermorel, quali ritiene siano le aree di maggiore interesse in termini di conoscenza della Supply Chain?” una delle mie risposte principali è solitamente i paradigmi di programmazione. E poi, non troppo frequentemente, ma abbastanza spesso, la reazione della persona con cui parlo è: “Paradigmi di programmazione, signor Vermorel? Di cosa diavolo sta parlando? In che modo è anche solo remotamente pertinente al compito in questione?” E questo genere di reazioni, ovviamente, non si verificano molto spesso, ma quando accadono, mi ricordano invariabilmente quella citazione incredibile di Robert A. Heinlein, considerato il decano degli scrittori di fantascienza.

Heinlein ha una fantastica citazione sull’uomo competente, che evidenzia l’importanza della competenza in vari campi, specialmente nella Supply Chain, dove ci troviamo ad affrontare problemi estremamente complessi. Questi problemi sono quasi altrettanto impegnativi quanto la vita stessa, e credo che valga davvero la pena dedicare del tempo ad esplorare l’idea dei paradigmi di programmazione, poiché potrebbero apportare molto valore alla vostra Supply Chain.

Slide 3

Fino ad ora, nella prima lezione, abbiamo visto che i problemi della Supply Chain sono estremamente complessi. Chiunque parli di soluzioni ottimali fraintende il punto; non esiste nulla che si avvicini minimamente all’ottimalità. Nella seconda lezione, ho delineato la Quantitative Supply Chain, una visione con cinque requisiti chiave per raggiungere l’eccellenza nella gestione della Supply Chain. Questi requisiti non sono sufficienti da soli, ma non possono essere trascurati se si vuole ottenere grandezza.

Nella terza lezione, ho discusso della consegna del prodotto software nel contesto dell’ottimizzazione della Supply Chain. Ho sostenuto la tesi secondo cui l’ottimizzazione della Supply Chain richiede che il prodotto software venga affrontato in modo capitalista, ma non è possibile trovare un tale prodotto sugli scaffali. C’è troppa diversità, e le sfide affrontate sono ben al di là delle tecnologie attualmente in nostro possesso. Quindi, per necessità, sarà qualcosa di completamente su misura. Pertanto, se si tratta di un prodotto software progettato su misura per l’azienda o la Supply Chain di interesse, sorge la questione di quali siano gli strumenti adeguati per effettivamente consegnare questo prodotto. Questo mi porta all’argomento di oggi: lo strumento appropriato inizia con i giusti paradigmi di programmazione, perché dovremo programmare questo prodotto in un modo o nell’altro.

Slide 4

Finora, richiediamo capacità programmatiche per affrontare il lato dell’ottimizzazione del problema, da non confondere con il lato della gestione. Quello che abbiamo visto, che è stato l’argomento della mia lezione precedente, è che Microsoft Excel è stato il vincitore finora. Dalle aziende molto piccole a quelle molto grandi, è ubiquo, è usato ovunque. Anche in aziende che hanno investito milioni di dollari in sistemi super-intelligenti, Excel domina ancora, e perché? Perché possiede le giuste proprietà di programmazione. È molto espressivo, agile, accessibile e manutenibile. Tuttavia, Excel non è l’obiettivo finale. Credo fermamente che possiamo fare molto di più, ma abbiamo bisogno degli strumenti giusti, della mentalità giusta, degli insight giusti e dei paradigmi di programmazione adeguati.

Slide 5

I paradigmi di programmazione potrebbero sembrare eccessivamente oscuri al pubblico, ma in realtà rappresentano un campo di studio che è stato approfonditamente studiato negli ultimi cinque decenni. È stata svolta un’enorme quantità di lavoro in questo campo. Non è ampiamente conosciuto da un pubblico più vasto, ma esistono intere biblioteche piene di lavori di alta qualità realizzati da molte persone. Quindi oggi, vi presenterò una serie di sette paradigmi che Lokad ha adottato. Non abbiamo inventato nessuna di queste idee; le abbiamo prese da coloro che le hanno inventate prima di noi. Tutti questi paradigmi sono stati implementati nel prodotto software di Lokad, e dopo quasi un decennio di esecuzione di Lokad in produzione, sfruttando questi paradigmi, credo che siano stati assolutamente fondamentali per il nostro successo operativo finora.

Slide 6

Procediamo con questa lista partendo dall’analisi statica. Il problema qui è la complessità. Come si affronta la complessità nella Supply Chain? Ti troverai di fronte a sistemi aziendali che hanno centinaia di tabelle, ciascuna con decine di campi. Se consideri un problema semplice come il riapprovvigionamento dell’inventario in un magazzino, ci sono così tante cose da tenere in considerazione. Puoi avere MOQs, scaglioni di prezzo, previsioni della domanda, previsioni dei lead times, e ogni genere di resi. Puoi avere limitazioni di spazio sugli scaffali, limiti di capacità di ricezione e date di scadenza che rendono obsoleti alcuni dei tuoi lotti. Quindi, finiscono per sommarsi in una marea di considerazioni. Nella Supply Chain, l’idea di “muoviti in fretta e rompi tutto” non è affatto la mentalità giusta. Se per caso ordini, inavvertitamente, merci per un milione di dollari di valore di cui non hai assolutamente bisogno, questo rappresenta un errore molto costoso. Non puoi avere un programma software che gestisce la tua Supply Chain, prendendo decisioni di routine, e quando c’è un bug, il costo è di milioni. Abbiamo bisogno di qualcosa con un altissimo grado di correttezza per design. Non vogliamo scoprire i bug in produzione. Questo è molto diverso dal software medio, dove un crash non è così grave.

Quando si parla di ottimizzazione della Supply Chain, questo non è il solito problema. Se hai appena passato un ordine enorme e errato a un fornitore, non puoi semplicemente chiamarlo una settimana dopo per dire: “Oh, è stato un errore, no, dimentica, non abbiamo mai ordinato nulla di simile.” Quegli errori costeranno un sacco di denaro. L’analisi statica si chiama così perché riguarda l’analisi di un programma senza eseguirlo. L’idea è che hai un programma scritto con istruzioni, parole chiave e tutto il resto, e senza nemmeno eseguirlo, puoi già capire se il programma presenta problemi che quasi certamente influenzeranno negativamente la tua produzione, specialmente la produzione della Supply Chain. La risposta è sì. Queste tecniche esistono, sono implementate e estremamente preziose.

Per fare un esempio, potete vedere uno screenshot di Envision sullo schermo. Envision è un linguaggio di programmazione specifico per il dominio, sviluppato per quasi un decennio da Lokad e dedicato all’ottimizzazione predittiva della Supply Chain. Quello che state vedendo è uno screenshot dell’editor di codice di Envision, una web app che potete usare online per modificare il codice. La sintassi è fortemente influenzata da Python. In questo minuscolo screenshot, con solo quattro righe, sto illustrando l’idea che se stai scrivendo una grande porzione di logica per il riapprovvigionamento dell’inventario in un magazzino, e introduci alcune variabili economiche, come gli scaglioni di prezzo, attraverso un’analisi logica del programma, puoi vedere che tali scaglioni di prezzo non hanno alcuna relazione con i risultati finali restituiti dal programma, ovvero le quantità da riapprovvigionare. Qui, abbiamo un problema evidente. Hai introdotto una variabile importante, gli scaglioni di prezzo, e questi scaglioni, logicamente, non influenzano i risultati finali. Quindi, qui, abbiamo un problema che può essere rilevato tramite analisi statica. È un problema evidente, perché se introduciamo variabili nel codice che non hanno alcun impatto sull’output del programma, allora non servono a nulla. In questo caso, ci troviamo di fronte a due opzioni: o queste variabili sono in realtà codice morto, e il programma non dovrebbe compilare (dovresti semplicemente eliminare questo codice morto per ridurre la complessità e non accumulare complessità accidentale), oppure è stato un errore genuino e c’è una variabile economica importante che avrebbe dovuto essere integrata nel tuo calcolo, ma hai commesso una svista per distrazione o per qualche altro motivo.

L’analisi statica è assolutamente fondamentale per raggiungere un qualsiasi grado di correttezza per design. Si tratta di risolvere i problemi al momento della compilazione, quando scrivi il codice, ancor prima di toccare i dati. Se i problemi emergono quando esegui il programma, è probabile che si verifichino solo durante la notte, quando il batch notturno gestisce il riapprovvigionamento del magazzino. Il programma probabilmente verrà eseguito in orari strani, quando nessuno lo sorveglia, quindi non vuoi che qualcosa si blocchi mentre non c’è nessuno davanti al programma. Dovrebbe invece bloccarsi al momento in cui le persone stanno effettivamente scrivendo il codice.

L’analisi statica ha molte finalità. Ad esempio, in Lokad, utilizziamo l’analisi statica per l’edition WYSIWYG dei dashboard. WYSIWYG sta per “what you see is what you get.” Immagina di costruire un dashboard per il reporting, con grafici a linee, a barre, tabelle, colori e vari effetti di stile. Vuoi poterlo fare in modo visuale, anziché modificare lo stile del tuo dashboard attraverso il codice, poiché sarebbe troppo macchinoso. Tutte le impostazioni che hai implementato verranno reiniettate nel codice stesso, e questo viene fatto tramite l’analisi statica.

Un altro aspetto in Lokad, che potrebbe non essere di così grande importanza per la Supply Chain in generale ma certamente critico per l’avvio del progetto, è stato affrontare un linguaggio di programmazione chiamato Envision che stiamo sviluppando. Sapevamo fin dal primo giorno, quasi un decennio fa, che si sarebbero commessi errori. Non avevamo una sfera di cristallo per avere, fin dal primo giorno, la visione perfetta. La domanda era: come possiamo assicurarci di poter correggere quegli errori di design nel linguaggio di programmazione nel modo più conveniente possibile? In questo contesto, Python mi ha servito da monito.

Python, che non è un linguaggio nuovo, è stato rilasciato per la prima volta nel 1991, quasi 30 anni fa. La migrazione da Python 2 a Python 3 ha richiesto all’intera comunità quasi un decennio, ed è stata un processo da incubo, molto doloroso per le aziende coinvolte in tale migrazione. La mia percezione era che il linguaggio in sé non avesse abbastanza costrutti. Non era progettato in modo da consentire la migrazione dei programmi da una versione all’altra del linguaggio. In realtà, era estremamente difficile farlo in maniera completamente automatizzata, ed è proprio perché Python non è stato sviluppato con l’analisi statica in mente. Quando hai un linguaggio di programmazione per la Supply Chain, desideri davvero uno che garantisca un’eccellente qualità in termini di analisi statica, perché i tuoi programmi saranno destinati a durare a lungo. Le Supply Chain non hanno il lusso di dire: “Aspettate tre mesi, stiamo solo riscrivendo il codice. Aspettateci, sta arrivando la cavalleria. Non funzionerà per un paio di mesi.” È letteralmente come riparare un treno mentre questo corre sui binari a tutta velocità, e tu vuoi riparare il motore mentre il treno è in funzione. È così che si presenta la riparazione di elementi della Supply Chain che sono effettivamente in produzione. Non hai il lusso di mettere in pausa il sistema; esso non si ferma mai.

Slide 7

Il secondo paradigma è la programmazione array. Vogliamo tenere sotto controllo la complessità, poiché questo è un tema ricorrente nelle Supply Chain. Vogliamo avere una logica in cui non esistono alcune classi di errori di programmazione. Ad esempio, ogni volta che si scrivono esplicitamente cicli o branch da parte dei programmatori, ci si espone a intere classi di problemi molto difficili. Diventa estremamente complicato quando le persone possono scrivere cicli arbitrari per avere garanzie sulla durata del calcolo. Sebbene possa sembrare un problema di nicchia, non è affatto così nell’ottimizzazione della Supply Chain.

In pratica, supponiamo di avere una catena retail. A mezzanotte, tutte le vendite dell’intera rete saranno state completamente consolidate, e i dati verranno raccolti e trasmessi a un sistema di ottimizzazione. Questo sistema avrà esattamente una finestra di 60 minuti per effettuare le previsioni, l’ottimizzazione dell’inventario e le decisioni di riallocazione per ogni singolo negozio della rete. Una volta terminato, i risultati saranno passati al sistema di gestione del magazzino affinché possa iniziare a preparare tutte le spedizioni. I camion verranno caricati, forse alle 5:00, e alle 9:00 i negozi apriranno con la merce già ricevuta e messa sugli scaffali.

Tuttavia, hai una tempistica molto rigorosa, e se il tuo calcolo supera questa finestra di 60 minuti, metti a rischio l’intera esecuzione della supply chain. Non vuoi trovarti nella situazione in cui scopri in produzione quanto tempo richiedono le operazioni. Se hai cicli in cui le persone possono decidere quante iterazioni effettuare, è molto difficile avere una prova della durata del tuo calcolo. Tieni presente che stiamo parlando di ottimizzazione della supply chain. Non hai il lusso di fare peer review e ricontrollare tutto. A volte, a causa della pandemia, alcuni paesi stanno chiudendo mentre altri riaprono in modo molto irregolare, solitamente con un preavviso di 24 ore. Devi reagire rapidamente.

Quindi, la programmazione array è l’idea che tu possa operare direttamente sugli array. Se osserviamo il frammento di codice che abbiamo qui, questo è il codice di Envision, il DSL di Lokad. Per capire cosa sta succedendo, devi comprendere che quando scrivo “orders.amounts”, quello che segue è una variabile e “orders” è in realtà una tabella nel senso di una tabella relazionale, come in una tabella del tuo database. Ad esempio, qui, nella prima riga, “amounts” sarebbe una colonna della tabella. Alla prima riga, quello che sto facendo è letteralmente dire che per ogni singola riga della tabella orders, prenderò semplicemente la “quantity”, che è una colonna, la moltiplicherò per “price”, e poi otterrò una terza colonna che viene generata dinamicamente, ossia “amount”.

A proposito, il termine moderno per la programmazione array al giorno d’oggi è anche noto come programmazione con data frame. Il campo di studio è abbastanza antico; risale a tre o quattro decenni, forse anche quattro o cinque. È stato conosciuto come programmazione array anche se oggi le persone sono di solito più familiari con il concetto di data frame. Alla seconda riga, quello che stiamo facendo è applicare un filtro, proprio come in SQL. Stiamo filtrando le date, e capita che la tabella orders contenga una data. Verrà filtrata, e dico “data maggiore di oggi meno 365”, quindi in giorni. Manteniamo i dati dell’anno scorso, e poi scriviamo “products.soldLastYear = SUM(orders.amount)”.

Ora, la cosa interessante è che abbiamo quello che chiamiamo un natural join tra products e orders. Perché? Perché ogni riga di ordine è associata a un solo prodotto, e un prodotto è associato a zero o più righe d’ordine. In questa configurazione, puoi dire direttamente, “Voglio calcolare qualcosa a livello di prodotto che sia semplicemente la somma di ciò che accade a livello degli ordini,” ed è esattamente ciò che viene fatto alla riga nove. Potresti notare che la sintassi è molto essenziale; non ci sono molti particolari o tecnicismi. Sostengo che questo codice è quasi del tutto privo di particolarità quando si tratta di programmazione con data frame. Poi, alle righe 10, 11 e 12, stiamo semplicemente mostrando una tabella sul nostro dashboard, cosa che può essere fatta in modo molto comodo: “LIST(PRODUCTS)”, e poi “TO(products)”.

Ci sono molti vantaggi nella programmazione array per le supply chain. Innanzitutto, elimina intere classi di problemi. Non avrai bug del tipo off-by-one nei tuoi array. Sarà molto più semplice parallelizzare e persino distribuire il calcolo. Questo è molto interessante perché significa che puoi scrivere un programma e farlo eseguire non su una macchina locale, ma direttamente su una flotta di macchine che operano nel cloud, e a proposito, è esattamente ciò che viene fatto da Lokad. Questa parallelizzazione automatica è di altissimo interesse.

Vedi, il funzionamento è che quando si fa ottimizzazione della supply chain, i tipici modelli di consumo in termini di hardware di calcolo sono estremamente intermittenti. Se torno all’esempio che ho fatto sulla finestra di 60 minuti per le reti retail durante il rifornimento dei negozi, significa che c’è un’ora al giorno in cui hai bisogno di potenza di calcolo per eseguire tutti i tuoi calcoli, mentre per il resto del tempo, le altre 23 ore, non te ne servono. Quindi, quello che vuoi è un programma che, quando sei pronto a eseguirlo, si distribuisca su molte macchine e poi, una volta terminato, liberi tutte quelle macchine affinché possano essere utilizzate per altri calcoli. L’alternativa sarebbe avere molte macchine che affitti e paghi per tutto il giorno, ma che utilizzi solo per il 5% del tempo, il che è molto inefficiente.

Questa idea che puoi distribuire su molte macchine in modo rapido e prevedibile, per poi cedere la potenza di elaborazione, richiede il cloud in una configurazione multi-tenant e una serie di altre soluzioni aggiuntive su cui sta lavorando Lokad. Ma, prima di tutto, è necessaria la cooperazione del linguaggio di programmazione stesso. È qualcosa che non è realizzabile con un linguaggio di programmazione generico come Python, perché il linguaggio stesso non si presta a questo tipo di approccio intelligente e rilevante. Questo è più di un semplice trucco; si tratta letteralmente di dividere i costi dell’hardware IT per 20, accelerando massivamente l’esecuzione ed eliminando intere classi di potenziali bug nella tua supply chain. Questo cambia le regole del gioco.

La programmazione array esiste già in molti aspetti, come in NumPy e pandas in Python, che sono così popolari per il segmento del data scientist del pubblico. Ma la domanda che ho per voi è: se è così importante e utile, perché queste cose non sono cittadini di prima classe del linguaggio stesso? Se tutto quello che fai è canalizzare attraverso NumPy, allora NumPy dovrebbe essere un cittadino di prima classe. Direi che puoi andare persino oltre NumPy. NumPy riguarda solamente la programmazione array su una singola macchina, ma perché non fare programmazione array su una flotta di macchine? È molto più potente e molto più adeguato quando hai un cloud con capacità hardware accessibile.

Slide 8

Allora, qual è il collo di bottiglia nell’ottimizzazione della supply chain? C’è un detto di Goldratt che afferma, “Ogni miglioramento apportato al di là del collo di bottiglia in una supply chain è un’illusione,” e sono pienamente d’accordo con questa affermazione. Realisticamente, quando vogliamo fare ottimizzazione della supply chain, il collo di bottiglia saranno le persone, e più specificamente, i Supply Chain Scientist che, sfortunatamente per Lokad e per i miei clienti, non crescono sugli alberi.

Il collo di bottiglia sono i Supply Chain Scientist, le persone che possono creare ricette numeriche che tengono conto di tutte le strategie dell’azienda, dei comportamenti avversari dei concorrenti, e che trasformano tutta questa intelligenza in qualcosa di meccanico che può essere eseguito su larga scala. La tragedia del modo ingenuo di fare data science, quando ho iniziato il mio dottorato, che, tra l’altro, non ho mai completato, era che vedevo tutti in laboratorio letteralmente impegnati nella data science. La maggior parte delle persone scriveva codice per qualche tipo di modello avanzato di machine learning, premeva invio e poi iniziava ad aspettare. Se hai un dataset di grandi dimensioni, diciamo 5-10 gigabyte, non sarà in tempo reale. Quindi, l’intero laboratorio era pieno di persone che scrivevano poche righe, premevano invio, e poi andavano a prendere una tazza di caffè o a leggere qualcosa online. Di conseguenza, la produttività era estremamente bassa.

Quando ho fondato la mia azienda, avevo ben chiaro che non volevo finire per pagare un esercito di persone super intelligenti che trascorrono la maggior parte della giornata sorseggiando caffè, aspettando che i loro programmi terminassero per ottenere risultati e proseguire. In teoria, potrebbero parallelizzare molte cose contemporaneamente ed eseguire esperimenti, ma in pratica, non l’ho mai davvero visto. Intellettualmente, quando sei impegnato a trovare la soluzione a un problema, vuoi testare la tua ipotesi e hai bisogno del risultato per andare avanti. È molto difficile fare multitasking su argomenti altamente tecnici e inseguire contemporaneamente più piste intellettuali.

Tuttavia, c’era un lato positivo. I data scientist, e ora i Supply Chain Scientist di Lokad, non finiscono per scrivere mille righe di codice per poi dire “per favore, esegui”. Di solito aggiungono due righe a uno script di mille righe, e poi chiedono che lo script venga eseguito. Questo script viene eseguito sugli stessi dati che sono stati processati pochi minuti prima. È quasi esattamente la stessa logica, tranne quelle due righe. Quindi, come puoi processare terabyte di dati in secondi invece che in diversi minuti? La risposta è: se per la precedente esecuzione dello script hai registrato tutti i passaggi intermedi del calcolo e li hai salvati su storage (tipicamente solid-state drives o SSD), che sono molto economici, veloci e comodi.

La prossima volta che esegui il tuo programma, il sistema noterà che lo script è quasi identico. Effettuerà un diff e vedrà che, in termini di grafo computazionale, è praticamente identico, salvo per alcune piccole differenze. Dal punto di vista dei dati, è solitamente identico al 100%. A volte ci sono qualche variazione, ma quasi nulla. Il sistema autodiagnosticherà che hai solo poche cose da calcolare, permettendoti di ottenere i risultati in secondi. Questo può aumentare drasticamente la produttività del tuo Supply Chain Scientist. Puoi passare da persone che premono invio e aspettano 20 minuti per il risultato, a persone che premono invio e, 5 o 10 secondi dopo, hanno il risultato e possono proseguire.

Sto parlando di qualcosa che può sembrare super oscuro, ma in pratica, stiamo parlando di qualcosa che ha un impatto di 10 volte sulla produttività. Questo è enorme. Quello che stiamo facendo qui è utilizzare un trucco ingegnoso che Lokad non ha inventato. Stiamo sostituendo una risorsa grezza di calcolo, ovvero il compute, con un’altra, che è la memoria e lo storage. Abbiamo le risorse fondamentali per il calcolo: compute, memoria (sia volatile che persistente) e larghezza di banda. Queste sono le risorse fondamentali per cui paghi quando acquisti risorse su una piattaforma di cloud computing. Puoi effettivamente sostituire una risorsa con un’altra, e l’obiettivo è ottenere il massimo beneficio per il tuo investimento.

Quando si dice che dovresti utilizzare il computing in-memory, direi che è una sciocchezza. Se parli di in-memory computing, significa che stai ponendo l’accento progettuale su una risorsa a discapito delle altre. Ma no, ci sono dei compromessi, e la cosa interessante è che puoi avere un linguaggio di programmazione e un ambiente che rendono più facili da implementare questi compromessi e queste prospettive. In un linguaggio di programmazione generico è possibile farlo, ma devi operare manualmente. Ciò significa che la persona che lo fa deve essere un ingegnere del software professionista. Un Supply Chain Scientist non eseguirà queste operazioni a basso livello con le risorse di calcolo fondamentali della tua piattaforma. Questo deve essere implementato a livello del linguaggio di programmazione stesso.

Slide 9

Adesso, parliamo di programmazione probabilistica. Nella seconda lezione in cui ho presentato la visione per la supply chain quantitativa, il mio primo requisito era che dovessimo considerare tutti i possibili futuri. La risposta tecnica a questo requisito è probabilistic forecasting. Vuoi affrontare futuri in cui sono presenti delle probabilità. Tutti i futuri sono possibili, ma non sono tutti ugualmente probabili. Hai bisogno di un’algebra che ti permetta di eseguire calcoli con l’incertezza. Una delle mie grandi critiche a Excel è che è estremamente difficile rappresentare l’incertezza in un foglio di calcolo, sia che si tratti di Excel o di qualche versione moderna basata sul cloud. In un foglio di calcolo, è molto complicato rappresentare l’incertezza perché serve qualcosa di migliore dei semplici numeri.

In questo piccolo frammento, sto illustrando l’algebra delle variabili casuali, che è una caratteristica nativa di Envision. Alla prima riga, sto generando una distribuzione di Poisson, discreta, con una media di 2, e la assegno alla variabile X. Poi, faccio lo stesso per un’altra distribuzione di Poisson, Y. Successivamente, calcolo Z come la moltiplicazione di X per Y. Questa operazione, la moltiplicazione di variabili casuali, può sembrare molto bizzarra. Perché avresti mai bisogno di questo tipo di operazione da una prospettiva della supply chain? Lasciami fare un esempio.

Supponiamo che tu operi nel mercato aftermarket automobilistico e che venda pastiglie dei freni. Le persone non acquistano le pastiglie dei freni alla singola unità; o ne comprano due o quattro. Quindi, se vuoi fare una previsione, potresti voler stimare le probabilità che i clienti si presentino effettivamente ad acquistare un certo tipo di pastiglie dei freni. Quella costituirà la tua prima variabile casuale, che ti fornirà la probabilità di osservare zero unità di domanda, una unità di domanda, due, tre, quattro, ecc. per le pastiglie dei freni. Successivamente, avrai un’altra distribuzione di probabilità che rappresenta se le persone acquisteranno due o quattro pastiglie dei freni. Forse sarà 50-50, oppure forse il 10% acquisterà due e il 90% quattro. Il punto è che hai questi due aspetti e, se vuoi conoscere il consumo totale effettivo delle pastiglie dei freni, devi moltiplicare la probabilità che un cliente si presenti per queste pastiglie per la distribuzione di probabilità dell’acquisto di due o quattro. Quindi, hai bisogno di questa moltiplicazione di queste due quantità incerte.

Qui, sto assumendo che le due variabili casuali siano indipendenti. A proposito, questa moltiplicazione di variabili casuali è conosciuta in matematica come convoluzione discreta. Puoi vedere nello screenshot il dashboard generato da Envision. Nelle prime tre righe sto effettuando questo calcolo di algebra casuale, e poi, alle righe quattro, cinque e sei, mostro questi risultati nella pagina web, nel dashboard generato dallo script. Sto tracciando A1, B2, per esempio, proprio come in una griglia Excel. I dashboard di Lokad sono organizzati in modo simile alle griglie di Excel, con posizioni che hanno colonne B, C, ecc., e righe 1, 2, 3, 4, 5.

Puoi notare che la convoluzione discreta, Z, presenta un pattern molto bizzarro ed estremamente spigoloso che si riscontra comunemente nelle supply chain, quando le persone possono acquistare confezioni, lotti o multipli. In questo tipo di situazione, è solitamente preferibile scomporre le fonti degli eventi moltiplicativi associati al lotto o alla confezione. Hai bisogno di un linguaggio di programmazione che metta a disposizione queste capacità come cittadini di prima classe. È esattamente questo l’obiettivo della programmazione probabilistica, ed è così che l’abbiamo implementata in Envision.

Slide 10

Adesso, discutiamo di differentiable programming. Devo mettere una precisazione: non mi aspetto che il pubblico capisca davvero cosa stia succedendo, e me ne scuso. Non è che la vostra intelligenza manchi; è solo che questo argomento merita un’intera serie di lezioni. Infatti, se guardate il programma delle prossime lezioni, c’è un’intera serie dedicata al differentiable programming. Andrò super veloce, e sarà piuttosto criptico, quindi mi scuso in anticipo.

Procediamo con il problema della supply chain di interesse qui, ovvero la cannibalizzazione e la sostituzione. Questi problemi sono molto interessanti, e probabilmente sono il campo in cui le previsioni time series — che sono ovunque — falliscono nel modo più brutale. Perché? Perché frequentemente mi vengono chiesti da clienti o potenziali clienti se possiamo fare, per esempio, previsioni a 13 settimane in anticipo per alcuni articoli come gli zaini. Direi di sì, possiamo, ma ovviamente, se prendiamo uno zaino e vogliamo prevederne la domanda, questa dipende massicciamente da ciò che fate con gli altri vostri zaini. Se avete un solo zaino, allora forse concentrerete tutta la domanda su questo unico prodotto. Se introducete 10 varianti diverse, ovviamente ci sarà una grande cannibalizzazione. Non moltiplicherete l’ammontare totale delle vendite per un fattore di 10 solo perché avete moltiplicato il numero di referenze per 10. Quindi, ovviamente, si verifica cannibalizzazione e sostituzione. Tali fenomeni sono prevalenti nelle supply chains.

Come si analizza la cannibalizzazione o la sostituzione? Il modo in cui lo facciamo a Lokad, e non pretendo che sia l’unico, ma è certamente un metodo che funziona, è tipicamente osservare il grafo che connette clienti e prodotti. Perché? Perché la cannibalizzazione si verifica quando i prodotti competono tra loro per gli stessi clienti. La cannibalizzazione è letteralmente il riflesso del fatto che un cliente ha un bisogno, ma ha anche delle preferenze e sceglie un solo prodotto tra l’insieme di prodotti che rispondono alla sua affinità. Questa è l’essenza della cannibalizzazione.

Se vuoi analizzarlo, devi analizzare non le serie temporali delle vendite, perché queste non catturano tali informazioni in primo luogo. Vuoi analizzare il grafo che connette le transazioni storiche tra clienti e prodotti. Risulta che nella maggior parte delle aziende questi dati sono facilmente disponibili. Per l’e-commerce, è scontato. Ogni unità che vendi, conosci il cliente. Nel B2B è lo stesso. Anche nel B2C nel retail, la maggior parte delle volte, le catene di vendita al dettaglio di oggi hanno programmi di loyalty in cui conoscono una percentuale a doppia cifra dei clienti che si presentano con le loro carte, così sai chi compra cosa. Non per il 100% del traffico, ma non ti serve. Se hai almeno il 10% delle tue transazioni storiche in cui conosci la coppia cliente-prodotto, è sufficiente per questo tipo di analisi.

In questo frammento relativamente breve, andrò a dettagliare un’analisi di affinità tra clienti e prodotti. Questo è letteralmente il passo fondamentale da compiere per eseguire qualsiasi tipo di analisi sulla cannibalizzazione. Diamo un’occhiata a ciò che sta succedendo in questo codice.

Dalle linee una a cinque, è molto banale; sto semplicemente leggendo un file flat che contiene una cronologia di transazioni. Sto leggendo un file CSV che ha quattro colonne: data, prodotto, cliente e quantità. Qualcosa di molto basilare. Non sto nemmeno utilizzando tutte queste colonne, ma serve solo a rendere l’esempio un po’ più concreto. Nella cronologia delle transazioni, presumo che i clienti siano conosciuti per tutte quelle transazioni. Quindi, è molto banale; sto semplicemente leggendo dati da una tabella.

Poi, nelle linee sette e otto, sto semplicemente creando la tabella per i prodotti e la tabella per i clienti. In un ambiente di produzione reale, di solito non creerei queste tabelle; le leggerei da altri file flat altrove. Volevo mantenere l’esempio super semplice, quindi sto semplicemente estraendo una tabella dei prodotti da quelli che ho osservato nella cronologia delle transazioni, e faccio lo stesso per i clienti. Vedi, è solo un trucco per mantenerlo super semplice.

Ora, le linee 10, 11 e 12 riguardano gli spazi Latin, e questo diventerà un po’ più oscuro. Prima, alla linea 10, sto creando una tabella con 64 righe. La tabella non contiene nulla; è definita solo dal fatto che ha 64 righe, e basta. Quindi è come un segnaposto, una tabella banale con molte righe e senza colonne. Non è molto utile così com’è. Poi, “P” è fondamentalmente un prodotto cartesiano, un’operazione matematica che genera tutte le coppie. È una tabella nella quale hai una riga per ogni riga dei prodotti e per ogni riga della tabella “L”. Quindi, questa tabella “P” ha 64 righe in più rispetto alla tabella dei prodotti, e sto facendo lo stesso per i clienti. Sto semplicemente espandendo quelle tabelle attraverso questa dimensione extra, che è la tabella “L”.

Questo sarà il mio supporto per i miei spazi Latin, che è esattamente ciò che andrò ad apprendere. Quello che voglio imparare è che, per ogni prodotto, esista uno spazio Latin che sia un vettore di 64 valori, e per ogni cliente, uno spazio Latin anch’esso di 64 valori. Se voglio conoscere l’affinità tra un cliente e un prodotto, voglio semplicemente poter effettuare il prodotto scalare tra i due. Il prodotto scalare è soltanto la moltiplicazione elemento per elemento di tutti i termini di quei due vettori, seguita dalla somma. Può sembrare molto tecnico, ma è solo moltiplicazione elemento per elemento più somma – questo è il prodotto scalare.

Questi spazi Latin sono solo un gergo sofisticato per creare uno spazio con parametri un po’ inventati, che è ciò che voglio apprendere. Tutta la magia del differentiable programming avviene in sole cinque righe, dalla linea 14 alla 18. Ho una parola chiave, “autodiff”, e “transactions”, che indica che questa è una tabella di interesse, una tabella di osservazioni. Elaborerò questa tabella riga per riga per svolgere il mio processo di apprendimento. In questo blocco, dichiaro un insieme di parametri. I parametri sono le cose che vuoi imparare, come numeri, ma di cui non conosci ancora i valori. Questi saranno semplicemente inizializzati in modo casuale, con numeri random.

Introduco “X”, “X*” e “Y”. Non entrerò nei dettagli su cosa faccia esattamente “X*”; magari nelle domande. Sto restituendo un’espressione che è la mia funzione di perdita, ed è la somma. L’idea del collaborative filtering o della decomposizione della matrice è semplicemente che vuoi apprendere spazi Latin che si adattino a tutti i tuoi collegamenti nel grafo bipartito. So che è un po’ tecnico, ma ciò che stiamo facendo è letteralmente molto semplice, dal punto di vista della supply chain. Stiamo apprendendo l’affinità tra prodotti e clienti.

So che sembra probabilmente super opaco, ma restate con me, e ci saranno altre lezioni in cui vi fornirò un’introduzione più approfondita. L’intero processo è realizzato in cinque righe, e questo è davvero notevole. Quando dico cinque righe, non sto imbroglionando dicendo: “Guardate, sono solo cinque righe, ma in realtà sto effettuando una chiamata a una libreria di terze parti di complessità gigantesca in cui nascondo tutta l’intelligenza.” No, no, no. Qui, in questo esempio, non c’è letteralmente alcuna magia del machine learning oltre alle due parole chiave “autodiff” e “params”. “Autodiff” viene usato per definire un blocco in cui avverrà il differentiable programming, e tra l’altro, questo è un blocco in cui posso programmare qualsiasi cosa, quindi letteralmente posso iniettare il nostro programma. Poi, ho “params” per dichiarare i miei problemi, ed ecco fatto. Quindi, vedete, non c’è alcuna magia opaca in atto; non c’è una libreria da un milione di righe in background a fare tutto il lavoro per voi. Tutto ciò che dovete sapere è letteralmente su questo schermo, e questa è la differenza tra un paradigma di programmazione e una libreria. Il paradigma di programmazione vi dà accesso a capacità apparentemente incredibilmente sofisticate, come eseguire un’analisi di cannibalizzazione con poche righe di codice, senza ricorrere a massicce librerie di terze parti che nascondono la complessità. Esso trascende il problema, rendendolo molto più semplice, così da poter risolvere qualcosa che sembra super complicato in poche righe.

Ora, alcune parole su come funziona il differentiable programming. Ci sono due intuizioni. Una è la derivazione automatica. Per chi ha avuto il privilegio di una formazione ingegneristica, si conoscono due modi per calcolare le derivate. C’è la derivata simbolica, per esempio, se hai x al quadrato, calcoli la derivata rispetto a x, e ti dà 2x. Quella è la derivata simbolica. Poi c’è la derivata numerica, quindi se hai una funzione f(x) che vuoi differenziare, sarà f’(x) ≈ (f(x + ε) - f(x))/ε. Questa è la derivazione numerica. Entrambe non sono adatte a ciò che stiamo cercando di fare qui. La derivata simbolica presenta problemi di complessità, poiché la tua derivata potrebbe essere un programma molto più complesso dell’originale. La derivazione numerica è numericamente instabile, quindi avrai molti problemi di stabilità numerica.

La derivazione automatica è un’idea fantastica risalente agli anni ‘70 e riscoperta dal mondo intero nell’ultimo decennio. È l’idea che tu possa calcolare la derivata di un programma arbitrario, il che è sconvolgente. Ancora più sorprendente, il programma che rappresenta la derivata ha la stessa complessità computazionale del programma originale, il che è stupefacente. Il differentiable programming è semplicemente una combinazione di derivazione automatica e parametri che vuoi apprendere.

Allora, come impari? Quando hai la derivata, significa che puoi propagare i gradienti verso l’alto, e con lo stochastic gradient descent puoi fare piccoli aggiustamenti ai valori dei parametri. Modificando questi parametri, convergerai gradualmente, attraverso molte iterazioni dello stochastic gradient descent, a parametri che abbiano senso e raggiungano ciò che vuoi apprendere o ottimizzare.

Il differentiable programming può essere usato per problemi di apprendimento, come quello che sto illustrando, in cui voglio apprendere l’affinità tra i miei clienti e i miei prodotti. Può anche essere usato per problemi di ottimizzazione numerica, come ottimizzare elementi sotto vincoli, ed è un paradigma molto scalabile. Come potete vedere, questo aspetto è stato elevato a cittadino di prima classe in Envision. A proposito, ci sono ancora alcune cose in fase di sviluppo per quanto riguarda la sintassi di Envision, quindi non aspettatevi esattamente quelle funzionalità ancora; stiamo ancora perfezionando alcuni aspetti. Ma l’essenza è lì. Non discuterò i dettagli minuti delle poche cose che sono ancora in evoluzione.

Slide 11

Passiamo ora a un altro problema rilevante per la prontezza della produzione del tuo sistema. Tipicamente, nell’ottimizzazione della supply chain, ti imbatti negli Heisenbug. Cos’è un Heisenbug? È un tipo di bug frustrante in cui un’ottimizzazione viene eseguita e produce risultati spazzatura. Ad esempio, hai effettuato un calcolo batch per il rifornimento dell’inventario durante la notte, e al mattino scopri che alcuni di quei risultati erano insensati, causando errori costosi. Non vuoi che il problema si ripresenti, quindi riesegui il processo. Tuttavia, quando lo riesegui, il problema è scomparso. Non riesci a riprodurre l’errore, e l’Heisenbug non si manifesta.

Può sembrare un caso limite strano, ma nei primi anni di Lokad ci siamo imbattuti ripetutamente in questi problemi. Ho visto molte iniziative nella supply chain, soprattutto di tipo data science, fallire a causa di Heisenbug non risolti. Si verificavano bug in produzione, si cercava di riprodurre i problemi localmente ma senza successo, quindi i problemi non venivano mai risolti. Dopo un paio di mesi in modalità panico, l’intero progetto veniva solitamente chiuso in silenzio, e la gente tornava a usare fogli di calcolo Excel.

Se vuoi ottenere una replicabilità completa della tua logica, devi versionare il codice e i dati. La maggior parte delle persone in pubblico, che sono ingegneri del software o data scientist, probabilmente conosce l’idea di versionare il codice. Tuttavia, devi versionare anche tutti i dati in modo che, quando il tuo programma viene eseguito, tu sappia esattamente quale versione del codice e dei dati viene utilizzata. Potresti non riuscire a replicare il problema il giorno dopo perché i dati sono cambiati a causa di nuove transazioni o altri fattori, quindi le condizioni che innescavano il bug in primo luogo non sono più presenti.

Devi assicurarti che il tuo ambiente di programmazione possa replicare esattamente la logica e i dati così come erano in produzione in un determinato momento. Ciò richiede una completa versioning di tutto. Di nuovo, il linguaggio di programmazione e lo stack devono cooperare per rendere ciò possibile. È realizzabile senza che il paradigma di programmazione sia una priorità assoluta nel tuo stack, ma in quel caso lo supply chain scientist deve essere estremamente attento a tutto ciò che fa e a come programma. Altrimenti, non riuscirà a replicare i propri risultati. Questo mette un’enorme pressione sulle spalle degli supply chain scientist, che sono già sottoposti a una significativa pressione dalla supply chain stessa. Non vuoi che questi professionisti si occupino di complessità accidentali, come il non riuscire a replicare i propri risultati. Da Lokad, chiamiamo questo una “time machine” in cui puoi replicare tutto in qualsiasi momento del passato.

Attenzione, non si tratta solo di replicare ciò che è successo la scorsa notte. A volte, scopri un errore molto tempo dopo i fatti. Ad esempio, se effettui un ordine d’acquisto con un fornitore che ha un tempo di consegna di tre mesi, potresti scoprire, tre mesi dopo, che l’ordine era insensato. Devi tornare indietro nel tempo di tre mesi al punto in cui hai generato questo ordine d’acquisto fasullo per capire qual è stato il problema. Non si tratta di versionare solo le ultime poche ore di lavoro; è letteralmente questione di avere una cronologia completa dell’ultimo anno di esecuzione.

Slide 12

Un’altra preoccupazione è l’aumento dei ransomware e degli attacchi informatici sulle supply chains. Questi attacchi sono estremamente dirompenti e possono essere molto costosi. Quando si implementano soluzioni guidate dal software, devi considerare se stai rendendo la tua azienda e la supply chain più vulnerabili agli attacchi informatici e ai rischi. Da questo punto di vista, Excel e Python non sono ideali. Questi componenti sono programmabili, il che significa che possono comportare numerose vulnerabilità di sicurezza.

Se hai un team di scienziati dei dati o Supply Chain Scientist che si occupano di problemi della supply chain, non possono permettersi il meticoloso e iterativo processo di revisione tra pari del codice, comune nell’industria del software. Se una tariffa cambia da un giorno all’altro o un magazzino viene allagato, hai bisogno di una risposta rapida. Non puoi spendere settimane a produrre specifiche del codice, revisioni e così via. Il problema è che stai conferendo capacità di programmazione a persone che, di default, hanno il potenziale di arrecare danno all’azienda in modo accidentale. La situazione può peggiorare se c’è un dipendente malintenzionato, ma anche mettendo da parte questo aspetto, hai comunque il problema che qualcuno esponga accidentalmente una parte interna dei sistemi IT. Ricorda, i sistemi di ottimizzazione della supply chain, per definizione, hanno accesso a una grande quantità di dati in tutta l’azienda. Questi dati non sono solo un bene, ma anche una passività.

Quello che desideri è un paradigma di programmazione che promuova una programmazione sicura. Vuoi un linguaggio di programmazione in cui intere classi di operazioni non possano essere eseguite. Ad esempio, perché dovresti avere un linguaggio di programmazione che possa effettuare chiamate al sistema per scopi di ottimizzazione della supply chain? Python può effettuare chiamate al sistema, e anche Excel. Ma perché vorresti un sistema programmabile con tali capacità in primo luogo? È come comprare una pistola per spararsi in un piede.

Vuoi qualcosa in cui intere classi o funzionalità siano assenti perché non ti servono per l’ottimizzazione della supply chain. Se queste funzionalità sono presenti, diventano una passività enorme. Se introduci capacità programmabili senza gli strumenti che garantiscono una programmazione sicura per design, aumenti il rischio di attacchi informatici e ransomware, peggiorando la situazione.

Naturalmente, è sempre possibile compensare raddoppiando la dimensione del team di cybersecurity, ma ciò è molto costoso e non ideale di fronte a situazioni urgenti della supply chain. Devi agire rapidamente e in sicurezza, senza il tempo per i soliti processi, revisioni e approvazioni. Vuoi anche una programmazione sicura che elimini problemi banali come eccezioni per riferimenti nulli, errori di memoria esaurita, loop off-by-one ed effetti collaterali.

Slide 13

In conclusione, gli strumenti contano. C’è un detto: “Don’t bring a sword to a gunfight.” Hai bisogno degli strumenti appropriati e dei paradigmi di programmazione adatti, non solo di quelli che hai imparato all’università. Hai bisogno di qualcosa di professionale e di livello produzione per soddisfare le esigenze della tua supply chain. Anche se potresti ottenere alcuni risultati con strumenti di qualità inferiore, non saranno straordinari. Un musicista fantastico può fare musica con un semplice cucchiaio, ma con uno strumento adeguato, può fare molto di meglio.

Slide 14

Ora, procediamo con le domande. Nota che c’è un ritardo di circa 20 secondi, quindi c’è una certa latenza nel flusso tra il video che stai vedendo e me che leggo le tue domande.

Domanda: Che diresti della programmazione dinamica in termini di ricerca operativa?

La programmazione dinamica, nonostante il nome, non è un paradigma di programmazione. È più una tecnica algoritmica. L’idea è che, se vuoi eseguire un compito algoritmico o risolvere un certo problema, ripeterai molto frequentemente la stessa sottooperazione. La programmazione dinamica è un caso specifico del compromesso spazio-tempo di cui ho parlato prima, in cui investi un po’ di più in memoria per risparmiare tempo sul lato computazionale. È stata una delle tecniche algoritmiche più antiche, risalente agli anni ‘60 e ‘70. È una tecnica valida, ma il nome è un po’ sfortunato perché non c’è nulla di veramente dinamico in essa, e non riguarda propriamente la programmazione. Per me, nonostante il nome, non si qualifica come paradigma di programmazione; è più una tecnica algoritmica specifica.

Domanda: Johannes, potresti gentilmente indicare alcuni libri di riferimento che ogni buon ingegnere della supply chain dovrebbe avere? Purtroppo, sono nuovo nel settore, e il mio attuale focus è sulla data science e sull’ingegneria dei sistemi.

Ho un’opinione molto mista riguardo alla letteratura esistente. Nella mia prima lezione, ho presentato due libri che considero il culmine degli studi accademici riguardanti la supply chain. Se vuoi leggere due libri, puoi leggere quei libri. Tuttavia, ho un problema costante con i libri che ho letto finora. Fondamentalmente, ci sono autori che presentano raccolte di ricette numeriche da giocattolo per supply chain idealizzate, e credo che questi libri non affrontino la supply chain dall’angolazione giusta, mancando completamente il concetto che si tratta di un problema intricato. Esiste un vasto corpo di letteratura molto tecnica, con equazioni, algoritmi, teoremi e dimostrazioni, ma credo che perda completamente di vista il punto centrale.

Poi, esiste un altro stile di libri sul management della supply chain, che è più in stile consulenziale. È facile riconoscere questi libri perché usano analogie sportive ogni due pagine. Questi libri contengono ogni sorta di diagrammi semplicistici, come varianti 2x2 degli SWOT (Strengths, Weaknesses, Opportunities, Threats), che considero modalità di ragionamento di bassa qualità. Il problema con questi libri è che tendono a comprendere meglio che la supply chain è un’impresa intricatissima. Capiscono molto meglio che si tratta di un gioco giocato da persone, in cui possono accadere ogni sorta di cose bizzarre, e che esistono modi intelligenti per affrontarlo. Devo riconoscere questo loro merito. Il problema di quei libri, tipicamente scritti da consulenti o professori di scuole di management, è che non sono molto applicabili. Il messaggio si riduce a “sii un leader migliore”, “sii più intelligente”, “abbi più energia”, e per me questo non è applicabile. Non ti fornisce elementi che puoi trasformare in qualcosa di altamente prezioso, come può fare il software.

Quindi, torno alla prima lezione: leggi i due libri se vuoi, ma non sono sicuro che ne valga il tempo. È utile sapere cosa hanno scritto gli altri. Dal lato consulenziale della letteratura, il mio preferito è probabilmente il lavoro di Katana, che non ho elencato nella prima lezione. Non tutto è negativo; alcune persone hanno più talento, anche se risultano un po’ più da consulente. Puoi dare un’occhiata al lavoro di Katana; ha un libro sulle dynamic supply chains. Elencherò il libro tra i riferimenti.

Domanda: Come si utilizza la parallelizzazione quando si tratta di cannibalizzazione o decisioni di assortimento, dove il problema non è facilmente parallelizzabile?

Perché non è facilmente parallelizzabile? La discesa del gradiente stocastico è piuttosto banale da parallelizzare. Hai dei passaggi stocastici del gradiente che possono essere eseguiti in ordini casuali, e puoi averne più allo stesso tempo. Quindi, credo che qualsiasi cosa guidata dalla discesa del gradiente stocastico sia piuttosto banale da parallelizzare.

Quando si tratta di cannibalizzazione, ciò che risulta più difficile è gestire un altro tipo di parallelizzazione, ovvero l’ordine di intervento. Se introduco questo prodotto per primo e poi faccio una previsione, ma successivamente ne introduco un altro, questo modifica il contesto. La risposta è che devi avere un modo per affrontare l’intero scenario in modo frontale. Non dici: “Prima introduco questo prodotto e faccio la previsione; poi introduco un altro prodotto e rifaccio la previsione, modificando la prima.” Lo affronti tutto in una volta, simultaneamente. Hai bisogno di più paradigmi di programmazione. I paradigmi che ho introdotto oggi possono essere di grande aiuto in questo senso.

Per quanto riguarda le decisioni di assortimento, questo genere di problemi non presenta grandi difficoltà in termini di parallelizzazione. Lo stesso vale se hai una rete di vendita al dettaglio mondiale e vuoi ottimizzare l’assortimento per tutti i tuoi negozi. Puoi eseguire calcoli in parallelo per tutti i negozi. Non vuoi farlo in sequenza, ottimizzando l’assortimento per un negozio e poi passando al successivo. Quello è il modo sbagliato di procedere; invece, puoi ottimizzare la rete in parallelo, propagare tutte le informazioni e poi ripetere il processo. Esistono diverse tecniche, e gli strumenti possono aiutarti notevolmente a farlo in maniera molto più semplice.

Domanda: State utilizzando un approccio basato su database a grafo?

No, non nel senso tecnico e canonico. Esistono molti database a grafo sul mercato che sono di grande interesse. Quello che utilizziamo internamente in Lokad è un’integrazione verticale completa tramite uno stack di compilatori unificato e monolitico, che elimina completamente tutti gli elementi tradizionali che si troverebbero in uno stack classico. È in questo modo che otteniamo prestazioni molto elevate, in termini di capacità computazionale, quasi a livello hardware. Non perché siamo programmatori fantastici, ma semplicemente perché abbiamo eliminato praticamente tutti gli strati che tradizionalmente esistono. Lokad non utilizza letteralmente alcun database. Abbiamo un compilatore che si occupa di tutto, fino all’organizzazione delle strutture dati per la persistenza. È un po’ strano, ma è molto più efficiente farlo in questo modo, e consente di sfruttare al meglio il fatto che compili uno script per una flotta di macchine nel cloud. La tua piattaforma target, in termini di hardware, non è una singola macchina; è una flotta di macchine.

Domanda: Qual è la tua opinione su Power BI, che esegue anche codici Python e algoritmi correlati come gradient descent, greedy, ecc.?

Il problema che ho con tutto ciò che riguarda la business intelligence, Power BI essendone un esempio, è che possiede un paradigma che ritengo inadeguato per la supply chain. Vedi tutti i problemi come un ipercubo, in cui hai dimensioni che vengono solamente sezionate e analizzate superficiale. Al centro c’è un problema di espressività, che è molto limitante. Quando finisci per usare Power BI con Python integrato, hai bisogno di Python perché l’espressività legata all’ipercubo è davvero scarsa. Per ritrovare l’espressività, aggiungi Python in mezzo. Tuttavia, ricorda ciò che ho detto nella domanda precedente riguardo a questi strati: la maledizione del software enterprise moderno è che ci sono troppe stratificazioni. Ogni singolo strato che aggiungi introdurrà inefficienze e bug. Se usi Power BI insieme a Python, finirai per avere troppi livelli. Quindi, hai Power BI che si pone sopra altri sistemi, il che significa che hai già molteplici sistemi prima di Power BI. Poi hai Power BI in cima, e sopra Power BI c’è Python. Ma Python agisce in autonomia? No, è probabile che utilizzi librerie Python, come Pandas o NumPy. Di conseguenza, gli strati in Python si accumuleranno, e finirai per avere decine di livelli. Possono nascere bug in uno qualsiasi di questi strati, per cui la situazione diventerà davvero un incubo.

Non sono un sostenitore di quelle soluzioni in cui finisci per avere un numero enorme di stack. C’è uno scherzo secondo cui, in C++, puoi sempre risolvere qualsiasi problema aggiungendo un ulteriore livello di indirezione, incluso il problema di avere troppi livelli di indirezione. Ovviamente, questa affermazione è in parte insensata, ma sono profondamente in disaccordo con l’approccio in cui le persone hanno un prodotto con un design core inadeguato e, invece di affrontare frontalmente il problema, finiscono per aggiungere elementi sopra mentre le fondamenta sono fragili. Questo non è il modo giusto di procedere, e finirai per avere una produttività scarsa, continue battaglie con bug irrisolvibili e, in termini di manutenibilità, sarà una vera ricetta per l’incubo.

Domanda: Come si possono integrare i risultati di un’analisi di collaborative filtering nell’algoritmo di previsione della domanda per ogni prodotto, come ad esempio gli zaini?

Mi dispiace, ma affronterò questo argomento nella prossima lezione. La risposta breve è che non vuoi incorporarlo in un algoritmo di previsione esistente. Vuoi avere qualcosa che sia molto più nativamente integrato. Non lo fai e poi torni ai vecchi modi di fare le previsioni; invece, abbandoni il vecchio metodo e adotti qualcosa di radicalmente diverso che ne sfrutti le potenzialità. Ne parlerò in una lezione successiva. Sarebbe troppo per oggi.

Penso che questo sia tutto per questa lezione. Grazie mille a tutti per aver partecipato. La prossima lezione sarà mercoledì 6 gennaio, alla stessa ora e nello stesso giorno della settimana. Mi prenderò qualche giorno di vacanza per Natale, quindi auguro a tutti un felice Natale e un felice Anno Nuovo. Continueremo la nostra serie di lezioni il prossimo anno. Grazie mille.