Skip to content

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
julia
mutable struct PreModel <: CTModels.Models.AbstractModel

Mutable 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 to EmptyControlModel(), 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 to CTModels.Components.EmptyDefinition and becomes a CTModels.Components.Definition when definition! is called with a real expression.

  • autonomous::Union{Bool,Nothing}: Whether the system is autonomous.

Example

julia
julia> using CTModels

julia> pre = CTModels.PreModel()
julia> # Set fields incrementally...
CTModels.Models.Model Type
julia
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.AbstractModel

Immutable 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
julia
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.AbstractSolution

Complete 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 trajectory t -> x(t) with metadata.

  • control::ControlModelType: Control trajectory t -> u(t) with metadata.

  • variable::VariableModelType: Optimisation variable value with metadata.

  • model::ModelType: Reference to the optimal control problem model.

  • costate::CostateModelType: Costate (adjoint) trajectory t -> p(t).

  • objective::ObjectiveValueType: Optimal objective value.

  • dual::DualModelType: Dual variables for all constraints.

  • solver_infos::SolverInfosType: Solver statistics and status.

Example

julia
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
julia
abstract type AbstractSolution

Abstract 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
julia
abstract type AbstractInitialGuess

Abstract 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
julia
struct InitialGuess{X<:Function, U<:Function, V} <: CTModels.Init.AbstractInitialGuess

Concrete 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 function t -> x(t) returning the state guess at time t.

  • control::U: A function t -> u(t) returning the control guess at time t.

  • variable::V: The initial guess for the optimisation variable (scalar or vector).

Example

julia
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
julia
struct ADNLP{P<:CPU} <: CTSolvers.Modelers.AbstractNLPModeler

Modeler 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

julia
# 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 (:strict or :permissive)

    • :strict (default): Rejects unknown options with detailed error message

    • :permissive: Accepts unknown options with warning, stores with :user source

  • 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 computation

  • hprod_backend: Override backend for Hessian-vector product

  • jprod_backend: Override backend for Jacobian-vector product

  • jtprod_backend: Override backend for transpose Jacobian-vector product

  • jacobian_backend: Override backend for Jacobian matrix computation

  • hessian_backend: Override backend for Hessian matrix computation

  • ghjvprod_backend: Override backend for g^T ∇²c(x)v computation

Examples

Basic Usage

julia
# 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

julia
# GPU is NOT supported - will throw IncorrectArgument
modeler = Modelers.ADNLP{GPU}()  # ❌ Error!

Advanced Backend Configuration

julia
# 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

julia
# 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 specified

  • CTBase.Exceptions.IncorrectArgument: If option validation fails

  • CTBase.Exceptions.IncorrectArgument: If invalid mode is provided

See also

  • CPU: CPU parameter type

  • Modelers.Exa: Alternative modeler using ExaModels (supports GPU)

  • Optimization.build_model: Build a backend NLP model from a problem and a modeler

  • Optimization.build_solution: Build a problem-level solution from execution statistics

Notes

  • The backend option supports: :default, :optimized, :generic, :enzyme, :zygote

  • Advanced 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

CTSolvers.Modelers.Exa Type
julia
struct Exa{P<:Union{CPU, GPU}} <: CTSolvers.Modelers.AbstractNLPModeler

Modeler 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

julia
# 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 (:strict or :permissive)

    • :strict (default): Rejects unknown options with detailed error message

    • :permissive: Accepts unknown options with warning, stores with :user source

  • 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: nothing for CPU, CUDA backend for GPU)

Examples

Basic Usage

julia
# 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

julia
# Single precision
modeler = Modelers.Exa(base_type=Float32)

# Double precision (default)
modeler = Modelers.Exa(base_type=Float64)

Backend Configuration

julia
# 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 automatically

Validation Modes

julia
# 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

julia
# Full configuration with type and backend
modeler = Modelers.Exa{GPU}(
    base_type=Float32;
    mode=:permissive
)

Throws

  • CTBase.Exceptions.IncorrectArgument: If option validation fails

  • CTBase.Exceptions.IncorrectArgument: If invalid mode is provided

  • CTBase.Exceptions.ExtensionError: If GPU backend requested but CUDA not available

See also

  • Modelers.ADNLP: Alternative modeler using ADNLPModels

  • build_model: Build model from problem and modeler

  • solve!: Solve optimization problem

  • CPU, GPU: Strategy parameters

Notes

  • The base_type option affects the precision of all computations

  • CPU backend (backend=nothing) is always available

  • GPU 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

