Public API
This page lists exported symbols of CTBase.Strategies.
From CTBase.Strategies
CTBase.Strategies [Module]
CTBase.Strategies Module
Strategy management and registry for the Control Toolbox ecosystem.
This module provides:
Abstract strategy contract and interface
Strategy registry for explicit dependency management
Strategy building and validation utilities
Metadata management for strategy families
The Strategies module depends on Options for option handling but provides higher-level strategy management capabilities.
AbstractStrategy [Abstract Type]
CTBase.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:
Type definition with an
options::StrategyOptionsfield (recommended)Type-level methods for
idandmetadataConstructor accepting keyword arguments (uses
build_strategy_options)Instance-level access to configured options
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
AbstractStrategyParameter [Abstract Type]
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
BypassValue [Struct]
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: bypass
CPU [Struct]
CTBase.Strategies.CPU Type
CPU parameter type for CPU-based computation.
This parameter indicates that a strategy should use CPU-based backends and default options optimized for CPU execution.
GPU [Struct]
CTBase.Strategies.GPU Type
GPU parameter type for GPU-based computation.
This parameter indicates that a strategy should use GPU-based backends and default options optimized for GPU execution.
Notes
Requires CUDA.jl to be loaded and functional
Strategies may throw
CTBase.Exceptions.ExtensionErrorif CUDA is not available
RoutedOption [Struct]
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: route_to
StrategyMetadata [Struct]
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: OptionDefinition, AbstractStrategy, build_strategy_options
StrategyOptions [Struct]
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: OptionValue, source, is_user, is_default, is_computed
StrategyRegistry [Struct]
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: create_registry, strategy_ids, type_from_id
available_parameters [Function]
CTBase.Strategies.available_parameters Function
available_parameters(
strategy_id::Symbol,
family::Type{<:CTBase.Strategies.AbstractStrategy},
registry::CTBase.Strategies.StrategyRegistry
) -> Vector{Type{<:CTBase.Strategies.AbstractStrategyParameter}}Return all available strategy parameter types for a given (strategy_id, family).
This function is used by orchestration to validate that a global parameter token present in the method tuple is compatible with all selected strategies.
Arguments
strategy_id::Symbol: Strategy identifier (e.g.:madnlp).family::Type{<:AbstractStrategy}: Family to search within.registry::StrategyRegistry: Strategy registry.
Returns
Vector{Type{<:AbstractStrategyParameter}}: Supported parameter types. Returns an empty vector if the strategy is not parameterized.
See also: extract_global_parameter_from_method, get_parameter_type
build_strategy [Function]
CTBase.Strategies.build_strategy Function
build_strategy(
id::Symbol,
family::Type{<:CTBase.Strategies.AbstractStrategy},
registry::CTBase.Strategies.StrategyRegistry;
mode,
kwargs...
) -> AnyBuild a strategy instance from its ID and options.
This function creates a concrete strategy instance by:
Looking up the strategy type from its ID in the registry
Constructing the instance with the provided options
Arguments
id::Symbol: Strategy identifier (e.g.,:adnlp,:ipopt)family::Type{<:AbstractStrategy}: Abstract family type to search withinregistry::StrategyRegistry: Registry containing strategy mappingsmode::Symbol=:strict: Validation mode (:strictor:permissive)kwargs...: Options to pass to the strategy constructor
Returns
- Concrete strategy instance of the appropriate type
Throws
Exceptions.IncorrectArgument: If the strategy ID is not found in the registry for the given family
Example
julia> registry = create_registry(
AbstractNLPModeler => (Modelers.ADNLP, Modelers.Exa)
)
julia> modeler = build_strategy(:adnlp, AbstractNLPModeler, registry; backend=:sparse)
Modelers.ADNLP(options=StrategyOptions{...})
julia> modeler = build_strategy(:adnlp, AbstractNLPModeler, registry;
backend=:sparse, mode=:permissive)
Modelers.ADNLP(options=StrategyOptions{...})See also: type_from_id
build_strategy(
id::Symbol,
parameter::Type{<:CTBase.Strategies.AbstractStrategyParameter},
family::Type{<:CTBase.Strategies.AbstractStrategy},
registry::CTBase.Strategies.StrategyRegistry;
mode,
kwargs...
) -> AnyBuild a parameterized strategy instance from ID, parameter, and options.
This function creates a concrete parameterized strategy instance by:
Looking up the parameterized strategy type from its ID and parameter
Constructing the instance with the provided options
Arguments
id::Symbol: Strategy identifier (e.g.,:madnlp)parameter::Type{<:AbstractStrategyParameter}: Parameter type (e.g.,GPU)family::Type{<:AbstractStrategy}: Abstract family type to search withinregistry::StrategyRegistry: Registry containing strategy mappingsmode::Symbol=:strict: Validation mode (:strictor:permissive)kwargs...: Options to pass to the strategy constructor
Returns
- Concrete parameterized strategy instance (e.g.,
MadNLP{GPU})
Throws
CTBase.Exceptions.IncorrectArgument: If the strategy-parameter combination is not found
Example
julia> registry = create_registry(
AbstractNLPSolver => ((MadNLP, [CPU, GPU]),)
)
julia> solver = build_strategy(:madnlp, GPU, AbstractNLPSolver, registry; max_iter=1000)
MadNLP{GPU}(options=StrategyOptions{...})See also: build_strategy
build_strategy_options [Function]
CTBase.Strategies.build_strategy_options Function
build_strategy_options(
strategy_type::Type{<:CTBase.Strategies.AbstractStrategy};
mode,
kwargs...
)Build StrategyOptions from user kwargs and strategy metadata.
This function creates a StrategyOptions instance by:
Validating the mode parameter (
:strictor:permissive)Extracting known options from kwargs using the Options API
Handling unknown options based on the mode
Converting the extracted Dict to NamedTuple
Wrapping in StrategyOptions
The Options.extract_options function handles:
Alias resolution to primary names
Type validation
Custom validators
Default values
Provenance tracking (:user, :default)
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy type to build options formode::Symbol = :strict: Validation mode (:strictor:permissive):strict(default): Rejects unknown options with detailed error message:permissive: Accepts unknown options with warning, stores with:usersource (unvalidated)
kwargs...: User-provided option values
Returns
StrategyOptions: Validated options with provenance tracking
Throws
Exceptions.IncorrectArgument: If mode is not:strictor:permissiveExceptions.IncorrectArgument: If an unknown option is provided in strict modeExceptions.IncorrectArgument: If type validation fails (both modes)Exceptions.IncorrectArgument: If custom validation fails (both modes)
Example
# Define a minimal strategy for demonstration
julia> struct MyStrategy <: AbstractStrategy end
julia> Strategies.metadata(::Type{MyStrategy}) = StrategyMetadata(
OptionDefinition(name=:max_iter, type=Int, default=100)
)
# Strict mode (default) - rejects unknown options
julia> opts = build_strategy_options(MyStrategy; max_iter=200)
StrategyOptions with 1 option:
max_iter = 200 [user]
# Permissive mode - accepts unknown options with warning
julia> opts = build_strategy_options(MyStrategy; max_iter=200, custom_opt=123, mode=:permissive)
┌ Warning: Unrecognized options passed to MyStrategy
│ Unvalidated options: [:custom_opt]
└ ...
StrategyOptions with 2 options:
max_iter = 200 [user]
custom_opt = 123 [user]Notes
Known options are always validated (type, custom validators) regardless of mode
Unknown options in permissive mode are stored with source
:userbut bypass validationUse permissive mode only when you need to pass backend-specific options not defined in the strategy metadata
See also: StrategyOptions, metadata, Options.extract_options
bypass [Function]
CTBase.Strategies.bypass Function
bypass(val) -> CTBase.Strategies.BypassValueMark an option value to bypass validation.
This function creates a BypassValue wrapper around the provided value. When passed to a strategy constructor, this value will be accepted even if the option name is unknown (not in metadata) or if validation would otherwise fail.
This can be combined with route_to to bypass validation for specific strategies when routing ambiguous options.
Arguments
val: The option value to wrap
Returns
BypassValue: The wrapped value
Example
julia> using CTBase.Strategies
julia> # Pass an unknown option directly to strategy
julia> solver = Ipopt(
max_iter=100,
custom_backend_option=bypass(42) # Bypasses validation
)
Ipopt(options=StrategyOptions{...})
julia> # Alternative syntax using force alias
julia> solver = Ipopt(
max_iter=100,
custom_backend_option=force(42) # Same as bypass(42)
)
Ipopt(options=StrategyOptions{...})
julia> # Combine with routing for ambiguous options
julia> solve(ocp, method;
backend = route_to(ipopt=bypass(42)) # Route to ipopt AND bypass validation
)Notes
Use with caution! Bypassed options are passed directly to the backend.
Typos in option names will not be caught by validation.
Invalid values for the backend will cause backend-level errors.
Can be combined with
route_tofor strategy-specific bypassingforceis an alias forbypass- they are identical functions
See also: BypassValue, route_to, force
create_registry [Function]
CTBase.Strategies.create_registry Function
create_registry(
pairs::Pair...
) -> CTBase.Strategies.StrategyRegistryCreate a strategy registry from family-to-strategies mappings.
This function validates the registry structure and ensures:
All strategy IDs are unique within each family
All strategies are subtypes of their declared family
No duplicate family definitions
Arguments
pairs...: Pairs of family type => tuple of strategy types
Returns
StrategyRegistry: Validated registry ready for use
Validation Rules
ID Uniqueness: Within each family, all strategy
id()values must be uniqueType Hierarchy: Each strategy must be a subtype of its family
No Duplicates: Each family can only appear once in the registry
Example
julia> using CTBase.Strategies
julia> registry = create_registry(
AbstractNLPModeler => (Modelers.ADNLP, Modelers.Exa),
AbstractNLPSolver => (Solvers.Ipopt, Solvers.MadNLP, Solvers.Knitro)
)
StrategyRegistry with 2 families
julia> strategy_ids(AbstractNLPModeler, registry)
(:adnlp, :exa)Throws
ErrorException: If duplicate IDs are found within a familyErrorException: If a strategy is not a subtype of its familyErrorException: If a family appears multiple times
See also: StrategyRegistry, strategy_ids, type_from_id
describe [Function]
CTBase.Strategies.describe Function
Display detailed information about a strategy type, including its id, supertype, and full metadata with all available option definitions.
This function is useful for discovering what options a strategy accepts before constructing an instance.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy type to describe
Example
julia> describe(Modelers.ADNLP)
Modelers.ADNLP (strategy type)
├─ id: :adnlp
├─ supertype: AbstractNLPModeler
└─ metadata: 4 options defined
├─ show_time :: Bool (default: false)
│ description: Whether to show timing information
├─ backend :: Symbol (default: optimized)
│ description: AD backend used by ADNLPModels
└─ matrix_free :: Bool (default: false)
description: Enable matrix-free modeSee also: metadata, id, options
description [Function]
CTBase.Strategies.description Function
description(_::Type{<:CTBase.Strategies.AbstractStrategy})Return an optional description for a strategy type.
By default returns nothing (no description). Strategies may override this to provide a human-readable summary and, optionally, a reference URL. Multi-line descriptions are supported using '\n'.
Returns
Nothing: When no description is defined (default)String: Human-readable description, optionally with URL on a second line
Example
# Default: no description
description(MyStrategy) # returns nothing
# Override with description and URL
description(::Type{<:Modelers.ADNLP}) =
"NLP modeler using ADNLPModels.\nSee: https://jso.dev/ADNLPModels.jl"See also: describe, AbstractStrategy
description(
parameter_type::Type{<:CTBase.Strategies.AbstractStrategyParameter}
) -> StringGet the description for a parameter type.
Every concrete parameter type should implement this method to provide a human-readable description of the parameter's purpose and behavior.
Arguments
parameter_type::Type{<:AbstractStrategyParameter}: The parameter type
Returns
String: Human-readable description of the parameter
Throws
Exceptions.NotImplemented: If the parameter type doesn't implement this method
Example
julia> using CTBase.Strategies
julia> description(CPU)
"CPU-based computation"
julia> description(GPU)
"GPU-based computation"See also: id, AbstractStrategyParameter
description(_::Type{CTBase.Strategies.CPU}) -> StringCPU parameter description.
description(_::Type{CTBase.Strategies.GPU}) -> StringGPU parameter description.
extract_id_from_method [Function]
CTBase.Strategies.extract_id_from_method Function
extract_id_from_method(
method::Tuple{Vararg{Symbol}},
family::Type{<:CTBase.Strategies.AbstractStrategy},
registry::CTBase.Strategies.StrategyRegistry
) -> SymbolExtract the strategy ID for a specific family from a method tuple.
A method tuple contains multiple strategy IDs (e.g., (:collocation, :adnlp, :ipopt)). This function identifies which ID corresponds to the requested family.
Arguments
method::Tuple{Vararg{Symbol}}: Tuple of strategy IDsfamily::Type{<:AbstractStrategy}: Abstract family type to search forregistry::StrategyRegistry: Registry containing strategy mappings
Returns
Symbol: The ID corresponding to the requested family
Throws
Exceptions.IncorrectArgument: If no ID or multiple IDs are found for the family
Example
julia> method = (:collocation, :adnlp, :ipopt)
julia> extract_id_from_method(method, AbstractNLPModeler, registry)
:adnlp
julia> extract_id_from_method(method, AbstractNLPSolver, registry)
:ipoptSee also: strategy_ids
filter_options [Function]
CTBase.Strategies.filter_options Function
filter_options(
nt::NamedTuple,
exclude::Symbol
) -> NamedTupleFilter a NamedTuple by excluding specified keys.
Arguments
nt::NamedTuple: NamedTuple to filterexclude::Symbol: Single key to exclude
Returns
NamedTuple: New NamedTuple without the excluded key
Example
julia> opts = (max_iter=100, tol=1e-6, debug=true)
julia> filter_options(opts, :debug)
(max_iter = 100, tol = 1.0e-6)See also: filter_options(::NamedTuple, ::Tuple)
filter_options(
nt::NamedTuple,
exclude::Tuple{Vararg{Symbol}}
) -> NamedTupleFilter a NamedTuple by excluding specified keys.
Arguments
nt::NamedTuple: NamedTuple to filterexclude::Tuple{Vararg{Symbol}}: Tuple of keys to exclude
Returns
NamedTuple: New NamedTuple without the excluded keys
Example
julia> opts = (max_iter=100, tol=1e-6, debug=true)
julia> filter_options(opts, (:debug, :tol))
(max_iter = 100,)See also: filter_options(::NamedTuple, ::Symbol)
force [Function]
CTBase.Strategies.force Function
Force an option value to bypass validation.
This function is an alias for bypass and provides identical functionality. The name force may be more intuitive for users who prefer "force" semantics when bypassing validation.
Arguments
val: The option value to wrap
Returns
BypassValue: The wrapped value
Example
julia> using CTBase.Strategies
julia> # Force acceptance of unknown option
julia> solver = Ipopt(
max_iter=100,
custom_backend_option=force(42) # Forces validation bypass
)
Ipopt(options=StrategyOptions{...})
julia> # Same as bypass(42)
julia> @test force(42) == bypass(42)
trueNotes
forceandbypassare the same function:force === bypassChoose the name that best fits your mental model
Both functions create
BypassValuewrappersUse with caution for the same reasons as
bypass
See also: BypassValue, bypass, route_to
format_suggestion [Function]
CTBase.Strategies.format_suggestion Function
format_suggestion(s::NamedTuple) -> StringFormat a suggestion entry as a human-readable string.
Example
julia> format_suggestion((primary=:backend, aliases=(:adnlp_backend,), distance=1))
":backend (alias: adnlp_backend) [distance: 1]"get_parameter_type [Function]
CTBase.Strategies.get_parameter_type Function
get_parameter_type(strategy_type::Type) -> AnyExtract the parameter type from a parameterized strategy type.
For parameterized strategies like MadNLP{CPU}, this returns the parameter type CPU. For non-parameterized strategies, this returns nothing.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy type to extract parameter from
Returns
Union{Type{<:AbstractStrategyParameter}, Nothing}: Parameter type ornothingif non-parameterized
Examples
julia> get_parameter_type(MadNLP{CPU})
CPU
julia> get_parameter_type(MadNLP{GPU})
GPU
julia> get_parameter_type(Ipopt)
nothinghas_option [Function]
CTBase.Strategies.has_option Function
has_option(
strategy::CTBase.Strategies.AbstractStrategy,
key::Symbol
) -> AnyCheck if an option exists in a strategy instance.
Returns true if the option is present in the strategy's options, false otherwise. This is useful for checking if unknown options were stored in permissive mode.
Arguments
strategy::AbstractStrategy: The strategy instancekey::Symbol: The option name
Returns
Bool:trueif the option exists
Example
julia> using CTBase.Strategies
julia> strategy = MyStrategy(max_iter=200; mode=:permissive, custom_opt=123)
julia> has_option(strategy, :max_iter)
true
julia> has_option(strategy, :custom_opt)
true
julia> has_option(strategy, :nonexistent)
falseSee also: option_value, option_source
id [Function]
CTBase.Strategies.id Function
Return the unique identifier for this strategy type.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy type
Returns
Symbol: Unique identifier for the strategy
Example
# For a concrete strategy type MyStrategy:
julia> id(MyStrategy)
:mystrategymetadata [Function]
CTBase.Strategies.metadata Function
Return metadata about a strategy type.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy type
Returns
StrategyMetadata: Option specifications and validation rules
Example
# For a concrete strategy type MyStrategy:
julia> meta = metadata(MyStrategy)
julia> meta
StrategyMetadata with option definitions for max_iter, etc.option_default [Function]
CTBase.Strategies.option_default Function
option_default(
strategy_type::Type{<:CTBase.Strategies.AbstractStrategy},
key::Symbol
)Get the default value for a specific option.
Returns the value that will be used if the option is not explicitly provided by the user during strategy construction.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy typekey::Symbol: The option name
Returns
- The default value for the option (type depends on the option)
Example
julia> using CTBase.Strategies
julia> option_default(MyStrategy, :max_iter)
100
julia> option_default(MyStrategy, :tol)
1.0e-6Throws
KeyError: If the option name does not exist
Notes
This function operates on types, not instances
If you have an instance, use
option_default(typeof(strategy), key)
See also: option_defaults, option_type
option_defaults [Function]
CTBase.Strategies.option_defaults Function
option_defaults(
strategy_type::Type{<:CTBase.Strategies.AbstractStrategy}
)Get all default values as a NamedTuple.
Returns a NamedTuple containing the default value for every option defined in the strategy's metadata. This is useful for resetting configurations or understanding the baseline behavior.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy type
Returns
NamedTuple: All default values keyed by option name
Example
julia> using CTBase.Strategies
julia> option_defaults(MyStrategy)
(max_iter = 100, tol = 1.0e-6)
julia> defaults = option_defaults(MyStrategy)
julia> defaults.max_iter
100Notes
This function operates on types, not instances
If you have an instance, use
option_defaults(typeof(strategy))
See also: option_default, option_names
option_description [Function]
CTBase.Strategies.option_description Function
option_description(
strategy_type::Type{<:CTBase.Strategies.AbstractStrategy},
key::Symbol
)Get the human-readable description for a specific option.
Returns the documentation string that explains what the option controls. This is useful for generating help messages and documentation.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy typekey::Symbol: The option name
Returns
String: The option description
Example
julia> using CTBase.Strategies
julia> option_description(MyStrategy, :max_iter)
"Maximum number of iterations"
julia> option_description(MyStrategy, :tol)
"Convergence tolerance"Throws
KeyError: If the option name does not exist
Notes
This function operates on types, not instances
If you have an instance, use
option_description(typeof(strategy), key)
See also: option_type, option_default
option_is_computed [Function]
CTBase.Strategies.option_is_computed Function
option_is_computed(
strategy::CTBase.Strategies.AbstractStrategy,
key::Symbol
) -> BoolCheck if an option value was computed from other options.
Returns true if the option was calculated based on other option values, false if it was provided by the user or is using the default.
Arguments
strategy::AbstractStrategy: The strategy instancekey::Symbol: The option name
Returns
Bool:trueif the option source is:computed
Example
julia> using CTBase.Strategies
julia> strategy = MyStrategy()
julia> is_computed(strategy, :derived_value)
trueSee also: is_user, is_default, option_source
option_is_default [Function]
CTBase.Strategies.option_is_default Function
option_is_default(
strategy::CTBase.Strategies.AbstractStrategy,
key::Symbol
) -> BoolCheck if an option value is using its default.
Returns true if the option is using the default value from metadata, false if it was provided by the user or computed.
Arguments
strategy::AbstractStrategy: The strategy instancekey::Symbol: The option name
Returns
Bool:trueif the option source is:default
Example
julia> using CTBase.Strategies
julia> strategy = MyStrategy(max_iter=200)
julia> is_default(strategy, :max_iter)
false
julia> is_default(strategy, :tol)
trueSee also: is_user, is_computed, option_source
option_is_user [Function]
CTBase.Strategies.option_is_user Function
option_is_user(
strategy::CTBase.Strategies.AbstractStrategy,
key::Symbol
) -> BoolCheck if an option value was provided by the user.
Returns true if the option was explicitly set by the user during construction, false if it's using the default value or was computed.
Arguments
strategy::AbstractStrategy: The strategy instancekey::Symbol: The option name
Returns
Bool:trueif the option source is:user
Example
julia> using CTBase.Strategies
julia> strategy = MyStrategy(max_iter=200)
julia> is_user(strategy, :max_iter)
true
julia> is_user(strategy, :tol)
falseSee also: is_default, is_computed, option_source
option_names [Function]
CTBase.Strategies.option_names Function
option_names(
strategy_type::Type{<:CTBase.Strategies.AbstractStrategy}
)Get all option names for a strategy type.
Returns a tuple of all option names defined in the strategy's metadata. This is useful for discovering what options are available without needing to instantiate the strategy.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy type to introspect
Returns
Tuple{Vararg{Symbol}}: Tuple of option names
Example
julia> using CTBase.Strategies
julia> option_names(MyStrategy)
(:max_iter, :tol, :backend)
julia> for name in option_names(MyStrategy)
println("Available option: ", name)
end
Available option: max_iter
Available option: tol
Available option: backendNotes
This function operates on types, not instances
If you have an instance, use
option_names(typeof(strategy))
See also: option_type, option_description, option_default
option_source [Function]
CTBase.Strategies.option_source Function
option_source(
strategy::CTBase.Strategies.AbstractStrategy,
key::Symbol
) -> SymbolGet the source provenance of an option value.
Returns a symbol indicating where the option value came from:
:user- Explicitly provided by the user:default- Using the default value from metadata:computed- Calculated from other options
Arguments
strategy::AbstractStrategy: The strategy instancekey::Symbol: The option name
Returns
Symbol: The source provenance (:user,:default, or:computed)
Example
julia> using CTBase.Strategies
julia> strategy = MyStrategy(max_iter=200)
julia> option_source(strategy, :max_iter)
:user
julia> option_source(strategy, :tol)
:defaultThrows
KeyError: If the option name does not exist
See also: option_value, is_user, is_default
option_type [Function]
CTBase.Strategies.option_type Function
option_type(
strategy_type::Type{<:CTBase.Strategies.AbstractStrategy},
key::Symbol
)Get the expected type for a specific option.
Returns the Julia type that the option value must satisfy. This is useful for validation and documentation purposes.
Arguments
strategy_type::Type{<:AbstractStrategy}: The strategy typekey::Symbol: The option name
Returns
Type: The expected type for the option value
Example
julia> using CTBase.Strategies
julia> option_type(MyStrategy, :max_iter)
Int64
julia> option_type(MyStrategy, :tol)
Float64Throws
KeyError: If the option name does not exist
Notes
This function operates on types, not instances
If you have an instance, use
option_type(typeof(strategy), key)
See also: option_description, option_default
option_value [Function]
CTBase.Strategies.option_value Function
option_value(
strategy::CTBase.Strategies.AbstractStrategy,
key::Symbol
) -> AnyGet the current value of an option from a strategy instance.
Returns the effective value that the strategy is using for the specified option. This may be a user-provided value or the default value.
Arguments
strategy::AbstractStrategy: The strategy instancekey::Symbol: The option name
Returns
- The current option value (type depends on the option)
Example
julia> using CTBase.Strategies
julia> strategy = MyStrategy(max_iter=200)
julia> option_value(strategy, :max_iter)
200
julia> option_value(strategy, :tol) # Uses default
1.0e-6Throws
KeyError: If the option name does not exist
See also: option_source, options
options [Function]
CTBase.Strategies.options Function
Return the current options of a strategy as a StrategyOptions.
Arguments
strategy::AbstractStrategy: The strategy instance
Returns
StrategyOptions: Current option values with provenance tracking
Example
# For a concrete strategy instance:
julia> strategy = MyStrategy(backend=:sparse)
julia> opts = options(strategy)
julia> opts
StrategyOptions with values=(backend=:sparse), sources=(backend=:user)options_dict [Function]
CTBase.Strategies.options_dict Function
options_dict(
opts::CTBase.Strategies.StrategyOptions
) -> Dict{Symbol, Any}Extract strategy options as a mutable Dict, ready for modification.
This method converts StrategyOptions to a Dict by unwrapping OptionValue wrappers and filtering out NotProvided values. The resulting Dict is mutable and can be modified before passing to backend solvers or model builders.
Arguments
opts::StrategyOptions: Strategy options to convert
Returns
Dict{Symbol, Any}: Mutable dictionary of option values
Example
julia> using CTBase.Strategies, CTBase.Options
julia> opts = StrategyOptions(
max_iter = OptionValue(500, :user),
tolerance = OptionValue(1e-8, :default)
)
julia> dict = options_dict(opts)
Dict{Symbol, Any} with 2 entries:
:max_iter => 500
:tolerance => 1.0e-8
julia> dict[:verbose] = true # Modify as needed
trueNotes
NotProvided values are filtered out
Explicit nothing values are preserved
The returned Dict is mutable and independent from the original StrategyOptions
See also: Options.extract_raw_options, _raw_options
options_dict(
strategy::CTBase.Strategies.AbstractStrategy
) -> Dict{Symbol, Any}Extract strategy options as a mutable Dict, ready for modification.
This is a convenience method that combines two steps into one:
Getting
StrategyOptionsfrom the strategyConverting to
Dictviaoptions_dict(StrategyOptions)
Arguments
strategy::AbstractStrategy: Strategy instance (solver, modeler, etc.)
Returns
Dict{Symbol, Any}: Mutable dictionary of option values
Example
julia> using CTBase
julia> solver = FakeSolver(max_iter=1000, tol=1e-8)
julia> opts = Strategies.options_dict(solver)
Dict{Symbol, Any} with 2 entries:
:max_iter => 1000
:tol => 1.0e-8
julia> opts[:max_iter] = 500 # Modify as needed
500
julia> solve_with_backend(nlp; opts...)Notes
This function delegates to options_dict(StrategyOptions) for the actual conversion. It is particularly useful in solver extensions and modelers where you need to extract options and potentially modify them before passing to backend solvers or model builders.
See also: options, options_dict(::StrategyOptions)
resolve_alias [Function]
CTBase.Strategies.resolve_alias Function
resolve_alias(
meta::CTBase.Strategies.StrategyMetadata,
key::Symbol
) -> Union{Nothing, Symbol}Resolve an alias to its primary key name.
Searches through strategy metadata to find if a given key is either:
A primary option name
An alias for a primary option name
Arguments
meta::StrategyMetadata: Strategy metadata to search inkey::Symbol: Key to resolve (can be primary name or alias)
Returns
Union{Symbol, Nothing}: Primary key if found,nothingotherwise
Example
julia> meta = metadata(MyStrategy)
julia> resolve_alias(meta, :max_iter) # Primary name
:max_iter
julia> resolve_alias(meta, :max) # Alias
:max_iter
julia> resolve_alias(meta, :unknown) # Not found
nothingSee also: StrategyMetadata, OptionDefinition
route_to [Function]
CTBase.Strategies.route_to Function
route_to(; kwargs...)Create a disambiguated option value by explicitly routing it to specific strategies.
This function resolves ambiguity when the same option name exists in multiple strategies (e.g., both modeler and solver have max_iter). It creates a RoutedOption that tells the orchestration layer exactly which strategy should receive which value.
Arguments
kwargs...: Named arguments where keys are strategy identifiers (:solver,:modeler, etc.) and values are the option values to route to those strategies
Returns
RoutedOption: A routed option containing the strategy => value mappings
Throws
Exceptions.PreconditionError: If no strategies are provided
Example
julia> using CTBase.Strategies
julia> # Single strategy
julia> route_to(solver=100)
RoutedOption((solver = 100,))
julia> # Multiple strategies with different values
julia> route_to(solver=100, modeler=50)
RoutedOption((solver = 100, modeler = 50))
julia> # Alternative positional syntax
julia> route_to(:solver, 100, :modeler, 50)
RoutedOption((solver = 100, modeler = 50))Usage in solve()
# Without disambiguation - error if max_iter exists in multiple strategies
solve(ocp, method; max_iter=100) # ❌ Ambiguous!
# With disambiguation - explicit routing (keyword syntax)
solve(ocp, method;
max_iter = route_to(solver=100) # Only solver gets 100
)
solve(ocp, method;
max_iter = route_to(solver=100, modeler=50) # Different values for each
)
# With disambiguation - explicit routing (positional syntax)
solve(ocp, method;
max_iter = route_to(:solver, 100, :modeler, 50) # Different values for each
)Notes
Strategy identifiers must match the actual strategy IDs in your method tuple
You can route to one or multiple strategies in a single call
Alternative positional syntax:
route_to(:solver, 100, :modeler, 50)Both syntaxes are equivalent; choose based on preference
This is the recommended way to disambiguate options
The orchestration layer will validate that the strategy IDs exist
See also: RoutedOption, route_all_options
route_to(args...)Create a disambiguated option value using positional arguments.
This is an alternative syntax to the keyword argument version. Accepts alternating strategy identifier (Symbol) and value pairs.
Arguments
args::Vararg{Any}: Alternating strategy_id (Symbol) and value pairs. Must have an even number of arguments. Odd-numbered arguments must be Symbols.
Returns
RoutedOption: A routed option containing the strategy => value mappings
Throws
Exceptions.PreconditionError: If no arguments provided, odd number of arguments, or odd-numbered arguments are not Symbols
Example
julia> using CTBase.Strategies
julia> # Single strategy
julia> route_to(:solver, 100)
RoutedOption((solver = 100,))
julia> # Multiple strategies
julia> route_to(:solver, 100, :modeler, 50)
RoutedOption((solver = 100, modeler = 50))Notes
This is equivalent to the keyword syntax:
route_to(solver=100, modeler=50)Strategy identifiers must be Symbols (e.g.,
:solver, not"solver")The number of arguments must be even (pairs of Symbol-value)
See also: route_to(; kwargs...), RoutedOption
strategy_ids [Function]
CTBase.Strategies.strategy_ids Function
strategy_ids(
family::Type{<:CTBase.Strategies.AbstractStrategy},
registry::CTBase.Strategies.StrategyRegistry
) -> Tuple{Vararg{Symbol}}Get all strategy IDs for a given family.
Returns a tuple of symbolic identifiers for all strategies registered under the specified family type. The order matches the registration order.
Arguments
family::Type{<:AbstractStrategy}: The abstract family typeregistry::StrategyRegistry: The registry to query
Returns
Tuple{Vararg{Symbol}}: Tuple of strategy IDs in registration order
Example
julia> using CTBase.Strategies
julia> ids = strategy_ids(AbstractNLPModeler, registry)
(:adnlp, :exa)
julia> for strategy_id in ids
println("Available: ", strategy_id)
end
Available: adnlp
Available: exaThrows
ErrorException: If the family is not found in the registry
See also: type_from_id, create_registry
suggest_options [Function]
CTBase.Strategies.suggest_options Function
suggest_options(
key::Symbol,
strategy_type::Type{<:CTBase.Strategies.AbstractStrategy};
max_suggestions
)Suggest similar option names for an unknown key using Levenshtein distance.
For each option, the distance is the minimum over the primary name and all its aliases. Results are grouped by primary option name and sorted by this minimum distance.
Arguments
key::Symbol: Unknown key to find suggestions forstrategy_type::Type{<:AbstractStrategy}: Strategy type to search inmax_suggestions::Int=3: Maximum number of suggestions to return
Returns
Vector{@NamedTuple{primary::Symbol, aliases::Tuple{Vararg{Symbol}}, distance::Int}}: Suggested options sorted by distance (closest first), each with primary name, aliases, and distance.
Example
julia> suggest_options(:max_it, MyStrategy)
1-element Vector{...}:
(primary = :max_iter, aliases = (), distance = 2)
julia> suggest_options(:adnlp_backen, MyStrategy)
1-element Vector{...}:
(primary = :backend, aliases = (:adnlp_backend,), distance = 1)Note
The distance of an option to the key is min(dist(key, primary), dist(key, alias1), ...). This ensures that options with a close alias are suggested even if the primary name is far.
See also: resolve_alias, levenshtein_distance
suggest_options(
key::Symbol,
meta::CTBase.Strategies.StrategyMetadata;
max_suggestions
) -> Vector{@NamedTuple{primary::Symbol, aliases::Tuple{Vararg{Symbol}}, distance::Int64}}Suggest similar option names from a StrategyMetadata using Levenshtein distance.
See suggest_options(::Symbol, ::Type{<:AbstractStrategy}) for details.
type_from_id [Function]
CTBase.Strategies.type_from_id Function
type_from_id(
strategy_id::Symbol,
family::Type{<:CTBase.Strategies.AbstractStrategy},
registry::CTBase.Strategies.StrategyRegistry;
parameter
) -> TypeLookup a strategy type from its ID within a family.
Searches the registry for a strategy with the given symbolic identifier within the specified family. This is the core lookup mechanism used by the builder functions to convert symbolic descriptions to concrete types.
Arguments
strategy_id::Symbol: The symbolic identifier to look upfamily::Type{<:AbstractStrategy}: The family to search withinregistry::StrategyRegistry: The registry to query
Returns
Type{<:AbstractStrategy}: The concrete strategy type matching the ID
Example
julia> using CTBase.Strategies
julia> T = type_from_id(:adnlp, AbstractNLPModeler, registry)
Modelers.ADNLP
julia> id(T)
:adnlpThrows
Exceptions.IncorrectArgument: If the family is not found in the registryExceptions.IncorrectArgument: If the ID is not found within the family (includes suggestions)
See also: strategy_ids, build_strategy