Skip to content

Commit 740616e

Browse files
Update Optimal Control Example Documentation (#380)
* Update Fishing example docs * Adjust unit test of fishing example to test output values within tolerance * Update Hanging Chain example docs * Update Jennings example docs * Added unit tests to examples (excluding pandemic control) * Update tolerance to 1E-06 * Minor update --------- Co-authored-by: pulsipher <[email protected]>
1 parent 5915743 commit 740616e

File tree

5 files changed

+124
-47
lines changed

5 files changed

+124
-47
lines changed
Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# # Fishing Optimal Control
22
# We will solve an optimal control problem to maximize profit
3-
# constrained by fish population
3+
# constrained by fish population.
4+
45
# # Problem Statement and Model
5-
# In this system out input is the rate of fishing ``u``, and the profit
6+
# In this system, our input is the fishing rate ``u``, and the profit
67
# ``J`` will be defined in the objective to maximize.
78
# Our profit objective is represented as:
89
# ```math
@@ -16,51 +17,76 @@
1617
# &&&&&J(0) = 0 \\
1718
# \end{aligned}
1819
# ```
19-
# # Model Definition
20+
21+
# # Modeling in InfiniteOpt
2022
# First we must import ``InfiniteOpt`` and other packages.
2123
using InfiniteOpt, Ipopt, Plots;
22-
# Next we specify an array of initial conditions as well as problem variables.
24+
25+
# Next we specify our initial conditions and problem variables.
2326
x0 = 70
2427
E, c, r, k, Umax = 1, 17.5, 0.71, 80.5, 20;
25-
# We initialize the infinite model and opt to use the Ipopt solver
28+
29+
# # Model Initialization
30+
# We initialize the infinite model with [`InfiniteModel`](@ref) and select Ipopt as our optimizer that will be used to solve it.
2631
m = InfiniteModel(Ipopt.Optimizer);
27-
# Now let's specify variables. ``u`` is as our fishing rate.
28-
# ``x`` will be used to model the fish population in response to ``u``
29-
# the infinite parameter ``t`` that will span over 10 years.
30-
@infinite_parameter(m, t in [0,10],num_supports=100)
32+
33+
# # Infinite Parameter Definition
34+
# We now define the infinite parameter ``t \in [0, 10]`` to represent time over a 10 year period. We'll also specify 100 equidistant time points.
35+
@infinite_parameter(m, t in [0, 10], num_supports=100)
36+
37+
# # Infinite Variable Definition
38+
# Now that we have our infinite parameter defined, let's specify our infinite variables:
39+
# - ``1 \leq x(t)`` : fish population at time ``t``
40+
# - ``0 \leq u(t) \leq 1`` : fishing rate
41+
# - ``J(t)`` : profit over time
3142
@variable(m, 1 <= x, Infinite(t))
3243
@variable(m, 0 <= u <= 1, Infinite(t));
33-
# ``J`` represents profit over time.
3444
@variable(m, J, Infinite(t));
35-
# Specifying the objective to maximize profit ``J``:
45+
46+
# # Objective Definition
47+
# Now we add the objective using `@objective` to maximize profit ``J`` at the end of the 10 year period:
3648
@objective(m, Max, J(10));
37-
# Define the ODEs which serve as our system model.
49+
50+
# # Constraint Definition
51+
# The last step is to add our constraints. First, define the ODEs which serve as our system model.
3852
@constraint(m, (J,t) == (E-c/x) * u * Umax)
3953
@constraint(m, (x,t) == r * x *(1 - x/k) - u*Umax);
40-
# Set our initial conditions.
54+
# We also set our initial conditions for ``x`` and ``J``.
4155
@constraint(m, x(0) == x0)
4256
@constraint(m, J(0) == 0);
57+
4358
# # Problem Solution
44-
# Optimize the model:
59+
# Now we're ready to solve! We can solve the model by invoking `optimize!`:
4560
optimize!(m)
46-
# Extract the results.
61+
62+
# # Extract and Plot the Results
63+
# Now we can extract the optimal results and plot them to visualize how the fish population compares to the profit. Note that the values of infinite variables are
64+
# returned as arrays corresponding to how the supports were used to discretize our model.
65+
# We can use the `value` function to extract the values of the infinite variables.
4766
ts = value(t)
4867
u_opt = value(u)
4968
x_opt = value(x)
5069
J_opt = value(J);
5170

71+
# Create the plot for the fish population and profit over time.
5272
p1 = plot(ts, [x_opt, J_opt] ,
5373
label=["Fish Pop" "Profit"],
54-
title="State Variables")
74+
title="State Variables");
75+
# Create the plot for the fishing rate over time.
5576
p2 = plot(ts, u_opt,
56-
label = "Rate",
57-
title = "Rate vs Time")
58-
plot(p1,p2 ,layout=(2,1), size=(800,600));
77+
label = "Fishing Rate",
78+
title = "Fishing Rate vs Time");
79+
# Visualize the two plots on one figure.
80+
plot(p1,p2 ,layout=(2,1), size=(800,600))
5981

