Skip to content

Getting Started

Installation

CTSolvers.jl is typically installed as a dependency of another package in the ecosystem (e.g. OptimalControl.jl). To install it directly:

julia
import Pkg
Pkg.add("CTSolvers")

Requires Julia ≥ 1.10.

Mental Model

CTSolvers provides the resolution infrastructure of the control-toolbox ecosystem, consumed by upstream packages:

  • CTDirect.jl discretizes OCPs (defined in CTModels.jl) and uses CTSolvers' Solvers and Modelers to solve them.

  • CTFlows.jl uses CTSolvers' Integrators to build Hamiltonian flows for indirect methods.

The resolution pipeline once CTDirect has discretized the problem:

text
DiscretizedModel    CTSolvers.Modelers     NLP backend      CTSolvers.Solvers
(docp)          →  (build NLP model)  →  (NLP problem)  →  (solve)  →  solution

All symbols are accessed via qualified module pathsusing CTSolvers brings nothing into scope directly.

Extension Loading

CTSolvers loads no backend at startup. Each constructor throws ExtensionError until the corresponding package is loaded:

julia
using CTSolvers
CTSolvers.Solvers.Ipopt()
Ipopt{CPU} (instance, id=:ipopt)
├─ max_iter = 1000  [default]
├─ tol = 1.0e-8  [default]
├─ linear_solver = mumps  [default]
├─ mu_strategy = adaptive  [default]
├─ sb = yes  [default]
└─ print_level = 5  [default]
Tip: use describe(Ipopt) to see all available options.
julia
CTSolvers.Integrators.SciML()
SciML{CPU} (instance, id=:sciml)
├─ internalnorm = real_norm  [default]
├─ alg = Tsit5{typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!), FastBroadcast.Serial}(OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, FastBroadcast.Serial())  [default]
├─ reltol = 1.0e-8  [default]
├─ save_everystep = auto  [default]
├─ abstol = 1.0e-8  [default]
├─ save_start = auto  [default]
└─ dense = auto  [default]
Tip: use describe(SciML) to see all available options.

Strategy identifiers and type information are always available, without any extension:

julia
julia> using CTBase

julia> CTBase.Strategies.id(CTSolvers.Solvers.Ipopt)
:ipopt

julia> CTBase.Strategies.id(CTSolvers.Modelers.ADNLP)
:adnlp

julia> CTBase.Strategies.id(CTSolvers.Integrators.SciML)
:sciml

Load a backend to unlock its constructor:

julia
using NLPModelsIpopt       # loads CTSolversIpopt       → enables Solvers.Ipopt
using ADNLPModels          # loads CTSolversADNLPModels  → enables Modelers.ADNLP
using OrdinaryDiffEqTsit5  # loads CTSolversSciMLIntegrator → enables Integrators.SciML

Configuring Options

Options are validated at construction. Unknown options are rejected with a Levenshtein suggestion; wrong types raise IncorrectArgument.

Without NLPModelsIpopt loaded, all constructor calls raise ExtensionError before option validation runs. A valid construction with the extension loaded:

julia
using NLPModelsIpopt
CTSolvers.Solvers.Ipopt(max_iter = 1000, tol = 1e-8)
Ipopt{CPU} (instance, id=:ipopt)
├─ max_iter = 1000  [user]
├─ tol = 1.0e-8  [user]
├─ linear_solver = mumps  [default]
├─ mu_strategy = adaptive  [default]
├─ sb = yes  [default]
└─ print_level = 5  [default]
Tip: use describe(Ipopt) to see all available options.

An unknown option name — with the extension loaded this raises IncorrectArgument with a Levenshtein suggestion (Did you mean: :max_iter?):

julia
CTSolvers.Solvers.Ipopt(max_itr = 1000)
IncorrectArgument #build_ipopt_solver#88, CTSolversIpopt.jl:575

  Unknown options provided for Ipopt
  
  Unrecognized options: [:max_itr]
  
  These options are not defined in the metadata of Ipopt.
  
  Available options:
    :acceptable_iter,   :acceptable_tol,   :constr_viol_tol,   :derivative_test,   :derivative_test_print_all,   :derivative_test_tol,   :diverging_iterates_tol,   :dual_inf_tol,   :hessian_approximation,   :limited_memory_update_type,   :linear_solver,   :max_cpu_time,   :max_iter,   :max_wall_time,   :mu_init,   :mu_max,   :mu_max_fact,   :mu_min,   :mu_strategy,   :print_frequency_iter,   :print_frequency_time,   :print_level,   :print_timing_statistics,   :sb,   :timing_statistics,   :tol,   :warm_start_bound_push,   :warm_start_init_point,   :warm_start_mult_bound_push
  
  Suggestions for :max_itr:
    - :max_iter (aliases: maxiter, max_iterations, maxit) [distance: 1]
    - :max_wall_time (aliases: maxtime, max_time, time_limit) [distance: 3]
    - :mu_init [distance: 5]
  
  If you are certain these options exist for the backend, you can:
  - bypass validation for a specific option (recommended):
      Ipopt(..., max_itr=bypass(value))   # or force(value)
  - or accept all unknown options with permissive mode:
      Ipopt(..., mode=:permissive)

  Context  build_strategy_options - strict validation
└─

Pass mode = :permissive to warn rather than error on unknown options. Introspect the full option schema and read back values with provenance:

julia
CTBase.Strategies.metadata(CTSolvers.Solvers.Ipopt)    # inspect all option definitions
StrategyMetadata with 29 options:

