CollapsedDocStrings = false
In this manual, we explain the solve function from OptimalControl.jl package.
solve(::CTModels.Model, ::Symbol...)
Let us define a basic optimal control problem.
using OptimalControl
t0 = 0
tf = 1
x0 = [-1, 0]
ocp = @def begin
t ∈ [ t0, tf ], time
x = (q, v) ∈ R², state
u ∈ R, control
x(t0) == x0
x(tf) == [0, 0]
ẋ(t) == [v(t), u(t)]
0.5∫( u(t)^2 ) → min
end
nothing # hide
We can now solve the problem:
using NLPModelsIpopt
solve(ocp)
nothing # hide
Note that we must import NLPModelsIpopt.jl before calling solve.
This is because the default method uses a direct approach, which transforms the optimal control problem into a nonlinear program (NLP) of the form:
!!! warning
Calling `solve` without loading a NLP solver package first will notify the user:
```julia
julia> solve(ocp)
ERROR: ExtensionError. Please make: julia> using NLPModelsIpopt
```
OptimalControl.jl offers a list of methods. To get it, simply call available_methods.
available_methods()
Each line is a method, with priority going from top to bottom. This means that
solve(ocp)is equivalent to
solve(ocp, :direct, :adnlp, :ipopt)- The first symbol refers to the general class of method. The only possible value is:
:direct: currently, only the so-called direct approach is implemented. Direct methods discretise the original optimal control problem and solve the resulting NLP. In this case, the mainsolvemethod redirects toCTDirect.solve.
- The second symbol refers to the NLP modeler. The possible values are:
:adnlp: the NLP problem is modeled by aADNLPModels.ADNLPModel. It provides automatic differentiation (AD)-based models that follow the NLPModels.jl API.:exa: the NLP problem is modeled by aExaModels.ExaModel. It provides automatic differentiation and SIMD abstraction.
- The third symbol specifies the NLP solver. Possible values are:
:ipopt: callsNLPModelsIpopt.ipoptto solve the NLP problem.:madnlp: creates a MadNLP.MadNLPSolver instance from the NLP problem and solve it. MadNLP.jl is an open-source solver in Julia implementing a filter line-search interior-point algorithm like Ipopt.:knitro: uses the Knitro solver (license required).
!!! warning
Dynamics and nonlinear constraints must be defined coordinatewise to use ExaModels.jl (`:exa`). Check [the problem definition manual](@ref manual-abstract-dynamics-coord) for more information.
For instance, let us try MadNLP solver with ExaModel modeller.
using MadNLP
ocp = @def begin
t ∈ [ t0, tf ], time
x = (q, v) ∈ R², state
u ∈ R, control
x(t0) == x0
x(tf) == [0, 0]
∂(q)(t) == v(t)
∂(v)(t) == u(t)
0.5∫( u(t)^2 ) → min
end
solve(ocp, :exa, :madnlp)
nothing # hide
Note that you can provide a partial description. If multiple full descriptions contain it, priority is given to the first one in the list. Hence, all of the following calls are equivalent:
solve(ocp)
solve(ocp, :direct )
solve(ocp, :adnlp )
solve(ocp, :ipopt)
solve(ocp, :direct, :adnlp )
solve(ocp, :direct, :ipopt)
solve(ocp, :direct, :adnlp, :ipopt)The main options for the direct method, with their [default] values, are:
display([true],false): settingdisplay = falsedisables output.init: information for the initial guess. It can be given as numerical values, functions, or an existing solution. See [how to set an initial guess](@ref manual-initial-guess).grid_size([250]): number of time steps in the (uniform) time discretization grid.
More precisely, ifN = grid_sizeand the initial and final times aret0andtf, then the step lengthΔt = (tf - t0) / N.time_grid([nothing]): explicit time grid (can be non-uniform).
Iftime_grid = nothing, a uniform grid of lengthgrid_sizeis used.disc_method([:trapeze],:midpoint,:euler,:euler_implicit,:gauss_legendre_2,:gauss_legendre_3): the discretisation scheme to transform the dynamics into nonlinear equations. See the discretization method tutorial for more details.adnlp_backend([:optimized],:manual,:default): backend used for automatic differentiation to create theADNLPModels.ADNLPModel.
For advanced usage, see:
!!! note
The main [`solve`](@ref) method from OptimalControl.jl simply redirects to [`CTDirect.solve`](@extref) in that case.
In addition to these options, any remaining keyword arguments passed to solve are forwarded to the NLP solver.
!!! warning
The option names and accepted values depend on the chosen solver. For example, in Ipopt, `print_level` expects an integer, whereas in MadNLP it must be a `MadNLP.LogLevels` value (valid options: `MadNLP.{TRACE, DEBUG, INFO, NOTICE, WARN, ERROR}`). Moreover, some options are solver-specific: for instance, `mu_strategy` exists in Ipopt but not in MadNLP.
Please refer to the Ipopt options list and the NLPModelsIpopt.jl documentation.
sol = solve(ocp; max_iter=0, tol=1e-6, print_level=0)
iterations(sol)
Likewise, see the MadNLP.jl options and the MadNLP.jl documentation.
sol = solve(ocp, :madnlp; max_iter=0, tol=1e-6, print_level=MadNLP.ERROR)
iterations(sol)