di Joannès Vermorel, gennaio 2016I quantitativi minimi di ordine (MOQ) rappresentano un vincolo piuttosto frequente in logistica, che consiste nell'imporre all'acquirente di ordinare una quantità minima, di solito espressa in unità o in valuta, per poter effettuare un ordine. Capita spesso, inoltre, che più vincoli MOQ debbano essere soddisfatti contemporaneamente. Per risolvere il problema, è necessario mettere a punto un ordine di acquisto (quasi) ottimale che soddisfi tutti i vincoli MOQ e che allo stesso tempo massimizzi il ritorno economico associato alle unità acquistate.
Il problema MOQ viene formalizzato come un problema di ottimizzazione non lineare
complesso, perché possiamo dimostrare che calcolare una soluzione
ottimale non rientra nelle nostre capacità computazionali. Sebbene non possiamo arrivare a una soluzione ottimale, possiamo però trovare una soluzione quasi ottimale, con l'aiuto di algoritmi avanzati per la risoluzione di problemi non lineari. In particolare, faremo qui riferimento a
moqsolv
, un risolutore numerico avanzato sviluppato da Lokad proprio per far fronte al problema MOQ.
I vincoli MOQ più frequenti
Un vincolo MOQ può presentarsi in forme diverse. Tra quelle più comuni che possiamo incontrare in una catena logistica, ricordiamo:
- un quantitativo minimo espresso in unità per SKU, di solito per gli articoli troppo economici per poter essere venduti singolarmente;
- un quantitativo minimo espresso in dollari per l'intero ordine di acquisto, di solito quando il fornitore non applica spese di consegna;
- un quantitativo minimo espresso in unità per categoria di articoli, di solito per i prodotti su ordinazione che prevedono una partita di produzione minima.
Gestire un vincolo alla volta è piuttosto semplice nella pratica. Quando però i vincoli da tenere in conto sono più di uno alla volta, mettere a punto un ordine di acquisto che li soddisfi tutti diventa molto più complicato.
MOQ: concetti da tenere a mente
Prima di passare all'ottimizzazione numerica, rivediamo i concetti più importanti da tenere a mente per risolvere il problema MOQ:
- gli articoli, che rappresentano quello che possiamo acquistare. La quantità di un articolo è spesso espressa da un numero intero, ma sono possibili eccezioni;
- le quantità ordinate per ogni articolo (eventualmente zero), una potenziale soluzione del problema MOQ;
- il rendimento associato a ogni unità extra per ogni articolo: in sostanza, quello che si ottiene con la funzione stockrwd (rendimento delle scorte), anche se non è necessario usare una funzione;
- i costi associati alle unità da acquistare. Lo scopo è quello di massimizzare il rendimento di un budget di spesa espresso in costi. I costi sono di solito fissi per unità, ma è bene considerare anche variazioni di prezzo;
- gli obiettivi, che servono a specificare un criterio di chiusura dell'ordine eventualmente diverso dai costi. Questo è forse il concetto più complesso, che vedremo perciò nel dettaglio.
Il criterio classico che determina la chiusura dell'ordine quando si stila una
lista di priorità degli acquisti è il
budget massimo: le unità sono acquistate in ordine di ROI decrescente fino a che il budget di spesa non viene esaurito. Basarsi unicamente sul budget, però, non ci dà alcuna indicazione sulla performance generale dell'inventario. Quindi, fermo restando che il nostro scopo rimane quello di ottimizzare il ROI indipendentemente dal criterio usato, è molto pratico considerare criteri alternativi, come un obiettivo, ad esempio il
fill rate.
Un
obiettivo è un meccanismo generico che serve a definire un criterio alternativo di chiusura dell'ordine, sulla base di una
strategia di ordine per priorità. In parole più semplici, il nostro scopo è quello di creare un ordine di acquisto che offra il rendimento più elevato possibile per l'investimento minore possibile, pur raggiungendo l'
obiettivo prefissato. Qui di seguito daremo una definizione più precisa di questo processo di ottimizzazione.
Esempio: Il responsabile della logistica di un'azienda fissa l'obiettivo di raggiungere un fill rate del 90%. Risolvere il problema MOQ significa calcolare un ordine che abbia il minor costo possibile, ma che al contempo massimizzi il rendimento di un fill rate del 90%. In questo caso, l'ordine NON sarà l'ordine minore possibile (in termini di costi) per raggiungere un fill rate del 90%: se così fosse, l'ordine avrebbe come unica priorità quella di ottimizzare il fill rate. Invece, il nostro ordine è quello minore possibile che, avendo come priorità il rendimento delle scorte, è anche abbastanza grande da fornire un fill rate del 90%. Usare come unica priorità il fill rate sarebbe un errore, perché, a differenza del rendimento delle scorte, il fill rate non tiene conto dei costi associati all'eventuale stock morto generato.
Definizione formale del problema MOQ
In questa sezione vedremo perché il problema MOQ è un problema formale di ottimizzazione non lineare. Si tratta di un problema arduo, per la precisione
NP-arduo: il problema MOQ estende infatti il
problema bin packing, che è già di per sé un problema NP-arduo. Il problema MOQ è quindi almeno altrettanto difficile del problema bin packing, ma, nonostante sia NP-arduo, esistono delle ottime soluzioni che possono essere applicate anche nella pratica.
Sia $I$ l'insieme degli articoli da considerare per l'ordine.
Sia $q_i$ con $i \in I$ la quantità da ordinare per l'articolo $i$.
Definiamo quindi una serie di funzioni.
- Sia $r_i(q)$ il rendimento associato al tenere a magazzino $q$ unità dell'articolo $i$.
- Sia $c_i(q)$ il costo associato all'acquisto di $q$ unità dell'articolo $i$.
- Sia $t_i(q)$ l' obiettivo associato al tenere a magazzino $q$ unità dell'articolo $i$.
La funzione di rendimento può restituire un valore positivo o negativo, mentre le funzioni di costo e di obiettivo sono solo positive:
$$\forall i, \forall q, c_i(q) > 0 \text{ e } t_i(q) >0$$
Sia $M$ la serie di vincoli MOQ. Per ogni $m \in M$, abbiamo $I_m$, la lista degli articoli che fanno riferimento al vincolo $m$, e $Q_m$, il quantitativo minimo da raggiungere per soddisfare il vincolo. Sia $m_i(q)$ la funzione che definisce il contributo dell'articolo $i$ al vincolo MOQ $m$ quando vengono acquistate $q$ unità. Il vincolo $m$ è soddisfatto se:
$$\forall i \in I_m, q_i = 0 \text{ o } \sum_{i \in I_m}m_i(q_i) \geq Q_m$$
Con questa funzione, quindi, tutti i vincoli MOQ possono essere soddisfatti in due modi: raggiungendo la soglia MOQ, oppure portando a zero la quantità di tutti gli articoli.
Poi, sia $C$ il costo massimo che può essere sostenuto per l'ordine di acquisto. Definiamo il miglior ordine di acquisto $\textbf{q}_C=(q_i)_i$ come:
$$\textbf{q}_C = \underset{q}{\operatorname{argmax}} \left\{ \sum_i r_i(q_i) \text{ con $m$ soddisfatto } \forall m\in M \right\}$$
L'ordine di acquisto è il "migliore" nel senso che massimizza il rendimento di un certo budget. La soluzione $\textbf{q}_C$ non è l'unica possibile (il problema MOQ è troppo arduo per una soluzione esatta, comunque), ma, per maggiore semplicità, procederemo come se fosse l'unica.
Infine, sia $T$ un obiettivo minimo. Definiamo $\textbf{q}^T$ con
$$C^T = \underset{C}{\operatorname{min}} \left\{ \left(\sum_{q_i \in \textbf{q}_C} t_i(q_i) \right) \geq T \right\}$$ e
$$\mathbf{q}^T = \textbf{q}_{C^T}$$
La soluzione $\mathbf{q}^T$ è costruita a partire da $\textbf{q}_C$, che rappresenta la soluzione ottimale minima (dal punto di vista del budget di spesa) che massimizzi il ritorno economico e allo stesso tempo permetta di raggiungere l'obiettivo.