6082
# ### Maintenance Tests
6183
# These are here to ensure this example stays up to date.
6284
using Test
85+
tol = 1E-6
6386
@test termination_status(m) == MOI.LOCALLY_SOLVED
6487
@test has_values(m)
6588
@test u_opt isa Vector{<:Real}
66-
@test J_opt isa Vector{<:Real}
89+
@test J_opt isa Vector{<:Real}
90+
@test isapprox(u_opt[end], 1.0000000088945395, atol=tol)
91+
@test isapprox(x_opt[end], 31.441105707837544, atol=tol)
92+
@test isapprox(J_opt[end], 106.80870543718251, atol=tol)

docs/src/examples/Optimal Control/Hanging Chain.jl

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,53 +25,78 @@
2525
# \end{aligned}
2626
# ```
2727

28-
# # Model Definition
28+
# # Modeling in InfiniteOpt
2929
# First we must import ``InfiniteOpt`` and other packages.
3030
using InfiniteOpt, Ipopt, Plots;
31-
# Next we specify an array of initial conditions as well as problem variables.
31+
32+
# Next we specify our initial conditions and problem variables.
3233
a, b, L = 1, 3, 4
3334
x0 = [a, 0, 0]
3435
xtf = [b, NaN, L];
35-
# We initialize the infinite model and opt to use the Ipopt solver
36+
37+
# # Model Definition
38+
# We initialize the infinite model with [`InfiniteModel`](@ref) and select Ipopt as our optimizer that will be used to solve it.
3639
m = InfiniteModel(Ipopt.Optimizer);
37-
# t is specified as ``\ t \in [0,1]``. The bounds are arbitrary for this problem:
40+
41+
# # Infinite Parameter Definition
42+
# We define the infinite parameter t as ``\ t \in [0,1]``. The bounds are arbitrary for this problem:
3843
@infinite_parameter(m, t in [0,1], num_supports = 100);
39-
# Now let's specify variables. ``u`` is our controller variable.
44+
45+
# # Infinite Variable Definition
46+
# Now let's specify variables. We define ``x`` as a vector containing the state variables for position, energy and chain length. ``u`` is our control variable.
4047
@variable(m, 0 <= x[1:3] <= 10, Infinite(t))
4148
@variable(m, -10 <= u <= 20, Infinite(t));
42-
# Specifying the objective to minimize kinetic energy at the final time:
49+
50+
# # Objective Definition
51+
# We specify the objective using `@objective` to minimize potential energy at the final time:
4352
@objective(m, Min, x[2](1));
44-
# Define the ODEs which serve as our system model.
53+
54+
# # Constraint Definition
55+
# The last step is to add our constraints. First, define the ODEs which serve as our system model.
4556
@constraint(m, (x[1],t) == u)
4657
@constraint(m, (x[2],t) == x[1] * (1 + u^2)^(1/2))
4758
@constraint(m, (x[3],t) == (1 + u^2)^(1/2));
48-
# Set our inital and final conditions.
59+
60+
# We also set our initial and final conditions for ``x``.
4961
@constraint(m, [i in 1:3], x[i](0) == x0[i])
5062
@constraint(m, x[1](1) == xtf[1])
5163
@constraint(m, x[3](1) == xtf[3]);
64+
5265
# # Problem Solution
53-
# Optimize the model:
66+
# Now we can solve the model with `optimize!`:
5467
optimize!(m)
55-
# Extract the results.
68+
69+
# # Extract and Plot the Results
70+
# Extract the results using `value`. Note that they are returned as arrays corresponding to the supports used to discretize the model.
5671
ts = value(t)
5772
u_opt = value(u)
5873
x1_opt = value(x[1])
5974
x2_opt = value(x[2])
60-
x3_opt = value(x[3])
75+
x3_opt = value(x[3]);
76+
77+
# We can also check the objective value:
6178
@show(objective_value(m))
79+
80+
# Create the plot for the state variables and input over time.
6281
p1 = plot(ts, [x1_opt, x2_opt, x3_opt],
82+
6383
label=["x1" "x2" "x3"],
6484
title="State Variables")
6585

