Skip to content

Commit 6024984

Browse files
authored
Merge pull request #5 from RXGottlieb/master
Updated examples to EAGO v0.7.1
2 parents 780bdac + a2472c4 commit 6024984

9 files changed

+1682
-710
lines changed

Manifest.toml

Lines changed: 1261 additions & 0 deletions
Large diffs are not rendered by default.

Project.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[deps]
2+
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
3+
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
4+
EAGO = "bb8be931-2a91-5aca-9f87-79e1cb69959a"
5+
Gurobi = "2e9cd046-0924-5485-92f1-d5272153d98b"
6+
IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253"
7+
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
8+
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
9+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
10+
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
11+
12+
[compat]
13+
CSV = "0.10.4"
14+
DataFrames = "1.3.4"
15+
EAGO = "0.7.1"
16+
Gurobi = "0.11.3"
17+
IntervalArithmetic = "0.20.6"
18+
JuMP = "1.1.1"
19+
MathOptInterface = "1.5.0"

notebooks/custom_quasiconvex.ipynb

Lines changed: 97 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@
77
"# Customizing EAGO to Solve a Quasiconvex Problem \n",
88
"\n",
99
"[Matthew Wilhelm](https://psor.uconn.edu/person/matthew-wilhelm/) \n",
10+
"Department of Chemical and Biomolecular Engineering, University of Connecticut\n",
11+
"\n",
12+
"[Robert Gottlieb](https://psor.uconn.edu/person/robert-gottlieb/) \n",
1013
"Department of Chemical and Biomolecular Engineering, University of Connecticut"
1114
]
1215
},
1316
{
1417
"cell_type": "markdown",
1518
"metadata": {},
1619
"source": [
17-
"In the following example, we illustrate how EAGO's basic branch and bound routine can be adapted for use in other algorithms.\n",
20+
"In the following example, we illustrate how EAGO's basic branch-and-bound routine can be adapted for use in other algorithms.\n",
1821
"\n",
1922
"## An Algorithm for Solving Quasiconvex Problems\n",
2023
"\n",
21-
"We'll adapt EAGO to implement the bisection based algorithm used to solve quasiconvex optimization problem presented in [1] to solve the below problem:\n",
24+
"We'll adapt EAGO to implement the bisection-based algorithm used to solve the quasiconvex optimization problem presented in [1]:\n",
2225
"\n",
2326
"$\n",
2427
"\\begin{align}\n",
@@ -50,35 +53,35 @@
5053
"\\end{align}\n",
5154
"$\n",
5255
"\n",
53-
"Let $\\phi_\\tau(\\mathbf y) = f(\\mathbf y) - \\tau$ such that $\\tau = (t^L + t^U)/2$. We solve for $\\mathbf y$ subject to constraints (24)-(27) were $\\phi_\\tau(\\mathbf y) \\leq 0$. If this is feasible, $t^* \\in [t^L, \\tau]$, else $t^* \\in [\\tau, t^U]$. The other interval containg $t^*$ is kept and the other is fathomed. This manner of bisection is repeated until an interval containing a feasible solution with a width of at most $\\epsilon$ is located [2]."
56+
"Let $\\phi_\\tau(\\mathbf y) = f(\\mathbf y) - \\tau$ such that $\\tau = (t^L + t^U)/2$. We solve for $\\mathbf y$ subject to constraints (24)-(27) where $\\phi_\\tau(\\mathbf y) \\leq 0$. If this is feasible, $t^* \\in [t^L, \\tau]$, else $t^* \\in [\\tau, t^U]$. The interval containg $t^*$ is kept and the other is fathomed. This manner of bisection is repeated until an interval containing a feasible solution with a width of at most $\\epsilon$ is located [2]."
5457
]
5558
},
5659
{
5760
"cell_type": "markdown",
5861
"metadata": {},
5962
"source": [
6063
"## Customizing EAGO's script\n",
61-
"First, the preprocessing step, upper problem, and postprocessing routines are short circuited as only a single optimization problem need be solved at each iteration."
64+
"First, the preprocessing step, upper problem, and postprocessing routines are short-circuited as only a single optimization problem needs to be solved at each iteration."
6265
]
6366
},
6467
{
6568
"cell_type": "code",
66-
"execution_count": 6,
69+
"execution_count": 1,
6770
"metadata": {},
6871
"outputs": [],
6972
"source": [
7073
"using MathOptInterface, EAGO, JuMP\n",
71-
"import EAGO: Optimizer\n",
74+
"import EAGO: Optimizer, GlobalOptimizer\n",
7275
"\n",
7376
"struct QuasiConvex <: EAGO.ExtensionType end\n",
7477
"import EAGO: preprocess!, upper_problem!, postprocess!\n",
75-
"function EAGO.preprocess!(t::QuasiConvex, x::Optimizer)\n",
78+
"function EAGO.preprocess!(t::QuasiConvex, x::GlobalOptimizer)\n",
7679
" x._preprocess_feasibility = true\n",
7780
" end\n",
78-
"function EAGO.upper_problem!(t::QuasiConvex, x::Optimizer)\n",
81+
"function EAGO.upper_problem!(t::QuasiConvex, x::GlobalOptimizer)\n",
7982
" x._upper_feasibility = true\n",
8083
" end\n",
81-
"function EAGO.postprocess!(t::QuasiConvex, x::Optimizer)\n",
84+
"function EAGO.postprocess!(t::QuasiConvex, x::GlobalOptimizer)\n",
8285
" x._postprocess_feasibility = true\n",
8386
"end"
8487
]
@@ -87,23 +90,24 @@
8790
"cell_type": "markdown",
8891
"metadata": {},
8992
"source": [
90-
"Next we specify that only an absolute tolerance should be checked for convergence and termination."
93+
"Next, we specify that only an absolute tolerance should be checked for convergence and termination."
9194
]
9295
},
9396
{
9497
"cell_type": "code",
95-
"execution_count": 7,
98+
"execution_count": 2,
9699
"metadata": {},
97100
"outputs": [],
98101
"source": [
99-
"import EAGO: convergence_check, termination_check, repeat_check\n",
100-
"function EAGO.convergence_check(t::QuasiConvex, x::Optimizer)\n",
102+
"import EAGO: convergence_check, termination_check\n",
103+
"function EAGO.convergence_check(t::QuasiConvex, x::GlobalOptimizer)\n",
101104
" gap = (x._upper_objective_value - x._lower_objective_value)\n",
102105
" return (gap <= x._parameters.absolute_tolerance)\n",
103106
"end\n",
104-
"function EAGO.termination_check(t::QuasiConvex, x::Optimizer)\n",
107+
"function EAGO.termination_check(t::QuasiConvex, x::GlobalOptimizer)\n",
105108
" flag = EAGO.convergence_check(t, x)\n",
106109
" if flag\n",
110+
" x._end_state = EAGO.GS_OPTIMAL\n",
107111
" x._termination_status_code = MathOptInterface.OPTIMAL\n",
108112
" x._result_status_code = MathOptInterface.FEASIBLE_POINT\n",
109113
" end\n",
@@ -115,47 +119,48 @@
115119
"cell_type": "markdown",
116120
"metadata": {},
117121
"source": [
118-
"Only these sixth variable representing $t$ need be branched on."
122+
"We then indicate that only the sixth variable, representing $t$, should be branched on. Since we will apply our knowledge about which $t^*$ should be kept in the lower problem definition, we also short-circuit EAGO's repeat_check function here to tell EAGO not to branch this node, but instead to repeatedly evaluate it."
119123
]
120124
},
121125
{
122126
"cell_type": "code",
123-
"execution_count": 8,
127+
"execution_count": 3,
124128
"metadata": {},
125129
"outputs": [],
126130
"source": [
131+
"import EAGO: repeat_check\n",
127132
"branch_variable = [i == 6 for i=1:6]\n",
128-
"EAGO.repeat_check(t::QuasiConvex, x::Optimizer) = true"
133+
"EAGO.repeat_check(t::QuasiConvex, x::GlobalOptimizer) = true"
129134
]
130135
},
131136
{
132137
"cell_type": "markdown",
133138
"metadata": {},
134139
"source": [
135-
"In the lower problem, we then specify that the problem is solved locally for a fixed $t$ value. The objective value is \n",
136-
"updated and the problem is contracted in order to discard the region which is known not to contain the optimal value."
140+
"In the lower problem, we then specify that the problem is to be solved locally for a fixed $t$ value. The objective value is then updated and the problem is contracted in order to discard the region which is known to not contain the optimal value."
137141
]
138142
},
139143
{
140144
"cell_type": "code",
141-
"execution_count": 9,
145+
"execution_count": 4,
142146
"metadata": {},
143147
"outputs": [],
144148
"source": [
145149
"import EAGO: lower_problem!\n",
146-
"function EAGO.lower_problem!(t::QuasiConvex, x::Optimizer)\n",
150+
"function EAGO.lower_problem!(t::QuasiConvex, x::GlobalOptimizer)\n",
147151
" y = x._current_node\n",
148-
" lower = y.lower_variable_bounds[6]\n",
149-
" upper = y.upper_variable_bounds[6]\n",
152+
" indx = x._sol_to_branch_map[6]\n",
153+
" lower = y.lower_variable_bounds[indx]\n",
154+
" upper = y.upper_variable_bounds[indx]\n",
150155
" midy = (lower + upper)/2.0\n",
151-
" y.lower_variable_bounds[6] = midy\n",
152-
" y.upper_variable_bounds[6] = midy\n",
156+
" y.lower_variable_bounds[indx] = midy\n",
157+
" y.upper_variable_bounds[indx] = midy\n",
153158
" EAGO.solve_local_nlp!(x)\n",
154159
" feas = x._upper_feasibility\n",
155-
" y.lower_variable_bounds[6] = feas ? lower : midy\n",
156-
" y.upper_variable_bounds[6] = feas ? midy : upper\n",
157-
" x._lower_objective_value = y.lower_variable_bounds[6]\n",
158-
" x._upper_objective_value = y.upper_variable_bounds[6]\n",
160+
" y.lower_variable_bounds[indx] = feas ? lower : midy\n",
161+
" y.upper_variable_bounds[indx] = feas ? midy : upper\n",
162+
" x._lower_objective_value = y.lower_variable_bounds[indx]\n",
163+
" x._upper_objective_value = y.upper_variable_bounds[indx]\n",
159164
" x._lower_feasibility = true\n",
160165
" return\n",
161166
"end"
@@ -165,45 +170,77 @@
165170
"cell_type": "markdown",
166171
"metadata": {},
167172
"source": [
168-
"We now build the JuMP model representing this problem, solve it and then retrieve the solution."
173+
"We now define the optimizer factory to extend the core EAGO optimizer for this special problem. The SubSolvers() constructor is used to set the extension type (t), as well as the relaxed optimizer (r) and upper-bounding optimizer (u), if necessary. In this case, we will use the default solvers and only set the extension type."
169174
]
170175
},
171176
{
172177
"cell_type": "code",
173-
"execution_count": 10,
178+
"execution_count": 5,
174179
"metadata": {},
175180
"outputs": [
176-
{
177-
"name": "stdout",
178-
"output_type": "stream",
179-
"text": [
180-
"-------------------------------------------------------------------------------------------------------\n",
181-
"| Iteration # | Nodes | Lower Bound | Upper Bound | Gap | Ratio | Time | Time Left |\n",
182-
"-------------------------------------------------------------------------------------------------------\n",
183-
"First Solution Found at Node 1\n",
184-
"UBD = -1.71690346673131\n",
185-
"Solution is :\n",
186-
" X[1] = 0.6521533635051513\n",
187-
" X[2] = 0.6687269925064182\n",
188-
" X[3] = 0.1827815731700123\n",
189-
" X[4] = 0.24121532455559402\n",
190-
" X[5] = 0.2994373267499198\n",
191-
" X[6] = -1.71690346673131\n"
192-
]
193-
},
194181
{
195182
"data": {
196183
"text/plain": [
197-
"-1.71690346673131"
184+
"#3 (generic function with 1 method)"
198185
]
199186
},
200-
"execution_count": 10,
187+
"execution_count": 5,
201188
"metadata": {},
202189
"output_type": "execute_result"
203190
}
204191
],
205192
"source": [
206-
"opt = with_optimizer(Optimizer, absolute_tolerance = 1E-8, branch_variable = branch_variable, ext_type = QuasiConvex())\n",
193+
"factory = () -> Optimizer(SubSolvers(; t = QuasiConvex()))"
194+
]
195+
},
196+
{
197+
"cell_type": "markdown",
198+
"metadata": {},
199+
"source": [
200+
"We now build the JuMP model representing this problem, solve it, and retrieve the solution."
201+
]
202+
},
203+
{
204+
"cell_type": "code",
205+
"execution_count": 6,
206+
"metadata": {},
207+
"outputs": [
208+
{
209+
"name": "stdout",
210+
"output_type": "stream",
211+
"text": [
212+
"\n",
213+
"******************************************************************************\n",
214+
"This program contains Ipopt, a library for large-scale nonlinear optimization.\n",
215+
" Ipopt is released as open source code under the Eclipse Public License (EPL).\n",
216+
" For more information visit https://github.com/coin-or/Ipopt\n",
217+
"******************************************************************************\n",
218+
"\n",
219+
"-----------------------------------------------------------------------------------------------------------------------------\n",
220+
"| Iteration # | Nodes | Lower Bound | Upper Bound | Gap | Ratio | Time | Time Left |\n",
221+
"-----------------------------------------------------------------------------------------------------------------------------\n",
222+
" \n",
223+
"Empty Stack: Exhaustive Search Finished\n",
224+
"First Solution Found at Node 1\n",
225+
"LBD = -1.7169029079377651\n",
226+
"UBD = -1.7169028893113136\n",
227+
"Solution is :\n",
228+
" X[1] = 0.65234819549671\n",
229+
" X[2] = 0.6685518965185859\n",
230+
" X[3] = 0.18303164806114738\n",
231+
" X[4] = 0.24118652470572963\n",
232+
" X[5] = 0.29934139369195156\n",
233+
" X[6] = -1.7169028893113136\n",
234+
" \n",
235+
"Global solution at y*=[0.65234819549671, 0.6685518965185859, 0.18303164806114738, 0.24118652470572963, 0.29934139369195156] with a value of f*=-1.7169028893113136"
236+
]
237+
}
238+
],
239+
"source": [
240+
"opt = optimizer_with_attributes(factory, \n",
241+
" \"absolute_tolerance\" => 1E-8, \n",
242+
" \"branch_variable\" => branch_variable,\n",
243+
" \"iteration_limit\" => 1000)\n",
207244
"m = Model(opt)\n",
208245
"@variable(m, ((i<6) ? 0 : -5) <= y[i=1:6] <= ((i<6) ? 5 : 0))\n",
209246
"@constraint(m, sum(i*y[i] for i=1:5) - 5 == 0)\n",
@@ -215,26 +252,20 @@
215252
"@NLconstraint(m, -expr2/(1 + sum(y[i]^2 for i=1:5)) - y[6] <= 0)\n",
216253
"@objective(m, Min, y[6])\n",
217254
"\n",
218-
"JuMP.optimize!(m)# retrieve solution info\n",
255+
"JuMP.optimize!(m) # Retrieve solution info\n",
219256
"solution = JuMP.value.(y[1:5])\n",
220-
"global_obj_value = JuMP.value.(y[6])"
257+
"global_obj_value = JuMP.value.(y[6])\n",
258+
"print(\"Global solution at y*=$solution with a value of f*=$global_obj_value\")"
221259
]
222260
},
223261
{
224262
"cell_type": "markdown",
225263
"metadata": {},
226264
"source": [
227265
"### Reference:\n",
228-
"1. C. Jansson,Quasiconvex relaxations based on interval arithmetic, Linear Algebra andits Applications, 324 (2001), pp. 27–53.\n",
229-
"2. S. Boyd and L. Vandenberghe,Convex optimization, Cambridge university press,2004."
266+
"1. C. Jansson, Quasiconvex relaxations based on interval arithmetic, Linear Algebra and its Applications, 324 (2001), pp. 27–53.\n",
267+
"2. S. Boyd and L. Vandenberghe, Convex optimization, Cambridge University Press, 2004."
230268
]
231-
},
232-
{
233-
"cell_type": "code",
234-
"execution_count": null,
235-
"metadata": {},
236-
"outputs": [],
237-
"source": []
238269
}
239270
],
240271
"metadata": {
@@ -243,15 +274,15 @@
243274
"lastKernelId": null
244275
},
245276
"kernelspec": {
246-
"display_name": "Julia 1.3.1",
277+
"display_name": "Julia 1.7.3",
247278
"language": "julia",
248-
"name": "julia-1.3"
279+
"name": "julia-1.7"
249280
},
250281
"language_info": {
251282
"file_extension": ".jl",
252283
"mimetype": "application/julia",
253284
"name": "julia",
254-
"version": "1.3.1"
285+
"version": "1.7.3"
255286
}
256287
},
257288
"nbformat": 4,

0 commit comments

Comments
 (0)