Skip to content

Your first problem

The shortest complete story: define a problem, solve it, look at the result. Fifteen lines, no options, no theory.

The problem

A point mass moves on a line under a bounded force: state   (position, velocity), scalar control (the force). Starting at rest at   , reach   at rest, in one unit of time, minimising the energy spent:

Define it

julia
using OptimalControl
using NLPModelsIpopt

ocp = @def begin
    t  [0, 1], time
    x  R², state
    u  R, control
    x(0) == [-1, 0]
    x(1) == [0, 0]
(t) == [x₂(t), u(t)]
(0.5u(t)^2)  min
end

See Abstract syntax for what each line above means.

Solve it

julia
sol = solve(ocp)
▫ This is OptimalControl 2.1.0-beta, solving with: collocationadnlpipopt (cpu)

  📦 Configuration:
   ├─ Discretizer: collocation
   ├─ Modeler: adnlp
   └─ Solver: ipopt

▫ This is Ipopt version 3.14.19, running with linear solver MUMPS 5.9.0.

Number of nonzeros in equality constraint Jacobian...:     1754
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:      250

Total number of variables............................:      752
                     variables with only lower bounds:        0
                variables with lower and upper bounds:        0
                     variables with only upper bounds:        0
Total number of equality constraints.................:      504
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  5.0000000e-03 1.10e+00 2.24e-14   0.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  6.0000960e+00 2.22e-16 1.78e-15 -11.0 6.08e+00    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 1

                                   (scaled)                 (unscaled)
Objective...............:   6.0000960015360381e+00    6.0000960015360381e+00
Dual infeasibility......:   1.7763568394002505e-15    1.7763568394002505e-15
Constraint violation....:   2.2204460492503131e-16    2.2204460492503131e-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             = 2
Number of objective gradient evaluations             = 2
Number of equality constraint evaluations            = 2
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 2
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 1
Total seconds in IPOPT                               = 4.019

EXIT: Optimal Solution Found.

Look at it

julia
using Plots
plot(sol; layout=:group)

(layout=:group sidesteps a known upstream bug in the default layout, CTModels.jl#392 — see Plotting for the full story.)

julia
objective(sol), iterations(sol), successful(sol)
(6.000096001536038, 1, true)

control(sol) is a function of time; because the control here is scalar, calling it returns a Number, not a length-1 vector — 1-D is a scalar throughout the package:

julia
control(sol)(0.5)
-0.02400038400614385

See Solution for the rest of what a solution carries, and Plotting for what else plot can show.

What just happened

solve(ocp) was called with no method at all, so it ran the default: (:collocation, :adnlp, :ipopt, :cpu). That default, what the four tokens mean, and how to override any of them, are the subject of Choosing a method.

Next

  • Choosing a method — pick a different solver, modeler, or grid.

  • Guided tour — the same problem in more depth, plus the indirect (Pontryagin) method and a second, harder problem.

  • Example gallery — worked problems covering singular arcs, state constraints, free variables, and more.