From 7dbf34cb0119dd9859cfeeec467d4f9366617975 Mon Sep 17 00:00:00 2001 From: Zoey Zheng Date: Mon, 18 May 2026 22:05:25 +1000 Subject: [PATCH 1/3] Clarify scipy linprog transformation description Clarifies that SciPy transforms the problem into standard form internally after presolve. --- lectures/lp_intro.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lectures/lp_intro.md b/lectures/lp_intro.md index 52504a5a..8fe94c98 100644 --- a/lectures/lp_intro.md +++ b/lectures/lp_intro.md @@ -487,9 +487,9 @@ The optimal plan tells the factory to produce $2.5$ units of Product 1 and $5$ We are using the `linprog` function as a *black box*. -Inside it, Python first transforms the problem into standard form. +Internally, after a presolve step, SciPy transforms the problem into a standard form before applying the selected solver. -To do that, for each inequality constraint it generates one slack variable. +In this transformation, one slack variable is added for each inequality constraint. Here the vector of slack variables is a two-dimensional NumPy array that equals $b_{ub} - A_{ub}x$. From 63172073bf164b614cff7f6bde113ed47aef1b30 Mon Sep 17 00:00:00 2001 From: Zoey Zheng Date: Mon, 25 May 2026 21:42:58 +1000 Subject: [PATCH 2/3] Revise linprog description after review Clarifies the description of SciPy's default highs method and the returned slack values. --- lectures/lp_intro.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lectures/lp_intro.md b/lectures/lp_intro.md index 8fe94c98..c8c3cadd 100644 --- a/lectures/lp_intro.md +++ b/lectures/lp_intro.md @@ -487,11 +487,11 @@ The optimal plan tells the factory to produce $2.5$ units of Product 1 and $5$ We are using the `linprog` function as a *black box*. -Internally, after a presolve step, SciPy transforms the problem into a standard form before applying the selected solver. +SciPy accepts inequality constraints in the form $A_{ub} x \leq b_{ub}$, equality constraints in the form $A_{eq} x = b_{eq}$, and variable bounds. -In this transformation, one slack variable is added for each inequality constraint. +In this lecture, `linprog` uses SciPy's default `highs` method, which calls the HiGHS optimization solver. -Here the vector of slack variables is a two-dimensional NumPy array that equals $b_{ub} - A_{ub}x$. +The slack value returned by `linprog` is a one-dimensional NumPy array whose entries measure the difference $b_{ub} - A_{ub}x$ for each inequality constraint. See the [official documentation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linprog.html#scipy.optimize.linprog) for more details. From 9c6606d0c21bf4a26b8e059dd8f4f0c559bfc718 Mon Sep 17 00:00:00 2001 From: John Stachurski Date: Thu, 28 May 2026 07:02:23 +1000 Subject: [PATCH 3/3] Fix errors in lp_intro lecture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix OR-Tools prose: x3 (bank) and x5 (bond) values were swapped in the investment strategy description. - Remove incorrect note claiming OR-Tools and SciPy give different solutions — the solution is unique. - Fix math error in slack variable transformation: RHS should be b_i, not 0. - Fix wrong comment: A_ex2/b_ex2 are equality constraints, not inequality. - Fix prose: iso-revenue lines show product combinations, not materials/labor; clarify firm's objective sentence. - Fix prose: "creates two variables" → correct for 5-variable example. - Fix grammar: "keep invest" → "keep investing", "it's" → "its", "where in" → "where". - Add missing x, y >= 0 constraint in Exercise 2 formulation. Addresses second part of #599. Co-Authored-By: Claude Opus 4.7 (1M context) --- lectures/lp_intro.md | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/lectures/lp_intro.md b/lectures/lp_intro.md index 39c06df0..522accd4 100644 --- a/lectures/lp_intro.md +++ b/lectures/lp_intro.md @@ -96,7 +96,7 @@ $$ The following graph illustrates the firm's constraints and iso-revenue lines. -Iso-revenue lines show all the combinations of materials and labor that produce the same revenue. +Iso-revenue lines show all the combinations of Product 1 and Product 2 that generate the same revenue. ```{code-cell} ipython3 --- @@ -133,9 +133,9 @@ The blue region is the feasible set within which all constraints are satisfied. Parallel black lines are iso-revenue lines. -The firm's objective is to find the parallel black lines to the upper boundary of the feasible set. +The firm's objective is to push the iso-revenue line as high as possible while remaining in the feasible set. -The intersection of the feasible set and the highest black line delineates the optimal set. +The intersection of the feasible set and the highest iso-revenue line delineates the optimal set. In this example, the optimal set is the point $(2.5, 5)$. @@ -278,7 +278,7 @@ $$ Let's try to solve the above problem using the package `ortools.linear_solver`. -The following cell instantiates a solver and creates two variables specifying the range of values that they can have. +The following cell instantiates a solver. ```{code-cell} ipython3 # Instantiate a GLOP(Google Linear Optimization Package) solver @@ -338,9 +338,9 @@ OR-Tools tells us that the best investment strategy is: 1. At the beginning of the first year, the mutual fund should buy $ \$24,927.755$ of the annuity. Its bank account balance should be $ \$75,072.245$. -2. At the beginning of the second year, the mutual fund should buy $ \$4,648.825$ of the corporate bond and borrow $ \$20,000$ from the bank. +2. At the beginning of the second year, the mutual fund should buy $ \$50,000$ of the corporate bond and keep investing in the annuity. Its bank account balance should be $ \$4,648.825$. -3. At the beginning of the third year, the bank balance should be $ \$50,000$. +3. At the beginning of the third year, the mutual fund should borrow $ \$20,000$ from the bank and invest in the annuity. 4. At the end of the third year, the mutual fund will get payouts from the annuity and corporate bond and repay its loan from the bank, leaving it with $ \$141,018.24$ and a total net rate of return over the three periods of $41.02\%$. @@ -407,7 +407,7 @@ By deploying the following steps, any linear programming problem can be transfor 2. Decision variables: Given a variable $x_j$ satisfying $x_j \le 0$, we can introduce a new variable $x_j' = - x_j$ and substitute it into original problem. Given a free variable $x_i$ with no restriction on its sign, we can introduce two new variables $x_j^+$ and $x_j^-$ satisfying $x_j^+, x_j^- \ge 0$ and replace $x_j$ by $x_j^+ - x_j^-$. -3. Inequality constraints: Given an inequality constraint $\sum_{j=1}^n a_{ij}x_j \le 0$, we can introduce a new variable $s_i$, called a **slack variable** that satisfies $s_i \ge 0$ and replace the original constraint by $\sum_{j=1}^n a_{ij}x_j + s_i = 0$. +3. Inequality constraints: Given an inequality constraint $\sum_{j=1}^n a_{ij}x_j \le b_i$, we can introduce a new variable $s_i$, called a **slack variable** that satisfies $s_i \ge 0$ and replace the original constraint by $\sum_{j=1}^n a_{ij}x_j + s_i = b_i$. Let's apply the above steps to the two examples described above. @@ -545,7 +545,7 @@ rate = 1.06 # Objective function parameters c_ex2 = np.array([1.30*3, 0, 0, 1.06, 1.30]) -# Inequality constraints +# Equality constraints A_ex2 = np.array([[1, 1, 0, 0, 0], [1, -rate, 1, 0, 1], [1, 0, -rate, 1, 0]]) @@ -584,18 +584,13 @@ SciPy tells us that the best investment strategy is: 1. At the beginning of the first year, the mutual fund should buy $ \$24,927.75$ of the annuity. Its bank account balance should be $ \$75,072.25$. -2. At the beginning of the second year, the mutual fund should buy $ \$50,000 $ of the corporate bond and keep invest in the annuity. Its bank account balance should be $ \$ 4,648.83$. +2. At the beginning of the second year, the mutual fund should buy $ \$50,000 $ of the corporate bond and keep investing in the annuity. Its bank account balance should be $ \$ 4,648.83$. 3. At the beginning of the third year, the mutual fund should borrow $ \$20,000$ from the bank and invest in the annuity. -4. At the end of the third year, the mutual fund will get payouts from the annuity and corporate bond and repay its loan from the bank. At the end it will own $ \$141,018.24 $, so that it's total net rate of return over the three periods is $ 41.02\% $. - +4. At the end of the third year, the mutual fund will get payouts from the annuity and corporate bond and repay its loan from the bank. At the end it will own $ \$141,018.24 $, so that its total net rate of return over the three periods is $ 41.02\% $. -```{note} -You might notice the difference in the values of optimal solution using OR-Tools and SciPy but the optimal value is the same. It is because there can be many optimal solutions for the same problem. -``` - ## Exercises @@ -604,7 +599,7 @@ You might notice the difference in the values of optimal solution using OR-Tools :label: lp_intro_ex1 ``` -Implement a new extended solution for the Problem 1 where in the factory owner decides that number of units of Product 1 should not be less than the number of units of Product 2. +Implement a new extended solution for Problem 1 where the factory owner decides that the number of units of Product 1 should not be less than the number of units of Product 2. ```{exercise-end} ``` @@ -700,6 +695,7 @@ $$ \max_{x,y} \ & z = 23 x + 10 y \\ \mbox{subject to } \ & x + y \le 20 \\ & 2 x + 0.8 y \le 25 \\ +& x, y \ge 0 \\ \end{aligned} $$