Download
/**
* Supply chain coordination problem
* OPL model for the root agent.
* The root receives demand for products from customers
* and agrees component delivery schedules from supplier agents.
*/
/**
* MODEL INPUT PARAMETERS
*/
// Time horizon
int numPeriods = ...;
range horizon 1..numPeriods;
// Number of product configurations
int numProducts = ...;
range products 1..numProducts;
// Number of components
int numComponents = ...;
range components 1..numComponents;
// Maximum number of orders to consider for each component
int numOrders[components] = ...;
// Bill Of Materials
int bom[products,components] = ...;
// The batch size of a component in a particularly delivery
int batchSize[components] = ...;
// Delivery cost for an order of components
int deliveryCost[components] = ...;
// The lead time/delivery time for a particular product
// I.e. the number of periods between an order being shipped
// and the order arriving at the customer
int leadtime[products] = ...;
// Number of processing cycles for each configuration
int cycles[products]= ...;
// Number of cycles required to setup a configuration
int setupCycles[products] = ...;
// Factory capacity
int capacity[horizon] = ...;
// Demand for products
int demand[horizon,products] = ...;
// Cost for not meeting an order for product i
int penaltyCost[products] = ...;
// Starting product inventory
int openingProductInventory[products] = ...;
// Starting component inventory
int openingComponentInventory[components] = ...;
// Holding costs
int productHoldingCost[products] = ...;
int componentHoldingCost[components] = ...;
// Setup costs
int setupCosts[products] = ...;
// Constants
int maxManufacture = max(t in horizon) capacity[t];
int maxDelivery = max(t in horizon, p in products) demand[t,p];
int maxOrders = max(c in components) maxNumOrders[c];
/**
* PUBLIC VARIABLES
* (variables constrained with other agents)
*/
// The number of orders for a each component to be delivered in each period.
var int componentDeliverySchedule[components,horizon] in 0..maxOrders;
/**
* PRIVATE VARIABLES
* (variables not constrained with other agents)
*/
// 0/1 variable indicating whether or not an order is made for a component in a particular period
var int isorder[horizon,components] in 0..1;
// 0/1 variable indicating whether or not a product will be built in a particular period
var int isbuilt[horizon,products] in 0..1;
// The number of a product built in a particular period
var int manufacture[horizon,products] in 0..maxManufacture;
/**
* AUXILIARY VARIABLES
* (additional variables used to simplify the model specification)
*/
// Expected inventory arriving for each component in the time horizon
var float+ componentArrivals[horizon,components];
// Remaining product inventory after each period
var float+ productInventory[0..numPeriods,products];
// Remaining component inventory after each period
var float+ componentInventory[0..numPeriods,components];
// The quantity of product delivered in each period
var int deliveryQuantity[horizon, products] in 0..maxDelivery;
// Components needed on a particular day to produce all products being manufactured
var float+ componentsUsed[horizon, components];
minimize
// Total cost
sum (t in horizon, p in products) (
(productHoldingCost[p]*productInventory[t,p]) +
(isbuilt[t,p]*setupCosts[p]) +
((demand[t,p]-deliveryQuantity[t,p])*penaltyCost[p])
) +
sum (t in horizon, c in components) (
(componentHoldingCost[c]*componentInventory[t,c]) +
(isorder[t,c] * deliveryCost[c])
)
subject to
{
// Opening product inventory
forall(p in products) productInventory[0,p]=openingProductInventory[p];
// Opening component inventory
forall(c in components) componentInventory[0,c]=openingComponentInventory[c];
// Calculate the component arrivals
forall(t in horizon, c in components) componentArrivals[t,c] = batchSize[c] * componentDeliverySchedule[c,t];
// The sum of the orders for any component should not be greater
// than the maximum number of orders required
forall(c in components) sum(t in horizon) componentDeliverySchedule[c,t] <= numOrders[c];
// Set the isorder variable correctly
forall(t in horizon, c in components) maxNumComponentOrders[c] * isorder[t,c] >= componentDeliverySchedule[c,t];
// Set the isbuilt variable correctly
// - should be 1 if any of that product is built on that day
forall(t in horizon, p in products) maxManufacture * isbuilt[t,p] >= manufacture[t,p];
// We can never deliver more than there is demand for
forall(p in products) forall (t in 1..numPeriods-leadtime[p]) deliveryQuantity[t,p] <= demand[t+leadtime[p],p];
forall(p in products) forall (t in [numPeriods-leadtime[p]+1..numPeriods]) deliveryQuantity[t,p] <= 0;
// Capacity constraint for manufacturing decision
// The factory's capacity for each day cannot be exceeded
forall(t in horizon) sum(p in products) (manufacture[t,p]*cycles[p] + isbuilt[t,p]*setupCycles[p]) <= capacity[t];
// The number of components needed is calculated by multiplying manufacturing decision by BOM
forall(t in horizon, c in components) componentsUsed[t,c] = sum(p in products) manufacture[t,p]*bom[p,c];
// Calculate the expected excess product inventory of each period
forall(t in horizon, p in products) productInventory[t,p] = productInventory[t-1,p] + manufacture[t,p] - deliveryQuantity[t,p];
// Calculate the expected excess component inventory of each period
forall(t in horizon, c in components) componentInventory[t,c] = componentInventory[t-1,c] + componentArrivals[t,c] - componentsUsed[t,c];
};