6686
p2 = plot(ts, u_opt,
6787
label="u(t)",
68-
title="Input")
69-
plot(p1, p2, layout=(2,1), size=(800,600));
88+
title="Input");
89+
90+
# Visualize the two plots on one figure.
91+
plot(p1, p2, layout=(2,1), size=(800,600))
7092

7193
# ### Maintenance Tests
7294
# These are here to ensure this example stays up to date.
7395
using Test
96+
tol = 1E-6
7497
@test termination_status(m) == MOI.LOCALLY_SOLVED
7598
@test has_values(m)
7699
@test u_opt isa Vector{<:Real}
77-
@test x1_opt isa Vector{<:Real}
100+
@test x1_opt isa Vector{<:Real}
101+
@test isapprox(objective_value(m), 5.127030122851338, atol=tol)
102+
@test isapprox(u_opt[end], 7.20355021172144, atol=tol)

docs/src/examples/Optimal Control/Jennings.jl

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,51 +27,69 @@
2727
# \end{aligned}
2828
# ```
2929

30-
# # Model Definition
31-
30+
# # Modeling in InfiniteOpt
3231
# First we must import ``InfiniteOpt`` and other packages.
3332
using InfiniteOpt, Ipopt, Plots;
33+
3434
# Next we specify an array of initial conditions.
35-
x0 =/2, 4, 0]; # x(0) for x1,x2,x3
36-
# We initialize the infinite model and opt to use the Ipopt solver
35+
x0 =/2, 4, 0]; # x(0) for x1, x2, x3
36+
37+
# # Model Definition
38+
# We initialize the infinite model with [`InfiniteModel`](@ref), opting to use the Ipopt solver.
3739
m = InfiniteModel(Ipopt.Optimizer);
40+
41+
# # Infinite Parameter Definition
3842
# Recall t is specified as ``\ t \in [0,1]``:
39-
@infinite_parameter(m, t in [0,1],num_supports= 100)
40-
# Now let's specify descision variables. Notice that ``t_f`` is
43+
@infinite_parameter(m, t in [0,1],num_supports= 100);
44+
45+
# # Variable Definition
46+
# Now let's specify decision variables. Notice that ``t_f`` is
4147
# not a function of time and is a singular value.
4248
@variable(m, x[1:3], Infinite(t))
4349
@variable(m, -2 <= u <= 2, Infinite(t))
4450
@variable(m, 0.1 <= tf);
45-
# Specifying the objective to minimize final time:
51+
52+
# # Objective Definition
53+
# Now we add the objective using `@objective` to minimize final time:
4654
@objective(m, Min, tf);
47-
# Define the ODEs which serve as our system model.
55+
56+
# # Constraint Definition
57+
# The last step is to add our constraints. First, define the ODEs which serve as our system model.
4858
@constraint(m, (x[1],t) == tf*u)
4959
@constraint(m, (x[2],t) == tf*cos(x[1]))
5060
@constraint(m, (x[3],t) == tf*sin(x[1]));
51-
# Set our inital and final conditions.
61+
62+
# Set our inital and final conditions for ``x``.
5263
@constraint(m, [i in 1:3], x[i](0) == x0[i])
5364
@constraint(m, x[2](1) <=0)
5465
@constraint(m, x[3](1) <= 1e-1);
66+
5567
# # Problem Solution
56-
# Optimize the model:
68+
# Now everything is ready for solving! We can solve the model with `@optimize!`:
5769
optimize!(m)
58-
# Extract the results. Notice that we multiply by ``t_f``
70+
71+
# # Extract and Plot the Results
72+
# We can extract the results as arrays using the `value` function. Notice that we multiply by ``t_f``
5973
# to scale our time.
6074
ts = value(t)*value(tf)
6175
u_opt = value(u)
6276
x1_opt = value(x[1])
6377
x2_opt = value(x[2])
6478
x3_opt = value(x[3]);
79+
6580
# Plot the results
6681
plot(ts, u_opt, label = "u(t)", linecolor = :black, linestyle = :dash)
6782
plot!(ts, x1_opt, linecolor = :blue, linealpha = 0.4, label = "x1")
6883
plot!(ts, x2_opt, linecolor = :green, linealpha = 0.4, label = "x2")
69-
plot!(ts, x3_opt, linecolor = :red, linealpha = 0.4, label = "x3");
84+
plot!(ts, x3_opt, linecolor = :red, linealpha = 0.4, label = "x3")
7085

