{ "cells": [ { "cell_type": "markdown", "id": "7c1856dd", "metadata": {}, "source": [ "\n", "*This notebook contains material from [CBE60499](https://ndcbe.github.io/CBE60499);\n", "content is available [on Github](git@github.com:ndcbe/CBE60499.git).*\n" ] }, { "cell_type": "markdown", "id": "373fb0a8", "metadata": {}, "source": [ "\n", "< [4.0 Constrained Nonlinear Optimization: Theory and Applications](https://ndcbe.github.io/CBE60499/04.00-Constrained.html) | [Contents](toc.html) | [Tag Index](tag_index.html) | [4.2 Local Optimality Conditions](https://ndcbe.github.io/CBE60499/04.02-Local-Optimality.html) >
"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 1,
"link": "[4.1 Convexity Revisited](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1-Convexity-Revisited)",
"section": "4.1 Convexity Revisited"
}
},
"source": [
"# 4.1 Convexity Revisited"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"nbpages": {
"level": 1,
"link": "[4.1 Convexity Revisited](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1-Convexity-Revisited)",
"section": "4.1 Convexity Revisited"
}
},
"outputs": [],
"source": [
"# This code cell installs packages on Colab\n",
"\n",
"import sys\n",
"if \"google.colab\" in sys.modules:\n",
" !wget \"https://raw.githubusercontent.com/ndcbe/CBE60499/main/notebooks/helper.py\"\n",
" import helper\n",
" helper.install_idaes()\n",
" helper.install_ipopt()\n",
" helper.install_glpk()\n",
" helper.download_figures(['pack1.png','pack2.png','pack3.png'])"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"nbpages": {
"level": 1,
"link": "[4.1 Convexity Revisited](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1-Convexity-Revisited)",
"section": "4.1 Convexity Revisited"
}
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import pyomo.environ as pyo"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.1 Background](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1-Background)",
"section": "4.1.1 Background"
}
},
"source": [
"## 4.1.1 Background"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.1 Background](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1-Background)",
"section": "4.1.1 Background"
}
},
"source": [
"**Reference**: Beginning of Chapter 4 in Biegler (2010)"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.1.1 Canonical Nonlinear Program](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1.1-Canonical-Nonlinear-Program)",
"section": "4.1.1.1 Canonical Nonlinear Program"
}
},
"source": [
"### 4.1.1.1 Canonical Nonlinear Program"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.1.1 Canonical Nonlinear Program](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1.1-Canonical-Nonlinear-Program)",
"section": "4.1.1.1 Canonical Nonlinear Program"
}
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.1.2 Types of Constrained Optimal Solutions](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1.2-Types-of-Constrained-Optimal-Solutions)",
"section": "4.1.1.2 Types of Constrained Optimal Solutions"
}
},
"source": [
"### 4.1.1.2 Types of Constrained Optimal Solutions"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.1.2 Types of Constrained Optimal Solutions](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1.2-Types-of-Constrained-Optimal-Solutions)",
"section": "4.1.1.2 Types of Constrained Optimal Solutions"
}
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.1.2 Types of Constrained Optimal Solutions](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1.2-Types-of-Constrained-Optimal-Solutions)",
"section": "4.1.1.2 Types of Constrained Optimal Solutions"
}
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.1.3 Key Questions](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1.3-Key-Questions)",
"section": "4.1.1.3 Key Questions"
}
},
"source": [
"### 4.1.1.3 Key Questions"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.1.3 Key Questions](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.1.3-Key-Questions)",
"section": "4.1.1.3 Key Questions"
}
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.2 Convexity for Constrained Optimization](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.2-Convexity-for-Constrained-Optimization)",
"section": "4.1.2 Convexity for Constrained Optimization"
}
},
"source": [
"## 4.1.2 Convexity for Constrained Optimization"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.2 Convexity for Constrained Optimization](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.2-Convexity-for-Constrained-Optimization)",
"section": "4.1.2 Convexity for Constrained Optimization"
}
},
"source": [
"**Reference**: Section 4.1 in Biegler (2010)"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.2 Convexity for Constrained Optimization](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.2-Convexity-for-Constrained-Optimization)",
"section": "4.1.2 Convexity for Constrained Optimization"
}
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.2 Convexity for Constrained Optimization](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.2-Convexity-for-Constrained-Optimization)",
"section": "4.1.2 Convexity for Constrained Optimization"
}
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.3 Circle Packing Example](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3-Circle-Packing-Example)",
"section": "4.1.3 Circle Packing Example"
}
},
"source": [
"## 4.1.3 Circle Packing Example"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.3 Circle Packing Example](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3-Circle-Packing-Example)",
"section": "4.1.3 Circle Packing Example"
}
},
"source": [
"**Reference**: Section 4.1 in Biegler (2010)"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.3 Circle Packing Example](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3-Circle-Packing-Example)",
"section": "4.1.3 Circle Packing Example"
}
},
"source": [
"**Motivating Question**: Is this problem convex?"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.1.3 Circle Packing Example](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3-Circle-Packing-Example)",
"section": "4.1.3 Circle Packing Example"
}
},
"source": [
"What is the smallest rectangle you can use to enclose three given circles? Reference: Example 4.4 in Biegler (2010).\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"source": [
"### 4.1.3.1 Optimization Model and Pyomo Implementation\n",
"\n",
"The following optimization model is given in Biegler (2010):"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"source": [
"\n",
""
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"outputs": [],
"source": [
"import random\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib.patches as mpatches\n",
"\n",
"def create_circle_model(circle_radii):\n",
" ''' Create circle optimization model in Pyomo\n",
" \n",
" Arguments:\n",
" circle_radii: dictionary with keys=circle name and value=radius (float)\n",
" \n",
" Returns:\n",
" model: Pyomo model\n",
" '''\n",
"\n",
" # Number of circles to consider\n",
" n = len(circle_radii)\n",
"\n",
" # Create a concrete Pyomo model.\n",
" model = pyo.ConcreteModel()\n",
"\n",
" # Initialize index for circles\n",
" model.CIRCLES = pyo.Set(initialize = circle_radii.keys())\n",
" \n",
" # Create parameter\n",
" model.R = pyo.Param(model.CIRCLES, domain=pyo.PositiveReals, initialize=circle_radii)\n",
"\n",
" # Create variables for box\n",
" model.a = pyo.Var(domain=pyo.PositiveReals)\n",
" model.b = pyo.Var(domain=pyo.PositiveReals)\n",
"\n",
" # Set objective\n",
" model.obj = pyo.Objective(expr=2*(model.a + model.b), sense = pyo.minimize)\n",
"\n",
" # Create variables for circle centers\n",
" model.x = pyo.Var(model.CIRCLES, domain=pyo.PositiveReals)\n",
" model.y = pyo.Var(model.CIRCLES, domain=pyo.PositiveReals)\n",
"\n",
" # \"In the box\" constraints\n",
" def left_x(m,c):\n",
" return m.x[c] >= model.R[c]\n",
" model.left_x_con = pyo.Constraint(model.CIRCLES, rule=left_x)\n",
"\n",
" def left_y(m,c):\n",
" return m.y[c] >= model.R[c]\n",
" model.left_y_con = pyo.Constraint(model.CIRCLES, rule=left_y)\n",
"\n",
" def right_x(m,c):\n",
" return m.x[c] <= m.b - model.R[c]\n",
" model.right_x_con = pyo.Constraint(model.CIRCLES, rule=right_x)\n",
"\n",
" def right_y(m,c):\n",
" return m.y[c] <= m.a - model.R[c]\n",
" model.right_y_con = pyo.Constraint(model.CIRCLES, rule=right_y)\n",
"\n",
" # No overlap constraints\n",
" def no_overlap(m,c1,c2):\n",
" if c1 < c2:\n",
" return (m.x[c1] - m.x[c2])**2 + (m.y[c1] - m.y[c2])**2 >= (model.R[c1] + model.R[c2])**2\n",
" else:\n",
" return pyo.Constraint.Skip\n",
" model.no_overlap_con = pyo.Constraint(model.CIRCLES, model.CIRCLES, rule=no_overlap)\n",
" \n",
" return model\n",
"\n",
"def initialize_circle_model(model, a_init=25, b_init=25):\n",
" ''' Initialize the x and y coordinates using uniform distribution\n",
" \n",
" Arguments:\n",
" a_init: initial value for a (default=25)\n",
" b_init: initial value for b (default=25)\n",
" \n",
" Returns:\n",
" Nothing. But per Pyomo scoping rules, the input argument `model`\n",
" can be modified in this function.\n",
" \n",
" '''\n",
" # Initialize \n",
" model.a = 25\n",
" model.b = 25\n",
"\n",
" for i in model.CIRCLES:\n",
" # Adding circle radii ensures the remains in the >0, >0 quadrant\n",
" model.x[i] = random.uniform(0,10) + model.R[i]\n",
" model.y[i] = random.uniform(0,10) + model.R[i]\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"source": [
"Next, we will create a dictionary containing the circle names and radii values."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'A': 10.0, 'B': 5.0, 'C': 3.0}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create dictionary with circle data\n",
"circle_data = {'A':10.0, 'B':5.0, 'C':3.0}\n",
"circle_data"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"outputs": [
{
"data": {
"text/plain": [
"dict_keys(['A', 'B', 'C'])"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Access the keys\n",
"circle_data.keys()"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"source": [
"Now let's create the model."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"outputs": [],
"source": [
"# Create model\n",
"model = create_circle_model(circle_data)"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"source": [
"And let's initialize the model."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.1 Optimization Model and Pyomo Implementation](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.1-Optimization-Model-and-Pyomo-Implementation)",
"section": "4.1.3.1 Optimization Model and Pyomo Implementation"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2 Set Declarations\n",
" CIRCLES : Size=1, Index=None, Ordered=Insertion\n",
" Key : Dimen : Domain : Size : Members\n",
" None : 1 : Any : 3 : {'A', 'B', 'C'}\n",
" no_overlap_con_index : Size=1, Index=None, Ordered=True\n",
" Key : Dimen : Domain : Size : Members\n",
" None : 2 : CIRCLES*CIRCLES : 9 : {('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')}\n",
"\n",
"1 Param Declarations\n",
" R : Size=3, Index=CIRCLES, Domain=PositiveReals, Default=None, Mutable=False\n",
" Key : Value\n",
" A : 10.0\n",
" B : 5.0\n",
" C : 3.0\n",
"\n",
"4 Var Declarations\n",
" a : Size=1, Index=None\n",
" Key : Lower : Value : Upper : Fixed : Stale : Domain\n",
" None : 0 : 25 : None : False : False : PositiveReals\n",
" b : Size=1, Index=None\n",
" Key : Lower : Value : Upper : Fixed : Stale : Domain\n",
" None : 0 : 25 : None : False : False : PositiveReals\n",
" x : Size=3, Index=CIRCLES\n",
" Key : Lower : Value : Upper : Fixed : Stale : Domain\n",
" A : 0 : 12.841552708011381 : None : False : False : PositiveReals\n",
" B : 0 : 5.317917334950976 : None : False : False : PositiveReals\n",
" C : 0 : 7.92668839728193 : None : False : False : PositiveReals\n",
" y : Size=3, Index=CIRCLES\n",
" Key : Lower : Value : Upper : Fixed : Stale : Domain\n",
" A : 0 : 15.93994957385218 : None : False : False : PositiveReals\n",
" B : 0 : 5.402476587728794 : None : False : False : PositiveReals\n",
" C : 0 : 7.556772365151705 : None : False : False : PositiveReals\n",
"\n",
"1 Objective Declarations\n",
" obj : Size=1, Index=None, Active=True\n",
" Key : Active : Sense : Expression\n",
" None : True : minimize : 2*(a + b)\n",
"\n",
"5 Constraint Declarations\n",
" left_x_con : Size=3, Index=CIRCLES, Active=True\n",
" Key : Lower : Body : Upper : Active\n",
" A : 10.0 : x[A] : +Inf : True\n",
" B : 5.0 : x[B] : +Inf : True\n",
" C : 3.0 : x[C] : +Inf : True\n",
" left_y_con : Size=3, Index=CIRCLES, Active=True\n",
" Key : Lower : Body : Upper : Active\n",
" A : 10.0 : y[A] : +Inf : True\n",
" B : 5.0 : y[B] : +Inf : True\n",
" C : 3.0 : y[C] : +Inf : True\n",
" no_overlap_con : Size=3, Index=no_overlap_con_index, Active=True\n",
" Key : Lower : Body : Upper : Active\n",
" ('A', 'B') : 225.0 : (x[A] - x[B])**2 + (y[A] - y[B])**2 : +Inf : True\n",
" ('A', 'C') : 169.0 : (x[A] - x[C])**2 + (y[A] - y[C])**2 : +Inf : True\n",
" ('B', 'C') : 64.0 : (x[B] - x[C])**2 + (y[B] - y[C])**2 : +Inf : True\n",
" right_x_con : Size=3, Index=CIRCLES, Active=True\n",
" Key : Lower : Body : Upper : Active\n",
" A : -Inf : x[A] - (b - 10.0) : 0.0 : True\n",
" B : -Inf : x[B] - (b - 5.0) : 0.0 : True\n",
" C : -Inf : x[C] - (b - 3.0) : 0.0 : True\n",
" right_y_con : Size=3, Index=CIRCLES, Active=True\n",
" Key : Lower : Body : Upper : Active\n",
" A : -Inf : y[A] - (a - 10.0) : 0.0 : True\n",
" B : -Inf : y[B] - (a - 5.0) : 0.0 : True\n",
" C : -Inf : y[C] - (a - 3.0) : 0.0 : True\n",
"\n",
"13 Declarations: CIRCLES R a b obj x y left_x_con left_y_con right_x_con right_y_con no_overlap_con_index no_overlap_con\n"
]
}
],
"source": [
"# Initialize model\n",
"initialize_circle_model(model)\n",
"model.pprint()"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.2 Visualize Initial Point](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.2-Visualize-Initial-Point)",
"section": "4.1.3.2 Visualize Initial Point"
}
},
"source": [
"### 4.1.3.2 Visualize Initial Point"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.2 Visualize Initial Point](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.2-Visualize-Initial-Point)",
"section": "4.1.3.2 Visualize Initial Point"
}
},
"source": [
"Next, we'll define a function to plot the solution (or initial point)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"nbpages": {
"level": 3,
"link": "[4.1.3.2 Visualize Initial Point](https://ndcbe.github.io/CBE60499/04.01-Convexity.html#4.1.3.2-Visualize-Initial-Point)",
"section": "4.1.3.2 Visualize Initial Point"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"
"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}