Modeling I: linear models, product mix, multiperiod planning and inventory

Week 2 · 2105623 Optimization of Chemical Processes

Soorathep Kheawhom

17 August 2026

Three hours, nine blocks

Today

  • 5 min Recap of Week 1, and one pitch card worth showing the room
  • 35 min Block 1: the structured specification, and the four reusable patterns
  • 15 min Activity 1 — from words to symbols
  • 10 min Break
  • 40 min Block 2: time-indexed formulation, inventory balance, backlog, capacity
  • 15 min Activity 2 — build it and predict it
  • 10 min Break
  • 45 min Block 3: multi-product and shared capacity, the value of look-ahead, where the spreadsheet stops
  • 5 min Wrap-up, and HW1 is released

Lecture 120 minutes, activities 30, breaks 20, administration 10. Tool of the week: OpenSolver, because periods laid across columns read naturally in a spreadsheet.

By three o’clock you should be able to

Learning objectives · CLO 1 and CLO 4

Write a specification

A unit on every symbol, bounds on every variable — and find the ambiguities in somebody else’s.

Name the four patterns

Index set, balance equation, capacity constraint, linking constraint, and apply each one.

Index over a horizon

Write an inventory balance linking consecutive periods, and state your start-versus-end convention.

Price a backlog

Separately from held stock, without a binary variable, and say why a horizon-end condition is mandatory.

Build it in OpenSolver

Map every spreadsheet range to its algebraic symbol, and reproduce a stated optimum.

Read a capacity dual

Period by period, and use it to justify where a debottlenecking budget goes.

Where Weeks 2 to 5 live

Recap of Week 1

1Verbalthe problem in prose

2Specificationwe are here

3Algebraand here

4CodeWeeks 7 and 8

5InterpretationWeeks 7 and 8

Week 1 established

The four parts of any problem, the standard form, the classification table, the tool stack, and one solved LP: x* = (6, 3) t/week at z* = 3,300.00 USD/week with two binding resources.

And the geometry

An LP with a finite optimum has an optimal vertex. That argument is not repeated today. Every model in this session is an LP and the same picture applies, unchanged.

The modeling block is stages 2 and 3, done four times on four kinds of structure. Weeks 2 to 5 add no new mathematics at all.

The specification, and the four patterns

Lecture block 1 · 35 minutes

One document, four patterns,
and one small model in which all four are visible at once.

Stage 2 is the real deliverable of engineering thinking

Why a document, and not algebra

  1. Index sets Each one named, with its membership stated.
  2. Parameters Symbol, meaning, unit, and the source of the number.
  3. Decision variables Symbol, unit, and bounds.
  4. One objective Stated in words, with its unit.
  5. Restrictions Numbered, in words, including the ones you assume away.

Why this and not algebra

Algebra hides assumptions. The symbol It looks precise, but it does not say whether inventory is measured at the start or the end of the period. The specification has to say so in words, where a reader can disagree with it.

A specification that requires guessing will be guessed at, and the guess will be plausible, silent and unlabeled.

The code is a translation of this document. If the specification is right, writing the algebra and then the model file is close to mechanical.

The specification template, blank

This is what Activity 1 asks you to fill in

Section What goes in it The question it forces you to answer
Sets and indices every dimension of the problem, named, with its membership What is repeated, and over what?
Parameters symbol, meaning, unit, source of the number Which numbers are fixed before the model is solved, and who owns them?
Decision variables symbol with full index, unit, bounds What is genuinely under your control?
Objective one sentence in words, with its unit What counts as better, in what currency, over what period?
Constraints numbered, in words What must hold, and is each one hard or soft?
Assumptions numbered alongside the constraints What did you decide to ignore, and would a reviewer accept it?

Assumptions are written as numbered restrictions, not as prose. “Everything produced is sold” is a modeling decision with a cost attached, and numbering it is what lets somebody challenge it.

Parameters carry a unit and a source

Specification, row 2