7186
# ### Maintenance Tests
7287
# These are here to ensure this example stays up to date.
7388
using Test
89+
tol = 1E-6
7490
@test termination_status(m) == MOI.LOCALLY_SOLVED
7591
@test has_values(m)
7692
@test u_opt isa Vector{<:Real}
77-
@test x1_opt isa Vector{<:Real}
93+
@test x1_opt isa Vector{<:Real}
94+
@test isapprox(x1_opt[end], 3.2501431326448293, atol=tol)
95+
@test isapprox(objective_value(m), 4.284564834847627, atol=tol)

docs/src/examples/Optimal Control/consumption_savings.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ plot!(ts[ix], BB, color = 4, linestyle=:dash, lab = "B: wealth balance, closed f
108108
# ### Maintenance Tests
109109
# These are here to ensure this example stays up to date.
110110
using Test
111+
tol = 1E-6
111112
@test termination_status(m) == MOI.LOCALLY_SOLVED
112113
@test has_values(m)
113114
@test B_opt isa Vector{<:Real}
114115
@test c_opt isa Vector{<:Real}
116+
@test isapprox(opt_obj, -67025.62174598589, atol=tol)
117+
@test isapprox(c_opt[end], -52.00096266262752, atol=tol)

docs/src/examples/Optimal Control/hovercraft.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ ylabel!("x_2")
7676
# ### Maintenance Tests
7777
# These are here to ensure this example stays up to date.
7878
using Test
79+
tol = 1E-6
7980
@test termination_status(m) == MOI.LOCALLY_SOLVED
8081
@test has_values(m)
8182
@test x_opt isa Vector{<:Vector{<:Real}}
83+
@test isapprox(objective_value(m), 0.043685293177035435, atol=tol)
84+
@test isapprox(value(u[1])[end], -0.010503853944039986, atol=tol)
85+
@test isapprox(value(u[2])[end], 0.005456780217220367, atol=tol)
86+

0 commit comments

Comments
 (0)