├─ tol::Real (default: 1.0e-8)
description: Desired convergence tolerance (relative). Determines the convergence tolerance for the algorithm. The algorithm terminates successfully, if the (scaled) NLP error becomes smaller than this value, and if the (absolute) criteria according to dual_inf_tol, constr_viol_tol, and compl_inf_tol are met.

├─ max_iter (maxiter, max_iterations, maxit)::Integer (default: 1000)
description: Maximum number of iterations. The algorithm terminates with a message if the number of iterations exceeded this number.

├─ max_wall_time (maxtime, max_time, time_limit)::Real (default: NotProvided)
description: Maximum number of walltime clock seconds. A limit on walltime clock seconds that Ipopt can use to solve one problem.

├─ max_cpu_time::Real (default: NotProvided)
description: Maximum number of CPU seconds. A limit on CPU seconds that Ipopt can use to solve one problem.

├─ dual_inf_tol::Real (default: NotProvided)
description: Desired threshold for the dual infeasibility. Absolute tolerance on the dual infeasibility. Successful termination requires that the max-norm of the (unscaled) dual infeasibility is less than this threshold.

├─ constr_viol_tol::Real (default: NotProvided)
description: Desired threshold for the constraint and variable bound violation. Absolute tolerance on the constraint and variable bound violation.

├─ acceptable_tol (acc_tol)::Real (default: NotProvided)
description: Acceptable convergence tolerance (relative). Determines which (scaled) optimality error is considered close enough.

├─ acceptable_iter::Integer (default: NotProvided)
description: Number of "acceptable" iterations required to trigger termination. If the algorithm encounters this many consecutive iterations that are acceptable, it terminates.

├─ diverging_iterates_tol::Real (default: NotProvided)
description: Threshold for maximal value of primal iterates. If any component of the primal iterates exceeds this value (in absolute terms), the optimization is aborted.

├─ derivative_test::String (default: NotProvided)
description: Enable derivative check. If enabled, performs a finite difference check of the derivatives.

├─ derivative_test_tol::Real (default: NotProvided)
description: Threshold for identifying incorrect derivatives. If the relative error of the finite difference approximation exceeds this value, an error is reported.

├─ derivative_test_print_all::String (default: NotProvided)
description: Indicates whether information for all estimated derivatives should be printed.

├─ hessian_approximation::String (default: NotProvided)
description: Indicates what Hessian information regarding the Lagrangian function is to be used.

├─ limited_memory_update_type::String (default: NotProvided)
description: Quasi-Newton update method for the limited memory approximation.

├─ warm_start_init_point::String (default: NotProvided)
description: Indicates whether specific warm start values should be used for the primal and dual variables.

├─ warm_start_bound_push::Real (default: NotProvided)
description: Indicates how much the primal variables should be pushed inside the bounds for the warm start.

├─ warm_start_mult_bound_push::Real (default: NotProvided)
description: Indicates how much the dual variables should be pushed inside the bounds for the warm start.

├─ mu_strategy::String (default: adaptive)
description: Barrier parameter update strategy

├─ mu_init::Real (default: NotProvided)
description: Initial value for the barrier parameter.

├─ mu_max_fact::Real (default: NotProvided)
description: Factor for maximal barrier parameter. This factor determines the upper bound on the barrier parameter.

├─ mu_max::Real (default: NotProvided)
description: Maximal value for barrier parameter. This option overrides the factor setting.

├─ mu_min::Real (default: NotProvided)
description: Minimal value for barrier parameter.

├─ timing_statistics::String (default: NotProvided)
description: Indicates whether to measure time spent in components of Ipopt and NLP evaluation. The overall algorithm time is unaffected by this option.

├─ linear_solver::String (default: mumps)
description: Linear solver used for step computations. Determines which linear algebra package is to be used for the solution of the augmented linear system (for obtaining the search directions).

├─ print_level::Integer (default: 5)
description: Ipopt output verbosity (0-12)

├─ print_timing_statistics::String (default: NotProvided)
description: Switch to print timing statistics. If selected, the program will print the time spent for selected tasks. This implies timing_statistics=yes.

├─ print_frequency_iter::Integer (default: NotProvided)
description: Determines at which iteration frequency the summarizing iteration output line should be printed. Summarizing iteration output is printed every print_frequency_iter iterations, if at least print_frequency_time seconds have passed since last output.

├─ print_frequency_time::Real (default: NotProvided)
description: Determines at which time frequency the summarizing iteration output line should be printed. Summarizing iteration output is printed if at least print_frequency_time seconds have passed since last output and the iteration number is a multiple of print_frequency_iter.

└─ sb::String (default: yes)
   description: Suppress Ipopt banner (yes/no)
julia
CTBase.Strategies.options(CTSolvers.Solvers.Ipopt())   # actual values with provenance
StrategyOptions with 6 options:
├─ max_iter = 1000  [default]
├─ tol = 1.0e-8  [default]
├─ linear_solver = mumps  [default]
├─ mu_strategy = adaptive  [default]
├─ sb = yes  [default]
└─ print_level = 5  [default]

Next Steps

TopicWhere
Module dependencies, type hierarchies, data flowArchitecture
Wrapping a new NLP solverImplementing a Solver
Wrapping a new ODE integratorImplementing an Integrator
Adapting a new NLP backendImplementing a Modeler
Connecting a new problem typeImplementing an Optimization Problem
All exception types with examplesError Messages Reference
Complete API referenceAPI Reference (left sidebar)