Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
Nonlinear constrained optimization chapter added (#6)
Browse files Browse the repository at this point in the history
* Create Nonlinear_constrained_optimization.md

* added chapter

* Update Nonlinear_constrained_optimization.md

* Update Nonlinear_constrained_optimization.md

* Added bounds properly

* Added question

* Added page

* renamed file

* Update nonlinear_constrained_optimization_example.ipynb

* Update nonlinear_constrained_optimization_example.ipynb

* update

* Update nonlinear_constrained_optimization_example.ipynb

* Update nonlinear_constrained_optimization_example.ipynb

* Test with html directly on page

* add iframe

* Update nonlinear_constrained_optimization_example.ipynb

* added units

* Finalized chapter

* Update block.html
  • Loading branch information
Tom-van-Woudenberg authored Apr 25, 2024
1 parent 0cd0e7f commit c507941
Show file tree
Hide file tree
Showing 7 changed files with 1,102 additions and 0 deletions.
126 changes: 126 additions & 0 deletions book/_static/block.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!DOCTYPE html>
<html>
<head>
<title>Find the optimum solution yourself!</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/numeric/1.2.6/numeric.min.js"></script>
<style>
.slider {
display: block;
margin-bottom: 10px;
width: 100%;
}
.slider-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
width: 100%;
}
.output {
margin-top: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}
.output p {
margin: 5px 0;
}
.output .emoji {
font-size: 20px;
margin-right: 5px;
}
</style>
</head>
<body>
<div id="sliderContainer" class="slider-container"></div>
<div id="outputContainer" class="output"></div>

<script>
function func(x) {
var vol = x[0] * x[1] * x[2];
return vol;
}

function nonlinconfun(x) {
var c1 = 0.8 - x[0] * x[1];
var c2 = 0.8 - x[0] * x[2];
var c3 = 0.8 - x[1] * x[2];
var c4 = 3000 - 2500 * x[0] * x[1] * x[2];
return [c1, c2, c3, c4];
}

function eval() {
var x_1 = parseFloat(document.getElementById("x_1").value);
var x_2 = parseFloat(document.getElementById("x_2").value);
var x_3 = parseFloat(document.getElementById("x_3").value);
var x = [x_1, x_2, x_3];

var output = document.getElementById("outputContainer");
output.innerHTML = "";

var vol = func(x);
output.innerHTML += "<p><strong><span style='font-size: 24px;'>Objective function: " + vol.toFixed(3) + " m<sup>3</sup></span></strong></p>";

var constraints = nonlinconfun(x);
for (var i = 0; i < constraints.length; i++) {
if (i === 3) {
if (constraints[i] < 0) {
output.innerHTML += "<p><span class='emoji'>👍</span> Constraint function " + (i + 1) + ": " + constraints[i].toFixed(0) + " kg</p>";
} else {
output.innerHTML += "<p><span class='emoji'>👎</span> Constraint function " + (i + 1) + ": " + constraints[i].toFixed(0) + " kg</p>";
}
} else {
if (constraints[i] < 0) {
output.innerHTML += "<p><span class='emoji'>👍</span> Constraint function " + (i + 1) + ": " + constraints[i].toFixed(2) + " m<sup>2</sup></p>";
} else {
output.innerHTML += "<p><span class='emoji'>👎</span> Constraint function " + (i + 1) + ": " + constraints[i].toFixed(2) + " m<sup>2</sup></p>";
}
}
}
}
var sliderContainer = document.getElementById("sliderContainer");
var sliders = [
{ id: "x_1", min: 0, max: 5, value: 2, step: 0.01, description: "x<sub>1</sub>" },
{ id: "x_2", min: 0, max: 5, value: 2, step: 0.01, description: "x<sub>2</sub>" },
{ id: "x_3", min: 0, max: 5, value: 2, step: 0.01, description: "x<sub>3</sub>" }
];

sliders.forEach(function(slider) {
var input = document.createElement("input");
input.type = "range";
input.min = slider.min;
input.max = slider.max;
input.value = slider.value;
input.step = slider.step;
input.id = slider.id;
input.oninput = function() {
document.getElementById(slider.id + "_value").textContent = this.value + " m";
eval();
};
input.classList.add("slider");

var label = document.createElement("label");
label.innerHTML = slider.description;
label.setAttribute("for", slider.id);
label.style.textAlign = "right";

var valueDisplay = document.createElement("span"); // Create a span element for value display
valueDisplay.id = slider.id + "_value"; // Set the id for value display
valueDisplay.textContent = slider.value + " m"; // Set the initial value

sliderContainer.appendChild(label);
sliderContainer.appendChild(input);
sliderContainer.appendChild(valueDisplay); // Append the value display element
});

var outputContainer = document.getElementById("outputContainer");
var button = document.createElement("button");
button.innerHTML = "Evaluate";
button.onclick = eval;
outputContainer.appendChild(button);