CTSolvers.Solvers.Ipopt Type
julia
struct Ipopt{P<:CPU} <: CTSolvers.Solvers.AbstractNLPSolver

Interior 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

julia
# 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:

julia
using NLPModelsIpopt

Examples

Basic Usage

julia
# 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

julia
# GPU is NOT supported - will throw IncorrectArgument
solver = Ipopt{GPU}()  # ❌ Error!

Extension Required

This solver requires the NLPModelsIpopt package to be loaded:

julia
using NLPModelsIpopt

Implementation Notes

  • Implements the AbstractStrategy contract via Strategies.id()

  • Metadata and constructor implementation provided by CTSolversIpopt extension

  • Options are validated at construction time using enriched Exceptions.IncorrectArgument

  • Callable interface: (solver::Ipopt)(nlp; display=true) provided by extension

Throws

  • CTBase.Exceptions.IncorrectArgument: If GPU or other unsupported parameter is specified

  • CTBase.Exceptions.ExtensionError: If the NLPModelsIpopt extension is not loaded

See also: CPU, AbstractNLPSolver, MadNLP, Knitro

CTSolvers.Solvers.MadNLP Type
julia
struct MadNLP{P<:Union{CPU, GPU}} <: CTSolvers.Solvers.AbstractNLPSolver

Pure-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 backend

    • Default for CPU: MadNLP.MumpsSolver

    • Default for GPU: MadNLPGPU.CUDSSSolver (requires MadNLPGPU.jl)

  • backend: Execution backend (default depends on parameter: CPU backend for CPU, CUDA backend for GPU)

Example

julia
# 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:

julia
using MadNLP

Implementation Notes

  • Implements the AbstractStrategy contract via Strategies.id, Strategies.metadata, and Strategies.options

  • Options are validated at construction time using enriched Exceptions.IncorrectArgument

  • Callable 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 to MadNLPGPU.CUDSSSolver instead of MadNLP.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
julia
struct MadNCL{P<:Union{CPU, GPU}} <: CTSolvers.Solvers.AbstractNLPSolver

