16 October 2021

Mycs - Logistics Optimisation - Declarative Constraint Programming

Using Constraint Programming / MiniZinc for Manufacturing Optimisation

Used Declarative Constraint Programming (with MiniZinc) to optimise the assignment of Purchase Orders to Manufacturers, increasing Supply Chain cost-efficiency while also introducing checks and safeguards. Built a RESTful API wrapper in Go to allow the constraint solver to be accessed over the network.

% Input Enums
enum Orders;
enum Suppliers;
enum ProductLines;

% Input Array: ProductLine Sets for each Order
array[Orders] of set of ProductLines: orderProductLines;

% Input Array: ProductLine Sets for each Supplier
array[Suppliers] of set of ProductLines: supplierProductLines;

% Input Array: Prices for Order-Supplier Combinations
array[Orders, Suppliers] of float: orderSupplierPrices;

% Variable Array (To hold results)
array[Orders] of var Suppliers: orderSupplier;

% Suppliers of Orders must have all ProductLines that the Order does.
constraint forall (d in Orders, s in Suppliers) (
    (s != orderSupplier[d]) \/
    (supplierProductLines[s] superset orderProductLines[d])
);

% Variable to optimise (Total Cost)
var float: totalCost = sum(d in Orders) (
    let {var Suppliers: s = orderSupplier[d]}
    in orderSupplierPrices[d,s]
);

% Lower cost preferred
solve minimize totalCost;

% Output as CSV of Order ID and orderSupplier ID pairs
output [ show(d) ++ "," ++ show(orderSupplier[d]) ++ "\n" | d in Orders ];

A simple example of some MiniZinc code (not the model used at Mycs!)

Supply Chain Managers at Mycs were using guesswork to choose which factories should be assigned which orders to produce. The different factories had different and overlapping subcategories of product that they could produce, and most had constraints on products they could produce (e.g. some cannot produce for UK market, some cannot produce leather products). Factories also needed to be given a number of orders within a minimum-maximum range. Additionally, the costs at different factories vary widely, and the assignment of products was inefficient.

I worked with logistics managers to develop a logic model for optimal assignment of products to suppliers, using Constraint Programming in MiniZinc. To test this model, I used SQL, awk, bash, make, and the COIN-BC solver to extract, prepare, and run the solver on current and historic data. Based on feedback from operations, I adjusted the model parameters.

Once the model was consistently yielding correct results, I built an HTTP service wrapper for it. This first required writing a Go library to interface between MiniZinc and Go, and then writing the HTTP service itself, and connecting the service to NetSuite, so that the system could automatically retrieve all the details on the latest unassigned orders. The backend web service / REST API was then deployed as a new Service within an existing AWS ECS cluster, using Github Actions, AWS CloudFormation, and Docker + Linux.

To allow Supply Chain Managers to use the system, I created a user interface in React. This used AWS Cognito for authentication and permissions. The interface was simple but clear and effective. The users could adjust certain parameters using a form, and then could run the solver and see a summary of the results. If they wanted they could also inspect the exact results, download a CSV of the assignment, or re-run the solver with adjusted parameters.

With the new system, Mycs was able to reduce costs, keep manufacturing partners happy, and reduce the burden on the overstretched Supply Chain Managers.

Tags: Industrial