Symbol Meaning Unit Where the number comes from
dt demand in period t t/month sales forecast, revision date recorded
Ct production capacity t/month line rate times available hours
ct unit production cost USD/t standard cost plus the electricity contract
h inventory holding cost USD/t/month working capital plus storage
b backlog penalty USD/t/month expedited freight plus contractual damages
I0 opening inventory t the stock ledger at the planning date
ρp reactor hours per tonne of p h/t the process, measured and not assumed

A parameter is anything fixed before the problem is solved. If you can change it, it is a variable; if you cannot, it is a parameter. Confusing the two is the commonest stage-2 error.

h and b carry per month in their unit. That is what makes a backlog charged again in every period until it is cleared — and it is exactly the modeling decision that drives the answer at half past two.

Decision variables carry a unit and bounds

Specification, row 3

  1. A symbol with its full index xp,t, not x.
  2. A unit Tonnes per month is not tonnes.
  3. Bounds At minimum: is it non-negative? Is it bounded above by something physical?
Symbol Meaning Unit
xt ≥ 0 production in period t t
It ≥ 0 inventory carried out of t t
Bt ≥ 0 backlog carried out of t t

Bounds are free performance and free safety

An unbounded variable is the commonest cause of an unbounded model, and an unbounded integer variable will cripple a solver’s presolve in Week 11. Write the physical bound even when you believe the constraints already imply it. It costs one line and it documents the physics.

A variable is not a formula

It is a variable that the balance equation ties to production and demand. Do not write it as an expression. Keeping it a variable is what lets you bound it, price it, and read its dual.

Units on every symbol: the cheapest error detector there is

Thirty seconds, every time

The check, applied to the inventory balance

It−1 [t]   −   Bt−1 [t]   +   xt [t]   −   dt [t]   =   It [t]   −   Bt [t]

Every term is a tonnage. If any one of them had carried a rate, the equation would be wrong, and it would still solve.

And to the objective

ct [USD/t] · xt [t]   +   h [USD/t/month] · It [t] · 1 [month]   ⇒   [USD]

The “one period” in the holding term is implicit. Writing it out is what stops you putting a weekly rate into a monthly model.

The class of error units catch

Mixing a stock (tonnes) with a flow (tonnes per month), or mixing two time bases. Neither produces an error message. Both produce a plan that is confidently wrong by a factor of four or five.

Pattern 1 · the index set

The same relation repeated over a family

Template

iI     and then     xi  ⟶  xi,t

  • Name every dimension once Then index parameters, variables and constraints over it, and write the relation once. The solver expands it.
  • Growth becomes a data change Adding a product, a period or a site changes the data, not the model. The number of rows grows; the number of ideas does not.
  • Where it reappears Every week of this course. It is the reason the Pyomo Set component exists at all.
Dimension Index Set
product or grade p P
resource or operation r, s R, S
period t T, ordered
node or site i, j N
scenario ω Ω

Ordered sets matter

A time set must be ordered, because the model needs to know what t − 1 means. In Pyomo, pyo.Set(initialize=T, ordered=True), then m.T.prev(t). In a spreadsheet, “the column immediately to the left” is the same statement — and it is why periods run across columns.

Pattern 2 · the balance equation

What goes in equals what goes out plus what accumulates

Template

accumulation  =  inflow  −  outflow

It−1  +  xt  −  dt  =  It

  • It is the same law as a material balance Only the boundary moves. Draw it around a vessel and it is a mass balance; draw it around a period and it is an inventory balance.
  • It is an equality And it is the backbone of the model, not a refinement of it.
  • Where it reappears As the node balance in Week 3, as a component balance in Week 4, and as a unit balance in both.

The most expensive class of error

A missing balance is worse than a wrong one. The model still solves. It still reports a plan. It has simply stopped conserving material, and nothing on the screen says so.

Patterns 1 and 2 together

Written once, expanded over the ordered set T. One line of specification becomes six rows in the spreadsheet, and the six rows are what make it a plan rather than six unrelated decisions.

