Skip to content

Commit

Permalink
Update various chapter 7, 8, 9, 10 notebooks
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrozocca committed Nov 26, 2023
1 parent d0dd3cb commit fe36f98
Show file tree
Hide file tree
Showing 14 changed files with 3,316 additions and 3,450 deletions.
2 changes: 1 addition & 1 deletion _toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ chapters:

- file: notebooks/10/10.00.md
sections:
- file: notebooks/10/01-airline-seating-allocation.ipynb
- file: notebooks/10/01-aircraft-seat-allocation.ipynb
- file: notebooks/10/02-opf-linear-decision-rule.ipynb
- file: notebooks/10/03-two-stage-production-planning.ipynb
- file: notebooks/10/04-farmer-problem.ipynb
Expand Down
4 changes: 2 additions & 2 deletions notebooks/01/01.00.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ and similarly for a maximization problem. Different types of function $f$ and se

In this introductory chapter, we present a simple example of optimization in the context of production planning.

- We first explain the structure and formalism of the corresponding optimization problem in a [first notebook](01-production-planning.ipynb)
- We then implement and solve the optimization in Pyomo in a [second notebook](02-production-planning-basic.ipynb), which also serves as a Pyomo tutorial.
- We first explain the structure and formalism of the corresponding optimization problem in a [first notebook](01-production-planning.ipynb);
- We then implement and solve the optimization in Pyomo in a [second notebook](02-production-planning-basic.ipynb), which also serves as a Pyomo tutorial;
- Lastly, we discuss some advance Pyomo features in a [third notebook](03-production-planning-advanced.ipynb).

Go to the [next chapter](../02/02.00.md) about linear optimization.
2 changes: 1 addition & 1 deletion notebooks/02/02.00.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ This chapter includes several with companion Pyomo implementation that explore v
* [The dual problem of the microchip production problem](04-bim-dual.ipynb)
* [A variant of BIM problem: maximizing the lowest possible profit](05-bim-maxmin.ipynb)
* [Two variants of the BIM problem using fractional objective or additional fixed costs](06-bim-fractional.ipynb)
* [The BIM production problem using demand forecasts](07-bim-raw-material-planning.ipynb)
* [The BIM production problem using demand forecasts](07-bim-demand-forecast.ipynb)
* [Extra material: Wine quality prediction problem using $L_1$ regression](08-L1-regression-wine-quality.ipynb)
* [Extra material: Multi-product facility production](09-production-faciliity-worst-case.ipynb)

Expand Down
339 changes: 164 additions & 175 deletions notebooks/05/04-svm-binary-classification.ipynb

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions notebooks/07/07.00.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ In all the optimization problems discussed in the previous chapters, we treated
- electrical power sent to an antenna is subject to the generator's errors.

Since there is so much uncertainty, natural questions are:
- how to check how bad `not knowing the numbers exactly in advance` can be for the performance of solutions?
- if a given solution is very sensitive to changes in the problem parameters, can a better solution be found by taking uncertainty into account in advance, and if so, how?
- How to check how bad *not knowing the numbers exactly in advance* can be for the performance of solutions?
- If a given solution is very sensitive to changes in the problem parameters, can a better solution be found by taking uncertainty into account in advance, and if so, how?

We will show three examples of how one can inspect solutions for their sensitivity to data changes.
We will show two examples of how one can inspect solutions for their sensitivity to data changes.

* [Fleet assignment problem](01-fleet-assignment.ipynb)
* [Robustness analysis of BIM production plan via simulations](02-bim-robustness-analysis.ipynb)
Expand Down
2 changes: 1 addition & 1 deletion notebooks/08/08.00.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 8. Robust Optimization - Single Stage Problems

In this chapter, there is a number of examples with companion Pyomo implementation that explore various modeling and implementation aspects of robust optimization:
In this chapter, we have a single yet extensive example implemented in Pyomo that explores various modeling and implementation aspects of robust optimization:

* [Robust version of BIM production problem](01-bim-robust-optimization.ipynb)

