Qualified access
These names are not exported by using OptimalControl, but they are reachable as OptimalControl.X.
A handful of module names are re-exported purely as escape hatches for generated code and cross-package qualification — CTBase, CTLie, CTFlows, CTModels, ADNLPModels, ExaModels. They carry no documentation of their own; see Ecosystem for what each package is for.
CTDirect.Collocation (the ADNLP/Exa discretizer, selected via discretizer=CTDirect.Collocation()) has no docstring upstream yet — tracked in control-toolbox/CTDirect.jl#623.
CTModels.Building.PreModel Type
mutable struct PreModel <: CTModels.Models.AbstractModelMutable optimal control problem model under construction.
A PreModel is used to incrementally define an optimal control problem before building it into an immutable CTModels.Models.Model. Fields can be set in any order and the model is validated before building.
Fields
times::Union{AbstractTimesModel,Nothing}: Initial and final time specification.state::Union{AbstractStateModel,Nothing}: State variable structure.control::AbstractControlModel: Control variable structure (defaults toEmptyControlModel(), i.e. no control).variable::AbstractVariableModel: Optimisation variable (defaults to empty).dynamics::Union{Function,Vector,Nothing}: System dynamics (function or component-wise).objective::Union{AbstractObjectiveModel,Nothing}: Cost functional.constraints::ConstraintsDictType: Dictionary of constraints being built.definition::AbstractDefinition: Symbolic definition; defaults toCTModels.Components.EmptyDefinitionand becomes aCTModels.Components.Definitionwhendefinition!is called with a real expression.autonomous::Union{Bool,Nothing}: Whether the system is autonomous.
Example
julia> using CTModels
julia> pre = CTModels.PreModel()
julia> # Set fields incrementally...CTModels.Models.Model Type
struct Model{TD<:CTBase.Traits.TimeDependence, TimesModelType<:CTModels.Components.AbstractTimesModel, StateModelType<:CTModels.Components.AbstractStateModel, ControlModelType<:CTModels.Components.AbstractControlModel, VariableModelType<:CTModels.Components.AbstractVariableModel, DynamicsModelType<:Function, ObjectiveModelType<:CTModels.Components.AbstractObjectiveModel, ConstraintsModelType<:CTModels.Components.AbstractConstraintsModel, DefinitionType<:CTModels.Components.AbstractDefinition, BuildExaModelType<:Union{Nothing, Function}} <: CTModels.Models.AbstractModelImmutable optimal control problem model containing all problem components.
A Model is created from a PreModel once all required fields have been set. It is parameterised by the time dependence type (Autonomous or NonAutonomous) and the types of all its components.
Fields
times::TimesModelType: Initial and final time specification.state::StateModelType: State variable structure (name, components).control::ControlModelType: Control variable structure (name, components).variable::VariableModelType: Optimisation variable structure (may be empty).dynamics::DynamicsModelType: System dynamics function(t, x, u, v) -> ẋ.objective::ObjectiveModelType: Cost functional (Mayer, Lagrange, or Bolza).constraints::ConstraintsModelType: All problem constraints.definition::DefinitionType: Original symbolic definition of the problem.build_examodel::BuildExaModelType: Optional ExaModels builder function.
CTModels.Solutions.Solution Type
struct Solution{TimeGridModelType<:CTModels.Solutions.AbstractTimeGridModel, TimesModelType<:CTModels.Components.AbstractTimesModel, StateModelType<:CTModels.Components.AbstractStateModel, ControlModelType<:CTModels.Components.AbstractControlModel, VariableModelType<:CTModels.Components.AbstractVariableModel, ModelType<:CTModels.Models.AbstractModel, CostateModelType<:Function, ObjectiveValueType<:Real, DualModelType<:CTModels.Solutions.AbstractDualModel, SolverInfosType<:CTModels.Solutions.AbstractSolverInfos} <: CTModels.Solutions.AbstractSolutionComplete solution of an optimal control problem.
Stores the optimal state, control, and costate trajectories, the optimisation variable value, objective value, dual variables, and solver information.
Fields
time_grid::TimeGridModelType: Discretised time points.times::TimesModelType: Initial and final time specification.state::StateModelType: State trajectoryt -> x(t)with metadata.control::ControlModelType: Control trajectoryt -> u(t)with metadata.variable::VariableModelType: Optimisation variable value with metadata.model::ModelType: Reference to the optimal control problem model.costate::CostateModelType: Costate (adjoint) trajectoryt -> p(t).objective::ObjectiveValueType: Optimal objective value.dual::DualModelType: Dual variables for all constraints.solver_infos::SolverInfosType: Solver statistics and status.
Example
julia> using CTModels
julia> # Solutions are typically returned by solvers
julia> sol = solve(ocp, ...) # Returns a Solution
julia> CTModels.objective(sol)CTModels.Solutions.AbstractSolution Type
abstract type AbstractSolutionAbstract base type for optimal control problem solutions.
Subtypes store the complete solution including primal trajectories, dual variables, and solver information.
See also: CTModels.Solutions.Solution.
CTModels.Init.AbstractInitialGuess Type
abstract type AbstractInitialGuessAbstract base type for initial guesses used in optimal control problem solvers.
Subtypes provide initial trajectories for state, control, and optimisation variables to warm-start numerical solvers.
See also: CTModels.Init.InitialGuess, CTModels.Init.PreInitialGuess.
CTModels.Init.InitialGuess Type
struct InitialGuess{X<:Function, U<:Function, V} <: CTModels.Init.AbstractInitialGuessConcrete initial guess for an optimal control problem, storing callable trajectories for state and control, and a value for the optimisation variable.
Fields
state::X: A functiont -> x(t)returning the state guess at timet.control::U: A functiont -> u(t)returning the control guess at timet.variable::V: The initial guess for the optimisation variable (scalar or vector).
Example
julia> using CTModels
julia> x_guess = t -> [cos(t), sin(t)]
julia> u_guess = t -> [0.5]
julia> v_guess = [1.0, 2.0]
julia> ig = CTModels.InitialGuess(x_guess, u_guess, v_guess)See also: CTModels.Init.AbstractInitialGuess, CTModels.Init.PreInitialGuess.
CTSolvers.Modelers.ADNLP Type
struct ADNLP{P<:CPU} <: CTSolvers.Modelers.AbstractNLPModelerModeler for building ADNLPModels from discretized optimal control problems.
This modeler uses the ADNLPModels.jl package to create NLP models with automatic differentiation support. It provides configurable options for timing information, AD backend selection, memory optimization, and model identification.
Parameterized Types
The modeler supports parameterization for execution backend:
ADNLP{CPU}: CPU execution (default and only supported parameter)
Note: Unlike Exa, MadNLP, and MadNCL, this modeler only supports CPU execution. GPU execution is not available for ADNLP.
Constructors
# Default constructor (CPU)
Modelers.ADNLP(; mode::Symbol=:strict, kwargs...)
# Explicit parameter specification (only CPU supported)
Modelers.ADNLP{CPU}(; mode::Symbol=:strict, kwargs...)Arguments
mode::Symbol=:strict: Validation mode (:strictor:permissive):strict(default): Rejects unknown options with detailed error message:permissive: Accepts unknown options with warning, stores with:usersource
kwargs...: Modeler options (see Options section)
Parameter Behavior
CPU Parameter (Default)
The CPU parameter indicates standard CPU-based execution:
Uses CPU-optimized automatic differentiation backends
No GPU acceleration available
Compatible with all standard Julia environments
Default AD backend:
:optimized
Options
Basic Options
show_time::Bool: Enable timing information for model building (default:false)backend::Symbol: AD backend to use (default::optimized)matrix_free::Bool: Enable matrix-free mode (default:false)name::String: Model name for identification (default:"CTSolvers-ADNLP")
Advanced Backend Overrides (expert users)
Each backend option accepts nothing (use default), a Type{<:ADBackend} (constructed by ADNLPModels), or an ADBackend instance (used directly).
gradient_backend: Override backend for gradient computationhprod_backend: Override backend for Hessian-vector productjprod_backend: Override backend for Jacobian-vector productjtprod_backend: Override backend for transpose Jacobian-vector productjacobian_backend: Override backend for Jacobian matrix computationhessian_backend: Override backend for Hessian matrix computationghjvprod_backend: Override backend for g^T ∇²c(x)v computation
Examples
Basic Usage
# Default modeler (CPU)
modeler = Modelers.ADNLP()
# Explicit CPU specification
modeler = Modelers.ADNLP{CPU}()
# With custom options
modeler = Modelers.ADNLP(
backend=:optimized,
matrix_free=true,
name="MyOptimizationProblem"
)Invalid Usage
# GPU is NOT supported - will throw IncorrectArgument
modeler = Modelers.ADNLP{GPU}() # ❌ Error!Advanced Backend Configuration
# Override with nothing (use default)
modeler = Modelers.ADNLP(
gradient_backend=nothing,
hessian_backend=nothing
)
# Override with a Type (ADNLPModels constructs it)
modeler = Modelers.ADNLP(
gradient_backend=ADNLPModels.ForwardDiffADGradient
)
# Override with an instance (used directly)
modeler = Modelers.ADNLP(
gradient_backend=ADNLPModels.ForwardDiffADGradient()
)Validation Modes
# Strict mode (default) - rejects unknown options
modeler = Modelers.ADNLP(backend=:optimized)
# Permissive mode - accepts unknown options with warning
modeler = Modelers.ADNLP(
backend=:optimized,
custom_option=123;
mode=:permissive
)Throws
CTBase.Exceptions.IncorrectArgument: If GPU or other unsupported parameter is specifiedCTBase.Exceptions.IncorrectArgument: If option validation failsCTBase.Exceptions.IncorrectArgument: If invalid mode is provided
See also
CPU: CPU parameter typeModelers.Exa: Alternative modeler using ExaModels (supports GPU)Optimization.build_model: Build a backend NLP model from a problem and a modelerOptimization.build_solution: Build a problem-level solution from execution statistics
Notes
The
backendoption supports::default,:optimized,:generic,:enzyme,:zygoteAdvanced backend overrides are for expert users only
Matrix-free mode reduces memory usage but may increase computation time
Model name is used for identification in solver output
References
ADNLPModels.jl: https://github.com/JuliaSmoothOptimizers/ADNLPModels.jl
Automatic Differentiation in Julia: https://github.com/JuliaDiff/
CTSolvers.Modelers.Exa Type
struct Exa{P<:Union{CPU, GPU}} <: CTSolvers.Modelers.AbstractNLPModelerModeler for building ExaModels from discretized optimal control problems.
This modeler uses the ExaModels.jl package to create NLP models with support for various execution backends (CPU, GPU) and floating-point types.
Parameterized Types
The modeler supports parameterization for execution backend:
Exa{CPU}: CPU execution (default)Exa{GPU}: GPU execution (requires CUDA.jl)
Constructors
# Default constructor (CPU)
Modelers.Exa(; mode::Symbol=:strict, kwargs...)
# Explicit parameter specification
Modelers.Exa{CPU}(; mode::Symbol=:strict, kwargs...)
Modelers.Exa{GPU}(; mode::Symbol=:strict, kwargs...)Arguments
mode::Symbol=:strict: Validation mode (:strictor:permissive):strict(default): Rejects unknown options with detailed error message:permissive: Accepts unknown options with warning, stores with:usersource
kwargs...: Modeler options (see Options section)
Options
Basic Options
base_type::Type{<:AbstractFloat}: Floating-point type (default:Float64)backend: Execution backend (default depends on parameter:nothingfor CPU, CUDA backend for GPU)
Examples
Basic Usage
# Default modeler (Float64, CPU)
modeler = Modelers.Exa()
# Explicit CPU modeler
modeler = Modelers.Exa{CPU}()
# GPU modeler (requires CUDA.jl)
modeler = Modelers.Exa{GPU}()Type Specification
# Single precision
modeler = Modelers.Exa(base_type=Float32)
# Double precision (default)
modeler = Modelers.Exa(base_type=Float64)Backend Configuration
# CPU backend (default for Exa{CPU})
modeler = Modelers.Exa{CPU}(backend=nothing)
# GPU backend (default for Exa{GPU})
modeler = Modelers.Exa{GPU}() # Uses CUDA backend automaticallyValidation Modes
# Strict mode (default) - rejects unknown options
modeler = Modelers.Exa(base_type=Float64)
# Permissive mode - accepts unknown options with warning
modeler = Modelers.Exa(
base_type=Float64,
custom_option=123;
mode=:permissive
)Complete Configuration
# Full configuration with type and backend
modeler = Modelers.Exa{GPU}(
base_type=Float32;
mode=:permissive
)Throws
CTBase.Exceptions.IncorrectArgument: If option validation failsCTBase.Exceptions.IncorrectArgument: If invalid mode is providedCTBase.Exceptions.ExtensionError: If GPU backend requested but CUDA not available
See also
Modelers.ADNLP: Alternative modeler using ADNLPModelsbuild_model: Build model from problem and modelersolve!: Solve optimization problemCPU,GPU: Strategy parameters
Notes
The
base_typeoption affects the precision of all computationsCPU backend (
backend=nothing) is always availableGPU backends require CUDA.jl to be loaded and functional
ExaModels.jl provides efficient GPU acceleration for large problems
Default backend is automatically selected based on the parameter type
References
ExaModels.jl: https://github.com/JuliaSmoothOptimizers/ExaModels.jl
KernelAbstractions.jl: https://github.com/JuliaGPU/KernelAbstractions.jl
CTSolvers.Solvers.Ipopt Type
struct Ipopt{P<:CPU} <: CTSolvers.Solvers.AbstractNLPSolverInterior point optimization solver using the Ipopt backend.
Ipopt (Interior Point OPTimizer) is an open-source software package for large-scale nonlinear optimization. It implements a primal-dual interior point method with proven global convergence properties.
Parameterized Types
The solver supports parameterization for execution backend:
Ipopt{CPU}: CPU execution (default and only supported parameter)
Note: Unlike MadNLP and MadNCL, this solver only supports CPU execution. GPU execution is not available for Ipopt.
Constructors
# Default constructor (CPU)
Solvers.Ipopt(; mode::Symbol=:strict, kwargs...)
# Explicit parameter specification (only CPU supported)
Solvers.Ipopt{CPU}(; mode::Symbol=:strict, kwargs...)Fields
options::CTBase.Strategies.StrategyOptions: Solver configuration options containing validated option values
Parameter Behavior
CPU Parameter (Default)
The CPU parameter indicates standard CPU-based execution:
Uses Ipopt's standard interior point algorithm
No GPU acceleration available
Compatible with all standard Julia environments
Proven global convergence properties
Solver Options
Solver options are defined in the CTSolversIpopt extension. Load the extension to access option definitions and documentation:
using NLPModelsIpoptExamples
Basic Usage
# Conceptual usage pattern (requires NLPModelsIpopt extension)
using NLPModelsIpopt
# Default solver (CPU)
solver = Ipopt(max_iter=1000, tol=1e-6, print_level=3)
# Explicit CPU specification
solver_cpu = Ipopt{CPU}(max_iter=1000, tol=1e-6)
nlp = ADNLPModel(x -> sum(x.^2), zeros(10))
stats = solver(nlp, display=true)Invalid Usage
# GPU is NOT supported - will throw IncorrectArgument
solver = Ipopt{GPU}() # ❌ Error!Extension Required
This solver requires the NLPModelsIpopt package to be loaded:
using NLPModelsIpoptImplementation Notes
Implements the
AbstractStrategycontract viaStrategies.id()Metadata and constructor implementation provided by CTSolversIpopt extension
Options are validated at construction time using enriched
Exceptions.IncorrectArgumentCallable interface:
(solver::Ipopt)(nlp; display=true)provided by extension
Throws
CTBase.Exceptions.IncorrectArgument: If GPU or other unsupported parameter is specifiedCTBase.Exceptions.ExtensionError: If the NLPModelsIpopt extension is not loaded
See also: CPU, AbstractNLPSolver, MadNLP, Knitro
CTSolvers.Solvers.MadNLP Type
struct MadNLP{P<:Union{CPU, GPU}} <: CTSolvers.Solvers.AbstractNLPSolverPure-Julia interior point solver with GPU support.
MadNLP is a modern implementation of an interior point method written entirely in Julia, with support for GPU acceleration and various linear solver backends. It provides excellent performance for large-scale optimization problems.
Parameterized Types
The solver supports parameterization for execution backend:
MadNLP{CPU}: CPU execution (default)MadNLP{GPU}: GPU execution (requires CUDA.jl)
Fields
options::CTBase.Strategies.StrategyOptions: Solver configuration options containing validated option values
Solver Options
max_iter::Integer: Maximum number of iterations (default: 3000, must be ≥ 0)tol::Real: Convergence tolerance (default: 1e-8, must be > 0)print_level::MadNLP.LogLevels: MadNLP log level (default: MadNLP.INFO)MadNLP.DEBUG: Detailed debugging output
MadNLP.INFO: Standard informational output
MadNLP.WARN: Warning messages only
MadNLP.ERROR: Error messages only
linear_solver::Type{<:MadNLP.AbstractLinearSolver}: Linear solver backendDefault for CPU:
MadNLP.MumpsSolverDefault for GPU:
MadNLPGPU.CUDSSSolver(requires MadNLPGPU.jl)
backend: Execution backend (default depends on parameter: CPU backend for CPU, CUDA backend for GPU)
Example
# Conceptual usage pattern (requires MadNLP extension)
using MadNLP
solver = MadNLP(max_iter=1000, tol=1e-6, print_level=MadNLP.DEBUG)
nlp = ADNLPModel(x -> sum(x.^2), zeros(10))
stats = solver(nlp, display=true)Extension Required
This solver requires the MadNLP package:
using MadNLPImplementation Notes
Implements the
AbstractStrategycontract viaStrategies.id,Strategies.metadata, andStrategies.optionsOptions are validated at construction time using enriched
Exceptions.IncorrectArgumentCallable interface:
(solver::MadNLP{P}(nlp; display=true)Supports GPU acceleration when appropriate backends are loaded
Default backend is automatically selected based on the parameter type
GPU linear solver: When using
MadNLP{GPU}, the linear solver automatically defaults toMadNLPGPU.CUDSSSolverinstead ofMadNLP.MumpsSolver. This ensures compatibility with GPU execution and avoids attempting to use CPU-only solvers on CUDA backends.
See also: AbstractNLPSolver, Ipopt, Solvers.MadNCL, CPU, GPU
CTSolvers.Solvers.MadNCL Type
struct MadNCL{P<:Union{CPU, GPU}} <: CTSolvers.Solvers.AbstractNLPSolverNCL (Non-Convex Lagrangian) variant of MadNLP solver.
MadNCL extends MadNLP with specialized handling for non-convex problems using a modified Lagrangian approach, providing improved convergence for challenging nonlinear optimization problems.
Parameterized Types
The solver supports parameterization for execution backend:
MadNCL{CPU}: CPU execution (default)MadNCL{GPU}: GPU execution (requires CUDA.jl)
Fields
options::CTBase.Strategies.StrategyOptions: Solver configuration options containing validated option values
Solver Options
Solver options are defined in the CTSolversMadNCL extension. Load the extension to access option definitions and documentation:
using MadNCL, MadNLPExample
# Conceptual usage pattern (requires MadNCL, MadNLP extensions)
using MadNCL, MadNLP
solver = Solvers.MadNCL(max_iter=1000, tol=1e-6, print_level=MadNLP.DEBUG)
nlp = ADNLPModel(x -> sum(x.^2), zeros(10))
stats = solver(nlp, display=true)Extension Required
This solver requires the MadNCL package:
using MadNCL, MadNLPImplementation Notes
Implements the
AbstractStrategycontract viaStrategies.id,Strategies.metadata, andStrategies.optionsOptions are validated at construction time using enriched
Exceptions.IncorrectArgumentCallable interface:
(solver::MadNCL{P})(nlp; display=true)Extends MadNLP with NCL-specific optimizations
Default backend is automatically selected based on the parameter type
GPU linear solver: When using
MadNCL{GPU}, the linear solver automatically defaults toMadNLPGPU.CUDSSSolverinstead ofMadNLP.MumpsSolver. This ensures compatibility with GPU execution and avoids attempting to use CPU-only solvers on CUDA backends.
See also: AbstractNLPSolver, MadNLP, Ipopt, CPU, GPU
CTSolvers.Solvers.Knitro Type
struct Knitro{P<:CPU} <: CTSolvers.Solvers.AbstractNLPSolverCommercial optimization solver with advanced algorithms.
Knitro is a commercial solver offering state-of-the-art algorithms for nonlinear optimization, including interior point, active set, and SQP methods. It provides excellent performance and robustness for large-scale problems.
Parameterized Types
The solver supports parameterization for execution backend:
Knitro{CPU}: CPU execution (default and only supported parameter)
Note: Unlike MadNLP and MadNCL, this solver only supports CPU execution. GPU execution is not available for Knitro.
Constructors
# Default constructor (CPU)
Solvers.Knitro(; mode::Symbol=:strict, kwargs...)
# Explicit parameter specification (only CPU supported)
Solvers.Knitro{CPU}(; mode::Symbol=:strict, kwargs...)Fields
options::CTBase.Strategies.StrategyOptions: Solver configuration options containing validated option values
Parameter Behavior
CPU Parameter (Default)
The CPU parameter indicates standard CPU-based execution:
Uses Knitro's advanced optimization algorithms
No GPU acceleration available
Compatible with all standard Julia environments
Requires valid Knitro license
Solver Options
Solver options are defined in the CTSolversKnitro extension. Load the extension to access option definitions and documentation:
using NLPModelsKnitroExamples
Basic Usage
# Conceptual usage pattern (requires NLPModelsKnitro extension)
using NLPModelsKnitro
# Default solver (CPU)
solver = Knitro(maxit=1000, maxtime=3600, ftol=1e-10, outlev=2)
# Explicit CPU specification
solver_cpu = Knitro{CPU}(maxit=1000, outlev=2)
nlp = ADNLPModel(x -> sum(x.^2), zeros(10))
stats = solver(nlp, display=true)Invalid Usage
# GPU is NOT supported - will throw IncorrectArgument
solver = Knitro{GPU}() # ❌ Error!Extension Required
This solver requires the NLPModelsKnitro package:
using NLPModelsKnitroNote: Knitro is a commercial solver requiring a valid license.
Implementation Notes
Implements the
AbstractStrategycontract viaStrategies.id()Metadata and constructor implementation provided by CTSolversKnitro extension
Options are validated at construction time using enriched
Exceptions.IncorrectArgumentCallable interface:
(solver::Knitro)(nlp; display=true)provided by extensionRequires valid Knitro license for operation
Throws
CTBase.Exceptions.IncorrectArgument: If GPU or other unsupported parameter is specifiedCTBase.Exceptions.ExtensionError: If the NLPModelsKnitro extension is not loaded
See also: CPU, AbstractNLPSolver, Ipopt, MadNLP
CTSolvers.Solvers.Uno Type
struct Uno{P<:CPU} <: CTSolvers.Solvers.AbstractNLPSolverUnified nonlinear optimization solver using the Uno backend.
Uno (Unifying Nonlinear Optimization) is a C++ library that unifies Lagrange-Newton methods (essentially SQP and interior-point) by breaking them down into modular building blocks. It solves nonlinearly constrained optimization problems by iteratively solving the optimality (KKT) conditions with Newton's method.
Unification Framework
Uno implements a modular framework with the following strategies:
Constraint relaxation: feasibility restoration
Inequality handling: inequality constrained method, interior-point method
Hessian models: exact, L-BFGS, identity, zero
Inertia control: primal, primal-dual, none
Globalization strategies: filter method, funnel method, merit function
Globalization mechanisms: backtracking line search, trust-region method
Presets
Uno provides presets that mimic existing solvers:
"ipopt": Line-search feasibility restoration filter barrier method with exact Hessian and primal-dual inertia correction (mimics IPOPT)"filtersqp": Trust-region feasibility restoration filter SQP method with exact Hessian (mimics filterSQP)
Parameterized Types
The solver supports parameterization for execution backend:
Uno{CPU}: CPU execution (default and only supported parameter)
Note: This solver only supports CPU execution with ADNLP modeler. GPU execution is not available for Uno.
Constructors
# Default constructor (CPU)
Solvers.Uno(; mode::Symbol=:strict, kwargs...)
# Explicit parameter specification (only CPU supported)
Solvers.Uno{CPU}(; mode::Symbol=:strict, kwargs...)Fields
options::CTBase.Strategies.StrategyOptions: Solver configuration options containing validated option values
Parameter Behavior
CPU Parameter (Default)
The CPU parameter indicates standard CPU-based execution:
Uses Uno's unified algorithmic framework
Supports multiple presets (ipopt, filtersqp)
Compatible with ADNLP modeler only
No GPU acceleration available
Solver Options
Solver options are defined in the CTSolversUno extension. Load the extension to access option definitions and documentation:
using UnoSolverExamples
Basic Usage
# Conceptual usage pattern (requires UnoSolver extension)
using UnoSolver
# Default solver (CPU) with ipopt preset
solver = Uno(max_iterations=1000, primal_tolerance=1e-6, preset="ipopt")
# Using filtersqp preset
solver_sqp = Uno(max_iterations=1000, preset="filtersqp")
# Explicit CPU specification
solver_cpu = Uno{CPU}(max_iterations=1000, dual_tolerance=1e-6)
nlp = ADNLPModel(x -> sum(x.^2), zeros(10))
stats = solver(nlp, display=true)Invalid Usage
# GPU is NOT supported - will throw IncorrectArgument
solver = Uno{GPU}() # ❌ Error!Extension Required
This solver requires the UnoSolver package to be loaded:
using UnoSolverImplementation Notes
Implements the
AbstractStrategycontract viaStrategies.id()Metadata and constructor implementation provided by CTSolversUno extension
Options are validated at construction time using enriched
Exceptions.IncorrectArgumentCallable interface:
(solver::Uno)(nlp; display=true)provided by extensionOnly compatible with ADNLP modeler (not ExaModeler)
Based on the unified framework described in Vanaret & Leyffer (2026)
Throws
CTBase.Exceptions.IncorrectArgument: If GPU or other unsupported parameter is specifiedCTBase.Exceptions.ExtensionError: If the UnoSolver extension is not loaded
References
Vanaret, C., & Leyffer, S. (2026). Implementing a unified solver for nonlinearly constrained optimization. Mathematical Programming Computation (accepted).
See also: CPU, AbstractNLPSolver, Ipopt, MadNLP
CTSolvers.DOCP.AbstractDiscretizer Type
abstract type AbstractDiscretizer <: CTBase.Strategies.AbstractStrategyAbstract base type for all discretization strategies.
Concrete subtypes implement specific transcription methods (collocation, direct shooting, etc.) and are defined in the package providing the method. A discretizer is a Strategies.AbstractStrategy: it carries validated options and drives discretize to turn an optimal control problem into a DiscretizedModel.
See also: DiscretizedModel, discretize.
CTSolvers.DOCP.DiscretizedModel Type
struct DiscretizedModel{TO<:CTModels.Models.AbstractModel, TD<:CTSolvers.DOCP.AbstractDiscretizer, TC<:CTBase.Core.AbstractCache} <: CTSolvers.Optimization.AbstractOptimizationProblemDiscretized optimal control problem ready for NLP solving.
A thin pairing of an optimal control problem with the discretizer that produced it, plus a backend cache. The actual NLP model and OCP solution are produced by multiple dispatch on (DiscretizedModel, modeler) through the build_model / build_solution contract, implemented in the package providing the discretizer (e.g. CTDirect). This mirrors Flow{system, integrator} on the ODE side.
Fields
ocp::TO: The original optimal control problem.discretizer::TD: The discretization strategy used.cache::TC: Backend cache (<: CTBase.Core.AbstractCache), opaque to CTSolvers, populated by the implementing package (e.g. CTDirect'sDOCPCache).
Type parameters
TO <: CTModels.AbstractModelTD <: AbstractDiscretizerTC <: CTBase.Core.AbstractCache
See also: ocp_model, discretize, build_model, build_solution.
CTSolvers.Modelers.AbstractNLPModeler Type
abstract type AbstractNLPModeler <: CTBase.Strategies.AbstractStrategyAbstract base type for all modeler strategies.
Modeler strategies are responsible for converting discretized optimization problems (Optimization.AbstractOptimizationProblem) into NLP backend models. They implement the Strategies.AbstractStrategy contract together with named model- and solution-building methods.
Implementation Requirements
All concrete modeler strategies must:
Implement the
Strategies.AbstractStrategycontractHave the package providing the problem implement, by multiple dispatch:
Optimization.build_model(prob, initial_guess, modeler)returning aOptimization.BuiltModelOptimization.build_solution(built::Optimization.BuiltModel, nlp_solution, modeler)
Example
struct MyModeler <: AbstractNLPModeler
options::Strategies.StrategyOptions
end
Strategies.id(::Type{<:MyModeler}) = :my_modeler
# In the package providing the concrete problem type:
function Optimization.build_model(prob::MyProblem, initial_guess, modeler::MyModeler)
# Build NLP model from problem and initial guess
nlp = ...
return Optimization.BuiltModel(prob, nlp, Optimization.NoCache())
end
function Optimization.build_solution(built::Optimization.BuiltModel{<:MyProblem}, nlp_solution, ::MyModeler)
# Reconstruct the problem-level solution from built and nlp_solution
return solution
endSee also: Strategies.AbstractStrategy, Optimization.build_model, Optimization.build_solution
CTSolvers.Solvers.AbstractNLPSolver Type
abstract type AbstractNLPSolver <: CTBase.Strategies.AbstractStrategyAbstract base type for optimization solvers in the Control Toolbox.
All concrete solver types must: 2. Be a subtype of AbstractNLPSolver
- Implement the
AbstractStrategycontract:
Strategies.id(::Type{<:MySolver})- Return unique Symbol identifierStrategies.metadata(::Type{<:MySolver})- Return StrategyMetadata with optionsHave an
options::Strategies.StrategyOptionsfield
- Implement the solve method (typically in a backend extension):
CommonSolve.solve(nlp::NLPModels.AbstractNLPModel, solver::MySolver; display=Bool)
Solver Types
Solvers.Ipopt- Interior point optimizer (Ipopt backend)Solvers.MadNLP- Matrix-free augmented Lagrangian (MadNLP backend)Solvers.MadNCL- NCL variant of MadNLPSolvers.Knitro- Commercial solver (Knitro backend)
Example
using CommonSolve
# Create solver with options
solver = Solvers.Ipopt(max_iter=1000, tol=1e-8)
# Solve an NLP problem
nlp = ADNLPModel(x -> sum(x.^2), zeros(10))
stats = solve(nlp, solver; display=true)See also: Solvers.Ipopt, Solvers.MadNLP, Solvers.MadNCL, Solvers.Knitro, CommonSolve.solve
CTLie.LiftedHamiltonianFunction Type
struct LiftedHamiltonianFunction{F, TD, VD} <: FunctionCallable struct representing the lifted Hamiltonian H(…) = p' * f(…).
Replaces the four argument-reordering closures previously returned by _Lift. TD and VD are compile-time trait parameters, so dispatch to the correct call method is resolved at compile time — no allocation per call.
Inherits from Function so that it satisfies the F<:Function constraint of Data.Hamiltonian and passes existing isa Function checks.
CTBase.Exceptions.CTException Type
abstract type CTException <: ExceptionAbstract supertype for all CTBase exceptions.
All exceptions in the CTBase ecosystem inherit from this type, enabling uniform error handling via a single catch clause.
Example
julia> using CTBase
julia> try
throw(CTBase.Exceptions.IncorrectArgument("invalid input"))
catch e
e isa CTBase.Exceptions.CTException || rethrow()
println("Caught: ", e)
end
Caught: IncorrectArgument: invalid inputSee also: CTBase.Exceptions.IncorrectArgument, CTBase.Exceptions.NotImplemented
CTBase.Exceptions.IncorrectArgument Type
struct IncorrectArgument <: CTBase.Exceptions.CTExceptionException thrown when an individual argument is invalid or violates a constraint.
Use when the problem is with the input data itself (wrong range, duplicate, empty collection, type mismatch) rather than the calling context or system state.
Fields
msg::String: Main error message describing the problem.got::Union{String, Nothing}: The invalid value received (optional).expected::Union{String, Nothing}: What was expected (optional).suggestion::Union{String, Nothing}: How to fix the problem (optional).context::Union{String, Nothing}: Where the error occurred (optional).
Example
julia> using CTBase
julia> throw(CTBase.Exceptions.IncorrectArgument("the argument must be a non-empty tuple"))
ERROR: IncorrectArgument: the argument must be a non-empty tupleWith optional fields:
throw(CTBase.Exceptions.IncorrectArgument(
"Dimension mismatch",
got="vector of length 3",
expected="vector of length 2",
suggestion="Provide a vector matching the state dimension",
context="initial_guess for state",
))See also: CTBase.Exceptions.AmbiguousDescription, CTBase.Exceptions.PreconditionError
CTBase.Exceptions.PreconditionError Type
struct PreconditionError <: CTBase.Exceptions.CTExceptionException thrown when a function call violates a precondition or is not allowed in the current state of the system.
Use when the arguments are valid but the call is forbidden because of when or how it is made (e.g., calling a method twice, missing a required prior setup step). Distinct from CTBase.Exceptions.IncorrectArgument, which signals a problem with the input values themselves.
Fields
msg::String: Main error message.reason::Union{String, Nothing}: Why the precondition failed (optional).suggestion::Union{String, Nothing}: How to fix the problem (optional).context::Union{String, Nothing}: Where the error occurred (optional).
Example
julia> using CTBase
julia> throw(CTBase.Exceptions.PreconditionError("state must be set before dynamics"))
ERROR: PreconditionError: state must be set before dynamicsWith optional fields:
throw(CTBase.Exceptions.PreconditionError(
"Cannot call state! twice",
reason="state has already been defined for this OCP",
suggestion="Create a new OCP instance",
context="state definition",
))See also: CTBase.Exceptions.IncorrectArgument, CTBase.Exceptions.NotImplemented
CTBase.Exceptions.NotImplemented Type
struct NotImplemented <: CTBase.Exceptions.CTExceptionException thrown to mark interface points that must be implemented by concrete subtypes.
Use when a default method on an abstract type should explicitly signal that a concrete subtype has not provided the required implementation. Prefer this over a generic error("not implemented") to give users a typed, catchable error.
Fields
msg::String: Description of what is not implemented.required_method::Union{String, Nothing}: The missing method signature (optional).suggestion::Union{String, Nothing}: How to fix the problem (optional).context::Union{String, Nothing}: Where the error occurred (optional).
Example
julia> using CTBase
julia> throw(CTBase.Exceptions.NotImplemented("feature X is not implemented"))
ERROR: NotImplemented: feature X is not implementedTypical interface stub pattern:
abstract type MyAbstractAlgorithm end
function run!(algo::MyAbstractAlgorithm, state)
throw(CTBase.Exceptions.NotImplemented(
"run! is not implemented for $(typeof(algo))",
required_method="run!(::MyAbstractAlgorithm, state)",
suggestion="Implement run! for your concrete algorithm type",
context="algorithm execution",
))
endSee also: CTBase.Exceptions.IncorrectArgument, CTBase.Exceptions.PreconditionError
CTBase.Exceptions.ParsingError Type
struct ParsingError <: CTBase.Exceptions.CTExceptionException thrown during parsing when a syntax error or invalid structure is detected.
Use when the structure or syntax of the input is invalid (e.g., DSL grammar violation). For semantic errors on a valid-syntax input, prefer CTBase.Exceptions.IncorrectArgument instead.
Fields
msg::String: Description of the parsing error.location::Union{String, Nothing}: Where in the input the error occurred (optional).suggestion::Union{String, Nothing}: How to fix the problem (optional).
Example
julia> using CTBase
julia> throw(CTBase.Exceptions.ParsingError("unexpected token 'end'"))
ERROR: ParsingError: unexpected token 'end'With optional fields:
throw(CTBase.Exceptions.ParsingError(
"Unexpected token 'end'",
location="line 42, column 15",
suggestion="Check syntax balance or remove extra 'end'",
))See also: CTBase.Exceptions.IncorrectArgument, CTBase.Exceptions.AmbiguousDescription
CTBase.Exceptions.AmbiguousDescription Type
struct AmbiguousDescription <: CTBase.Exceptions.CTExceptionException thrown when a description (a tuple of Symbols) cannot be matched to any known valid description in a catalogue.
Raised by CTBase.Descriptions.complete when the partial description provided by the user is not a subset of any catalogue entry.
Fields
msg::String: Main error message.description::Tuple{Vararg{Symbol}}: The ambiguous or unrecognised description tuple.candidates::Union{Vector{String}, Nothing}: Suggested valid descriptions (optional).suggestion::Union{String, Nothing}: How to fix the problem (optional).context::Union{String, Nothing}: Where the error occurred (optional).diagnostic::Union{String, Nothing}: Diagnostic tag, e.g."unknown symbols"(optional).
Example
julia> using CTBase
julia> D = ((:a, :b), (:a, :b, :c), (:b, :c))
julia> CTBase.complete(:f; descriptions=D)
ERROR: AmbiguousDescription: the description (:f,) is ambiguous / incorrectWith optional fields:
throw(CTBase.Exceptions.AmbiguousDescription(
(:f,),
candidates=["(:descent, :bfgs, :bisection)", "(:descent, :gradient, :fixedstep)"],
suggestion="Use a complete description like (:descent, :bfgs, :bisection)",
context="algorithm selection",
))See also: CTBase.Descriptions.complete, CTBase.Descriptions.add, CTBase.Exceptions.IncorrectArgument
CTBase.Exceptions.ExtensionError Type
struct ExtensionError <: CTBase.Exceptions.CTExceptionException thrown when an optional dependency (weak dependency) is required by a feature but has not been loaded.
Calling the zero-argument constructor ExtensionError() is forbidden and throws a CTBase.Exceptions.PreconditionError instead — at least one dependency symbol must be supplied.
Fields
msg::String: Auto-generated error message listing the missing packages.weakdeps::Tuple{Vararg{Symbol}}: The missing dependency symbols.feature::Union{String, Nothing}: The functionality that requires these dependencies (optional).context::Union{String, Nothing}: Where the error occurred (optional).
Throws
CTBase.Exceptions.PreconditionError: If called with no arguments.
Example
julia> using CTBase
julia> throw(CTBase.Exceptions.ExtensionError(:MyExtension))
ERROR: ExtensionError. Please make: julia> using MyExtensionWith multiple dependencies:
julia> throw(CTBase.Exceptions.ExtensionError(:MyExtension, :AnotherDep; message="to use this feature"))
ERROR: ExtensionError. Please make: julia> using MyExtension, AnotherDep to use this featureWith full context:
throw(CTBase.Exceptions.ExtensionError(
:Plots;
message="to plot optimization results",
feature="plotting functionality",
context="solve! call",
))See also: CTBase.Exceptions.PreconditionError
CTBase.Core.NotProvided Constant
NotProvidedSingleton instance of CTBase.Core.NotProvidedType.
The canonical "not provided" sentinel used across the control-toolbox ecosystem (option defaults, optional variable parameters, optional AD backends, …).
Example
julia> using CTBase.Core
julia> x = NotProvided
NotProvided
julia> x isa NotProvidedType
true
julia> x === NotProvided
trueSee also: CTBase.Core.NotProvidedType.
CTBase.Core.NotProvidedType Type
struct NotProvidedTypeSingleton type marking the absence of a provided value.
Ecosystem-wide sentinel for "no default / argument not given". The canonical value is CTBase.Core.NotProvided.
See also: CTBase.Core.NotProvided.
CTBase.Core.ctNumber Type
Type alias for a real number.
This constant is primarily meant as a short, semantic alias when writing APIs that accept real-valued quantities.
Example
julia> using CTBase
julia> CTBase.ctNumber === Real
trueCTBase.Strategies.AbstractStrategy Type
abstract type AbstractStrategyAbstract base type for all strategies in the control-toolbox ecosystem.
Every concrete strategy must implement a two-level contract separating static type metadata from dynamic instance configuration.
Contract Overview
Type-Level Contract (Static Metadata)
Methods defined on the type that describe what the strategy can do:
id(::Type{<:MyStrategy})::Symbol- Unique identifier for routing and introspectionmetadata(::Type{<:MyStrategy})::StrategyMetadata- Option specifications and validation rules
Why type-level? These methods enable:
Introspection without instantiation - Query capabilities without creating objects
Routing and dispatch - Select strategies by symbol for automated construction
Validation before construction - Verify compatibility before resource allocation
Instance-Level Contract (Configured State)
Methods defined on instances that provide the actual configuration:
options(strategy::MyStrategy)::StrategyOptions- Current option values with provenance tracking
Why instance-level? These methods enable:
Multiple configurations - Different instances with different settings
Provenance tracking - Know which options came from user vs defaults
Encapsulation - Configuration state belongs to the executing object
Implementation Requirements
Every concrete strategy must provide: 2. Type definition with an options::StrategyOptions field (recommended)
Type-level methods for
idandmetadataConstructor accepting keyword arguments (uses
build_strategy_options)Instance-level access to configured options
Parameter Position Contract
For strategies registered with a device/backend parameter via create_registry (e.g. (MyStrategy, [CPU, GPU])), the parameter must be the first declared type parameter:
julia> struct MyStrategy{P<:AbstractStrategyParameter, O} <: AbstractStrategy end # ✓ correct
julia> struct MyStrategy{O, P<:AbstractStrategyParameter} <: AbstractStrategy end # ✗ wrong slotThis is required because every Strategies.parameter implementation in the ecosystem reads slot 1: parameter(::Type{<:MyStrategy{P}}) where {P} = P. create_registry validates this by round-tripping through parameter, raising Exceptions.IncorrectArgument if the parameter did not bind to the first slot.
Validation Modes
The strategy system supports two validation modes for option handling:
Strict Mode (default): Rejects unknown options with detailed error messages
Provides early error detection and safety
Suggests corrections for typos using Levenshtein distance
Ideal for development and production environments
Permissive Mode: Accepts unknown options with warnings
Allows backend-specific options without breaking changes
Maintains validation for known options (types, custom validators)
Ideal for advanced users and experimental features
The validation mode is controlled by the mode parameter in constructors:
# Strict mode (default) - rejects unknown options
julia> MyStrategy(unknown_option=123) # ERROR
# Permissive mode - accepts unknown options with warning
julia> MyStrategy(unknown_option=123; mode=:permissive) # WARNING but worksAPI Methods
The Strategies module provides these methods for working with strategies:
id(strategy_type)- Get the unique identifiermetadata(strategy_type)- Get option specificationsoptions(strategy)- Get current configurationbuild_strategy_options(Type; mode=:strict, kwargs...)- Validate and merge options
Example
# Define strategy type
julia> struct MyStrategy <: AbstractStrategy
options::StrategyOptions
end
# Implement type-level contract
julia> id(::Type{<:MyStrategy}) = :mystrategy
julia> metadata(::Type{<:MyStrategy}) = StrategyMetadata(
OptionDefinition(name=:max_iter, type=Int, default=100, description="Max iterations")
)
# Implement constructor (required)
julia> function MyStrategy(; mode::Symbol=:strict, kwargs...)
options = build_strategy_options(MyStrategy; mode=mode, kwargs...)
return MyStrategy(options)
end
# Use the strategy
julia> strategy = MyStrategy(max_iter=200) # Instance with custom config (strict mode)
julia> id(typeof(strategy)) # => :mystrategy (type-level)
julia> options(strategy) # => StrategyOptions (instance-level)
# Use with permissive mode for unknown options
julia> strategy = MyStrategy(max_iter=200, custom_option=123; mode=:permissive)Notes
Type-level methods are called on the type:
id(MyStrategy)Instance-level methods are called on instances:
options(strategy)Constructor pattern is required for registry-based construction
Strategy families can be created with intermediate abstract types
CTBase.Strategies.StrategyRegistry Type
struct StrategyRegistryRegistry mapping strategy families to their concrete types.
This type provides an explicit, immutable registry for managing strategy types organized by family. It enables:
Type lookup by ID: Find concrete types from symbolic identifiers
Family introspection: List all strategies in a family
Validation: Ensure ID uniqueness and type hierarchy correctness
Design Philosophy
The registry uses an explicit passing pattern rather than global mutable state:
Created once via
create_registryPassed explicitly to functions that need it
Thread-safe (no shared mutable state)
Testable (easy to create multiple registries)
Fields
families::Dict{Type{<:AbstractStrategy}, Vector{Type}}: Maps abstract family types to concrete strategy types
Example
julia> using CTBase.Strategies
julia> registry = create_registry(
AbstractNLPModeler => (Modelers.ADNLP, Modelers.Exa),
AbstractNLPSolver => (Solvers.Ipopt, Solvers.MadNLP)
)
StrategyRegistry with 2 families
julia> strategy_ids(AbstractNLPModeler, registry)
(:adnlp, :exa)
julia> T = type_from_id(:adnlp, AbstractNLPModeler, registry)
Modelers.ADNLPSee also: CTBase.Strategies.create_registry, CTBase.Strategies.strategy_ids, CTBase.Strategies.type_from_id, Base.merge
CTBase.Strategies.StrategyMetadata Type
struct StrategyMetadata{NT<:NamedTuple}Metadata about a strategy type, wrapping option definitions.
This type serves as a container for OptionDefinition objects that define the contract for a strategy's configuration options. It is returned by the type-level metadata(::Type{<:AbstractStrategy}) method and provides a convenient interface for accessing and managing option definitions.
Strategy Contract
Every concrete strategy type must implement the metadata method to return a StrategyMetadata instance describing its configurable options:
function metadata(::Type{<:MyStrategy})
return StrategyMetadata(
OptionDefinition(...),
OptionDefinition(...),
# ... more option definitions
)
endThis metadata is used by:
Validation: Check option types and values before construction
Documentation: Auto-generate option documentation
Introspection: Query available options without instantiation
Construction: Build
StrategyOptionswithbuild_strategy_options
Fields
specs::NamedTuple: NamedTuple mapping option names to their definitions (type-stable)
Type Parameter
NT <: NamedTuple: The concrete NamedTuple type holding the option definitions
Constructor
The constructor accepts a variable number of OptionDefinition arguments and automatically builds the internal NamedTuple, validating that all option names are unique. The type parameter is inferred automatically.
Collection Interface
StrategyMetadata implements standard Julia collection interfaces:
meta[:option_name]- Access definition by namekeys(meta)- Get all option namesvalues(meta)- Get all definitionspairs(meta)- Iterate over name-definition pairslength(meta)- Number of options
Example - Standalone Usage
julia> using CTBase.Strategies
julia> meta = StrategyMetadata(
OptionDefinition(
name = :max_iter,
type = Int,
default = 100,
description = "Maximum iterations",
aliases = (:max, :maxiter),
validator = x -> x > 0 || throw(ArgumentError("$x must be positive"))
),
OptionDefinition(
name = :tol,
type = Float64,
default = 1e-6,
description = "Convergence tolerance"
)
)
StrategyMetadata with 2 options:
max_iter (max, maxiter) :: Int64
default: 100
description: Maximum iterations
tol :: Float64
default: 1.0e-6
description: Convergence tolerance
julia> meta[:max_iter].name
:max_iter
julia> collect(keys(meta))
2-element Vector{Symbol}:
:max_iter
:tolExample - Strategy Implementation
# Define a concrete strategy type
struct MyOptimizer <: AbstractStrategy
options::StrategyOptions
end
# Implement the metadata contract (type-level)
function metadata(::Type{<:MyOptimizer})
return StrategyMetadata(
OptionDefinition(
name = :max_iter,
type = Int,
default = 100,
description = "Maximum number of iterations",
validator = x -> x > 0 || throw(ArgumentError("max_iter must be positive"))
),
OptionDefinition(
name = :tol,
type = Float64,
default = 1e-6,
description = "Convergence tolerance",
validator = x -> x > 0 || throw(ArgumentError("tol must be positive"))
)
)
end
# Implement the id contract (type-level)
id(::Type{<:MyOptimizer}) = :myoptimizer
# Implement constructor using build_strategy_options
function MyOptimizer(; kwargs...)
options = build_strategy_options(MyOptimizer; kwargs...)
return MyOptimizer(options)
end
# Now the strategy can be used with automatic validation
julia> strategy = MyOptimizer(max_iter=200, tol=1e-8)
julia> options(strategy)
StrategyOptions(max_iter=200, tol=1.0e-8)Throws
Exceptions.IncorrectArgument: If duplicate option names are provided
See also: CTBase.Options.OptionDefinition, CTBase.Strategies.AbstractStrategy, CTBase.Strategies.build_strategy_options
CTBase.Strategies.StrategyOptions Type
struct StrategyOptions{NT<:NamedTuple}Wrapper for strategy option values with provenance tracking.
This type stores options as a collection of OptionValue objects, each containing both the value and its source (:user, :default, or :computed).
Validation Modes
Strategy options are built using build_strategy_options() which supports two validation modes:
Strict Mode (default): Only known options are accepted
Unknown options trigger detailed error messages with suggestions
Type validation and custom validators are enforced
Provides early error detection and safety
Permissive Mode: Unknown options are accepted with warnings
Unknown options are stored with
:usersourceType validation and custom validators still apply to known options
Allows backend-specific options without breaking changes
Fields
options::NamedTuple: NamedTuple of OptionValue objects with provenancealias_map::Dict{Symbol, Symbol}: Mapping from alias names to canonical names
Construction
julia> using CTBase.Strategies, CTBase.Options
julia> opts = StrategyOptions(
max_iter = OptionValue(200, :user),
tol = OptionValue(1e-6, :default)
)
StrategyOptions with 2 options:
max_iter = 200 [user]
tol = 1.0e-6 [default]Building Options with Validation
# Strict mode (default) - rejects unknown options
julia> opts = build_strategy_options(MyStrategy; max_iter=200)
StrategyOptions(...)
# Permissive mode - accepts unknown options with warning
julia> opts = build_strategy_options(MyStrategy; max_iter=200, custom_opt=123; mode=:permissive)
StrategyOptions(...) # with warning about custom_optAccess patterns
# Get value only (canonical name)
julia> opts[:max_iter]
200
# Get value using alias
julia> opts[:maxiter] # Alias automatically resolved
200
# Get OptionValue (value + source)
julia> opts.max_iter
OptionValue(200, :user)
# Get source only
julia> source(opts, :max_iter)
:user
# Check if user-provided
julia> is_user(opts, :max_iter)
true
# Check if option exists (works with aliases)
julia> haskey(opts, :maxiter)
trueIteration
# Iterate over values
julia> for value in opts
println(value)
end
# Iterate over (name, value) pairs
julia> for (name, value) in opts
println("$name = $value")
endSee also: CTBase.Options.OptionValue, CTBase.Options.source, CTBase.Options.is_user, CTBase.Options.is_default, CTBase.Options.is_computed
CTBase.Strategies.RoutedOption Type
struct RoutedOptionRouted option value with explicit strategy targeting.
This type is created by route_to to disambiguate options that exist in multiple strategies. It wraps one or more (strategy_id => value) pairs, allowing the orchestration layer to route each value to its intended strategy.
Fields
routes::NamedTuple: NamedTuple of strategy_id => value mappings
Iteration
RoutedOption implements the collection interface and can be iterated like a dictionary:
keys(opt): Strategy IDsvalues(opt): Option valuespairs(opt): (strategy_id, value) pairsfor (id, val) in opt: Direct iteration over pairsopt[:strategy]: Index by strategy IDhaskey(opt, :strategy): Check if strategy existslength(opt): Number of routes
Example
julia> using CTBase.Strategies
julia> # Single strategy
julia> opt = route_to(solver=100)
RoutedOption((solver = 100,))
julia> # Multiple strategies
julia> opt = route_to(solver=100, modeler=50)
RoutedOption((solver = 100, modeler = 50))
julia> # Iterate over routes
julia> for (id, val) in opt
println("$id => $val")
end
solver => 100
modeler => 50See also: CTBase.Strategies.route_to
CTBase.Strategies.BypassValue Type
struct BypassValue{T}Wrapper type for option values that should bypass validation.
This type is used to explicitly skip validation for specific options when constructing strategies. It is particularly useful for passing backend-specific options that are not defined in the strategy's metadata.
Fields
value::T: The wrapped option value
Example
julia> val = bypass(42)
BypassValue(42)See also: CTBase.Strategies.bypass
CTBase.Strategies.AbstractStrategyParameter Type
Abstract base type for strategy parameters.
Strategy parameters allow specialization of strategy behavior and default options. Every concrete parameter must implement:
id(::Type{<:AbstractStrategyParameter})::Symbol- Unique identifier
Examples
struct CPU <: AbstractStrategyParameter end
id(::Type{CPU}) = :cpu
struct GPU <: AbstractStrategyParameter end
id(::Type{GPU}) = :gpuNotes
Parameters are singleton types (no fields) - they exist only for type dispatch
IDs must be globally unique across all strategies and parameters
Parameters are used to specialize default options in strategy metadata
CTBase.Options.OptionDefinition Type
struct OptionDefinition{T}Unified option definition for both option extraction and strategy contracts.
This type provides a comprehensive option definition that can be used for:
Option extraction in the Options module
Strategy contract definition in the Strategies module
Action schema definition
Fields
name::Symbol: Primary name of the optiontype::Type: Expected Julia type for the option valuedefault::T: Default value when the option is not provided (type parameterT)description::String: Human-readable description of the option's purposealiases::Tuple{Vararg{Symbol}}: Alternative names for this option (default: empty tuple)validator::Union{Function, Nothing}: Optional validation function (default:nothing)computed::Bool: Whether the default value is computed from parameters (default:false)
Type Parameter T
The type parameter T represents the type of the default value:
T = Anywhendefault = nothing(explicit nothing default)T = NotProvidedTypewhendefault = NotProvided(no default value)T = typeof(default)for concrete default values
Validator Contract
Validators must follow this pattern:
x -> condition || throw(ArgumentError("error message"))The validator should:
Return
true(or any truthy value) if the value is validThrow an exception (preferably
ArgumentError) if the value is invalidBe a pure function without side effects
Constructor Validation
The constructor performs the following validations: 2. Checks that default matches the specified type (unless default is nothing or NotProvided)
- Runs the
validatoron thedefaultvalue (if both are provided anddefaultis notNotProvided)
Example
def = OptionDefinition(
name = :max_iter,
type = Int,
default = 100,
description = "Maximum number of iterations",
aliases = (:max, :maxiter),
validator = x -> x > 0 || throw(ArgumentError("$x must be positive"))
)
def.name # :max_iter
def.aliases # (:max, :maxiter)
all_names(def) # (:max_iter, :max, :maxiter)Throws
CTBase.Exceptions.IncorrectArgument: If the default value does not match the declared typeException: If the validator function fails when applied to the default value
See also: CTBase.Options.all_names, CTBase.Options.extract_option, CTBase.Options.extract_options, CTBase.Core.NotProvided
CTBase.Options.OptionValue Type
struct OptionValue{T}Represents an option value with its source provenance.
Fields
value::T: The actual option value.source::Symbol: Where the value came from (:default,:user,:computed).
Constructor Validation
The constructor validates that source is one of :default, :user, or :computed. Invalid sources throw Exceptions.IncorrectArgument.
Notes
The source field tracks the provenance of the option value:
:default: Value comes from the tool's default configuration:user: Value was explicitly provided by the user:computed: Value was computed/derived from other options
Example
julia> using CTBase.Options
julia> opt = OptionValue(100, :user)
OptionValue{Int64}(100, :user)
julia> opt.value
100
julia> opt.source
:userThrows
Exceptions.IncorrectArgument: If source is not one of:default,:user, or:computed
See also: CTBase.Options.value, CTBase.Options.source, CTBase.Options.is_user