Pattern 3 · the capacity constraint

A shared resource limits a sum

Template

Σi ari xi   ≤   br    for every rR

  • One inequality per resource And one per resource per period as well, if the resource is renewed each period.
  • The sum is what makes it a constraint If only one activity used the resource, it would be a bound on a single variable and the solver would handle it for free.
  • Where it reappears Arc capacity in Week 3, pool capacity in Week 4, unit capacity in Week 5.

Renewable, or consumed once

xtCt for every t    versus    Σt xtC

Line hours that reset every month give one inequality per period. A fixed allocation of catalyst consumed once over the horizon gives one inequality summed over t.

They behave completely differently, and nothing in the English of a problem statement tells you which is meant. The specification has to say.

Pattern 4 · the linking constraint

A variable in one block constrains another

Template

any constraint whose index
spans more than one block

  • It destroys separability Which sounds like a defect and is in fact the whole point. If the blocks separated, you would not need a solver — you would need arithmetic.
  • That is where the value of optimizing lives Every dollar a planning model earns comes through a linking constraint.
  • Where it reappears Transshipment nodes in Week 3, pooling in Week 4, big-M links in Week 5.

Temporal linking · block 2

The inventory balance carries stock from t − 1 into t, so the periods cannot be planned one at a time.

Resource linking · block 3

One shared reactor is used by both products, so the products cannot be planned one at a time.

Remove both and the model falls apart into a stack of independent one-period problems that nobody needs a solver for.

The same four patterns in four unrelated domains

Why they are worth naming

1 Index set 2 Balance 3 Capacity 4 Linking
Refinery blend feedstocks c, properties q volume balance: blend = Σ components feedstock availability, over c quality specs, over q
Staff roster staff e, shifts t only if headcount carries across periods cover per shift; hours per person rest rules, over consecutive t
Battery dispatch hours t, |T| = 24 state-of-charge balance, over t power limit and energy capacity per t the state-of-charge balance itself
Warehouse network plants i, warehouses j, customers k node balance at each warehouse plant supply; warehouse throughput the warehouse node balance

The honest nuance. The roster’s balance row is arguable. If staff are simply assigned to shifts, the cover requirement is a capacity constraint with a ≥ sense and there is no balance at all. A balance appears only if a pool of people is carried across periods. Both readings are defensible — and the specification is where you say which one you chose.

The warm-up, stages 1 to 3 · the finishing shop

All four patterns, in a model small enough to hold in the head

A finishing shop attached to the electrolyte plant packages two grades for zinc-air cell assembly, a Standard grade and a HighPurity grade. Both pass through the same three operations in order: mixing, ion-exchange purification, and filling. The three operations have different weekly hour allocations because they are shared with other campaigns. HighPurity is worth more per tonne but spends four times as long in purification. Everything finished is sold.

Operation Standard, h/t HighPurity, h/t Available, h/week
Mixing 2 3 120
Ion-exchange purification 1 4 104
Filling 1 1 44
Contribution margin, USD/t 520 790

Stage 2, restrictions in words. R1. On each operation, the hours consumed cannot exceed the hours allocated. R2. Production cannot be negative. R3. There is no demand limit, because everything finished is sold — and R3 is an assumption, numbered so that it can be challenged.   Stage 3. max Σp cp xp subject to Σp asp xpbs for every s, with xp ≥ 0 and [h/t]·[t/week] = [h/week] on every row.

The warm-up, stages 4 and 5 · the answer and what it says

Busiest and binding are different words

Operation Used, h Avail., h Slack, h Dual, USD/h
Mixing 108 120 12 0
Purification 104 104 0 90
Filling 44 44 0 430

The answer

24 t of Standard and 20 t of HighPurity, for 28,280.00 USD of contribution margin in the week.

Verified two ways in the notebook: vertex enumeration in NumPy, and a finite-difference check on every dual.

The engineering reading