Expand Down
174 changes: 69 additions & 105 deletions notebooks/09/01-pop-up-shop.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
" \n",
"import pyomo.environ as pyo\n",
"SOLVER = pyo.SolverFactory(solver)\n",
" \n",
"assert SOLVER.available(), f\"Solver {solver} is not available.\""
]
},
Expand Down Expand Up @@ -364,15 +363,15 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Solver Termination Condition: optimal\n",
"\n"
"Expected Profit: 8920.0\n"
]
},
{
Expand Down Expand Up @@ -445,79 +444,58 @@
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Expected Profit: 8920.0\n"
]
}
],
"source": [
"import pyomo.environ as pyo\n",
"import pandas as pd\n",
"\n",
"# price and scenario information\n",
"r = 40\n",
"c = 12\n",
"w = 2\n",
"\n",
"scenarios = {\n",
" \"sunny skies\": {\"demand\": 650, \"probability\": 0.1},\n",
" \"good weather\": {\"demand\": 400, \"probability\": 0.6},\n",
" \"poor weather\": {\"demand\": 200, \"probability\": 0.3},\n",
"}\n",
"\n",
"# create model instance\n",
"m = pyo.ConcreteModel(\"Pop-up shop\")\n",
"\n",
"# set of scenarios\n",
"m.S = pyo.Set(initialize=scenarios.keys())\n",
"def PopUpShop(r, c, w, scenarios):\n",
" m = pyo.ConcreteModel(\"Pop-up shop\")\n",
"\n",
"# decision variables\n",
"m.x = pyo.Var(domain=pyo.NonNegativeIntegers)\n",
"m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)\n",
"m.f = pyo.Var(m.S, domain=pyo.Reals)\n",
" # set of scenarios\n",
" m.S = pyo.Set(initialize=scenarios.keys())\n",
"\n",
" # decision variables\n",
" m.x = pyo.Var(domain=pyo.NonNegativeIntegers)\n",
" m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)\n",
" m.f = pyo.Var(m.S, domain=pyo.Reals)\n",
"\n",
"# objective\n",
"@m.Objective(sense=pyo.maximize)\n",
"def EV(m):\n",
" return sum([scenarios[s][\"probability\"] * m.f[s] for s in m.S])\n",
" # parameters\n",
" m.r = pyo.Param(initialize=r)\n",
" m.c = pyo.Param(initialize=c)\n",
" m.w = pyo.Param(initialize=w)\n",
"\n",
" # objective\n",
" @m.Objective(sense=pyo.maximize)\n",
" def EV(m):\n",
" return sum([scenarios[s][\"probability\"] * m.f[s] for s in m.S])\n",
"\n",
"# constraints\n",
"@m.Constraint(m.S)\n",
"def profit(m, s):\n",
" return m.f[s] == r * m.y[s] + w * (m.x - m.y[s]) - c * m.x\n",
" # constraints\n",
" @m.Constraint(m.S)\n",
" def profit(m, s):\n",
" return m.f[s] == m.r * m.y[s] + m.w * (m.x - m.y[s]) - m.c * m.x\n",
"\n",
" @m.Constraint(m.S)\n",
" def sales_less_than_order(m, s):\n",
" return m.y[s] <= m.x\n",
"\n",
"@m.Constraint(m.S)\n",
"def sales_less_than_order(m, s):\n",
" return m.y[s] <= m.x\n",
" @m.Constraint(m.S)\n",
" def sales_less_than_demand(m, s):\n",
" return m.y[s] <= scenarios[s][\"demand\"]\n",
"\n",
"\n",
"@m.Constraint(m.S)\n",
"def sales_less_than_demand(m, s):\n",
" return m.y[s] <= scenarios[s][\"demand\"]\n",
" return m\n",
"\n",
"\n",
"m = PopUpShop(r, c, w, scenarios)\n",
"results = SOLVER.solve(m)\n",
"\n",
"print(\"Solver Termination Condition:\", results.solver.termination_condition)\n",
"print()\n",
"\n",
"# display solution using Pandas\n",
"print(f\"Solver termination condition: {results.solver.termination_condition}\")\n",
"print(f\"Expected profit: {m.EV()}\")\n",
"for s in m.S:\n",
" scenarios[s][\"order\"] = m.x()\n",
" scenarios[s][\"sold\"] = m.y[s]()\n",
" scenarios[s][\"salvage\"] = m.x() - m.y[s]()\n",
" scenarios[s][\"profit\"] = m.f[s]()\n",
"\n",
"df = pd.DataFrame.from_dict(scenarios).T\n",
"display(df)\n",
"print(\"Expected Profit:\", m.EV())"
"display(df)"
]
},
{
Expand All @@ -541,7 +519,7 @@
"\n",
"Nevertheless, we can perform the hypothetical calculation of what profit would be realized if we could know the future. We are still subject to the variability of weather, what is different is we know what the weather will be at the time the order is placed. \n",
"\n",
"The resulting value for the expected profit is called the **Expected Value of Perfect Information (EVPI)**. The difference EVPI - EV is the extra profit due to having perfect knowledge of the future.\n",
"The resulting value for the expected profit is called the **Expected Value of Perfect Information (EVPI)**. The difference $EVPI - EV$ is the extra profit due to having perfect knowledge of the future.\n",
"\n",
"To compute the expected profit with perfect information, we let the order variable $x$ be indexed by the subsequent scenario that will unfold. Given decision varaible $x_s$, the model for EVPI becomes\n",
"\n",
Expand All @@ -555,21 +533,20 @@
"\\end{align*}\n",
"$$\n",
"\n",
"The following implementation is a variation of the prior cell."
"The following implementation is a variation of the prior Pyomo model, with the only difference that now $x$ is a decision variable indexed by the scenarios."
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Solver Termination Condition: optimal\n",
"Expected Profit: 10220.0\n",
"\n"
"Expected Profit: 10220.0\n"
]
},
{
Expand Down Expand Up @@ -645,61 +622,48 @@
}
],
"source": [
"import pyomo.environ as pyo\n",
"import pandas as pd\n",
"\n",
"# price information\n",
"r = 40\n",
"c = 12\n",
"w = 2\n",
"\n",
"# scenario information\n",
"scenarios = {\n",
" \"sunny skies\": {\"demand\": 650, \"probability\": 0.1},\n",
" \"good weather\": {\"demand\": 400, \"probability\": 0.6},\n",
" \"poor weather\": {\"demand\": 200, \"probability\": 0.3},\n",
"}\n",
"\n",
"# create model instance\n",
"m = pyo.ConcreteModel(\"Pop-up Shop\")\n",
"\n",
"# set of scenarios\n",
"m.S = pyo.Set(initialize=scenarios.keys())\n",
"\n",
"# decision variables\n",
"m.x = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)\n",
"m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)\n",
"m.f = pyo.Var(m.S, domain=pyo.Reals)\n",
"def PopUpShop_PI(r, c, w, scenarios):\n",
" m = pyo.ConcreteModel(\"Pop-up shop with perfect information\")\n",
"\n",
" # set of scenarios\n",
" m.S = pyo.Set(initialize=scenarios.keys())\n",
"\n",
"# objective\n",
"@m.Objective(sense=pyo.maximize)\n",
"def EV(m):\n",
" return sum([scenarios[s][\"probability\"] * m.f[s] for s in m.S])\n",
" # decision variables\n",
" m.x = pyo.Var(m.S, domain=pyo.NonNegativeIntegers) # one for each scenario\n",
" m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)\n",
" m.f = pyo.Var(m.S, domain=pyo.Reals)\n",
"\n",
" # parameters\n",
" m.r = pyo.Param(initialize=r)\n",
" m.c = pyo.Param(initialize=c)\n",
" m.w = pyo.Param(initialize=w)\n",
"\n",
"# constraints\n",
"@m.Constraint(m.S)\n",
"def profit(m, s):\n",
" return m.f[s] == r * m.y[s] + w * (m.x[s] - m.y[s]) - c * m.x[s]\n",
" # objective\n",
" @m.Objective(sense=pyo.maximize)\n",
" def EV(m):\n",
" return sum([scenarios[s][\"probability\"] * m.f[s] for s in m.S])\n",
"\n",
" # constraints\n",
" @m.Constraint(m.S)\n",
" def profit(m, s):\n",
" return m.f[s] == m.r * m.y[s] + m.w * (m.x[s] - m.y[s]) - m.c * m.x[s]\n",
"\n",
"@m.Constraint(m.S)\n",
"def sales_less_than_order(m, s):\n",
" return m.y[s] <= m.x[s]\n",
" @m.Constraint(m.S)\n",
" def sales_less_than_order(m, s):\n",
" return m.y[s] <= m.x[s]\n",
"\n",
" @m.Constraint(m.S)\n",
" def sales_less_than_demand(m, s):\n",
" return m.y[s] <= scenarios[s][\"demand\"]\n",
"\n",
"@m.Constraint(m.S)\n",
"def sales_less_than_demand(m, s):\n",
" return m.y[s] <= scenarios[s][\"demand\"]\n",
" return m\n",
"\n",
"\n",
"m = PopUpShop_PI(r, c, w, scenarios)\n",
"results = SOLVER.solve(m)\n",
"\n",
"# display solution using Pandas\n",
"print(\"Solver Termination Condition:\", results.solver.termination_condition)\n",
"print(\"Expected Profit:\", m.EV())\n",
"print()\n",
"print(f\"Solver termination condition: {results.solver.termination_condition}\")\n",
"print(f\"Expected profit: {m.EV()}\")\n",
"for s in m.S:\n",
" scenarios[s][\"order\"] = m.x[s]()\n",
" scenarios[s][\"sold\"] = m.y[s]()\n",
Expand Down Expand Up @@ -757,7 +721,7 @@
"$$\n",
"\n",
"\n",
"As one might expect, there is a cost that results from lack of knowledge about an uncertain future."
"As one might have expected, there is a cost that results from lack of knowledge about an uncertain future."
]
}
],
Expand All @@ -777,7 +741,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
"version": "3.10.10"
}
},
"nbformat": 4,
Expand Down
Loading

0 comments on commit fe36f98

Please sign in to comment.