# The inventory dispatch problem

Home » Resources » Here By Joannès Vermorel, November 2016

Inventory dispatch refers to a supply chain issue which involves balancing the initial inventory quantities across multiple locations. The inventory split needs to respect the amount of stock initially available at each location, and to account for the transportation costs involved in the dispatch itself. The dispatch solver is a numerical solver that is essentially similar to the MOQ solver but intended for working with the dispatch problem.

## Dispatch problem overview

The notion of inventory dispatch refers to a quantitative supply chain problem where stocks of products need to be balanced between locations. Each pair of product+location is referred to as a SKU (Stock-Keeping Unit).

There are economic incentives in deciding to keep a certain amount of stock for each SKU; those incentives are modeled as economic rewards. Adding more stock to a location may generate a positive reward if the stock was in demand in that particular location, but the extra stock can also generate a negative reward if it only inflates the carrying costs without substantially improving the service.

Similarly, the transportation costs need to be considered too. These costs typically represent the investment that needs to be made to transport inventory from one location to another. These costs may have a linear component - whereby the transportation costs increase in a linear manner with the quantities of goods transported, but may also have a non-linear component - with flat costs being involved whenever a transportation operation is being considered.

Finally, because of transportation constraints, all pairs of locations may not be eligible for transportation. When inventory can be balanced between a pair of compatible SKUs, or in other words two SKUs stocking the same product, we refer to this pair as a transportation edge.

The overall goal is to maximize the economic rewards associated with new stock positions obtained by transporting the products to different locations, while minimizing the associated transportation costs.

## Formal definition of the dispatch problem

Let $i$ and $j$ be the locations, and let $k$ be the products. Let $T_{ijk}$ be the non-negative integral quantity transported from $i$ to $j$ for product $k$. Let $U_{ijk}$ be the per-unit transportation cost. Let $G$ be a partition of the triplets $(i,j,k)$ and $V_g$ with $g \in G$ be the threshold transportation cost associated with the subset $g$. Let $R_{ik}: \mathbb{Z}\to\mathbb{R}$ be the reward function associated with stock variations at location $i$ for product $k$. Let $Q_{ik}$ be the maximum stock quantity that can be transported away from location $i$ for product $k$. Let $H$ be the Heaviside step function.

We are seeking the transportation solution $T_{ijk}$ that maximizes: $$\sum_{i,k} R_{ik}\left(\sum_j (T_{ijk} - T_{jik}) \right) + \sum_{i,j,k} T_{ijk} U_{ijk} + \sum_{g \in G} V_g\ H\left(\sum_{(i,j,k) \in g} T_{ijk}\right)$$ while respecting the following constraints: $$\forall i, \forall j, \forall k, T_{ijk} \geq 0 \\ \forall i, \forall k, \sum_j T_{ijk} \leq Q_{ik}$$ Here, the reward $R$ typically represents the positive part of the equation, while the costs $U$ and $V$ represent the negative part.

In the general case, finding the optimal level of transportation is a complex numerical problem; but approximate solutions can nevertheless be found with a dedicated solver.

## Envision syntax for the dispatch solver

Lokad provides a component dedicated to the numerical resolution of the dispatch problem, named the dispatch solver. In this section, we present the Envision syntax associated with this solver. The solve.dispatch() function leverages the named arguments:
T.Q = solve.dispatch(
sku: S.Product, S.Location
reward: S.Reward
stockAvailable: S.Available
stockEligible: S.Eligible // optional
edge: T.Product, T.Source, T.Destination
unitCost: T.UnitCost // optional
groupId: T.Group // optional
groupCost: T.GroupCost) // optional

Table S is intended to be a representation of all the SKUs, that is, all the product+location pairings. Table T is intended to be the transport graph, representing all edges where transportation might take place. The quantities returned - T.Q - represent the actual optimized transported quantities.

The arguments are as follows:

• sku (text, text) : the product and the location of the SKU, implicitly associated with the edge argument which lists all the possible transfers.
• reward (distribution): the reward distribution associated with the final stock position for the item at the given location.
• stockAvailable (number): represents the starting point for computing the reward for every SKU, before any inventory transfer takes place.
• stockEligible (number): represents the maximum amount of stock that can be taken from the SKU. When omitted, the entire stockAvailable is considered as eligible. In practice, inventory that is in transit will be counted as part of the stockAvailable, however this inventory cannot be counted as eligible for immediate (re)transfer.
• edge (text, text, text): the list of all the acceptable transfer edges. If an edge is not present in this table, then no quantities can be transported along this edge.
• unitCost (number): a linear transportation cost per unit when transporting quantities along the edge. When this cost is omitted, it is assumed to be zero.
• groupId (text) and groupCost (number): a non-linear transportation cost that comes into effect if any edge that belongs to the group is non-zero. Otherwise, the transportation cost remains at zero. When this cost is omitted, it is assumed to be zero.

The dispatch solver puts to use the algebra of distributions available in Envision in order to represent the economic rewards. These distributions are typically generated beforehand by leveraging the stock reward function.

Based on the transportation results computed by the dispatch solver, it becomes straightforward to compute the resulting stock variations for each SKU with:
S.Added = sum(T.Q) by [T.Product, S.Destination] at [S.Product, S.Location]
S.Taken = sum(T.Q) by [T.Product, S.Source] at [S.Product, S.Location]