Buy an overtime shift on filling first, not on the operation that looks busiest.

Mixing consumes 108 hours, more than either other operation in absolute terms, and it is worth exactly zero at the margin.

And the limitation we spend the rest of the day removing

This plans one week in isolation. It has no memory. It cannot build stock now for a peak later, and it cannot say that a shortfall this week must be delivered next week.

From words to symbols

Activity 1 · 15 minutes · pairs, paper

You may not write a single equation
for the next eight minutes. Not one.

Write what the symbols mean, what units they carry, and what the constraints say in English.

Aurora Specialty Chemicals

Activity 1 · 15 minutes · pairs, paper

Aurora Specialty Chemicals makes two grades of electrolyte, Standard and HighPurity, on one shared reactor train. The reactor is available 640 hours per month. Standard needs 1.0 reactor hours per tonne and HighPurity needs 1.4. Marketing has issued a demand forecast for the next four months: for Standard, 180, 210, 260 and 190 tonnes; for HighPurity, 90, 120, 150 and 110 tonnes. Production cost differs by grade and rises in month 3, when electricity is dearest. Anything finished but not shipped in the month it is made is stored in a single warehouse that holds 120 tonnes, at 7 USD per tonne per month. Thirty tonnes of Standard are already in store. The plant wants the cheapest four-month plan that meets the forecast.

Write only the specification table

Sets and indices · parameters with symbol and units · decision variables with symbol, units and bounds · the objective in words with its units · the constraints in words.

Writing algebra is forbidden. So is writing any spreadsheet formula.

  1. 0 to 8 min · pairs Write the specification table.
  2. 8 to 13 min · swapped Find one ambiguity in the sheet of the pair beside you, and circle it.
  3. 13 to 15 min · plenary Two pairs read theirs out.

 

10

minute break

Then: what a time index does to a model, the inventory balance and its start-versus-end convention, backlog priced separately from held stock, and the whole six-period model assembled one family at a time

The time-indexed formulation

Lecture block 2 · 40 minutes

One index, added to every variable,
turns a decision into a plan.

A time index turns one decision into a plan

Pattern 4, drawn

t = 1t = 2t = 3t = 4t = 5t = 6 Iₜ, BₜIₜ, BₜIₜ, BₜIₜ, BₜIₜ, Bₜ xₜ produced dₜ shipped the amber arrows are the only place consecutive periods meet cover them and six independent problems are left

Without the amber arrows these are six independent problems. Each would be solved on its own, and nothing at all would be gained by solving them together. The optimization would be arithmetic.

The amber arrows are the linking constraint of pattern 4. Everything a multiperiod model can do about seasonality, a demand spike or a cost profile passes through them.

The inventory balance

Pattern 2, with the boundary drawn around a period

period t Iₜ₋₁ − Bₜ₋₁ Iₜ − Bₜ xₜ produced dₜ shipped same law, new boundary

Accumulation equals inflow minus outflow, around a period

It−1Bt−1 + xtdt  =  ItBt    for every tT

with I0 given and B0 = 0.

  • The net stock position Positive means stock on hand at the close of the period, negative means stock owed to a customer.
  • The same law, a new boundary Drawn around a period rather than around a vessel.
  • Patterns 1 and 2 together Written once, and expanded over the ordered set of periods.

Start or end of period? Say which, because the answer changes

This is ambiguity 1 from Activity 1

Convention A — used here

Measure at the end

It is the stock after period t has produced and shipped.

It−1 + xtdt = It

Holding is charged on what is left over at the close of the period, so material that arrives and ships inside the same period is never charged holding.

Convention B

Measure at the start

Ĩt is the stock before period t produces and ships, so Ĩt = It−1.

Ĩt + xtdt = Ĩt+1

Holding is charged on the opening stock, so the 20 t on hand at the planning date is charged in period 1 — and the closing stock of the last period is not charged at all.

