Skip to content

Commit 0b308bf

Browse files
authored
[docs] add ellipsoid approximation tutorial (#3218)
1 parent 237fd6c commit 0b308bf

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

docs/make.jl

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ const _PAGES = [
163163
"tutorials/conic/max_cut_sdp.md",
164164
"tutorials/conic/min_distortion.md",
165165
"tutorials/conic/min_ellipse.md",
166+
"tutorials/conic/ellipse_approx.md",
166167
"tutorials/conic/robust_uncertainty.md",
167168
],
168169
"Algorithms" => [
+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Copyright 2017, Iain Dunning, Joey Huchette, Miles Lubin, and contributors #src
2+
# This Source Code Form is subject to the terms of the Mozilla Public License #src
3+
# v.2.0. If a copy of the MPL was not distributed with this file, You can #src
4+
# obtain one at https://mozilla.org/MPL/2.0/. #src
5+
6+
# # Ellipsoid approximation
7+
8+
# This example considers the problem of computing _extremal ellipsoids_:
9+
# finding ellipsoids that best approximate a given set.
10+
# Our example will focus on outer approximations of finite sets
11+
# of points.
12+
13+
# This example comes from section 4.9 "Applications VII: Extremal Ellipsoids"
14+
# of the book *Lectures on Modern Convex Optimization* by
15+
# [Ben-Tal and Nemirovski (2001)](http://epubs.siam.org/doi/book/10.1137/1.9780898718829).
16+
17+
# For a related example, see also the [Minimal ellipses](@ref) tutorial.
18+
19+
# ## Problem formulation
20+
21+
# Suppose that we are given a set ``S`` consisting of ``m`` points in ``n``-dimensional space:
22+
# ```math
23+
# \mathcal{S} = \{ x_1, \ldots, x_m \} \subset \mathbb{R}^n
24+
# ```
25+
# Our goal is to determine an optimal vector ``c \in \mathbb{R}^n`` and
26+
# an optimal ``n \times n`` real symmetric matrix ``D`` such that the ellipse
27+
# ```math
28+
# E(D, c) = \{ x : (x - c)^\top D ( x - c) \leq 1 \},
29+
# ```
30+
# contains ``\mathcal{S}`` and such that this ellipse has
31+
# the smallest possible volume.
32+
33+
# The optimal ``D`` and ``c`` are given by the convex semidefinite program
34+
# ```math
35+
# \begin{aligned}
36+
# \text{maximize } && \quad (\det(Z))^{\frac{1}{n}} & \\
37+
# \text{subject to } && \quad Z \; & \succeq \; 0 & \text{ (PSD) }, & \\
38+
# && \quad\begin{bmatrix}
39+
# s & z^\top \\
40+
# z & Z \\
41+
# \end{bmatrix}
42+
# \; & \succeq \; 0 & \text{ (PSD) }, & \\
43+
# && x_i^\top Z x_i - 2x_i^\top z + s \; & \leq \; 0 & i=1, \ldots, m &
44+
# \end{aligned}
45+
# ```
46+
# with matrix variable ``Z``, vector variable ``z`` and real variables ``t, s``.
47+
# The optimal solution ``(t_*, Z_*, z_*, s_*)`` gives the optimal ellipse data as
48+
# ```math
49+
# D = Z_*, \quad c = Z_*^{-1} z_*.
50+
# ```
51+
52+
# ## Required packages
53+
54+
# This tutorial uses the following packages:
55+
56+
using JuMP
57+
import LinearAlgebra
58+
import Random
59+
import Plots
60+
import SCS
61+
import Test #src
62+
63+
# ## Data
64+
65+
# We first need to generate some points to work with.
66+
67+
function generate_point_cloud(
68+
m; # number of 2-dimensional points
69+
a = 10, # scaling in x direction
70+
b = 2, # scaling in y direction
71+
rho = deg2rad(30), # rotation of points around origin
72+
random_seed = 1,
73+
)
74+
rng = Random.MersenneTwister(random_seed)
75+
P = randn(rng, Float64, m, 2)
76+
Phi = [a*cos(rho) a*sin(rho); -b*sin(rho) b*cos(rho)]
77+
S = P * Phi
78+
return S
79+
end
80+
81+
# For the sake of this example, let's take ``m = 600``:
82+
S = generate_point_cloud(600)
83+
84+
# We will visualise the points (and ellipse) using the Plots package:
85+
86+
function plot_point_cloud(plot, S; r = 1.1 * maximum(abs.(S)), colour = :green)
87+
Plots.scatter!(
88+
plot,
89+
S[:, 1],
90+
S[:, 2];
91+
xlim = (-r, r),
92+
ylim = (-r, r),
93+
label = nothing,
94+
c = colour,
95+
shape = :x,
96+
)
97+
return
98+
end
99+
100+
plot = Plots.plot(; size = (600, 600))
101+
plot_point_cloud(plot, S)
102+
plot
103+
104+
# ## JuMP formulation
105+
106+
# Now let's build the JuMP model. We'll be able to compute
107+
# ``D`` and ``c`` after the solve.
108+
109+
model = Model(SCS.Optimizer)
110+
## We need to use a tighter tolerance for this example, otherwise the bounding
111+
## ellipse won't actually be bounding...
112+
set_optimizer_attribute(model, "eps_rel", 1e-6)
113+
set_silent(model)
114+
m, n = size(S)
115+
@variable(model, z[1:n])
116+
@variable(model, Z[1:n, 1:n], PSD)
117+
@variable(model, t)
118+
@variable(model, s)
119+
120+
X = [
121+
s z'
122+
z Z
123+
]
124+
@constraint(model, LinearAlgebra.Symmetric(X) >= 0, PSDCone())
125+
126+
for i in 1:m
127+
x = S[i, :]
128+
@constraint(model, (x' * Z * x) - (2 * x' * z) + s <= 1)
129+
end
130+
131+
# We cannot directly represent the objective ``(\det(Z))^{\frac{1}{n}}``, so we introduce
132+
# the conic reformulation:
133+
134+
@variable(model, nth_root_det_Z)
135+
@constraint(model, [nth_root_det_Z; vec(Z)] in MOI.RootDetConeSquare(n))
136+
@objective(model, Max, nth_root_det_Z)
137+
138+
# Now, solve the program:
139+
140+
optimize!(model)
141+
Test.@test termination_status(model) == OPTIMAL #src
142+
Test.@test primal_status(model) == FEASIBLE_POINT #src
143+
solution_summary(model)
144+
145+
# ## Results
146+
147+
# After solving the model to optimality we can recover the solution in terms of
148+
# ``D`` and ``c``:
149+
150+
D = value.(Z)
151+
c = D \ value.(z)
152+
153+
# Finally, overlaying the solution in the plot we see the minimal volume approximating
154+
# ellipsoid:
155+
156+
Test.@test isapprox(D, [0.00707 -0.0102; -0.0102173 0.0175624]; atol = 1e-2) #src
157+
Test.@test isapprox(c, [-3.24802, -1.842825]; atol = 1e-2) #src
158+
159+
P = sqrt(D)
160+
q = -P * c
161+
162+
Plots.plot!(
163+
plot,
164+
[tuple(P \ [cos(θ) - q[1], sin(θ) - q[2]]...) for θ in 0:0.05:(2pi+0.05)];
165+
c = :crimson,
166+
label = nothing,
167+
)

docs/styles/Vocab/JuMP-Vocab/accept.txt

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ transpiled
6262
[Cc]anonicaliz(e|ation|ing)
6363
DAE(?s)
6464
[Dd]et
65+
[Ee]xtremal
6566
functionize
6667
geomean
6768
infeasibilities
@@ -155,6 +156,7 @@ Maurer
155156
Mehdi
156157
Mittelman
157158
Montoison
159+
Nemirovski
158160
Pacaud
159161
[Rr]osenbrock
160162
Schermer

0 commit comments

Comments
 (0)