Skip to content

Commit b877dde

Browse files
authored
Merge pull request #339 from JuliaOpt/literate-examples
Switch examples to use Literate.jl and update to 1.0
2 parents d2bb5cd + 302c678 commit b877dde

File tree

70 files changed

+1866
-41342
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1866
-41342
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ problem.optval
4848
```
4949

5050
## More Examples
51-
A number of examples can be found [here](https://www.juliaopt.org/Convex.jl/stable/examples/). The [basic usage notebook](https://nbviewer.jupyter.org/github/JuliaOpt/Convex.jl/blob/master/examples/basic_usage.ipynb) gives a simple tutorial on problems that can be solved using Convex.jl. Many use cases of the package in complex-domain optimization can be found [here](https://github.com/JuliaOpt/Convex.jl/tree/master/examples/optimization_with_complex_variables).
5251

53-
Note: many of the examples are currently outdated (August 2019). Pull requests to update them are greatly appreciated!
52+
A number of examples can be found [here](https://www.juliaopt.org/Convex.jl/stable/).
53+
The [basic usage notebook](https://www.juliaopt.org/Convex.jl/stable/examples/general_examples/basic_usage/)
54+
gives a simple tutorial on problems that can be solved using Convex.jl. All examples can be downloaded as
55+
a zip file from [here](https://www.juliaopt.org/Convex.jl/stable/examples/notebooks.zip/).
5456

5557
## Citing this package
5658

docs/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
build/
1+
build/
2+
src/examples
3+
notebooks

docs/Project.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
[deps]
22
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
33
Convex = "f65535da-76fb-5f13-bab9-19810c17039a"
4+
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
5+
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
6+
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
47
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
8+
ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199"
9+
GLPKMathProgInterface = "3c7084bd-78ad-589a-b5bb-dbd673274bea"
10+
Interact = "c601a237-2ae4-5e1e-952c-7a85b0c7eef1"
11+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
12+
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
13+
MAT = "23992714-dd62-5051-b70f-ba57cb901cac"
14+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
15+
RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
16+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
517
SCS = "c946c3f1-0d1f-5ce8-9dea-7daa1f7e2d13"
18+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
19+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

docs/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Documentation and examples
2+
3+
This file describes how to generate Convex.jl's documentation and examples. If
4+
you just want to read the documentation, or try out the examples, please visit
5+
the website: <https://www.juliaopt.org/Convex.jl/stable/>. You can download a
6+
zip file of Jupyter notebooks of all the examples there as well.
7+
8+
The examples and documentation are constructed together. Run
9+
10+
```sh
11+
julia --project=docs -e 'using Pkg; Pkg.instantiate(); include("docs/make.jl")'
12+
```
13+
14+
to generate the examples notebooks (which will be placed in `docs/notebooks`)
15+
and the documentation itself, which is generated into the `doc/build` folder,
16+
and can be previewed by opening a webserver there. Note that this command can
17+
take some time.
18+
19+
To generate a single Jupyter notebook, run e.g.
20+
21+
```julia
22+
Literate.notebook(file_path, notebook_dir, execute=false) # or execute = true, to run the code
23+
```
24+
25+
Then the notebook can be opened with IJulia.
26+
27+
To just generate a single markdown file, run e.g.
28+
29+
```julia
30+
fix_math_md(content) = replace(content, r"\$\$(.*?)\$\$"s => s"```math\1```")
31+
Literate.markdown(file_path, output_directory; preprocess = fix_math_md)
32+
```
33+
34+
This won't execute the code however; that is done by Documenter, so the above
35+
`docs/make.jl` file is needed. This can be slow because all the examples will be
36+
re-run. By re-including `docs/make.jl` into a running session, however, compile
37+
times can be minimized.
38+
39+
The `fix_math_md` function allows us to use `$$` for LaTeX display in the
40+
Literate.jl files by replacing it with the tags expected by Documenter.jl when
41+
we generate the markdown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# # DCP analysis
2+
using Convex
3+
x = Variable();
4+
y = Variable();
5+
expr = quadoverlin(x - y, 1 - max(x, y));
6+
println("expression curvature = ", vexity(expr));
7+
println("expression sign = ", sign(expr));
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# # Basic Usage
2+
3+
using Convex
4+
using LinearAlgebra
5+
if VERSION < v"1.2.0-DEV.0"
6+
(I::UniformScaling)(n::Integer) = Diagonal(fill(I.λ, n))
7+
end
8+
9+
using SCS
10+
## passing in verbose=0 to hide output from SCS
11+
solver = SCSSolver(verbose=0)
12+
13+
# ### Linear program
14+
#
15+
# $$
16+
# \begin{array}{ll}
17+
# \mbox{maximize} & c^T x \\
18+
# \mbox{subject to} & A x \leq b\\
19+
# & x \geq 1 \\
20+
# & x \leq 10 \\
21+
# & x_2 \leq 5 \\
22+
# & x_1 + x_4 - x_2 \leq 10 \\
23+
# \end{array}
24+
# $$
25+
#
26+
27+
x = Variable(4)
28+
c = [1; 2; 3; 4]
29+
A = I(4)
30+
b = [10; 10; 10; 10]
31+
p = minimize(dot(c, x)) # or c' * x
32+
p.constraints += A * x <= b
33+
p.constraints += [x >= 1; x <= 10; x[2] <= 5; x[1] + x[4] - x[2] <= 10]
34+
solve!(p, solver)
35+
36+
println(round(p.optval, digits=2))
37+
println(round.(x.value, digits=2))
38+
println(evaluate(x[1] + x[4] - x[2]))
39+
40+
# ### Matrix Variables and promotions
41+
#
42+
# $$
43+
# \begin{array}{ll}
44+
# \mbox{minimize} & \| X \|_F + y \\
45+
# \mbox{subject to} & 2 X \leq 1\\
46+
# & X' + y \geq 1 \\
47+
# & X \geq 0 \\
48+
# & y \geq 0 \\
49+
# \end{array}
50+
# $$
51+
#
52+
53+
X = Variable(2, 2)
54+
y = Variable()
55+
## X is a 2 x 2 variable, and y is scalar. X' + y promotes y to a 2 x 2 variable before adding them
56+
p = minimize(norm(X) + y, 2 * X <= 1, X' + y >= 1, X >= 0, y >= 0)
57+
solve!(p, solver)
58+
println(round.(X.value, digits=2))
59+
println(y.value)
60+
p.optval
61+
62+
# ### Norm, exponential and geometric mean
63+
#
64+
# $$
65+
# \begin{array}{ll}
66+
# \mbox{satisfy} & \| x \|_2 \leq 100 \\
67+
# & e^{x_1} \leq 5 \\
68+
# & x_2 \geq 7 \\
69+
# & \sqrt{x_3 x_4} \geq x_2
70+
# \end{array}
71+
# $$
72+
#
73+
74+
x = Variable(4)
75+
p = satisfy(norm(x) <= 100, exp(x[1]) <= 5, x[2] >= 7, geomean(x[3], x[4]) >= x[2])
76+
solve!(p, SCSSolver(verbose=0))
77+
println(p.status)
78+
x.value
79+
80+
# ### SDP cone and Eigenvalues
81+
82+
83+
y = Semidefinite(2)
84+
p = maximize(lambdamin(y), tr(y)<=6)
85+
solve!(p, SCSSolver(verbose=0))
86+
p.optval
87+
88+
#-
89+
90+
x = Variable()
91+
y = Variable((2, 2))
92+
## SDP constraints
93+
p = minimize(x + y[1, 1], isposdef(y), x >= 1, y[2, 1] == 1)
94+
solve!(p, solver)
95+
y.value
96+
97+
# ### Mixed integer program
98+
#
99+
# $$
100+
# \begin{array}{ll}
101+
# \mbox{minimize} & \sum_{i=1}^n x_i \\
102+
# \mbox{subject to} & x \in \mathbb{Z}^n \\
103+
# & x \geq 0.5 \\
104+
# \end{array}
105+
# $$
106+
#
107+
108+
using GLPKMathProgInterface
109+
x = Variable(4, :Int)
110+
p = minimize(sum(x), x >= 0.5)
111+
solve!(p, GLPKSolverMIP())
112+
x.value
113+
114+
#-
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# # Chebyshev center
2+
# Boyd & Vandenberghe, "Convex Optimization"
3+
# Joëlle Skaf - 08/16/05
4+
#
5+
# Adapted for Convex.jl by Karanveer Mohan and David Zeng - 26/05/14
6+
#
7+
# The goal is to find the largest Euclidean ball (i.e. its center and
8+
# radius) that lies in a polyhedron described by affine inequalites in this
9+
# fashion: $P = \{x : a_i'*x \leq b_i, i=1,\ldots,m \}$ where $x \in \mathbb{R}^2$.
10+
11+
using Convex, LinearAlgebra, SCS
12+
13+
# Generate the input data
14+
a1 = [ 2; 1];
15+
a2 = [ 2; -1];
16+
a3 = [-1; 2];
17+
a4 = [-1; -2];
18+
b = ones(4, 1);
19+
20+
# Create and solve the model
21+
r = Variable(1)
22+
x_c = Variable(2)
23+
p = maximize(r)
24+
p.constraints += a1' * x_c + r * norm(a1, 2) <= b[1];
25+
p.constraints += a2' * x_c + r * norm(a2, 2) <= b[2];
26+
p.constraints += a3' * x_c + r * norm(a3, 2) <= b[3];
27+
p.constraints += a4' * x_c + r * norm(a4, 2) <= b[4];
28+
solve!(p, SCSSolver(verbose=0))
29+
p.optval
30+
31+
# Generate the figure
32+
x = range(-1.5, stop=1.5, length=100);
33+
theta = 0:pi/100:2*pi;
34+
using Plots
35+
plot(x, x -> -x * a1[1] / a1[2] + b[1] / a1[2])
36+
plot!(x, x -> -x * a2[1]/ a2[2] + b[2] / a2[2])
37+
plot!(x, x -> -x * a3[1]/ a3[2] + b[3] / a3[2])
38+
plot!(x, x -> -x * a4[1]/ a4[2] + b[4] / a4[2])
39+
plot!(x_c.value[1] .+ r.value * cos.(theta), x_c.value[2] .+ r.value * sin.(theta), linewidth = 2)
40+
plot!(title ="Largest Euclidean ball lying in a 2D polyhedron", legend = nothing)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# # Control
2+
3+
#-
4+
5+
# A simple control problem on a system usually involves a variable $x(t)$
6+
# that denotes the state of the system over time, and a variable $u(t)$ that
7+
# denotes the input into the system over time. Linear constraints are used to
8+
# capture the evolution of the system over time:
9+
#
10+
# $$
11+
# x(t) = Ax(t - 1) + Bu(t), \ \text{for} \ t = 1,\ldots, T,
12+
# $$
13+
#
14+
# where the numerical matrices $A$ and $B$ are called the dynamics and input matrices,
15+
# respectively.
16+
#
17+
# The goal of the control problem is to find a sequence of inputs
18+
# $u(t)$ that will allow the state $x(t)$ to achieve specified values
19+
# at certain times. For example, we can specify initial and final states of the system:
20+
#
21+
# $$
22+
# \begin{aligned}
23+
# x(0) &= x_i \\
24+
# x(T) &= x_f
25+
# \end{aligned}
26+
# $$
27+
#
28+
# Additional states between the initial and final states can also be specified. These
29+
# are known as waypoint constraints. Often, the input and state of the system will
30+
# have physical meaning, so we often want to find a sequence inputs that also
31+
# minimizes a least squares objective like the following:
32+
#
33+
# $$
34+
# \sum_{t = 0}^T \|Fx(t)\|^2_2 + \sum_{t = 1}^T\|Gu(t)\|^2_2,
35+
# $$
36+
#
37+
# where $F$ and $G$ are numerical matrices.
38+
#
39+
# We'll now apply the basic format of the control problem to an example of controlling
40+
# the motion of an object in a fluid over $T$ intervals, each of $h$ seconds.
41+
# The state of the system at time interval $t$ will be given by the position and the velocity of the
42+
# object, denoted $p(t)$ and $v(t)$, while the input will be forces
43+
# applied to the object, denoted by $f(t)$.
44+
# By the basic laws of physics, the relationship between force, velocity, and position
45+
# must satisfy:
46+
#
47+
# $$
48+
# \begin{aligned}
49+
# p(t+1) &= p(t) + h v(t) \\
50+
# v(t+1) &= v(t) + h a(t)
51+
# \end{aligned}.
52+
# $$
53+
#
54+
# Here, $a(t)$ denotes the acceleration at time $t$, for which we we use
55+
# $a(t) = f(t) / m + g - d v(t)$,
56+
# where $m$, $d$, $g$ are constants for the mass of the object, the drag
57+
# coefficient of the fluid, and the acceleration from gravity, respectively.
58+
#
59+
# Additionally, we have our initial/final position/velocity conditions:
60+
#
61+
# $$
62+
# \begin{aligned}
63+
# p(1) &= p_i\\
64+
# v(1) &= v_i\\
65+
# p(T+1) &= p_f\\
66+
# v(T+1) &= 0
67+
# \end{aligned}
68+
# $$
69+
#
70+
# One reasonable objective to minimize would be
71+
#
72+
# $$
73+
# \text{objective} = \mu \sum_{t = 1}^{T+1} (v(t))^2 + \sum_{t = 1}^T (f(t))^2
74+
# $$
75+
#
76+
# We would like to keep both the forces small to perhaps save fuel, and keep
77+
# the velocities small for safety concerns.
78+
# Here $\mu$ serves as a parameter to control which part of the objective we
79+
# deem more important, keeping the velocity small or keeping the force small.
80+
#
81+
# The following code builds and solves our control example:
82+
83+
84+
using Convex, SCS, Plots
85+
86+
## Some constraints on our motion
87+
## The object should start from the origin, and end at rest
88+
initial_velocity = [-20; 100]
89+
final_position = [100; 100]
90+
91+
T = 100 # The number of timesteps
92+
h = 0.1 # The time between time intervals
93+
mass = 1 # Mass of object
94+
drag = 0.1 # Drag on object
95+
g = [0, -9.8] # Gravity on object
96+
97+
## Declare the variables we need
98+
position = Variable(2, T)
99+
velocity = Variable(2, T)
100+
force = Variable(2, T - 1)
101+
102+
## Create a problem instance
103+
mu = 1
104+
105+
## Add constraints on our variables
106+
constraints = Constraint[ position[:, i + 1] == position[:, i] + h * velocity[:, i] for i in 1 : T - 1]
107+
108+
109+
for i in 1 : T - 1
110+
acceleration = force[:, i]/mass + g - drag * velocity[:, i]
111+
push!(constraints, velocity[:, i + 1] == velocity[:, i] + h * acceleration)
112+
end
113+
114+
## Add position constraints
115+
push!(constraints, position[:, 1] == 0)
116+
push!(constraints, position[:, T] == final_position)
117+
118+
## Add velocity constraints
119+
push!(constraints, velocity[:, 1] == initial_velocity)
120+
push!(constraints, velocity[:, T] == 0)
121+
122+
## Solve the problem
123+
problem = minimize(sumsquares(force), constraints)
124+
solve!(problem, SCSSolver(verbose=0))
125+
126+
# We can plot the trajectory taken by the object.
127+
128+
pos = evaluate(position)
129+
plot([pos[1, 1]], [pos[2, 1]], st=:scatter, label="initial point")
130+
plot!([pos[1, T]], [pos[2, T]], st=:scatter, label="final point")
131+
plot!(pos[1, :], pos[2, :], label="trajectory")
132+
133+
# We can also see how the magnitude of the force changes over time.
134+
135+
plot(vec(sum(evaluate(force).^2, dims=1)), label="force (magnitude)")

0 commit comments

Comments
 (0)