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:
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'
SolversandModelersto solve them.CTFlows.jl uses CTSolvers'
Integratorsto build Hamiltonian flows for indirect methods.
The resolution pipeline once CTDirect has discretized the problem:
DiscretizedModel CTSolvers.Modelers NLP backend CTSolvers.Solvers
(docp) → (build NLP model) → (NLP problem) → (solve) → solutionAll symbols are accessed via qualified module paths — using CTSolvers brings nothing into scope directly.
Extension Loading
CTSolvers loads no backend at startup. Each constructor throws ExtensionError until the corresponding package is loaded:
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.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> 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)
:scimlLoad a backend to unlock its constructor:
using NLPModelsIpopt # loads CTSolversIpopt → enables Solvers.Ipopt
using ADNLPModels # loads CTSolversADNLPModels → enables Modelers.ADNLP
using OrdinaryDiffEqTsit5 # loads CTSolversSciMLIntegrator → enables Integrators.SciMLConfiguring 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:
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?):
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:
CTBase.Strategies.metadata(CTSolvers.Solvers.Ipopt) # inspect all option definitionsStrategyMetadata 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)CTBase.Strategies.options(CTSolvers.Solvers.Ipopt()) # actual values with provenanceStrategyOptions 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
| Topic | Where |
|---|---|
| Module dependencies, type hierarchies, data flow | Architecture |
| Wrapping a new NLP solver | Implementing a Solver |
| Wrapping a new ODE integrator | Implementing an Integrator |
| Adapting a new NLP backend | Implementing a Modeler |
| Connecting a new problem type | Implementing an Optimization Problem |
| All exception types with examples | Error Messages Reference |
| Complete API reference | API Reference (left sidebar) |