Both are correct. They are not the same model: they differ by one period of holding charge at each end of the horizon, so they return different total costs and can return different plans. What is wrong is failing to say which one you used, because the next engineer to touch the sheet will assume the other.

Backlog, the horizon end, and two kinds of capacity

Three modeling decisions, one slide

Why split the net position into two variables

A single free variable st = ItBt would be simpler, but it could not be priced: holding costs h, shortage costs b, and bh. Splitting into It ≥ 0 and Bt ≥ 0 keeps the model linear while pricing the two directions differently.

Complementarity comes free

Because h > 0, b > 0 and this is a minimization, no optimal solution ever has It > 0 and Bt > 0 at once — carrying stock and owing stock at the same time costs money and changes nothing. No binary variable is needed. The cost structure enforces it.

The horizon-end condition

B|T| = 0

This is what makes the plan honest. Without it, the model pushes all the difficult demand past the end of the horizon and reports a cost that cannot be achieved.

Capacity: per period, or across the horizon

xtCt for every t    versus    Σt xtC

Line hours reset each month: one inequality per period. A fixed catalyst allocation consumed once: a single inequality. Today’s model uses the first.

The complete single-product model, family by family

Everything so far, on one slide

Minimize total cost over the horizon

min   Σt ( ct xt + h It + b Bt )    [USD]    over x, I, B ≥ 0

Constraint family Pattern
It−1Bt−1 + xtdt = ItBt for every t balance, P2 + P4
xtCt for every t capacity, P3
B|T| = 0 once horizon end
xt, It, Bt ≥ 0 for every t bounds
Size, for six periods
Decision variables 18
Constraints 13

Three variable families times six periods. Six balances, six capacities, one horizon-end condition.

Everything is linear and continuous, so this is an LP and the Week 1 vertex argument applies unchanged. The whole model is patterns 1 to 4 and nothing else.

The same model in the spreadsheet: periods across columns

The sheet you are about to complete

BCDEFGH 123456 period, row 5 demand dₜ · row 6capacity Cₜ · row 7unit cost cₜ · row 8 120150180210160130170 in every period424245484643 production xₜ · row 16inventory Iₜ · row 17backlog Bₜ · row 18 C16:H18 — 18 changing cells balance C28:C33 = E28:E33capacity C34:C39 ≤ E34:E39 C40: B₆ = 0 · the only scalar row C24: objective, Min, sum of C21:C23 t − 1 is the column to the left
Algebraic symbol Range Pyomo component
tT C5:H5 Set(..., ordered=True)
dt, Ct, ct C6:H8 Param(m.T, ...)
h, b, I0, B0 C9:H10, C11:C12 scalar Param
x, I, B ≥ 0 C16:H18 three Var(m.T, ...)
balance ∀ t C28:C33 Constraint(m.T, rule=...)
xtCt C34:C39 Constraint(m.T, ...)
objective C24 Objective(sense=minimize)

The transposition. In Week 1 the model ran down the rows. Here periods run across columns, so each constraint family becomes a block of rows. Only the layout changed.

Build it and predict it

Activity 2 · 15 minutes · pairs, one computer

The number is on the board.
Forty-two thousand and eighty.

If your sheet does not say that, your sheet is wrong — and finding out why is more useful than anything I could tell you in the next eight minutes.

Complete the sheet, then predict

Activity 2 · 15 minutes · pairs, one computer

Data already on the sheet

Six monthly periods. Demand 120, 150, 180, 210, 160, 130 t. Line capacity 170 t/month throughout. Production cost 42, 42, 45, 48, 46, 43 USD/t. Holding 6 USD/t/month, backlog 45 USD/t/month, opening stock 20 t, and B6 = 0.

OpenSolver setup

