The optimal solution for a model is not necessarily the optimal solution for the real problem.
["Supplement B"]
This is a set of demo problems to try PuLP, python librabry for linear programming. There are three isolated tasks and a combination of them into bigger, more realistic production problem.
- Task 1 - Production schedule for one perishable product
- Task 2 - Sequential production
- Task 3 - Select orders when demand over capacity (mixed integer problem)
- Task 4 - Combine tasks 1, 2 and 3
The problems are kept simple and toy size (7 days of planning, 1-2 goods) for traceability and ease of review and testing.
Why this excercise should be useful?
- Build and test parts first before solving a bigger problem
- Differentiate model vs real world, detect what we capture in the model and what not with respect to real production,
- See if enforcing model rules can be feasible in practice
- What judgement and intuition may suggest vs the model
- What are data requirements for model to work well
- What should change on the business side (eg pricing, contract structure, sourcing procedures)
- What "lean" materially is
There are also project notes and several references below.
Setting:
- 1 product
- production planning for 7 days
- production quantaties are
x[t], t = 0...6 - max production capacity C,
0 <= x[t] <= C, letC = 5 - product is perishable, it can be stored for s days, let
s = 3 - we are given a purchases schedule on each day, let
purchases = [0, 0, 2, 8, 1, 0, 1]
Introduce target funсtion and find production volumes x[t]. Explore situation where result is not unique.
Target function:
- without target function we just find some feasible solution within the constraints
- we introduce min phycial inventories as target function to make solution unique
We had to make more assumptions:
- closed sum - everything produced must be consumed, zero outgoing inventory
- we set no limit on storage capacity - infinite warehouse
- we assume full end of day clearance, all purchases made at end of day - everything produced at day t can be sold at day t
| Is contrained? | |
|---|---|
| Production capacity | Yes |
| Max storage duration | Yes |
| Storage capacity | No |
| Outgoing inventory | Yes, set to zero |
Other comments:
- we looked at several ways to formulate constraints for limited shelf-life / limit on storage duration ("условие непротухания")
- minumum inventory is not necessarily the freshest shipment
- may need to check if FIFO warehouse works without goods expiry, as a safeguard for problem solution
Solution code here.
| Day | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| Purchases (given) | 2 | 8 | 1 | 1 | |||
| Production (found) | 5 | 5 | 1 | 1 | |||
| Inventory | 3 |
- 2 products, daily production volumes
xa[t]andxb[t] - good A is precursor to good B, to produce 1 ton of B one needs 2 tons of A
- there are capacity constraints for A and B:
0 <= xa[t] <= 150 <= xb[t] <= 5
- there are sales orders for both A and B (
sales_aandsales_b) - goods A and B are storable, there is no shelf life constraint
Introduce target function and find optimal production of product A and B (xa, xb)
Solution code here.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|---|
| Product B | |||||||
| sales_b (given) | 1 | 0 | 0 | 7 | 4 | 0 | 1 |
| production_b | 1 | 0 | 2 | 5 | 4 | 0 | 1 |
| inventory_b | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
| Product A | |||||||
| processing_a | 2 | 0 | 4 | 10 | 8 | 0 | 2 |
| sales_a (given) | 0 | 0 | 0 | 15 | 4 | 0 | 1 |
| requirement_a | 2 | 0 | 4 | 25 | 12 | 0 | 3 |
| production_a | 2 | 0 | 14 | 15 | 12 | 0 | 3 |
| inventory_a | 0 | 0 | 10 | 0 | 0 | 0 | 0 |
Extra notation: processing_a + sales_a = requirement_a
Things learned:
- we may omit closed sum constraint if min inventory
- we need scale the inventory in sequential production min target function
- we can keep only decision variables as
lpVariable - we can use dicts or numpy arrays
Pick most profitable orders from a list of orders when demand (sum of orders) is over production capacity.
Production:
- 2 products
- constant cost of production for each product, expressed as USD/t
- capacity constraints, t/day
Orders:
- total of
morders - each order is (product, price, day_of_delivery)
- prices for same products may vary by order
- orders are indivisible
- choice on order is accept/reject
Simplifications:
- no storage conditions (to be relaxed)
- no inventory minimisation (to be relaxed)
Solution code here.
Orders:
(order_1_quantity, order_1_price, order_1_delievery_day)- ...
(order_m_quantity, order_1_price, order_1_delievery_day)
We will need intergers accept_1, ..., accept_m, 0 <= accept_i <= 1 to mark if order is accepted.
purchase_t = sum of accept_<j> * order_quantity_<j> for all j where order_j_day == t
Similar formulation for profit = accept_<j> * order_<j>_quantity_ * (order_<j>_price - product_cost_<j>),
where the only variable is accept_<j> and the rest are values, known at time of construction of
target function.
Also need a good test example, showing cases when something could have gone wrong.
What can go wrong when combining three tasks:
- more constraints overlap
- will need more days of planning (>7)
- may need to relax more constraints (eg zero incoming and outgoing inventory)
- must write exhaustive list of assumptions
- should expiry dates affect storage at the warehouse or is is global product life?
Remaining questions about the PuLP solver:
- The solution may be not unique, but how do we know it from solver? How do we extract other solutions from solver?
- How to know which constraint was binding?
- Are dual prices meaningful for this type of problem?
- Is any sensitivity analysis possible?
- Can we do multiple criteria optimisation (eg better decide on weights in target func)?
- How to list second-best, third-best solution?
- What would 'soft constraints' enable us to do?
- Maybe there is a built-in nice table view of model variables?
- May need extra way to shift production right - prefer later production for any specific order. This happens because our product is perishable. Perhaps minimal inventory is not a guarantee this is the latest-in-time production, but I may be wrong.
- We may need a check to model FIFO stack as in issue #1
- We may need to model lead times for production - production may take more than 1 day, this will affect solutions for task 2.
Software:
Papers (review, etc):
- Mixed Integer Linear Programming in Process Scheduling: Modeling, Algorithms, and Applications
- Multiproduct, multistage machine requirements planning models
Other:
