Week 4 · 2105623 Optimization of Chemical Processes
31 August 2026
Outline
Today
The designed crossover session: OpenSolver before the break, Python and ipopt after it. Notebook w04-modeling3-blending-pooling.ipynb; workbook w04-blending.xlsx.
Learning objectives
CLO 1 (formulation) and CLO 4 (implementation and solution in Pyomo). Reference: Rao Ch. 1 and Ch. 10; Edgar, Himmelblau and Lasdon Ch. 7; Haverly (1978); Tawarmalani and Sahinidis Ch. 9.
Where the money actually is
Choose the least costly mixture of purchased component streams that still meets every quality specification of every finished product.
The one modeling assumption that makes it linear. Properties blend linearly on a mass basis. Good for sulfur and density, acceptable for RVP if a blending index is used, and only rough for octane, where real blending is measurably nonlinear.
The second, usually unstated, assumption
Every component reaches the blender as a separate stream, perfectly segregated up to the blend header.
Lecture 2 removes exactly this assumption, and the model stops being linear.
Five component streams, two finished grades
| Component | RON | RVP kPa | S ppm | cost USD/t | avail t |
|---|---|---|---|---|---|
| Reformate | 98.0 | 3.0 | 110 | 760 | 3200 |
| FCC naphtha | 92.0 | 6.5 | 380 | 730 | 4000 |
| Alkylate | 95.0 | 4.5 | 15 | 805 | 2000 |
| Butane | 93.0 | 62.0 | 5 | 510 | 900 |
| Straight-run naphtha | 68.0 | 9.0 | 520 | 695 | 2600 |
| Regular | Premium | |
|---|---|---|
| RON minimum | 91.0 | 95.0 |
| RVP maximum, kPa | 9.0 | 8.5 |
| Sulfur maximum, ppm | 290 | 190 |
| Price, USD/t | 742 | 806 |
| Minimum volume, t | 4000 | 2500 |
| Maximum volume, t | 7000 | 5000 |
The same instance appears in the notebook (Section 1) and in the solution workbook. The two routes must agree to the cent.
Nine constraint families, and one of them is doing something unusual
Decision variables
xcg ≥ 0 tonnes of component c sent to grade g · yg ≥ 0 tonnes of grade g produced
The model
max Σg priceg yg − Σc Σg costc xcg
s.t. Σc xcg = yg
Σg xcg ≤ availc
dgmin ≤ yg ≤ dgmax
Σc ronc xcg ≥ rongmin yg
Σc rvpc xcg ≤ rvpgmax yg
Σc sulc xcg ≤ sulgmax yg
Look at the last three rows. Every specification row has the decision variable yg on its right-hand side. That is not an accident, and the next slide explains it.
The single manipulation that makes blending an LP
The physical requirement
( Σc ronc xcg ) ⁄ ( Σc xcg ) ≥ rongmin
is a ratio of decision variables, and therefore nonlinear.
The rule
Multiply through by the denominator, which is yg and is non-negative:
Σc ronc xcg − rongmin yg ≥ 0
or equivalently Σc ( ronc − rongmin ) xcg ≥ 0
The linear form is not a linearization. It is the same feasible set, intersected with yg > 0.
Solving the ratio form with ipopt returns the same optimum to within solver tolerance — while the constraint reports a polynomial degree of None instead of 1.
On a spreadsheet. The specification RHS cell contains a changing cell: =C11*C26. That is what “multiply the ratio through by its denominator” looks like on a sheet, and the plain RHS-column convention does not anticipate it.
When the rule is exact, and when it quietly is not
Let a, b be data vectors and x the decision vector. Then (aᵀx) ⁄ (bᵀx) ≤ β is equivalent to aᵀx − β bᵀx ≤ 0 provided that bᵀx > 0 at every point of interest.
The practical test, one question. Is the denominator the same aggregate that the numerator is normalised by, in the same balance? If yes, the constraint is linear in disguise. If no, expect bilinear terms.
Reusable, and the last row is the rest of this session
| Engineering requirement | Natural form | Linear equivalent | Condition |
|---|---|---|---|
| average property at most β | Σqcxc ⁄ Σxc ≤ β | Σ(qc−β)xc ≤ 0 | Σxc > 0 |
| average property at least β | Σqcxc ⁄ Σxc ≥ β | Σ(qc−β)xc ≥ 0 | Σxc > 0 |
| recycle ratio at most r | R ⁄ (R+F) ≤ r | (1−r)R − rF ≤ 0 | R+F > 0 |
| conversion at least η | (Fin−Fout) ⁄ Fin ≥ η | Fout ≤ (1−η)Fin | Fin > 0 |
| fixed split fraction θ | S₁ ⁄ (S₁+S₂) = θ | (1−θ)S₁ − θS₂ = 0 | S₁+S₂ > 0 |
| purity of a mixed stream at least π | mkey ⁄ mtot ≥ π | mkey − π mtot ≥ 0 | mtot > 0 |
| ratio objective | max (cᵀx+c₀) ⁄ (dᵀx+d₀) | Charnes–Cooper LP | dᵀx+d₀ > 0 |
| property of a stream leaving a pool | p = ΣqiFi ⁄ ΣPg, and p multiplies Pg | no linear equivalent | denominator is in another balance |
Charnes–Cooper, and a plant that deliberately makes less
Charnes–Cooper
Maximising (cᵀx+c₀) ⁄ (dᵀx+d₀) over {Ax ≤ b, x ≥ 0} with dᵀx+d₀ > 0 is a linear-fractional program. Substituting
t = 1 ⁄ (dᵀx+d₀) > 0, x′ = t x
gives the equivalent LP max cᵀx′ + c₀t
s.t. Ax′ − bt ≤ 0, dᵀx′ + d₀t = 1, x′, t ≥ 0
and x = x′⁄t recovers the original solution.
On this instance
| Total margin (Section 1 LP) | 413,439.75 USD |
| Margin per tonne (CC LP) | 45.8708 USD/t |
| its plan | 4,000.00 t Regular |
| 5,000.00 t Premium | |
| its total margin | 412,837.10 USD |
| margin given up | 602.65 USD |
Read this carefully. The plant that maximises the ratio deliberately declines the last 80.6 t of Regular, because that increment earns less than the current average. Which objective is correct is a business question, not a mathematical one — but the two must never be confused.
Quality above specification is quality given away
Optimum: 413,439.75 USD
| Component, t | Regular | Premium | slack |
|---|---|---|---|
| Reformate | 107.63 | 3092.37 | 0 |
| FCC naphtha | 2623.63 | 1376.37 | 0 |
| Alkylate | 833.01 | 0 | 1166.99 |
| Butane | 206.67 | 367.83 | 325.50 |
| Straight-run naphtha | 309.67 | 163.42 | 2126.91 |
| Volume yg, t | 4080.60 | 5000.00 |
This recipe is one of several. The optimum is degenerate: your solver will very likely report different numbers in this table at exactly the same margin. Compare objectives, not recipes.
All six quality rows bind exactly. Regular sits at RON 91.00, RVP 9.00 kPa, 290.00 ppm sulfur; Premium at RON 95.00, RVP 8.50, 190.00 ppm.
That is normal, and it is the point of a blending model: quality above specification is quality given away, so the optimizer gives away nothing.
Marginal values
Availability duals: reformate 41.9412, FCC naphtha 13.3609 USD/t.
Alkylate, butane and straight-run have slack and a dual of zero.
18 min · two halves of the room · paper
The refinery blends the five component streams of slide 6 into Regular and Premium. Component costs, availabilities and properties as tabulated. Regular sells at 742, Premium at 806 USD/t. Contractual volumes: Regular 4,000–7,000 t, Premium 2,500–5,000 t. The plan must cover one month.
Brief for the Production half
Your objective is minimum cost, that is maximum blending margin. You are accountable for meeting the contracted volumes from the components actually on site, and for not buying more of the expensive streams than you must.
Write down the constraint set you would insist the model contain. Anything you leave out, you are agreeing to give away.
Brief for the Quality Control half
The product must meet three named specifications per grade. Regular: RON ≥ 91.0, RVP ≤ 9.0 kPa, sulfur ≤ 290 ppm. Premium: RON ≥ 95.0, RVP ≤ 8.5, sulfur ≤ 190 ppm.
The octane floor is a customer contract term: a delivery below it is a rejected cargo. The RVP and sulfur ceilings are internal laboratory targets, set inside the legal limits with a deliberate margin.
Two halves, working in pairs within each half. 10 min separately, then compare and agree one constraint set, explicitly labelling each constraint hard or soft. Hand back the agreed list, one sheet per side, with H or S against every row.
Nothing in the physics distinguishes the octane floor from the sulfur ceiling
| Constraint | H/S |
|---|---|
| grade material balance | H (physics) |
| component availability | H (physics) |
| contract volume window | H (contract) |
| octane floor | H (contract) |
| vapour pressure ceiling | S (internal target) |
| sulfur ceiling | S (internal target) |
| non-negativity | H |
A soft constraint belongs in the objective
Σc sulcxcg − sulgmaxyg ≤ vg, vg ≥ 0, objective − πgvg
What distinguishes them is who wrote them down, and what happens when they are missed.
What the numbers say once all three are hard
Margin 413,439.75 USD, all six quality rows binding. The value of relaxing each row by one unit — the LP dual of the multiplied-through row, identical for both grades — is
| row | USD |
|---|---|
| octane | 0.69276 |
| vapour pressure | 5.12983 |
| sulfur | 0.13507 |
So the internal RVP target is by far the most expensive of the three to hold — and it is precisely the one nobody in the room called a contract term.
One physical fact destroys linearity
Segregated: linear
Quality delivered to X is Σi qixiX, a linear function. Multiply the ratio through by Σi xiX and the model is an LP.
Pooled: bilinear
Everything drawn from the tank has the same composition p, whatever it is fed by. p is a decision, and it multiplies flows.
Streams are collected in a common pool. The pool quality satisfies p ΣgPg = ΣiqiFi, and the quality delivered to product g is p Pg. Both expressions contain the product of two decision variables.
Condition 3 of slide 9, failing
The pool quality is a ratio
p = Σi qiFi ⁄ Σg Pg
Its denominator is the total pool throughput. But the quantity that has to be constrained is the pool’s contribution to the balance of a different stream, namely product g:
p Pg + qCCg ≤ specg ( Pg + Cg )
Multiplying by ΣgPg clears the ratio and leaves p Pg untouched.
The feasible set is no longer convex.
A nonconvex NLP with bilinear terms, and every guarantee that came with linear programming is gone:
Where this bites in practice. Refinery gasoline pools, crude tank farms, LPG caverns, hydrogen headers, and any electrolyte make-up tank feeding more than one cell chemistry.
Seven variables, three bilinear rows, and it has defeated people for fifty years
| Stream | route | S % | USD |
|---|---|---|---|
| Feed A | into the pool | 3.0 | 6 |
| Feed B | into the pool | 1.0 | 16 |
| Feed C | bypasses the pool | 2.0 | 10 |
| Product X | ≤ 2.5 % S | 9 | |
| Product Y | ≤ 1.5 % S | 15 |
Feeds are costs, products are prices. Demand limits X ≤ 100, Y ≤ 200. Seven variables: A, B into the pool; PX, PY out; CX, CY direct; and the pool sulfur p. The bounds 1 ≤ p ≤ 3 are physical.
The p-formulation
max 9(PX+CX) + 15(PY+CY) − 6A − 16B − 10(CX+CY)
s.t. A + B = PX + PY
3A + B = p (PX+PY)
p PX + 2CX ≤ 2.5(PX+CX)
p PY + 2CY ≤ 1.5(PY+CY)
PX+CX ≤ 100, PY+CY ≤ 200
1 ≤ p ≤ 3, all flows ≥ 0
Three of these rows are bilinear, and each contains a product of two decision variables.
Same feasible set, same global optimum, different relaxation
Change of variables
Let qi be the fraction of the pool inlet contributed by feed i, so Σiqi = 1 and 0 ≤ qi ≤ 1. Then Fi = qi ΣgPg, and the amount of feed i reaching product g is qiPg.
max 9(PX+CX) + 15(PY+CY) − 6qA(PX+PY) − 16qB(PX+PY) − 10(CX+CY)
s.t. qA + qB = 1
(3qA+qB)PX + 2CX ≤ 2.5(PX+CX)
(3qA+qB)PY + 2CY ≤ 1.5(PY+CY)
But they are not the same relaxation. And that, not the algebra, is the whole reason for preferring one over the other. Reparametrizing a nonconvex problem does not make it convex.
“Optimal” is a statement about a point, not about the problem
A termination status of optimal from a local NLP solver is a statement about the KKT conditions at the point it stopped.
It is not, and never was, a statement about global optimality.
What a global solver adds. A spatial branch-and-bound code (couenne, BARON, ANTIGONE) maintains a convex relaxation of the nonconvex problem, so it can report an incumbent and a bound, and therefore a gap. That is the only kind of guarantee available here.
The discipline this forces
Turn the nonconvex problem into an LP whose optimum is a valid bound
The construction
Replace a product w = uv with u ∈ [uL, uU], v ∈ [vL, vU] by a new variable w and four linear inequalities:
w ≥ uLv + vLu − uLvL
w ≥ uUv + vUu − uUvU
w ≤ uUv + vLu − uUvL
w ≤ uLv + vUu − uLvU
This is exactly the convex hull of the graph of uv over the box, so it is the tightest possible relaxation of one product in isolation.
Reformulation–linearization (RLT)
In the q-formulation the bilinear variables vig = qiPg inherit the identity Σiqi = 1. Multiplying it by Pg and by the pool throughput limit gives
Σi vig = Pg ∀g, Σg vig ≤ Cap · qi ∀i
These rows are redundant for the nonlinear model but not for its relaxation.
Why this is the practical lever. The bound is what a spatial branch-and-bound tree spends its time closing, so choosing the formulation with the tighter relaxation is worth more than any solver setting.
Break
12 minutes.
Next: open w04-blending.xlsx with OpenSolver loaded, and check that ipopt is on your path. Activity 2 starts on the spreadsheet. Activity 3, after Lecture 3, is the reason this course leaves the spreadsheet behind.
25 min · computer · individual
Part 1 — reproduce the optimum and read off what binds
Open w04-blending.xlsx, sheet Model. Complete the yellow cells: the availability VALUE column E19:E23, the constraint VALUE column E33:E44 — every quality row in multiplied-through form, so its RHS is 0 — and the objective C29.
OpenSolver with CBC: objective $C$29 set to Max, changing cells $C$19:$D$24, constraints as listed on the Readme sheet, and tick Get sensitivity report.
The objective cell must read 413,439.75 USD.
Then write down, from the check block in rows 46–51, which specifications bind.
Part 2 — predict before you solve
Change one specification by a small amount — for example tighten the Regular sulfur ceiling from 290 to 250 ppm.
Before re-solving, write on paper: will the margin rise or fall, and roughly by how much? Use the sensitivity report from Part 1 to justify the number. Then re-solve and compare.
Your recipe will probably not match slide 12, and that is not an error. The optimum is degenerate: several recipes achieve the same margin. Check the objective and the binding set, not the recipe.
Individual. Hand back nothing — the instructor walks the room. Anyone whose objective differs has a formula error.
And the linear prediction is not a bound in the direction you expect
Part 1
Objective C29 = 413,439.75 USD, matching the Pyomo model to the cent (413,439.749277).
Binding: all six quality rows; the Premium volume ceiling at 5,000 t; and the availability rows for reformate (3,200 t) and FCC naphtha (4,000 t).
Not binding: the Regular volume window — it settles at 4,080.60 t, above its floor and below its ceiling — and the availability of alkylate, butane and straight-run naphtha.
The optimum is degenerate: several different recipes achieve the same margin, and a different solver reports a different one. The binding set and the objective are stable; the recipe is not.
Part 2 — the prediction rule, and its direction
Predicted change = (dual of the row) × (change in the row). Tightening a ceiling that binds can only reduce the margin, so the sign is known before any arithmetic.
| Regular S ceiling | actual | linear prediction |
|---|---|---|
| 290 → 250 ppm | −27,445 | −22,047 |
| 290 → 200 ppm | −63,231 | −49,606 |
| 290 → 150 ppm | −110,056 | −77,164 |
The linear prediction under-states the loss, and always will. The LP value function is concave in the right-hand side for a maximisation, so the tangent lies above it. Push the specification far enough and a different set of constraints binds, the dual rises, and the real cost runs away from the prediction.
And why a gradient method cannot see across it
Schematic. Every marked point satisfies the KKT conditions, and a local solver reports optimal at each.
The mechanism
A gradient-based method climbs the hill it starts on. It has no information about the landscape beyond the neighbourhood it has visited, and no mechanism for crossing a valley of infeasible or worse points.
The starting point selects the answer.
On a nonconvex problem the initial values are not a numerical detail — they are part of the specification of what you computed. A result reported without them is not reproducible.
Evidence, and a good incumbent. Not a proof.
The procedure
It gives no bound, so it cannot prove optimality. A multistart that always returns the same value has found either a convex problem or a badly chosen sampling range.
Practical advice
Six warning signs
A blend recipe from a local optimum is not infeasible. It meets every specification.
It is wrong in the sense of leaving margin on the table, silently, every day, with no signal that it is doing so.
And for electrolyte blending: the same structure appears whenever one make-up tank feeds more than one cell chemistry. The tank composition is a variable, and it multiplies every draw from the tank.
15 min · computer · groups of 3 to 4
What to do
Open w04-modeling3-blending-pooling.ipynb and run everything up to and including the Haverly section. The model builder is build_haverly(p0=...), where p0 is the starting value of the pool sulfur p, and the solver is ipopt.
Solve the same model twice: once from p₀ = 1.0, once from p₀ = 3.0.
Nothing else changes. Same data, same constraints, same solver, same tolerances.
Record, for each of the two runs
Do not compare with the group next to you until the poll. When both columns are on the board, the question to the room is simply: which one is right?
Groups of 3 to 4, one machine per group. Hand back nothing written — each group reports its two numbers out loud when polled.
Same model, same solver, same tolerances
| start p₀ = 1.0 | start p₀ = 3.0 | |
|---|---|---|
| termination | optimal |
optimal |
| profit, USD | 400.00 | 100.00 |
| final p, % S | 1.000 | 3.000 |
| A | 0 | 50 |
| B | 100 | 0 |
| PX | 0 | 50 |
| PY | 100 | 0 |
| CX | 0 | 50 |
| CY | 100 | 0 |
300 USD out of 400 — 75 percent of the achievable margin, on a problem with seven variables. Both points genuinely satisfy the KKT conditions, so both status words are honest.
Fixing p turns the pooling problem back into an ordinary LP, so sweeping p traces the true profile. Two separated hills, and a valley over which no feasible plan makes any money.
Four of nine starts reach the better solution, and every run reports optimal
| starting p₀ | profit | final p |
|---|---|---|
| 1.00 | 400.00 | 1.00 |
| 1.25 | 400.00 | 1.00 |
| 1.50 | 400.00 | 1.00 |
| 1.75 | 400.00 | 1.00 |
| 2.00 | 100.00 | 3.00 |
| 2.25 | 100.00 | 3.00 |
| 2.50 | 100.00 | 3.00 |
| 2.75 | 100.00 | 3.00 |
| 3.00 | 100.00 | 3.00 |
On the 81-point sweep the profit is exactly zero for p from 1.525 to 2.400.
That flat valley is the boundary between the two basins of attraction, and it is why no gradient step crosses it.
The closing point of the session. A spreadsheet solver would have returned one of these two numbers and never mentioned the other. No message, no bound, no gap. That is why the course moves to Python from here — and the reason is not size. It is that a spreadsheet cannot tell you its answer is local.
“Profit 400” is an opinion. Here is what a result looks like.
| Instance | form | global | bound | gap |
|---|---|---|---|---|
| Haverly, 2 feeds, no pool limit | p | 400 | 500.00 | 25.0 % |
| Haverly, 2 feeds, no pool limit | q | 400 | 500.00 | 25.0 % |
| extended, 4 feeds, pool ≤ 150 | p | 400 | 555.56 | 38.9 % |
| extended, 4 feeds, pool ≤ 150 | q | 400 | 466.67 | 16.7 % |
The honest report.
“Profit 400” is an opinion.
“Profit 400, from p₀ = 1.0, with a valid upper bound of 500 from the McCormick relaxation, and a multistart over nine starts in which four reached 400 and five reached 100” is a result.
Forward
Week 10 supplies the KKT theory behind the word optimal. Week 11 supplies the branch-and-bound machinery that closes a gap. Week 13 returns to what to do when the model is not known at all.
What today established
Numbers established today
| Linear blending margin | 413,439.75 USD |
| Regular / Premium volume | 4,080.60 / 5,000.00 t |
| Binding quality rows | all six |
| Availability duals, reformate / FCC | 41.9412 / 13.3609 |
| Spec duals, RON / RVP / S | 0.69276 / 5.12983 / 0.13507 |
| Margin per tonne (Charnes-Cooper) | 45.8708 USD/t |
| margin given up | 602.65 USD |
| Haverly from p₀ = 1.0 | 400.00 USD, p = 1 |
| Haverly from p₀ = 3.0 | 100.00 USD, p = 3 |
| Multistart, 9 starts | 4 reach 400, 5 reach 100 |
| Flat zero valley | p ∈ [1.525, 2.400] |
| McCormick, Haverly p / q | 500.00 / 500.00 |
| McCormick, extended p / q | 555.56 / 466.67 |
Next: Week 5 — logical and discrete decisions, big-M versus convex hull, and formulation strength.
Reading, notebook, and HW2
Reading
Notebook to finish
w04-modeling3-blending-pooling.ipynb, all sections, plus Exercises 2, 4 and 6. Exercise 4 is the proper 100-point multistart on Haverly and is the one that settles the argument started today.
HW1 is released today, due Monday 7 September — the start of Week 5.
The Week 3 self-study pack is released today too, due Friday 11 September, midnight — the session I was away for. The files have been on the course page without a deadline; the deadline starts now.
HW2 is not released today. It comes in Week 5, so you meet these one at a time.
Where to go deeper
Forward references made today. The disjunction that a shut-off grade really needs is Week 5; the KKT conditions behind the word optimal are Week 10; the branch-and-bound machinery that closes a relaxation gap is Week 11.
Before you go · 45 seconds
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

Scan now — I will wait