Objective $C$24, Min · changing cells $C$16:$H$18 · balance $C$28:$C$33 = $E$28:$E$33 · capacity $C$34:$C$39 ≤ $E$34:$E$39 · $C$40 = $E$40 · engine CBC · tick Sensitivity Analysis.

  1. 0 to 8 min Open W02_multiperiod_planning_STUDENT.xlsx. Complete the yellow cells: the balance row for each period, and the objective. Run Solver.
  2. 8 to 11 min · on paper, hands off the keyboard If the period-4 capacity is raised by one tonne, by how much does total cost fall? Write a number.
  3. 11 to 15 min Change it, re-solve, compare. Then explain why the same change in period 1 does nothing at all.

Target: total cost 42,080.00 USD.

 

10

minute break

Then: what the plan you just solved actually says, the measured value of planning ahead, a second product on the same reactor, where the spreadsheet stops being the right tool, and HW1

Multi-product, look-ahead, and the limits of the sheet

Lecture block 3 · 45 minutes

What the plan says, what planning ahead is worth,
and where this tool stops.

Reading the solution: where inventory is built, and why

Activity 2, revealed

Period 1 2 3 4 5 6
Demand dt, t 120 150 180 210 160 130
Capacity Ct, t 170 170 170 170 170 170
Unit cost ct, USD/t 42 42 45 48 46 43
Production xt, t 130 170 170 170 160 130
Inventory It, t 30 50 40 0 0 0
Backlog Bt, t 0 0 0 0 0 0

Total cost 42,080.00 USD = 41,360.00 production + 720.00 holding + 0 backlog. Opening stock 20 t. Capacity binds in periods 2, 3 and 4 only.

Why the plan pre-builds. Periods 3 and 4 together demand 390 t against a combined capacity of 340 t — a shortfall of 50 t that physically must be made earlier. Closing inventory at the end of period 2 is exactly 50 t: the shortfall, and nothing more. It is not price arbitrage. Producing in period 2 at 42 and holding two months costs 42 + 2(6) = 54 USD/t, worse than making it in period 4 at 48. The plant builds stock in spite of the price signal.

Reading the capacity duals: what to buy, and when

The practical output of the whole model

Period 1 2 3 4 5 6
Capacity slack, t 40 0 0 0 10 40
Dual, USD/t 0 6 9 12 0 0

Where the debottlenecking budget goes

Period 4 first, at 12 USD per tonne of extra capacity. Nowhere near periods 1, 5 or 6, where extra capacity is worth exactly zero.

A capital request must name the period, not just the resource.

Binding in a period is not binding across the horizon

Total capacity over six periods is 1,020 t against total demand of 950 t, with 20 t of opening stock. In aggregate the horizon is comfortable. It is only period by period that the plan is tight, and only in three periods of six.

An annual capacity number would have reported no problem at all.

Pyomo returns a negative dual for a ≤ constraint in a minimization, so the magnitude is the cost reduction from one extra tonne. The OpenSolver sensitivity report gives the same magnitudes, and every one is reproduced in the notebook by re-solving with one extra tonne.

The value of look-ahead, measured

The most persuasive number of the week

The myopic benchmark is a rule with no look-ahead: in each period, produce only what is needed now, up to capacity.

Period 1 2 3 4 5 6
Production, t 100 150 170 170 170 170
Backlog, t 0 0 10 50 40 0

This is not a straw man

A plant that runs a monthly production meeting, looks at this month’s order book, and fills it, is executing exactly this rule. Nobody in that meeting is being careless. The horizon simply is not on the table.

The comparison

Myopic cost
45,940.00 USD
Optimal cost
42,080.00 USD
Value of look-ahead
3,860.00 USD — 8.4 %

8.4 percent of cost, from no capital, no new equipment and no new people.

Both plans make the same total tonnage: 930 t. The myopic rule falls behind in period 3 and then pays 45 USD/t/month in periods 3, 4 and 5 on a backlog that peaks at 50 t.

Myopic versus look-ahead, period by period

Same tonnage, different timing

050100150200 capacity 170 t/month demand 123456 production, t · period 1 to 6 look-aheadmyopic