NCL (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:

julia
using MadNCL, MadNLP

Example

julia
# 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:

julia
using MadNCL, MadNLP

Implementation Notes

  • Implements the AbstractStrategy contract via Strategies.id, Strategies.metadata, and Strategies.options

  • Options are validated at construction time using enriched Exceptions.IncorrectArgument

  • Callable 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 to MadNLPGPU.CUDSSSolver instead of MadNLP.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
julia
struct Knitro{P<:CPU} <: CTSolvers.Solvers.AbstractNLPSolver

Commercial 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

julia
# 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:

julia
using NLPModelsKnitro

Examples

Basic Usage

julia
# 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

julia
# GPU is NOT supported - will throw IncorrectArgument
solver = Knitro{GPU}()  # ❌ Error!

Extension Required

This solver requires the NLPModelsKnitro package:

julia
using NLPModelsKnitro

Note: Knitro is a commercial solver requiring a valid license.

Implementation Notes

  • Implements the AbstractStrategy contract via Strategies.id()

  • Metadata and constructor implementation provided by CTSolversKnitro extension

  • Options are validated at construction time using enriched Exceptions.IncorrectArgument

  • Callable interface: (solver::Knitro)(nlp; display=true) provided by extension

  • Requires valid Knitro license for operation

Throws

  • CTBase.Exceptions.IncorrectArgument: If GPU or other unsupported parameter is specified

  • CTBase.Exceptions.ExtensionError: If the NLPModelsKnitro extension is not loaded

See also: CPU, AbstractNLPSolver, Ipopt, MadNLP

CTSolvers.Solvers.Uno Type
julia
struct Uno{P<:CPU} <: CTSolvers.Solvers.AbstractNLPSolver

Unified 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

julia
# 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:

julia
using UnoSolver

Examples

Basic Usage

julia
# 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

julia
# GPU is NOT supported - will throw IncorrectArgument
solver = Uno{GPU}()  # ❌ Error!

Extension Required

This solver requires the UnoSolver package to be loaded:

julia
using UnoSolver

Implementation Notes

  • Implements the AbstractStrategy contract via Strategies.id()

  • Metadata and constructor implementation provided by CTSolversUno extension

  • Options are validated at construction time using enriched Exceptions.IncorrectArgument

  • Callable interface: (solver::Uno)(nlp; display=true) provided by extension

  • Only 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 specified

  • CTBase.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
julia
abstract type AbstractDiscretizer <: CTBase.Strategies.AbstractStrategy

Abstract 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
julia
struct DiscretizedModel{TO<:CTModels.Models.AbstractModel, TD<:CTSolvers.DOCP.AbstractDiscretizer, TC<:CTBase.Core.AbstractCache} <: CTSolvers.Optimization.AbstractOptimizationProblem

Discretized 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's DOCPCache).

Type parameters

  • TO <: CTModels.AbstractModel

  • TD <: AbstractDiscretizer

  • TC <: CTBase.Core.AbstractCache

See also: ocp_model, discretize, build_model, build_solution.

CTSolvers.Modelers.AbstractNLPModeler Type
julia
abstract type AbstractNLPModeler <: CTBase.Strategies.AbstractStrategy

Abstract 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.AbstractStrategy contract

  • Have the package providing the problem implement, by multiple dispatch:

    • Optimization.build_model(prob, initial_guess, modeler) returning a Optimization.BuiltModel

    • Optimization.build_solution(built::Optimization.BuiltModel, nlp_solution, modeler)

Example

julia
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
end

See also: Strategies.AbstractStrategy, Optimization.build_model, Optimization.build_solution

CTSolvers.Solvers.AbstractNLPSolver Type
julia
abstract type AbstractNLPSolver <: CTBase.Strategies.AbstractStrategy

Abstract base type for optimization solvers in the Control Toolbox.

All concrete solver types must: 2. Be a subtype of AbstractNLPSolver

  1. Implement the AbstractStrategy contract:
  • Strategies.id(::Type{<:MySolver}) - Return unique Symbol identifier

  • Strategies.metadata(::Type{<:MySolver}) - Return StrategyMetadata with options

  • Have an options::Strategies.StrategyOptions field

  1. 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 MadNLP

  • Solvers.Knitro - Commercial solver (Knitro backend)

Example

julia
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
julia
struct LiftedHamiltonianFunction{F, TD, VD} <: Function

Callable 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
julia
abstract type CTException <: Exception

Abstract 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
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 input

See also: CTBase.Exceptions.IncorrectArgument, CTBase.Exceptions.NotImplemented

CTBase.Exceptions.IncorrectArgument Type
julia
struct IncorrectArgument <: CTBase.Exceptions.CTException

Exception 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
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 tuple

With optional fields:

julia
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
julia
struct PreconditionError <: CTBase.Exceptions.CTException

Exception 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
julia> using CTBase

julia> throw(CTBase.Exceptions.PreconditionError("state must be set before dynamics"))
ERROR: PreconditionError: state must be set before dynamics

With optional fields:

julia
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
julia
struct NotImplemented <: CTBase.Exceptions.CTException

Exception 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
julia> using CTBase

julia> throw(CTBase.Exceptions.NotImplemented("feature X is not implemented"))
ERROR: NotImplemented: feature X is not implemented

Typical interface stub pattern:

julia
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",
    ))
end

See also: CTBase.Exceptions.IncorrectArgument, CTBase.Exceptions.PreconditionError

CTBase.Exceptions.ParsingError Type
julia
struct ParsingError <: CTBase.Exceptions.CTException

Exception 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
julia> using CTBase

julia> throw(CTBase.Exceptions.ParsingError("unexpected token 'end'"))
ERROR: ParsingError: unexpected token 'end'

With optional fields:

julia
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
julia
struct AmbiguousDescription <: CTBase.Exceptions.CTException

Exception 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&#125;&#125;: 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
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 / incorrect

With optional fields:

julia
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
julia
struct ExtensionError <: CTBase.Exceptions.CTException

Exception 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&#125;&#125;: 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

Example

julia
julia> using CTBase

julia> throw(CTBase.Exceptions.ExtensionError(:MyExtension))
ERROR: ExtensionError. Please make: julia> using MyExtension

With multiple dependencies:

julia
julia> throw(CTBase.Exceptions.ExtensionError(:MyExtension, :AnotherDep; message="to use this feature"))
ERROR: ExtensionError. Please make: julia> using MyExtension, AnotherDep to use this feature

With full context:

julia
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
julia
NotProvided

Singleton 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
julia> using CTBase.Core

julia> x = NotProvided
NotProvided

julia> x isa NotProvidedType
true

julia> x === NotProvided
true

See also: CTBase.Core.NotProvidedType.

CTBase.Core.NotProvidedType Type
julia
struct NotProvidedType