// Call func with initial values
eval();
</script>
</body>
</html>
3 changes: 3 additions & 0 deletions book/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ parts:
- file: pages/linear_constrained_optimization
sections:
- file: pages/linear_constrained_optimization_example
- file: pages/Nonlinear_constrained_optimization
sections:
- file: pages/nonlinear_constrained_optimization_example
- file: more_will_follow
60 changes: 60 additions & 0 deletions book/pages/Nonlinear_constrained_optimization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Nonlinear constrained optimization

In this chapter, we'll cover how to apply `scipy.optimize.minimize` to nonlinear constrained optimization problems. As a reminder, nonlinear constrained optimization considers:

```{math}
:label: nonlinear_constrained_optimization
\eqalign{
& \mathop {\min }\limits_x f\left( x \right) \cr
& {\text{such that}} & {{g}_j}\left( x \right) \le 0 & j = 1,m \cr
& & {h_k}\left( x \right) = 0 & k = 1,p \cr
& & x_i^l \le {x_i} \le x_i^u & i = 1,n \cr}
```
with:
- $f\left(x\right)$, the linear or nonlinear objective function.
- $x$, the $n$ design variables
- $g_j\left(x\right)$, the $m$ linear or nonlinear inequality constraints
- $h_k\left(x\right)$, the $p$ linear or nonlinear inequality constraints
- $x_k^l$ and $x_k^u$, the $n$ low er and upper bounds of the design variable

## Method
For linear programs, we can use the function `scipy.optimize.minimize` again. The documentation of this function is available here:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html. In this course we'll cover only the relevant parts.

For unconstrained optimization we need to run at least `scipy.optimize.minimize(fun, x0, bounds, constraints, ...)` with:
- `fun`, the function representing the objective function $f\left(x\right)$ to be minimized. `fun` is a callable. The `scipy.optimize.minimize` function takes care of defining and inputting our design variable $x$.
- `x0`, the initial guess for our design variable $x$. It needs to be a `ndarray` with length $n$
- `Bounds`: A sequence of $i$ `(min, max)` pairs for each element in $x$, defining the minimum $x_i^l$ and maximum values $x_i^u$ of that decision variable. `None` is used to specify no bound.
- `constraints`, a single or a list of constraint objective either being:
- `scipy.optimize.LinearConstraint`
- `scipy.optimize.NonlinearConstraint`

:::{card} Test yourself
<iframe src="https://tudelft.h5p.com/content/1292254710251972777/embed" aria-label="Need for x0" width="1088" height="637" frameborder="0" allowfullscreen="allowfullscreen" allow="autoplay *; geolocation *; microphone *; camera *; midi *; encrypted-media *"></iframe><script src="https://tudelft.h5p.com/js/h5p-resizer.js" charset="UTF-8"></script>
:::

As you can see, the constraints are stored in an object `scipy.optimize.LinearConstraint` and/or `scipy.optimize.NonlinearConstraint`. These function have the following input, for `scipy.optimize.NonlinearConstraint(fun, lb, ub, ...)`:
- `fun`, the function representing the constraint function $g\left(x\right)$ or $h\left(x\right)$ to be minimized. Again, `fun` is a callable. The `scipy.optimize.minimize` function takes care of defining and inputting our design variable $x$.
- `lb` and `ub`, two arrays containing the lower- and upper bounds for each of the constraint functions $g\left(x\right)$. This lower bound can be `-np.inf` or `np.inf` to represent one-sides constraints. If the lower- and upper bound are set to the same value, an equality function is modelled.

For linear constraints, the constraint function is stored in a matrix again: `scipy.optimize.NonlinearConstraint(A, lb, ub, ...)`:
- `A`, a twodimensional numpy array with the $n$ coefficient of the $m$ linear inequality constraints matrix ${A_{ub}}$.
- `lb` and `ub` as for `scipy.optimize.NonlinearConstraint`

Please note that unlike with linear constraints optimization, the right-hand-side of the constraints are not stored in an upper bound vector, but defined with `lb` and `ub`.


:::{card} Test yourself
<iframe src="https://tudelft.h5p.com/content/1292253866845965907/embed" aria-label="Nonlinear constrained optimization method" width="1088" height="637" frameborder="0" allowfullscreen="allowfullscreen" allow="autoplay *; geolocation *; microphone *; camera *; midi *; encrypted-media *"></iframe><script src="https://tudelft.h5p.com/js/h5p-resizer.js" charset="UTF-8"></script>
:::

The function `scipy.optimize.linprog` outputs an object `scipy.optimize.OptimizeResult` similar as `scipy.optimize.minimize` explained for [unconstrained optimization](method_unconstrained).

## Questions, discussions and comments
<script src="https://utteranc.es/client.js"
repo="TeachBooks/engineering-systems-optimization"
issue-term="title"
theme="github-light"
crossorigin="anonymous"
async>
</script>
Binary file added book/pages/figures/blocks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions book/pages/linear_constrained_optimization_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"(linear_constraint_function_method)=\n",
"### Define constraint functions\n",
"\n",
"The constraint functions were defined in {eq}`linear_constrained_optimization_g_matrix` and {eq}`linear_constrained_optimization_g_eq_matrix`, which can be coded as follows:"
Expand Down
Loading

0 comments on commit c507941

Please sign in to comment.