The teal bars sit above demand in periods 1 and 2 and below it in period 4. The rust bars sit on demand until period 3 and then sit on the capacity line for the rest of the horizon, never catching up until the last month. Same 930 tonnes. 3,860.00 USD apart.

A second product on the same reactor

Resource linking

What changes

Every variable and every balance gains a product index: xp,t, Ip,t, Bp,t. The balance and the line capacity are written once per product and are otherwise unchanged.

One genuinely new constraint appears, indexed over time only:

Σp ρp xp,t  ≤  Rt    for every t

That is pattern 3 and pattern 4 in the same row: a shared resource limiting a sum, whose index spans both product blocks.

Additive Binder
Line capacity, t/month 170 150
Holding, USD/t/month 6 8
Backlog, USD/t/month 45 60
Reactor ρp, h/t 1.0 1.4
Opening stock, t 20 10

Reactor hours available: 330 per month

Just-in-time would need 246.0, 304.0, 362.0, 406.0, 328.0, 270.0 h. Periods 3 and 4 are impossible without shifting work earlier, so the reactor constraint will bind.

What sharing the reactor costs

The coupling constraint is what makes this one problem

Measured

Uncoupled, no reactor limit
83,330.00 USD
Coupled, reactor ≤ 330 h
83,930.86 USD
Cost of the shared reactor
600.86 USD

The uncoupled plan is not a plan at all: it needs 366.0 reactor hours in period 4 and only 330 exist.

Without the shared rows the model is block diagonal

It separates exactly into one independent LP per product. The reactor links the blocks, destroys separability, and creates the real decision: in a period when reactor time is short, which product gets it.

600.86 USD over six months

That is what the plant pays for owning one reactor train instead of two, and it is the figure to weigh against annualized capacity. Sharing is cheap here, because inventory smooths the peaks.

The shadow price of reactor time is periodic, not constant: 0, 5.7143, 9.2857, 12.2857, 0, 0 USD/h. Only periods 2, 3 and 4 bind. Re-solving with 331 hours in period 4 gives 83,918.5714 USD — exactly 12.2857 below the base case, which is the definition of the dual, not a coincidence.

Where the spreadsheet stops working

The argument is about auditability, not arithmetic

Today: 6 periods, 1 product 52 periods, 3 products, shared reactor
Changing cells 18 468
Balance rows 6 156
Capacity rows 6 156
Reactor rows 0 52
Fits on a screen yes no

3 × 3 × 52 = 468 changing cells; 3 × 52 = 156 balance rows; 3 × 52 = 156 capacity rows; 52 reactor rows. These are the closing note on the workbook’s Readme sheet.

None of that is hard. It is simply not auditable

No diffing, no unit tests, no scenario loop. There is no way to prove that the formula in one column of 52 is the same as in the other 51 — and one mis-anchored $ produces a plan the sheet reports as feasible and the plant cannot execute.

Adding a fourth product means rebuilding the sheet. Adding a warehouse limit means inserting 52 rows in the middle and repairing every reference below. Re-solving under 20 demand scenarios means 20 copies of the workbook.

The plan from here

Week 3 stays in the spreadsheet, because a cost matrix is a spreadsheet. Week 4 is the crossover, because pooling multiplies a flow by a quality and a spreadsheet cannot handle it at all. In Pyomo, 6 periods and 52 periods are the same six lines of code.

The same model in Pyomo, side by side

Two implementations, one number

Spreadsheet · W02_multiperiod_planning

C5:H5 six period headers

C6:H8 demand, capacity, unit cost

C16:H18 changing cells, 18 of them

C28:C33 balance rows, one per period

C34:C39 capacity rows, one per period

C40   B6 = 0

C24   objective, minimize

Adding a period means inserting a column and repairing every formula that crosses it.

Pyomo · W02_modeling1_linear_multiperiod

m.T = pyo.Set(initialize=T, ordered=True)

m.d = pyo.Param(m.T, initialize=...)

m.x = pyo.Var(m.T, domain=NonNegativeReals)

