|
1 | 1 | using ModelingToolkit |
2 | | -using JuMP, InfiniteOpt |
| 2 | +import JuMP, InfiniteOpt |
3 | 3 | using DiffEqDevTools, DiffEqBase |
4 | 4 | using SimpleDiffEq |
5 | 5 | using OrdinaryDiffEqSDIRK |
6 | 6 | using Ipopt |
7 | 7 | using BenchmarkTools |
| 8 | +using CairoMakie |
8 | 9 | const M = ModelingToolkit |
9 | 10 |
|
10 | 11 | @testset "ODE Solution, no cost" begin |
11 | 12 | # Test solving without anything attached. |
12 | 13 | @parameters α=1.5 β=1.0 γ=3.0 δ=1.0 |
13 | | - M.@variables x(..) y(..) |
| 14 | + @variables x(..) y(..) |
14 | 15 | t = M.t_nounits |
15 | 16 | D = M.D_nounits |
16 | 17 |
|
17 | 18 | eqs = [D(x(t)) ~ α * x(t) - β * x(t) * y(t), |
18 | 19 | D(y(t)) ~ -γ * y(t) + δ * x(t) * y(t)] |
19 | 20 |
|
| 21 | + @mtkbuild sys = ODESystem(eqs, t) |
20 | 22 | tspan = (0.0, 1.0) |
21 | 23 | u0map = [x(t) => 4.0, y(t) => 2.0] |
22 | 24 | parammap = [α => 1.5, β => 1.0, γ => 3.0, δ => 1.0] |
23 | | - @mtkbuild sys = ODESystem(eqs, t) |
24 | 25 |
|
25 | 26 | # Test explicit method. |
26 | 27 | jprob = JuMPControlProblem(sys, u0map, tspan, parammap, dt = 0.01) |
@@ -58,27 +59,70 @@ const M = ModelingToolkit |
58 | 59 | sol = isol.sol |
59 | 60 | @test sol(0.6)[1] ≈ 3.5 |
60 | 61 | @test sol(0.3)[1] ≈ 7.0 |
| 62 | + |
| 63 | + # Test whole-interval constraints |
| 64 | + constr = [x(t) > 3, y(t) > 4] |
| 65 | + @mtkbuild lksys = ODESystem(eqs, t; constraints = constr) |
| 66 | + iprob = InfiniteOptControlProblem( |
| 67 | + lksys, u0map, tspan, parammap; guesses = guess, dt = 0.01) |
| 68 | + isol = @btime solve( |
| 69 | + $iprob, Ipopt.Optimizer, derivative_method = OrthogonalCollocation(3), silent = true) # 48.564 ms, 9.58 MiB |
| 70 | + sol = isol.sol |
| 71 | + @test all(u -> u .> [3, 4], sol.u) |
| 72 | + |
| 73 | + jprob = JuMPControlProblem(lksys, u0map, tspan, parammap; guesses = guess, dt = 0.01) |
| 74 | + jsol = @btime solve($jprob, Ipopt.Optimizer, :RadauIA3, silent = true) # 12.190 s, 9.68 GiB |
| 75 | + sol = jsol.sol |
| 76 | + @test all(u -> u .> [3, 4], sol.u) |
61 | 77 | end |
62 | 78 |
|
63 | | -#@testset "Optimal control: bees" begin |
64 | | -# # Example from Lawrence Evans' notes |
65 | | -# M.@variables w(..) q(..) |
66 | | -# M.@parameters α(t) [bounds = [0, 1]] b c μ s ν |
67 | | -# |
68 | | -# tspan = (0, 4) |
69 | | -# eqs = [D(w(t)) ~ -μ*w(t) + b*s*α*w(t), |
70 | | -# D(q(t)) ~ -ν*q(t) + c*(1 - α)*s*w(t)] |
71 | | -# costs = [-q(tspan[2])] |
72 | | -# |
73 | | -# @mtkbuild beesys = ODESystem(eqs, t; costs) |
74 | | -# u0map = [w(0) => 40, q(0) => 2] |
75 | | -# pmap = [b => 1, c => 1, μ => 1, s => 1, ν => 1] |
76 | | -# |
77 | | -# jprob = JuMPControlProblem(beesys, u0map, tspan, pmap) |
78 | | -# jsol = solve(jprob, Ipopt.Optimizer, :Tsitouras5) |
79 | | -# control_sol = jsol.control_sol |
80 | | -# # Bang-bang control |
81 | | -#end |
| 79 | +@testset "Linear systems" begin |
| 80 | + function is_bangbang(input_sol, lbounds, ubounds) |
| 81 | + bangbang = true |
| 82 | + for v in 1:length(input_sol.u[1]) |
| 83 | + all(i -> i[v] ≈ bounds[v] || i[v] ≈ bounds[u], input_sol.u) || (bangbang = false) |
| 84 | + end |
| 85 | + bangbang |
| 86 | + end |
| 87 | + |
| 88 | + # Double integrator |
| 89 | + @variables x(..) [bounds = (0., 0.25)] v(..) |
| 90 | + @variables u(t) [bounds = (-1., 1.), input = true] |
| 91 | + constr = [v(1.0) ~ 0.0] |
| 92 | + cost = [-x(1.0)] # Optimize the final distance. |
| 93 | + @named block = ODESystem([D(x(t)) ~ v(t), D(v(t)) ~ u], t) |
| 94 | + block, input_idxs = structural_simplify(block, ([u],[])) |
| 95 | + |
| 96 | + u0map = [x(t) => 0., v(t) => 0.] |
| 97 | + tspan = (0., 1.) |
| 98 | + parammap = [u => 0.] |
| 99 | + jprob = JuMPControlProblem(block, u0map, tspan, parammap; dt = 0.01) |
| 100 | + jsol = solve(jprob, Ipopt.Optimizer, :Verner8) |
| 101 | + # Linear systems have bang-bang controls |
| 102 | + @test is_bangbang(jsol.input_sol, [-1.], [1.]) |
| 103 | + # Test reached final position. |
| 104 | + @test jsol.sol.u[end][1] ≈ 0.25 |
| 105 | + |
| 106 | + # Cart-pole system |
| 107 | + |
| 108 | + # Bee example (from Lawrence Evans' notes) |
| 109 | + M.@variables w(..) q(..) |
| 110 | + M.@parameters α(t) [bounds = [0, 1]] b c μ s ν |
| 111 | + |
| 112 | + tspan = (0, 4) |
| 113 | + eqs = [D(w(t)) ~ -μ*w(t) + b*s*α*w(t), |
| 114 | + D(q(t)) ~ -ν*q(t) + c*(1 - α)*s*w(t)] |
| 115 | + costs = [-q(tspan[2])] |
| 116 | + |
| 117 | + @mtkbuild beesys = ODESystem(eqs, t; costs) |
| 118 | + u0map = [w(0) => 40, q(0) => 2] |
| 119 | + pmap = [b => 1, c => 1, μ => 1, s => 1, ν => 1] |
| 120 | + |
| 121 | + jprob = JuMPControlProblem(beesys, u0map, tspan, pmap) |
| 122 | + jsol = solve(jprob, Ipopt.Optimizer, :Tsitouras5) |
| 123 | + control_sol = jsol.control_sol |
| 124 | + # Bang-bang control |
| 125 | +end |
82 | 126 | # |
83 | 127 | #@testset "Constrained optimal control problems" begin |
84 | 128 | #end |
0 commit comments