Singleton 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
julia> using CTBase

julia> CTBase.ctNumber === Real
true
CTBase.Strategies.AbstractStrategy Type
julia
abstract type AbstractStrategy

Abstract 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 introspection

  • metadata(::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)

  1. Type-level methods for id and metadata

  2. Constructor accepting keyword arguments (uses build_strategy_options)

  3. 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
julia> struct MyStrategy{P<:AbstractStrategyParameter, O} <: AbstractStrategy end  # ✓ correct
julia> struct MyStrategy{O, P<:AbstractStrategyParameter} <: AbstractStrategy end  # ✗ wrong slot

This is required because every Strategies.parameter implementation in the ecosystem reads slot 1: parameter(::Type{<:MyStrategy{P&#125;&#125;) 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:

julia
# 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 works

API Methods

The Strategies module provides these methods for working with strategies:

  • id(strategy_type) - Get the unique identifier

  • metadata(strategy_type) - Get option specifications

  • options(strategy) - Get current configuration

  • build_strategy_options(Type; mode=:strict, kwargs...) - Validate and merge options

Example

julia
# 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
julia
struct StrategyRegistry

Registry 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_registry

  • Passed 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&#125;&#125;: Maps abstract family types to concrete strategy types

Example

julia
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.ADNLP

See also: CTBase.Strategies.create_registry, CTBase.Strategies.strategy_ids, CTBase.Strategies.type_from_id, Base.merge

CTBase.Strategies.StrategyMetadata Type
julia
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:

julia
function metadata(::Type{<:MyStrategy})
    return StrategyMetadata(
        OptionDefinition(...),
        OptionDefinition(...),
        # ... more option definitions
    )
end

This 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 StrategyOptions with build_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 name

  • keys(meta) - Get all option names

  • values(meta) - Get all definitions

  • pairs(meta) - Iterate over name-definition pairs

  • length(meta) - Number of options

Example - Standalone Usage

julia
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
 :tol

Example - Strategy Implementation

julia
# 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
julia
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 :user source

    • Type validation and custom validators still apply to known options

    • Allows backend-specific options without breaking changes

Fields

  • options::NamedTuple: NamedTuple of OptionValue objects with provenance

  • alias_map::Dict{Symbol, Symbol}: Mapping from alias names to canonical names

Construction

julia
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

julia
# 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_opt

Access patterns

julia
# 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)
true

Iteration

julia
# 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")
       end

See also: CTBase.Options.OptionValue, CTBase.Options.source, CTBase.Options.is_user, CTBase.Options.is_default, CTBase.Options.is_computed

CTBase.Strategies.RoutedOption Type
julia
struct RoutedOption

Routed 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 IDs

  • values(opt): Option values

  • pairs(opt): (strategy_id, value) pairs

  • for (id, val) in opt: Direct iteration over pairs

  • opt[:strategy]: Index by strategy ID

  • haskey(opt, :strategy): Check if strategy exists

  • length(opt): Number of routes

Example

julia
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 => 50

See also: CTBase.Strategies.route_to

CTBase.Strategies.BypassValue Type
julia
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
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

julia
struct CPU <: AbstractStrategyParameter end
id(::Type{CPU}) = :cpu

struct GPU <: AbstractStrategyParameter end
id(::Type{GPU}) = :gpu

Notes

  • 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
julia
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 option

  • type::Type: Expected Julia type for the option value

  • default::T: Default value when the option is not provided (type parameter T)

  • description::String: Human-readable description of the option's purpose

  • aliases::Tuple{Vararg{Symbol&#125;&#125;: 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 = Any when default = nothing (explicit nothing default)

  • T = NotProvidedType when default = NotProvided (no default value)

  • T = typeof(default) for concrete default values

Validator Contract

Validators must follow this pattern:

julia
x -> condition || throw(ArgumentError("error message"))

The validator should:

  • Return true (or any truthy value) if the value is valid

  • Throw an exception (preferably ArgumentError) if the value is invalid

  • Be 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)

  1. Runs the validator on the default value (if both are provided and default is not NotProvided)

Example

julia
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 type

  • Exception: 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
julia
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
julia> using CTBase.Options

julia> opt = OptionValue(100, :user)
OptionValue{Int64}(100, :user)

julia> opt.value
100

julia> opt.source
:user

Throws

  • Exceptions.IncorrectArgument: If source is not one of :default, :user, or :computed

See also: CTBase.Options.value, CTBase.Options.source, CTBase.Options.is_user