m.I = pyo.Var(m.T, domain=NonNegativeReals)

m.B = pyo.Var(m.T, domain=NonNegativeReals)

m.balance = pyo.Constraint(m.T, rule=...)

m.capacity = pyo.Constraint(m.T, rule=...)

m.cost = pyo.Objective(..., sense=pyo.minimize)

Adding a period means adding one entry to T.

Both routes report 42,080.00 USD, and that agreement is the verification. If the spreadsheet and the notebook ever disagree, the spreadsheet is wrong.

HW1 is released today

Due Week 4

  1. Released today, Week 2. Due Week 4. On myCourseVille at the end of this session.
  2. Linear and network model construction. The linear half rests on today; the network half needs Week 3, so start with the linear half now.
  3. Every question that asks for a model asks for the structured specification first, exactly as in Activity 1, and marks it separately.
  4. One question asks for a multiperiod plan built in OpenSolver and reproduced in Pyomo, with the two answers compared.

The instruction that carries the most marks

Write the specification before any algebra.

A correct model with no specification loses marks. A specification that states its assumptions and its start-versus-end convention earns them even where the algebra slips.

Two habits to carry into it

A unit on every symbol, and a bound on every variable. Both are checkable by a reader in thirty seconds, and both catch the errors a solver never reports.

Numbers established today

Summary

Quantity Value
Warm-up optimum (24, 20) t/week, 28,280.00
Its duals, mix / pur. / fill 0 / 90 / 430 USD/h
Six-period optimal cost 42,080.00 = 41,360.00 + 720.00 + 0
Production plan, t 130, 170, 170, 170, 160, 130
Inventory plan, t 30, 50, 40, 0, 0, 0
Capacity duals, USD/t 0, 6, 9, 12, 0, 0
One extra tonne in period 4 42,068.00 USD
Myopic cost, and the gap 45,940.00 USD
Value of look-ahead 3,860.00 USD, 8.4 %
Two products, uncoupled / coupled 83,330.00 / 83,930.86 USD
Cost of sharing the reactor 600.86 USD
52 periods, 3 products 468 cells, 156 + 156 rows
  • The specification is the deliverable A unit on every symbol, bounds on every variable. The code is a translation of it.
  • Four patterns, and nothing else Index set, balance, capacity, linking. Recognizing the pattern is most of stage 3.
  • A multiperiod model is its linking constraint The balance is the only place consecutive periods meet, and a horizon-end condition is mandatory.
  • Say start or end Both conventions are valid, and they give different answers.
  • Split the net position Two non-negative variables price the two directions differently and stay linear.
  • Duals are period by period A capital request names the period, not just the resource.

Before we meet again

Five things, and reading

  1. Start HW1, released today, due Week 4. The linear half needs only today.
  2. Finish the Week 2 notebook end to end, including Exercises 1 to 3. It reproduces every number quoted today and cross-checks each dual by finite difference.
  3. Complete the workbook if Activity 2 was not finished, and confirm cell C24 reads 42,080.00.
  4. Read the closing note on the workbook’s Readme sheet.
  5. If Solver failed today, come to the Week 3 clinic.

Reading

Rao, Ch. 3, on the formulation of linear programs.

Williams, Ch. 3 and 4. Chapter 4 is the single best treatment of the inventory balance in print, with a long discussion of exactly the modeling choices Activity 1 exposed as ambiguities.

Edgar, Himmelblau and Lasdon, Ch. 7, for the process framing.

Week 3 · 24 August — Networks: transportation, transshipment and process superstructures.

 

The balance equation you wrote
around a period today

is written around a node next week,
and almost nothing else changes.

Same four patterns. New index set. See you Monday.

 

Before you go · 45 seconds

How was today?

Five questions. Anonymous — no name, no email, no login.

The fourth question is the one I actually use.

The two most common answers open next week’s session.

oxidized-challenge-ed9.notion.site

QR code linking to the weekly feedback form

Scan now — I will wait