The solve function
In this tutorial, we explain the solve
function from OptimalControl.jl package.
Basic usage
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.5u(t)^2 ) → min
end
We can now solve the problem:
using NLPModelsIpopt
solve(ocp)
This is Ipopt version 3.14.17, running with linear solver MUMPS 5.7.3.
Number of nonzeros in equality constraint Jacobian...: 3005
Number of nonzeros in inequality constraint Jacobian.: 0
Number of nonzeros in Lagrangian Hessian.............: 251
Total number of variables............................: 1004
variables with only lower bounds: 0
variables with lower and upper bounds: 0
variables with only upper bounds: 0
Total number of equality constraints.................: 755
Total number of inequality constraints...............: 0
inequality constraints with only lower bounds: 0
inequality constraints with lower and upper bounds: 0
inequality constraints with only upper bounds: 0
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
0 1.0000000e-01 1.10e+00 1.99e-14 0.0 0.00e+00 - 0.00e+00 0.00e+00 0
1 -5.0000000e-03 7.36e-02 2.66e-15 -11.0 6.08e+00 - 1.00e+00 1.00e+00h 1
2 6.0003829e+00 8.88e-16 1.78e-15 -11.0 6.01e+00 - 1.00e+00 1.00e+00h 1
Number of Iterations....: 2
(scaled) (unscaled)
Objective...............: 6.0003828724303254e+00 6.0003828724303254e+00
Dual infeasibility......: 1.7763568394002505e-15 1.7763568394002505e-15
Constraint violation....: 8.8817841970012523e-16 8.8817841970012523e-16
Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00
Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00
Overall NLP error.......: 1.7763568394002505e-15 1.7763568394002505e-15
Number of objective function evaluations = 3
Number of objective gradient evaluations = 3
Number of equality constraint evaluations = 3
Number of inequality constraint evaluations = 0
Number of equality constraint Jacobian evaluations = 3
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations = 2
Total seconds in IPOPT = 0.112
EXIT: Optimal Solution Found.
Notice that we need to load the NLPModelsIpopt
package before calling solve
. This is because the method currently implements a direct approach, where the optimal control problem is transcribed to a nonlinear optimization problem (NLP) of the form
\[\text{minimize}\quad F(y), \quad\text{subject to the constraints}\quad g(y)=0, \quad h(y)\le 0. \]
Note: calling solve
without loading a NLP solver package first will notify the user:
julia> solve(ocp)
ERROR: ExtensionError. Please make: julia> using NLPModelsIpopt
See below for the NLP solver options.
Options
Methods
OptimalControl.jl offers a list of methods to solve your optimal control problem. To get the list of methods, simply call available_methods
.
available_methods()
(:direct, :adnlp, :ipopt)
(:direct, :adnlp, :madnlp)
(:direct, :adnlp, :knitro)
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 :direct
refers to the general class of method, with only the so-called direct approach currently implemented. Direct methods discretize the original optimal control problem and solve the resulting NLP problem. The second symbol :adnlp
is for the choice of NLP modeler. We currently use ADNLPModels.jl which provides an automatic differentiation (AD)-based model implementations that conform to the NLPModels.jl API. The third symbol corresponds to the NLP solver, with the possible values:
:ipopt
(default value) for Ipopt (via the NLPModelsIpopt.jl package).:madnlp
is MadNLP.jl, an open-source nonlinear programming solver purely implemented in Julia, which implements a filter line-search interior-point algorithm, as the one in Ipopt.:knitro
for the Knitro solver (requires a license).
For instance, let us try MadNLP.jl.
using MadNLP
solve(ocp, :madnlp)
This is MadNLP version v0.8.5, running with umfpack
Number of nonzeros in constraint Jacobian............: 3005
Number of nonzeros in Lagrangian Hessian.............: 251
Total number of variables............................: 1004
variables with only lower bounds: 0
variables with lower and upper bounds: 0
variables with only upper bounds: 0
Total number of equality constraints.................: 755
Total number of inequality constraints...............: 0
inequality constraints with only lower bounds: 0
inequality constraints with lower and upper bounds: 0
inequality constraints with only upper bounds: 0
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
0 1.0000000e-01 1.10e+00 2.45e-13 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0
1 -5.0000000e-03 7.36e-02 3.46e-12 -1.0 6.08e+00 - 1.00e+00 1.00e+00h 1
2 6.0003829e+00 1.78e-15 2.66e-15 -2.5 6.01e+00 - 1.00e+00 1.00e+00h 1
Number of Iterations....: 2
(scaled) (unscaled)
Objective...............: 6.0003828724303387e+00 6.0003828724303387e+00
Dual infeasibility......: 2.6645352591003757e-15 2.6645352591003757e-15
Constraint violation....: 1.7763568394002505e-15 1.7763568394002505e-15
Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00
Overall NLP error.......: 2.6645352591003757e-15 2.6645352591003757e-15
Number of objective function evaluations = 3
Number of objective gradient evaluations = 3
Number of constraint evaluations = 3
Number of constraint Jacobian evaluations = 3
Number of Lagrangian Hessian evaluations = 2
Total wall-clock secs in solver (w/o fun. eval./lin. alg.) = 0.001
Total wall-clock secs in linear solver = 0.004
Total wall-clock secs in NLP function evaluations = 0.002
Total wall-clock secs = 0.008
EXIT: Optimal Solution Found (tol = 1.0e-06).
Note that you can provide a partial description. If several full descriptions contain it, the priority is given to first one in the list. Hence, these calls are all 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)
Direct method
The options for the direct method are listed in the direct_solve
keywords. The main options, with their [default values], are:
display
([true], false): settingdisplay
to false will disable outputgrid_size
([250]): size of the (uniform) time discretization grid. More precisely, it is the number of time steps, that is ifN = grid_size
and if the initial and final times are denoted respectivelyt0
andtf
, then we haveΔt = (tf - t0) / N
disc_method
([:trapeze
],:midpoint
,:gauss_legendre_2
): see discretisation methodsinit
: info for the starting guess, which can be provided as numerical values, functions, or an existing solution. See initial guess tutorial.
For examples of more advanced use, see
NLP solver specific options
In addition to these options, all remaining keyword arguments passed to solve
will be transmitted to the NLP solver used.
Please check the list of Ipopt options and the NLPModelsIpopt.jl documentation.
solve(ocp; max_iter=0)
This is Ipopt version 3.14.17, running with linear solver MUMPS 5.7.3.
Number of nonzeros in equality constraint Jacobian...: 3005
Number of nonzeros in inequality constraint Jacobian.: 0
Number of nonzeros in Lagrangian Hessian.............: 251
Total number of variables............................: 1004
variables with only lower bounds: 0
variables with lower and upper bounds: 0
variables with only upper bounds: 0
Total number of equality constraints.................: 755
Total number of inequality constraints...............: 0
inequality constraints with only lower bounds: 0
inequality constraints with lower and upper bounds: 0
inequality constraints with only upper bounds: 0
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
0 1.0000000e-01 1.10e+00 1.99e-14 0.0 0.00e+00 - 0.00e+00 0.00e+00 0
Number of Iterations....: 0
(scaled) (unscaled)
Objective...............: 1.0000000000000001e-01 1.0000000000000001e-01
Dual infeasibility......: 1.9885771589406212e-14 1.9885771589406212e-14
Constraint violation....: 1.1000000000000001e+00 1.1000000000000001e+00
Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00
Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00
Overall NLP error.......: 1.1000000000000001e+00 1.1000000000000001e+00
Number of objective function evaluations = 1
Number of objective gradient evaluations = 1
Number of equality constraint evaluations = 1
Number of inequality constraint evaluations = 0
Number of equality constraint Jacobian evaluations = 1
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations = 0
Total seconds in IPOPT = 0.003
EXIT: Maximum Number of Iterations Exceeded.
Similarly, please check the MadNLP.jl documentation and the list of MadNLP.jl options.
solve(ocp, :madnlp; max_iter=0)
This is MadNLP version v0.8.5, running with umfpack
Number of nonzeros in constraint Jacobian............: 3005
Number of nonzeros in Lagrangian Hessian.............: 251
Total number of variables............................: 1004
variables with only lower bounds: 0
variables with lower and upper bounds: 0
variables with only upper bounds: 0
Total number of equality constraints.................: 755
Total number of inequality constraints...............: 0
inequality constraints with only lower bounds: 0
inequality constraints with lower and upper bounds: 0
inequality constraints with only upper bounds: 0
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
0 1.0000000e-01 1.10e+00 2.45e-13 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0
Number of Iterations....: 0
(scaled) (unscaled)
Objective...............: 1.0000000000000001e-01 1.0000000000000001e-01
Dual infeasibility......: 2.4462294465047466e-13 2.4462294465047466e-13
Constraint violation....: 1.1000000000000001e+00 1.1000000000000001e+00
Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00
Overall NLP error.......: 1.1000000000000001e+00 1.1000000000000001e+00
Number of objective function evaluations = 1
Number of objective gradient evaluations = 1
Number of constraint evaluations = 1
Number of constraint Jacobian evaluations = 1
Number of Lagrangian Hessian evaluations = 1
Total wall-clock secs in solver (w/o fun. eval./lin. alg.) = 0.001
Total wall-clock secs in linear solver = 0.002
Total wall-clock secs in NLP function evaluations = 0.001
Total wall-clock secs = 0.004
EXIT: Maximum Number of Iterations Exceeded.