diff --git a/Project.toml b/Project.toml index ba09a34c..79ff8a8c 100644 --- a/Project.toml +++ b/Project.toml @@ -10,7 +10,6 @@ CTModels = "34c4fa32-2049-4079-8329-de33c2a22e2d" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" -Reexport = "189a3867-3050-52da-a836-e630ba90ab69" [weakdeps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" @@ -33,8 +32,8 @@ CTFlowsStaticArrays = ["StaticArrays"] [compat] ADTypes = "1" Aqua = "0.8" -CTBase = "0.21" -CTModels = "0.12" +CTBase = "0.22" +CTModels = "0.13" DiffEqBase = "6, 7" DifferentiationInterface = "0.7" DocStringExtensions = "0.9" @@ -44,7 +43,6 @@ NonlinearSolve = "4" OrdinaryDiffEqTsit5 = "2" Plots = "1" RecipesBase = "1" -Reexport = "1" SciMLBase = "3" StaticArrays = "1" Test = "1" diff --git a/docs/api_reference.jl b/docs/api_reference.jl index 276391fb..7aa19873 100644 --- a/docs/api_reference.jl +++ b/docs/api_reference.jl @@ -26,32 +26,6 @@ function generate_api_reference(src_dir::String, ext_dir::String) EXCLUDE_BASE = Symbol[:include, :eval] pages = [ - # ─────────────────────────────────────────────────────────────────── - # Traits - # ─────────────────────────────────────────────────────────────────── - CTBase.automatic_reference_documentation(; - subdirectory="api", - primary_modules=[ - CTFlows.Traits => src( - joinpath("Traits", "Traits.jl"), - joinpath("Traits", "abstract.jl"), - joinpath("Traits", "ad.jl"), - joinpath("Traits", "dynamics.jl"), - joinpath("Traits", "helpers.jl"), - joinpath("Traits", "mode.jl"), - joinpath("Traits", "mutability.jl"), - joinpath("Traits", "time_dependence.jl"), - joinpath("Traits", "variable_costate.jl"), - joinpath("Traits", "variable_dependence.jl"), - ), - ], - exclude=EXCLUDE_BASE, - public=true, - private=true, - title="Traits", - title_in_menu="Traits", - filename="api_traits", - ), # ─────────────────────────────────────────────────────────────────── # Configs # ─────────────────────────────────────────────────────────────────── diff --git a/docs/make.jl b/docs/make.jl index 2096cccb..49731e8a 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -100,15 +100,12 @@ with_api_reference(src_dir, ext_dir) do api_pages asset("https://control-toolbox.org/assets/css/documentation.css"), asset("https://control-toolbox.org/assets/js/documentation.js"), ], - size_threshold_ignore=[ - joinpath("api", "api_traits_public.md"), - ], + size_threshold_ignore=String[], ), pages=[ "Introduction" => "index.md", "Flows" => [ "Overview" => "flows/index.md", - "Traits" => "flows/traits.md", "Data structures" => "flows/data.md", "Building a flow" => "flows/building_a_flow.md", "Integrating" => "flows/integrating.md", diff --git a/docs/src/flows/traits.md b/docs/src/flows/traits.md deleted file mode 100644 index 620c5b52..00000000 --- a/docs/src/flows/traits.md +++ /dev/null @@ -1,148 +0,0 @@ -# Traits - -```@meta -CurrentModule = CTFlows -``` - -Every object in CTFlows — data wrappers, systems, flows — carries up to three -**compile-time traits** encoded as type parameters. These traits determine the -**call signature** of the object and enable static dispatch without runtime -type checks. - -The traits are provided by [`CTFlows.Traits`](@ref CTFlows.Traits). - -```@example flows_traits -using CTFlows -using CTFlows.Traits -nothing # hide -``` - -## The three trait axes - -### 1. Time dependence - -Does the object depend on time ``t``? - -| Value | Type | Meaning | -|---|---|---| -| `Autonomous` | `Traits.Autonomous` | ``t`` is not an argument | -| `NonAutonomous` | `Traits.NonAutonomous` | ``t`` must be supplied | - -`Autonomous` and `NonAutonomous` are re-exported from `CTModels.OCP`. They are -available directly from `CTFlows.Traits`. - -```@example flows_traits -Traits.Autonomous # the singleton type -Traits.NonAutonomous -``` - -Predicates: `is_autonomous(obj)`, `is_nonautonomous(obj)`. - -### 2. Variable dependence - -Does the object depend on an extra parameter ``v`` (e.g. a free final time or a -design variable)? - -| Value | Type | Meaning | -|---|---|---| -| `Fixed` | [`CTFlows.Traits.Fixed`](@ref) | no ``v`` argument | -| `NonFixed` | [`CTFlows.Traits.NonFixed`](@ref) | ``v`` must be supplied | - -```@example flows_traits -Traits.Fixed -Traits.NonFixed -``` - -Predicates: `is_variable(obj)`, `is_nonvariable(obj)`, `has_variable(obj)`. - -### 3. Mutability - -Does the function allocate a new output, or write into a pre-allocated buffer? - -| Value | Type | Meaning | -|---|---|---| -| `OutOfPlace` | [`CTFlows.Traits.OutOfPlace`](@ref) | returns a new value | -| `InPlace` | [`CTFlows.Traits.InPlace`](@ref) | writes into `dx` (first arg) | - -```@example flows_traits -Traits.OutOfPlace -Traits.InPlace -``` - -Predicates: `is_outofplace(obj)`, `is_inplace(obj)`. - -!!! note "Default" - When you construct a `VectorField` without specifying `is_inplace`, the - mutability is **auto-detected** from the function's arity. Prefer out-of-place - for simplicity; use in-place only when avoiding allocations matters. - -## Call signatures - -The combination of time dependence and variable dependence gives four natural call -signatures. For a **vector field** ``X``: - -| Time | Variable | Natural signature | Buffer (in-place) | -|---|---|---|---| -| `Autonomous` | `Fixed` | `X(x)` | `X(dx, x)` | -| `NonAutonomous` | `Fixed` | `X(t, x)` | `X(dx, t, x)` | -| `Autonomous` | `NonFixed` | `X(x, v)` | `X(dx, x, v)` | -| `NonAutonomous` | `NonFixed` | `X(t, x, v)` | `X(dx, t, x, v)` | - -For a **Hamiltonian** ``H`` the costate `p` follows `x`: - -| Time | Variable | Natural signature | -|---|---|---| -| `Autonomous` | `Fixed` | `H(x, p)` | -| `NonAutonomous` | `Fixed` | `H(t, x, p)` | -| `Autonomous` | `NonFixed` | `H(x, p, v)` | -| `NonAutonomous` | `NonFixed` | `H(t, x, p, v)` | - -For a **Hamiltonian vector field** ``\vec{H}`` (returns `(dx, dp)`): - -| Time | Variable | Natural signature | -|---|---|---| -| `Autonomous` | `Fixed` | `HVF(x, p)` | -| `NonAutonomous` | `Fixed` | `HVF(t, x, p)` | -| `Autonomous` | `NonFixed` | `HVF(x, p, v)` | -| `NonAutonomous` | `NonFixed` | `HVF(t, x, p, v)` | - -## Trait accessors - -All typed objects expose the same accessor API: - -```@example flows_traits -using CTFlows.Data - -vf = Data.VectorField((t, x, v) -> x .* v; is_autonomous=false, is_variable=true) - -Traits.time_dependence(vf) # NonAutonomous -Traits.variable_dependence(vf) # NonFixed -Traits.mutability(vf) # OutOfPlace (auto-detected) - -Traits.is_autonomous(vf) # false -Traits.is_variable(vf) # true -Traits.is_outofplace(vf) # true -``` - -The same accessors work on systems, flows, and configuration objects — the -trait is always extracted from the type parameter, so there is **no runtime cost**. - -## Uniform call signature - -Internally, every `VectorField` also responds to a **uniform** call `(t, x, v)` -that ignores unused arguments. This lets system builders write trait-agnostic code: - -```julia -# Works regardless of the VectorField's traits: -dx = vf(t, x, v) -``` - -The uniform signature is used by `VectorFieldSystem.rhs` to build the ODE -right-hand side without trait branches. Users normally never call it directly. - -## See also - -- [`CTFlows.Traits.Fixed`](@ref), [`CTFlows.Traits.NonFixed`](@ref) — variable-dependence trait values. -- [`CTFlows.Traits.InPlace`](@ref), [`CTFlows.Traits.OutOfPlace`](@ref) — mutability trait values. -- [`CTFlows.Traits.time_dependence`](@ref), [`CTFlows.Traits.variable_dependence`](@ref), [`CTFlows.Traits.mutability`](@ref) — trait accessor functions. -- [`CTFlows.Traits.is_inplace`](@ref), [`CTFlows.Traits.is_outofplace`](@ref) — mutability predicates. diff --git a/ext/CTFlowsSciMLFlows/CTFlowsSciMLFlows.jl b/ext/CTFlowsSciMLFlows/CTFlowsSciMLFlows.jl index 5f6a116c..07c0aae3 100644 --- a/ext/CTFlowsSciMLFlows/CTFlowsSciMLFlows.jl +++ b/ext/CTFlowsSciMLFlows/CTFlowsSciMLFlows.jl @@ -20,7 +20,7 @@ import CTBase.Exceptions using CTFlows: CTFlows using CTFlows.Common: Common using CTFlows.Configs: Configs -using CTFlows.Traits: Traits +using CTBase.Traits: Traits using CTFlows.Systems: Systems using CTFlows.Integrators: Integrators using CTFlows.Flows: Flows, AbstractFlow, build_flow diff --git a/ext/CTFlowsSciMLIntegrator/CTFlowsSciMLIntegrator.jl b/ext/CTFlowsSciMLIntegrator/CTFlowsSciMLIntegrator.jl index 1090b440..e806a001 100644 --- a/ext/CTFlowsSciMLIntegrator/CTFlowsSciMLIntegrator.jl +++ b/ext/CTFlowsSciMLIntegrator/CTFlowsSciMLIntegrator.jl @@ -28,7 +28,7 @@ using CTFlows: CTFlows using CTFlows.Common: Common using CTFlows.Configs: Configs using CTFlows.Systems: Systems -using CTFlows.Traits: Traits +using CTBase.Traits: Traits using CTFlows.Integrators: Integrators, SciML, SciMLTag, Tsit5Tag using DiffEqBase: DiffEqBase using SciMLBase: SciMLBase, ODEProblem diff --git a/src/CTFlows.jl b/src/CTFlows.jl index 136b4bc0..e6abc9a0 100644 --- a/src/CTFlows.jl +++ b/src/CTFlows.jl @@ -27,8 +27,8 @@ module CTFlows # Include submodules in topological order # ============================================================================== -include(joinpath(@__DIR__, "Traits", "Traits.jl")) -using .Traits +# Traits moved to CTBase.Traits; alias kept so `CTFlows.Traits` still resolves. +import CTBase.Traits include(joinpath(@__DIR__, "Configs", "Configs.jl")) using .Configs diff --git a/src/Configs/Configs.jl b/src/Configs/Configs.jl index d95b1874..956d900e 100644 --- a/src/Configs/Configs.jl +++ b/src/Configs/Configs.jl @@ -44,7 +44,7 @@ import CTBase.Exceptions # Sibling imports # ============================================================================== -import ..Traits: Traits +import CTBase.Traits # ============================================================================== # Includes diff --git a/src/Data/Data.jl b/src/Data/Data.jl index ba9f63da..c6ccdf97 100644 --- a/src/Data/Data.jl +++ b/src/Data/Data.jl @@ -17,7 +17,7 @@ import CTBase.Exceptions # ============================================================================== import ..Common: Common -import ..Traits: Traits +import CTBase.Traits # ============================================================================== # Include files diff --git a/src/DifferentialGeometry/DifferentialGeometry.jl b/src/DifferentialGeometry/DifferentialGeometry.jl index 29d63c7a..4c3365d2 100644 --- a/src/DifferentialGeometry/DifferentialGeometry.jl +++ b/src/DifferentialGeometry/DifferentialGeometry.jl @@ -28,7 +28,7 @@ import MacroTools: postwalk, @capture # Internal sibling-submodule imports # ============================================================================== -import ..Traits: Traits +import CTBase.Traits import ..Common: Common import ..Data: Data import ..Differentiation: Differentiation diff --git a/src/Flows/Flows.jl b/src/Flows/Flows.jl index 6fe80013..ed47b906 100644 --- a/src/Flows/Flows.jl +++ b/src/Flows/Flows.jl @@ -25,7 +25,7 @@ import CTModels import ..Common: Common import ..Configs: Configs -import ..Traits: Traits +import CTBase.Traits import ..Data: Data import ..Differentiation: Differentiation import ..Systems: Systems, hamiltonian_vector_field @@ -40,7 +40,6 @@ include(joinpath(@__DIR__, "abstract_flow.jl")) include(joinpath(@__DIR__, "flow.jl")) include(joinpath(@__DIR__, "registry.jl")) include(joinpath(@__DIR__, "flow_routing.jl")) -include(joinpath(@__DIR__, "ocp_model_traits.jl")) include(joinpath(@__DIR__, "optimal_control_flow.jl")) include(joinpath(@__DIR__, "building.jl")) include(joinpath(@__DIR__, "calling.jl")) diff --git a/src/Flows/ocp_model_traits.jl b/src/Flows/ocp_model_traits.jl deleted file mode 100644 index 295c3b83..00000000 --- a/src/Flows/ocp_model_traits.jl +++ /dev/null @@ -1,40 +0,0 @@ -# ============================================================================= -# Trait contracts for CTModels.Models.Model -# -# TEMPORARY — will move to CTModels once the contracts are stable. -# -# Implements has_time_dependence_trait / time_dependence and -# has_variable_dependence_trait / variable_dependence for CTModels.Models.Model, -# enabling Flow(ocp) to read TD/VD at the type level without boolean inspection. -# ============================================================================= - -import CTModels - -# ----------------------------------------------------------------------------- -# Time dependence -# -# CTModels.Model{TD, ...} carries TD ∈ {Components.Autonomous, Components.NonAutonomous} -# as a type parameter. CTFlows.Traits.is_autonomous compares via: -# time_dependence(obj) === Models.Autonomous -# so returning the TD type itself satisfies the contract. -# ----------------------------------------------------------------------------- - -Traits.has_time_dependence_trait(::CTModels.Models.Model) = true - -Traits.time_dependence(::CTModels.Models.Model{TD}) where {TD} = TD - -# ----------------------------------------------------------------------------- -# Variable dependence -# -# Position 5 of CTModels.Model is VariableModelType. -# CTModels.Components.EmptyVariableModel ⟹ no optimisation variable ⟹ Traits.Fixed -# Any other VariableModelType ⟹ Traits.NonFixed -# -# CTFlows.Traits.Fixed / NonFixed are types; the contract compares via ===, so -# return the type (not an instance). -# ----------------------------------------------------------------------------- - -Traits.has_variable_dependence_trait(::CTModels.Models.Model) = true - -Traits.variable_dependence(ocp::CTModels.Models.Model) = - CTModels.Models.is_nonvariable(ocp) ? Traits.Fixed : Traits.NonFixed diff --git a/src/MultiPhase/MultiPhase.jl b/src/MultiPhase/MultiPhase.jl index 56a732e5..bfafcba9 100644 --- a/src/MultiPhase/MultiPhase.jl +++ b/src/MultiPhase/MultiPhase.jl @@ -20,7 +20,7 @@ import CTBase.Options import ..Common: Common import ..Configs: Configs -import ..Traits: Traits +import CTBase.Traits import ..Systems: Systems import ..Integrators: Integrators import ..Flows: Flows diff --git a/src/Systems/Systems.jl b/src/Systems/Systems.jl index cfc687eb..1bc1faca 100644 --- a/src/Systems/Systems.jl +++ b/src/Systems/Systems.jl @@ -20,7 +20,7 @@ import CTBase.Exceptions # ============================================================================== import ..Common: Common -import ..Traits: Traits +import CTBase.Traits import ..Configs: Configs import ..Data: Data import ..Differentiation: Differentiation diff --git a/src/Traits/Traits.jl b/src/Traits/Traits.jl deleted file mode 100644 index 26a029f1..00000000 --- a/src/Traits/Traits.jl +++ /dev/null @@ -1,69 +0,0 @@ -""" - Traits - -Trait types and trait-based dispatch for CTFlows. - -This module provides the trait system used throughout CTFlows for compile-time -dispatch on: -- Time dependence: [`Autonomous`](@extref), [`NonAutonomous`](@extref) -- Variable dependence: [`Fixed`](@ref), [`NonFixed`](@ref) -- Integration mode: [`EndPointMode`](@ref), [`TrajectoryMode`](@ref) -- Dynamics type: [`StateDynamics`](@ref), [`HamiltonianDynamics`](@ref), [`AugmentedHamiltonianDynamics`](@ref) -- Mutability: [`InPlace`](@ref), [`OutOfPlace`](@ref) -- Automatic differentiation: [`WithAD`](@ref), [`WithoutAD`](@ref) -- Variable costate capability: [`SupportsVariableCostate`](@ref), [`NoVariableCostate`](@ref) - -Traits are used as type parameters in configuration types, vector fields, and systems -to enable static dispatch without runtime type checks. - -See also: [`CTFlows.Configs.AbstractConfig`](@ref), [`CTFlows.Data.AbstractVectorField`](@ref). -""" -module Traits - -# ============================================================================== -# External package imports -# ============================================================================== - -using Reexport -import DocStringExtensions: TYPEDEF, TYPEDSIGNATURES -import CTBase.Exceptions -import CTModels.Models - -# ============================================================================== -# Includes -# ============================================================================== - -include(joinpath(@__DIR__, "helpers.jl")) -include(joinpath(@__DIR__, "abstract.jl")) -include(joinpath(@__DIR__, "mode.jl")) -include(joinpath(@__DIR__, "dynamics.jl")) -include(joinpath(@__DIR__, "ad.jl")) -include(joinpath(@__DIR__, "variable_costate.jl")) -include(joinpath(@__DIR__, "mutability.jl")) -include(joinpath(@__DIR__, "time_dependence.jl")) -include(joinpath(@__DIR__, "variable_dependence.jl")) - -# ============================================================================== -# Module exports -# ============================================================================== - -@reexport import CTModels.Models: Autonomous, NonAutonomous, TimeDependence -@reexport import CTModels.Models: is_autonomous, is_nonautonomous, is_variable, is_nonvariable, has_variable - -export AbstractTrait -export AbstractModeTrait, AbstractDynamicsTrait -export AbstractMutabilityTrait -export AbstractADTrait -export AbstractVariableCostateCapability -export EndPointMode, TrajectoryMode -export StateDynamics, HamiltonianDynamics, AugmentedHamiltonianDynamics -export InPlace, OutOfPlace -export WithAD, WithoutAD -export SupportsVariableCostate, NoVariableCostate -export VariableDependence, Fixed, NonFixed -export ad_trait, variable_costate_trait, dynamics_trait -export is_inplace, is_outofplace -export has_time_dependence_trait, time_dependence, has_mutability_trait, mutability -export has_variable_dependence_trait, variable_dependence - -end # module Traits diff --git a/src/Traits/abstract.jl b/src/Traits/abstract.jl deleted file mode 100644 index d4e1b309..00000000 --- a/src/Traits/abstract.jl +++ /dev/null @@ -1,51 +0,0 @@ -""" -$(TYPEDEF) - -Abstract base type for trait markers in CTFlows. - -Traits are empty marker types used as type parameters to encode configuration -properties at compile time. Unlike tags (which mark extension implementations), -traits encode semantic properties of the configuration itself (e.g., integration -mode, content type, mutability). - -# Trait Pattern - -Traits are used as type parameters in abstract configuration types to enable -compile-time dispatch without runtime type checks. For example, `AbstractConfig` -uses `EndPointMode` vs `TrajectoryMode` to distinguish integration modes, and -`StateDynamics` vs `HamiltonianDynamics` to distinguish dynamics types. - -All concrete trait types are empty structs with no fields, making them zero-cost -at runtime. - -# Interface Requirements - -Concrete trait subtypes should: -- Be empty structs with no fields (pure markers) -- Subtype an intermediate abstract trait category (e.g., `AbstractModeTrait`) -- Be used as type parameters in configuration types - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> EndPointMode <: Traits.AbstractTrait -true - -julia> EndPointMode <: Traits.AbstractModeTrait -true - -julia> # Used as type parameters in configs: -julia> StateEndPointConfig <: CTFlows.Configs.AbstractConfig{<:Any, EndPointMode, StateDynamics} -true -\`\`\` - -# Notes -- Traits are distinct from tags: tags mark extension implementations (e.g., `SciMLTag`), - while traits encode configuration semantics (e.g., `EndPointMode`) -- All trait types have zero runtime overhead (empty structs) -- The trait pattern enables static dispatch on configuration properties - -See also: [`CTFlows.Traits.VariableDependence`](@ref), [`CTFlows.Traits.AbstractModeTrait`](@ref), [`CTFlows.Traits.AbstractDynamicsTrait`](@ref), [`CTFlows.Traits.AbstractMutabilityTrait`](@ref). -""" -abstract type AbstractTrait end diff --git a/src/Traits/ad.jl b/src/Traits/ad.jl deleted file mode 100644 index 6986d588..00000000 --- a/src/Traits/ad.jl +++ /dev/null @@ -1,127 +0,0 @@ -""" -$(TYPEDEF) - -Abstract base type for automatic differentiation capability traits. - -AD traits encode whether a system supports automatic differentiation for gradient -computation. This distinction enables compile-time dispatch for cache preparation, -derivative computation, and other AD-related operations. - -Common use cases include: -- Hamiltonian systems: distinguishing between scalar Hamiltonians with AD backends - and pre-computed Hamiltonian vector fields -- General optimization: marking systems that can compute gradients via AD vs. those - with manual derivative implementations -- Cache preparation: enabling static dispatch for AD-specific cache initialization - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> WithAD() isa Traits.AbstractADTrait -true - -julia> WithoutAD() isa Traits.AbstractADTrait -true -\`\`\` - -# Notes -- AD traits are used as type parameters in system types to enable static dispatch -- `WithAD` indicates the system carries differentiable functions and an AD backend -- `WithoutAD` indicates the system uses pre-computed derivatives or manual implementations -- The specific meaning depends on the system type and context - -See also: [`CTFlows.Traits.WithAD`](@ref), [`CTFlows.Traits.WithoutAD`](@ref), [`CTFlows.Common.AbstractCache`](@ref). -""" -abstract type AbstractADTrait <: AbstractTrait end - -""" -$(TYPEDEF) - -Trait for systems with automatic differentiation support. - -Indicates that a system carries differentiable functions and an AD backend, -enabling automatic computation of derivatives. Such systems typically require -cache preparation before operations that need gradients or Jacobians. - -Common use cases include: -- Hamiltonian systems: scalar Hamiltonians where the vector field is computed via AD -- Optimization: objective functions where gradients are computed via AD -- General systems: any differentiable function that benefits from automatic gradient computation - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> with = WithAD() -WithAD() - -julia> with isa Traits.AbstractADTrait -true -\`\`\` - -# Notes -- Used as a type parameter in system types to enable AD-based derivative computation -- Systems with `WithAD` typically require cache preparation via the backend's `prepare_cache` method -- The cache is passed through parameters during integration or evaluation -- The specific operations enabled depend on the system type and AD backend - -See also: [`CTFlows.Traits.AbstractADTrait`](@ref), [`CTFlows.Traits.WithoutAD`](@ref), [`CTFlows.Common.AbstractCache`](@ref). -""" -struct WithAD <: AbstractADTrait end # system carries H + AD backend - -""" -$(TYPEDEF) - -Trait for systems without automatic differentiation support. - -Indicates that a system uses pre-computed derivatives or manual implementations, -without requiring AD or cache preparation. This is the traditional mode where -derivatives are provided explicitly by the user or computed offline. - -Common use cases include: -- Hamiltonian systems: pre-computed Hamiltonian vector fields provided manually -- Optimization: manually implemented gradient functions -- General systems: any system where derivatives are known analytically or computed externally - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> without = WithoutAD() -WithoutAD() - -julia> without isa Traits.AbstractADTrait -true -\`\`\` - -# Notes -- Used as a type parameter in system types for derivative-based systems without AD -- No cache preparation is required for `WithoutAD` systems -- This is the default mode for systems with pre-computed derivatives -- The specific derivative implementations depend on the system type - -See also: [`CTFlows.Traits.AbstractADTrait`](@ref), [`CTFlows.Traits.WithAD`](@ref). -""" -struct WithoutAD <: AbstractADTrait end # system carries HVF directly - -""" -$(TYPEDSIGNATURES) - -Return the automatic differentiation capability trait of a system or flow. - -# Arguments -- `obj`: Any object (default implementation returns `WithoutAD`). - -# Returns -- `Type{<:AbstractADTrait}`: The AD capability trait, either `WithAD` or `WithoutAD`. - -# Notes -- Default implementation returns `WithoutAD` for all objects -- Specialized implementations on system types return the appropriate trait based on the system's AD support -- Used for dispatch in cache preparation, derivative computation, and augmented integration -- The specific operations enabled by the trait depend on the system type - -See also: [`CTFlows.Traits.AbstractADTrait`](@ref), [`CTFlows.Traits.WithAD`](@ref), [`CTFlows.Traits.WithoutAD`](@ref). -""" -ad_trait(::Any) = WithoutAD diff --git a/src/Traits/dynamics.jl b/src/Traits/dynamics.jl deleted file mode 100644 index 03592348..00000000 --- a/src/Traits/dynamics.jl +++ /dev/null @@ -1,121 +0,0 @@ -""" -$(TYPEDEF) - -Abstract base type for dynamics traits (State vs Hamiltonian). - -Dynamics traits encode the dynamics type in configuration types, distinguishing -between state-only configurations (no costate) and Hamiltonian configurations -(state + costate). - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> StateDynamics <: Traits.AbstractDynamicsTrait -true - -julia> HamiltonianDynamics <: Traits.AbstractDynamicsTrait -true - -julia> # Used in configuration type parameters: -julia> StateEndPointConfig <: CTFlows.Configs.AbstractConfig{<:Any, <:Traits.AbstractModeTrait, StateDynamics} -true -\`\`\` - -# Notes -- Dynamics traits are used as the third type parameter in `AbstractConfigWithMaC` -- State dynamics indicates configurations with only state variables (no costate) -- Hamiltonian dynamics indicates configurations with both state and costate variables - -See also: [`CTFlows.Traits.StateDynamics`](@ref), [`CTFlows.Traits.HamiltonianDynamics`](@ref), [`CTFlows.Configs.AbstractConfig`](@ref). -""" -abstract type AbstractDynamicsTrait <: AbstractTrait end - -""" -$(TYPEDEF) - -Trait for state dynamics (no costate). - -Used as a type parameter in `AbstractConfig` to indicate state-only configurations, -which contain only state variables without associated costate variables. - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> st = StateDynamics() -StateDynamics() - -julia> st isa Traits.AbstractDynamicsTrait -true - -julia> # Used in state-only configurations: -julia> StateEndPointConfig <: CTFlows.Configs.AbstractConfig{<:Any, <:Traits.AbstractModeTrait, StateDynamics} -true -\`\`\` - -# Notes -- State configurations store only `x0` (initial state) -- The `initial_costate` accessor throws a `PreconditionError` for state configurations -- This mode is suitable for standard ODE integration without adjoint variables - -See also: [`CTFlows.Traits.HamiltonianDynamics`](@ref), [`CTFlows.Traits.AbstractDynamicsTrait`](@ref), [`CTFlows.Configs.StateEndPointConfig`](@ref). -""" -struct StateDynamics <: AbstractDynamicsTrait end - -""" -$(TYPEDEF) - -Trait for Hamiltonian dynamics (state + costate). - -Used as a type parameter in `AbstractConfig` to indicate Hamiltonian configurations, -which contain both state variables and associated costate (adjoint) variables. - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> ham = HamiltonianDynamics() -HamiltonianDynamics() - -julia> ham isa Traits.AbstractDynamicsTrait -true - -julia> # Used in Hamiltonian configurations: -julia> HamiltonianEndPointConfig <: CTFlows.Configs.AbstractConfig{<:Any, <:Traits.AbstractModeTrait, HamiltonianDynamics} -true -\`\`\` - -# Notes -- Hamiltonian configurations store both `x0` (initial state) and `p0` (initial costate) -- The `initial_condition` accessor returns `vcat(x0, p0)` for Hamiltonian configurations -- This mode is suitable for optimal control problems with Pontryagin's maximum principle - -See also: [`CTFlows.Traits.StateDynamics`](@ref), [`CTFlows.Traits.AbstractDynamicsTrait`](@ref), [`CTFlows.Configs.HamiltonianEndPointConfig`](@ref). -""" -struct HamiltonianDynamics <: AbstractDynamicsTrait end - -""" -$(TYPEDEF) - -Trait marker for augmented Hamiltonian dynamics, where the Hamiltonian includes an augmented variable (e.g., a parameter or control variable) in addition to state and costate variables. - -# Notes -- Used in conjunction with [`CTFlows.Configs.AbstractAugmentedHamiltonianConfig`](@ref) to specify that a configuration is for an augmented Hamiltonian system. -- Subtypes [`CTFlows.Traits.AbstractDynamicsTrait`](@ref). -- Used to distinguish augmented Hamiltonian systems from standard Hamiltonian systems in trait-based dispatch. - -See also: [`CTFlows.Traits.HamiltonianDynamics`](@ref), [`CTFlows.Configs.AbstractAugmentedHamiltonianConfig`](@ref), [`CTFlows.Traits.AbstractDynamicsTrait`](@ref). -""" -struct AugmentedHamiltonianDynamics <: AbstractDynamicsTrait end - -""" - dynamics_trait(x) - -Return the dynamics trait of `x`. - -Methods are defined on concrete types in `Systems` and `Configs`. - -See also: [`CTFlows.Traits.AbstractDynamicsTrait`](@ref), [`CTFlows.Traits.StateDynamics`](@ref), [`CTFlows.Traits.HamiltonianDynamics`](@ref). -""" -function dynamics_trait end diff --git a/src/Traits/helpers.jl b/src/Traits/helpers.jl deleted file mode 100644 index 1b878697..00000000 --- a/src/Traits/helpers.jl +++ /dev/null @@ -1,26 +0,0 @@ -""" - _caller_function_name() -> Symbol - -Return the name of the calling function by inspecting the stacktrace. - -This is used to provide better error messages in trait check functions -without requiring an explicit `source_method` argument. - -# Returns -- `Symbol`: The name of the calling function, or `:unknown` if it cannot be determined. -""" -function _caller_function_name() - stack = stacktrace() - for frame in stack - func_name = frame.func - func_str = string(func_name) - if func_str != "_caller_function_name" && - !startswith(func_str, "#") && - func_str != "has_time_dependence_trait" && - func_str != "has_variable_dependence_trait" && - func_str != "has_mutability_trait" - return func_name - end - end - return :unknown -end diff --git a/src/Traits/mode.jl b/src/Traits/mode.jl deleted file mode 100644 index 5a98e021..00000000 --- a/src/Traits/mode.jl +++ /dev/null @@ -1,96 +0,0 @@ -""" -$(TYPEDEF) - -Abstract base type for mode traits (Point vs Trajectory). - -Mode traits encode the integration mode in configuration types, distinguishing -between point-to-point integration (single endpoint evaluation) and trajectory -integration (full time evolution). - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> EndPointMode <: Traits.AbstractModeTrait -true - -julia> TrajectoryMode <: Traits.AbstractModeTrait -true - -julia> # Used in configuration type parameters: -julia> StateEndPointConfig <: CTFlows.Configs.AbstractConfig{<:Any, EndPointMode, <:Traits.AbstractDynamicsTrait} -true -\`\`\` - -# Notes -- Mode traits are used as the second type parameter in `AbstractConfigWithMaC` -- Point mode indicates integration from a single initial condition to a specific final time -- Trajectory mode indicates integration over a continuous time interval - -See also: [`CTFlows.Traits.EndPointMode`](@ref), [`CTFlows.Traits.TrajectoryMode`](@ref), [`CTFlows.Configs.AbstractConfig`](@ref). -""" -abstract type AbstractModeTrait <: AbstractTrait end - -""" -$(TYPEDEF) - -Trait for point integration mode (single endpoint evaluation). - -Used as a type parameter in `AbstractConfig` to indicate point integration, -which computes the solution at a specific final time from a single initial condition. - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> pt = EndPointMode() -EndPointMode() - -julia> pt isa Traits.AbstractModeTrait -true - -julia> # Used in point-to-point configurations: -julia> StateEndPointConfig <: CTFlows.Configs.AbstractConfig{<:Any, EndPointMode, <:Traits.AbstractDynamicsTrait} -true -\`\`\` - -# Notes -- Point mode configurations store `t0` and `tf` as separate fields -- This mode is suitable for boundary value problems and shooting methods -- The `tspan` accessor returns `(c.t0, c.tf)` for point configurations - -See also: [`CTFlows.Traits.TrajectoryMode`](@ref), [`CTFlows.Traits.AbstractModeTrait`](@ref), [`CTFlows.Configs.StateEndPointConfig`](@ref). -""" -struct EndPointMode <: AbstractModeTrait end - -""" -$(TYPEDEF) - -Trait for trajectory integration mode (full time evolution). - -Used as a type parameter in `AbstractConfig` to indicate trajectory integration, -which computes the full solution trajectory over a continuous time interval. - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> traj = TrajectoryMode() -TrajectoryMode() - -julia> traj isa Traits.AbstractModeTrait -true - -julia> # Used in trajectory configurations: -julia> StateTrajectoryConfig <: CTFlows.Configs.AbstractConfig{<:Any, TrajectoryMode, <:Traits.AbstractDynamicsTrait} -true -\`\`\` - -# Notes -- Trajectory mode configurations store `tspan` as a tuple field -- This mode is suitable for generating full time evolution and visualization -- The `tspan` accessor returns `c.tspan` directly for trajectory configurations - -See also: [`CTFlows.Traits.EndPointMode`](@ref), [`CTFlows.Traits.AbstractModeTrait`](@ref), [`CTFlows.Configs.StateTrajectoryConfig`](@ref). -""" -struct TrajectoryMode <: AbstractModeTrait end diff --git a/src/Traits/mutability.jl b/src/Traits/mutability.jl deleted file mode 100644 index 63c23b6a..00000000 --- a/src/Traits/mutability.jl +++ /dev/null @@ -1,180 +0,0 @@ -""" -$(TYPEDEF) - -Abstract trait for mutability characteristics of function evaluation. - -Distinguishes between in-place functions (which modify a pre-allocated buffer) -and out-of-place functions (which allocate and return new results). - -Subtypes must implement: -- `InPlace`: For functions that write to a mutable buffer -- `OutOfPlace`: For functions that return newly allocated results - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> InPlace() isa AbstractMutabilityTrait -true - -julia> OutOfPlace() isa AbstractMutabilityTrait -true -\`\`\` - -See also: [`CTFlows.Traits.InPlace`](@ref), [`CTFlows.Traits.OutOfPlace`](@ref). -""" -abstract type AbstractMutabilityTrait <: AbstractTrait end - -""" -$(TYPEDEF) - -Trait for in-place function evaluation. - -Indicates that a function modifies a pre-allocated buffer passed as an argument, -rather than allocating and returning a new result. This pattern is used for -performance-critical code where avoiding allocations is important. - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> ip = InPlace() -InPlace() - -julia> ip isa AbstractMutabilityTrait -true -\`\`\` - -See also: [`CTFlows.Traits.AbstractMutabilityTrait`](@ref), [`CTFlows.Traits.OutOfPlace`](@ref). -""" -struct InPlace <: AbstractMutabilityTrait end - -""" -$(TYPEDEF) - -Trait for out-of-place function evaluation. - -Indicates that a function allocates and returns a new result, rather than -modifying a pre-allocated buffer. This is the default pattern in Julia and -is suitable for most use cases. - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> oop = OutOfPlace() -OutOfPlace() - -julia> oop isa AbstractMutabilityTrait -true -\`\`\` - -See also: [`CTFlows.Traits.AbstractMutabilityTrait`](@ref), [`CTFlows.Traits.InPlace`](@ref). -""" -struct OutOfPlace <: AbstractMutabilityTrait end - -""" -$(TYPEDSIGNATURES) - -Check if the object has the mutability trait. - -This fallback method throws an error indicating the object does not support -mutability queries. Concrete types that have the trait should implement -`has_mutability_trait(obj::MyType) = true`. - -The calling function name is automatically detected from the stacktrace -for better error messages. - -# Arguments -- `obj::Any`: The object to check. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): Always, indicating the object does not have the trait. - -See also: [`CTFlows.Traits.AbstractMutabilityTrait`](@ref), [`CTFlows.Traits.mutability`](@ref). -""" -function has_mutability_trait(obj::Any) - source_method = _caller_function_name() - throw(Exceptions.IncorrectArgument( - "Cannot call $(source_method) on object of type $(typeof(obj)): no mutability trait"; - suggestion = "Implement has_mutability_trait(obj::$(typeof(obj))) = true and mutability(obj::$(typeof(obj))) to enable mutability trait support.", - context = "Mutability trait not available", - )) -end - -""" -$(TYPEDSIGNATURES) - -Return the mutability trait value for the object. - -This fallback method throws an error indicating the method is not implemented. -Concrete types that have the trait should implement `mutability(obj::MyType)` -to return the specific trait value (`InPlace` or `OutOfPlace`). - -# Arguments -- `obj::Any`: The object to query. - -# Throws -- [`CTBase.Exceptions.NotImplemented`](@extref): Always, indicating the method must be implemented. - -See also: [`CTFlows.Traits.AbstractMutabilityTrait`](@ref), [`CTFlows.Traits.has_mutability_trait`](@ref). -""" -function mutability(obj::Any) - has_mutability_trait(obj) - throw(Exceptions.NotImplemented( - "mutability not implemented for $(typeof(obj))"; - required_method = "mutability(obj::$(typeof(obj)))", - suggestion = "Implement mutability for your concrete object type to return the specific mutability trait (InPlace or OutOfPlace).", - context = "Mutability trait - required method implementation", - )) -end - -""" -$(TYPEDSIGNATURES) - -Return true if the object uses in-place function evaluation. - -Checks that the object has the mutability trait, then returns true -if `mutability(obj)` is `InPlace`. - -# Arguments -- `obj::Any`: The object to check. - -# Returns -- `Bool`: true if the object uses in-place evaluation. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): If the object does not support mutability queries. -- [`CTBase.Exceptions.NotImplemented`](@extref): If `mutability` is not implemented for the object type. - -See also: [`CTFlows.Traits.AbstractMutabilityTrait`](@ref), [`CTFlows.Traits.mutability`](@ref). -""" -function is_inplace(obj::Any) - has_mutability_trait(obj) - return mutability(obj) === InPlace -end - -""" -$(TYPEDSIGNATURES) - -Return true if the object uses out-of-place function evaluation. - -Checks that the object has the mutability trait, then returns true -if `mutability(obj)` is `OutOfPlace`. - -# Arguments -- `obj::Any`: The object to check. - -# Returns -- `Bool`: true if the object uses out-of-place evaluation. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): If the object does not support mutability queries. -- [`CTBase.Exceptions.NotImplemented`](@extref): If `mutability` is not implemented for the object type. - -See also: [`CTFlows.Traits.AbstractMutabilityTrait`](@ref), [`CTFlows.Traits.mutability`](@ref). -""" -function is_outofplace(obj::Any) - has_mutability_trait(obj) - return mutability(obj) === OutOfPlace -end diff --git a/src/Traits/time_dependence.jl b/src/Traits/time_dependence.jl deleted file mode 100644 index df90034a..00000000 --- a/src/Traits/time_dependence.jl +++ /dev/null @@ -1,105 +0,0 @@ -""" -$(TYPEDSIGNATURES) - -Check if the object has the time-dependence trait. - -This fallback method throws an error indicating the object does not support -time-dependence queries. Concrete types that have the trait should implement -`has_time_dependence_trait(obj::MyType) = true`. - -The calling function name is automatically detected from the stacktrace -for better error messages. - -# Arguments -- `obj::Any`: The object to check. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): Always, indicating the object does not have the trait. - -See also: [`CTModels.Models.TimeDependence`](@extref), [`CTFlows.Traits.time_dependence`](@ref). -""" -function has_time_dependence_trait(obj::Any) - source_method = _caller_function_name() - throw(Exceptions.IncorrectArgument( - "Cannot call $(source_method) on object of type $(typeof(obj)): no time-dependence trait"; - suggestion = "Implement has_time_dependence_trait(obj::$(typeof(obj))) = true and time_dependence(obj::$(typeof(obj))) to enable time-dependence trait support.", - context = "Time-dependence trait not available", - )) -end - -""" -$(TYPEDSIGNATURES) - -Return the time-dependence trait value for the object. - -This fallback method throws an error indicating the method is not implemented. -Concrete types that have the trait should implement `time_dependence(obj::MyType)` -to return the specific trait value (`Autonomous` or `NonAutonomous`). - -# Arguments -- `obj::Any`: The object to query. - -# Throws -- [`CTBase.Exceptions.NotImplemented`](@extref): Always, indicating the method must be implemented. - -See also: [`CTModels.Models.TimeDependence`](@extref), [`CTFlows.Traits.has_time_dependence_trait`](@ref). -""" -function time_dependence(obj::Any) - has_time_dependence_trait(obj) - throw(Exceptions.NotImplemented( - "time_dependence not implemented for $(typeof(obj))"; - required_method = "time_dependence(obj::$(typeof(obj)))", - suggestion = "Implement time_dependence for your concrete object type to return the specific time-dependence trait (Autonomous or NonAutonomous).", - context = "Time-dependence trait - required method implementation", - )) -end - -""" -$(TYPEDSIGNATURES) - -Return true if the object is autonomous (time-independent). - -Checks that the object has the time-dependence trait, then returns true -if `time_dependence(obj)` is `Autonomous`. - -# Arguments -- `obj::Any`: The object to check. - -# Returns -- `Bool`: true if the object is autonomous. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): If the object does not support time-dependence queries. -- [`CTBase.Exceptions.NotImplemented`](@extref): If `time_dependence` is not implemented for the object type. - -See also: [`CTModels.Models.TimeDependence`](@extref), [`CTFlows.Traits.time_dependence`](@ref). -""" -function Models.is_autonomous(obj::Any) - has_time_dependence_trait(obj) - return time_dependence(obj) === Models.Autonomous -end - -""" -$(TYPEDSIGNATURES) - -Return true if the object is non-autonomous (time-dependent). - -Checks that the object has the time-dependence trait, then returns true -if `time_dependence(obj)` is `NonAutonomous`. - -# Arguments -- `obj::Any`: The object to check. - -# Returns -- `Bool`: true if the object is non-autonomous. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): If the object does not support time-dependence queries. -- [`CTBase.Exceptions.NotImplemented`](@extref): If `time_dependence` is not implemented for the object type. - -See also: [`CTModels.Models.TimeDependence`](@extref), [`CTFlows.Traits.time_dependence`](@ref). -""" -function Models.is_nonautonomous(obj::Any) - has_time_dependence_trait(obj) - return time_dependence(obj) === Models.NonAutonomous -end diff --git a/src/Traits/variable_costate.jl b/src/Traits/variable_costate.jl deleted file mode 100644 index 87e20885..00000000 --- a/src/Traits/variable_costate.jl +++ /dev/null @@ -1,126 +0,0 @@ -""" -$(TYPEDEF) - -Abstract base type for variable costate capability traits. - -Variable costate capability traits encode whether a system or flow can integrate -augmented variables (e.g., parameters, controls) and compute their associated -costates. This capability is used for trait-based dispatch in augmented integration. - -Common use cases include: -- Hamiltonian systems: computing the costate of an augmented variable (∂H/∂v integration) -- Optimal control: integrating control variables with their adjoint equations -- Parameter estimation: treating parameters as dynamic variables with derivatives - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> SupportsVariableCostate() isa Traits.AbstractVariableCostateCapability -true - -julia> NoVariableCostate() isa Traits.AbstractVariableCostateCapability -true -\`\`\` - -# Notes -- `SupportsVariableCostate` indicates the system can compute derivatives with respect to augmented variables -- `NoVariableCostate` indicates the system cannot compute such derivatives -- This trait is used for dispatch to determine whether augmented integration is possible -- The specific operations enabled depend on the system type and context - -See also: [`CTFlows.Traits.SupportsVariableCostate`](@ref), [`CTFlows.Traits.NoVariableCostate`](@ref). -""" -abstract type AbstractVariableCostateCapability <: AbstractTrait end - -""" -$(TYPEDEF) - -Trait for systems/flows that support augmented variable integration. - -Indicates that the system or flow can compute derivatives with respect to augmented -variables (e.g., parameters, controls) and integrate their associated costates. -This typically requires automatic differentiation support and variable dependence. - -Common use cases include: -- Hamiltonian systems: computing ∂H/∂v via AD from a scalar Hamiltonian -- Optimal control: integrating control variables with their adjoint equations -- General systems: any system where augmented variables need derivative computation - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> svc = SupportsVariableCostate() -SupportsVariableCostate() - -julia> svc isa Traits.AbstractVariableCostateCapability -true -\`\`\` - -# Notes -- Used as a return value from `variable_costate_trait` for systems that support augmented variable integration -- Typically requires AD support and variable dependence in the system -- This trait enables augmented integration operations in flow calls -- The specific implementation depends on the system type and AD backend - -See also: [`CTFlows.Traits.AbstractVariableCostateCapability`](@ref), [`CTFlows.Traits.NoVariableCostate`](@ref), [`CTFlows.Traits.variable_costate_trait`](@ref). -""" -struct SupportsVariableCostate <: AbstractVariableCostateCapability end - -""" -$(TYPEDEF) - -Trait for systems/flows that do not support augmented variable integration. - -Indicates that the system or flow cannot compute derivatives with respect to augmented -variables or integrate their associated costates. This is the default for most systems, -including those with pre-computed derivatives or fixed parameters. - -Common use cases include: -- Hamiltonian systems: pre-computed Hamiltonian vector fields without AD -- Fixed systems: systems with parameters that are not treated as dynamic variables -- General systems: any system where augmented variable integration is not applicable - -# Example -\`\`\`julia-repl -julia> using CTFlows.Traits - -julia> nvc = NoVariableCostate() -NoVariableCostate() - -julia> nvc isa Traits.AbstractVariableCostateCapability -true -\`\`\` - -# Notes -- Default return value from `variable_costate_trait` for most systems and flows -- Systems without AD support or with fixed variable dependence typically return this -- Attempting augmented integration operations on such systems will throw an error -- The specific constraints depend on the system type - -See also: [`CTFlows.Traits.AbstractVariableCostateCapability`](@ref), [`CTFlows.Traits.SupportsVariableCostate`](@ref), [`CTFlows.Traits.variable_costate_trait`](@ref). -""" -struct NoVariableCostate <: AbstractVariableCostateCapability end - -""" -$(TYPEDSIGNATURES) - -Return the augmented variable integration capability trait of a system or flow. - -# Arguments -- `obj`: Any object (default implementation returns `NoVariableCostate`). - -# Returns -- `Type{<:AbstractVariableCostateCapability}`: The capability trait, either - `SupportsVariableCostate` or `NoVariableCostate`. - -# Notes -- Default implementation returns `NoVariableCostate` for all objects -- Specialized implementations on system and flow types return the appropriate trait based on the system's capabilities -- Used for dispatch to determine if augmented integration operations are possible -- The specific operations enabled depend on the system type - -See also: [`CTFlows.Traits.SupportsVariableCostate`](@ref), [`CTFlows.Traits.NoVariableCostate`](@ref). -""" -variable_costate_trait(::Any) = NoVariableCostate diff --git a/src/Traits/variable_dependence.jl b/src/Traits/variable_dependence.jl deleted file mode 100644 index a6c73060..00000000 --- a/src/Traits/variable_dependence.jl +++ /dev/null @@ -1,196 +0,0 @@ -""" -$(TYPEDEF) - -Abstract supertype for variable-dependence traits. - -# Trait Pattern - -Objects that have a variable-dependence trait must implement two methods: -- `has_variable_dependence_trait(obj::MyType) = true`: Indicates the type has this trait -- `variable_dependence(obj::MyType)`: Returns the specific trait value (`Fixed` or `NonFixed`) - -Once these are implemented, the object automatically gains: -- `is_variable(obj)`: Returns true if `variable_dependence(obj)` is `NonFixed` -- `is_nonvariable(obj)`: Returns true if `variable_dependence(obj)` is `Fixed` -- `has_variable(obj)`: Alias for `is_variable` (CTModels compatibility) - -If `has_variable_dependence_trait` is not implemented or returns `false`, -calling `is_variable`, `is_nonvariable`, `has_variable`, or `variable_dependence` will throw an error -indicating the object does not support variable-dependence queries. -""" -abstract type VariableDependence <: AbstractTrait end - -""" -$(TYPEDEF) - -Trait indicating the system or function has no variable parameters. - -Indicates that the system operates with fixed parameters only, without additional -variable arguments that can be treated as dynamic variables during integration. - -Common use cases include: -- Functions with fixed parameters only -- Systems with constant parameters that are not integrated -- Configurations where all parameters are known at compile time - -See also: [`CTFlows.Traits.NonFixed`](@ref), [`CTFlows.Traits.VariableDependence`](@ref). -""" -struct Fixed <: VariableDependence end - -""" -$(TYPEDEF) - -Trait indicating the system or function depends on variable parameters. - -Indicates that the system operates with additional variable parameters that can -be treated as dynamic variables during integration or optimization. These variables -may be integrated alongside state variables or used for sensitivity analysis. - -Common use cases include: -- Functions with an extra variable argument `v` -- Systems with parameters that vary during integration -- Configurations where parameters are treated as control variables -- Sensitivity analysis and parameter estimation - -See also: [`CTFlows.Traits.Fixed`](@ref), [`CTFlows.Traits.VariableDependence`](@ref). -""" -struct NonFixed <: VariableDependence end - -# ============================================================================= -# Check has trait -# ============================================================================= - -""" -$(TYPEDSIGNATURES) - -Check if the object has the variable-dependence trait. - -This fallback method throws an error indicating the object does not support -variable-dependence queries. Concrete types that have the trait should implement -`has_variable_dependence_trait(obj::MyType) = true`. - -The calling function name is automatically detected from the stacktrace -for better error messages. - -# Arguments -- `obj::Any`: The object to check. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): Always, indicating the object does not have the trait. - -See also: [`CTFlows.Traits.VariableDependence`](@ref), [`CTFlows.Traits.variable_dependence`](@ref). -""" -function has_variable_dependence_trait(obj::Any) - source_method = _caller_function_name() - throw(Exceptions.IncorrectArgument( - "Cannot call $(source_method) on object of type $(typeof(obj)): no variable-dependence trait"; - suggestion = "Implement has_variable_dependence_trait(obj::$(typeof(obj))) = true and variable_dependence(obj::$(typeof(obj))) to enable variable-dependence trait support.", - context = "Variable-dependence trait not available", - )) -end - -""" -$(TYPEDSIGNATURES) - -Return the variable-dependence trait value for the object. - -This fallback method throws an error indicating the method is not implemented. -Concrete types that have the trait should implement `variable_dependence(obj::MyType)` -to return the specific trait value (`Fixed` or `NonFixed`). - -# Arguments -- `obj::Any`: The object to query. - -# Throws -- [`CTBase.Exceptions.NotImplemented`](@extref): Always, indicating the method must be implemented. - -See also: [`CTFlows.Traits.VariableDependence`](@ref), [`CTFlows.Traits.has_variable_dependence_trait`](@ref). -""" -function variable_dependence(obj::Any) - has_variable_dependence_trait(obj) - throw(Exceptions.NotImplemented( - "variable_dependence not implemented for $(typeof(obj))"; - required_method = "variable_dependence(obj::$(typeof(obj)))", - suggestion = "Implement variable_dependence for your concrete object type to return the specific variable-dependence trait (Fixed or NonFixed).", - context = "Variable-dependence trait - required method implementation", - )) -end - -# ============================================================================= -# Trait accessors -# ============================================================================= - -""" -$(TYPEDSIGNATURES) - -Return true if the object depends on variable parameters. - -Checks that the object has the variable-dependence trait, then returns true -if `variable_dependence(obj)` is `NonFixed`. - -# Arguments -- `obj::Any`: The object to check. - -# Returns -- `Bool`: true if the object depends on variable parameters. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): If the object does not support variable-dependence queries. -- [`CTBase.Exceptions.NotImplemented`](@extref): If `variable_dependence` is not implemented for the object type. - -See also: [`CTFlows.Traits.VariableDependence`](@ref), [`CTFlows.Traits.variable_dependence`](@ref). -""" -function Models.is_variable(obj::Any) - has_variable_dependence_trait(obj) - return variable_dependence(obj) === NonFixed -end - -""" -$(TYPEDSIGNATURES) - -Return true if the object does not depend on variable parameters. - -Checks that the object has the variable-dependence trait, then returns true -if `variable_dependence(obj)` is `Fixed`. - -# Arguments -- `obj::Any`: The object to check. - -# Returns -- `Bool`: true if the object does not depend on variable parameters. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): If the object does not support variable-dependence queries. -- [`CTBase.Exceptions.NotImplemented`](@extref): If `variable_dependence` is not implemented for the object type. - -See also: [`CTFlows.Traits.VariableDependence`](@ref), [`CTFlows.Traits.variable_dependence`](@ref). -""" -function Models.is_nonvariable(obj::Any) - has_variable_dependence_trait(obj) - return variable_dependence(obj) === Fixed -end - -""" -$(TYPEDSIGNATURES) - -Return true if the object depends on variable parameters. - -Checks that the object has the variable-dependence trait, then returns true -if `variable_dependence(obj)` is `NonFixed`. - -# Arguments -- `obj::Any`: The object to check. - -# Returns -- `Bool`: true if the object depends on variable parameters. - -# Throws -- [`CTBase.Exceptions.IncorrectArgument`](@extref): If the object does not support variable-dependence queries. -- [`CTBase.Exceptions.NotImplemented`](@extref): If `variable_dependence` is not implemented for the object type. - -See also: `is_variable`, [`CTFlows.Traits.VariableDependence`](@ref). -""" -function Models.has_variable(obj::Any) - has_variable_dependence_trait(obj) - return variable_dependence(obj) === NonFixed -end diff --git a/src/Trajectories/Trajectories.jl b/src/Trajectories/Trajectories.jl index 5f4a1a52..5c1b5986 100644 --- a/src/Trajectories/Trajectories.jl +++ b/src/Trajectories/Trajectories.jl @@ -31,7 +31,7 @@ import ..Common: Common import ..Configs: Configs import ..Systems: Systems import ..Integrators: Integrators -import ..Traits: Traits +import CTBase.Traits # ============================================================================== # Include files diff --git a/test/suite/traits/test_abstract_traits.jl b/test/suite/traits/test_abstract_traits.jl deleted file mode 100644 index a4a3f521..00000000 --- a/test/suite/traits/test_abstract_traits.jl +++ /dev/null @@ -1,42 +0,0 @@ -module TestAbstractTraits - -import Test -import CTFlows.Traits - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -function test_abstract_traits() - Test.@testset "Abstract Traits Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Abstract Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Abstract Types" begin - Test.@testset "AbstractTrait" begin - Test.@testset "AbstractTrait is exported" begin - Test.@test isdefined(Traits, :AbstractTrait) - end - - Test.@testset "AbstractTrait is abstract" begin - Test.@test isabstracttype(Traits.AbstractTrait) - end - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported abstract trait" begin - Test.@test isdefined(Traits, :AbstractTrait) - end - end - end -end - -end # module - -test_abstract_traits() = TestAbstractTraits.test_abstract_traits() diff --git a/test/suite/traits/test_ad.jl b/test/suite/traits/test_ad.jl deleted file mode 100644 index aa408b0e..00000000 --- a/test/suite/traits/test_ad.jl +++ /dev/null @@ -1,119 +0,0 @@ -module TestAD - -import Test -import CTFlows.Traits - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -function test_ad() - Test.@testset "AD Trait Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Abstract Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Abstract Types" begin - Test.@testset "AbstractADTrait" begin - Test.@testset "AbstractADTrait is exported" begin - Test.@test isdefined(Traits, :AbstractADTrait) - end - - Test.@testset "AbstractADTrait is abstract" begin - Test.@test isabstracttype(Traits.AbstractADTrait) - end - - Test.@testset "AbstractADTrait subtypes AbstractTrait" begin - Test.@test Traits.AbstractADTrait <: Traits.AbstractTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Concrete Trait Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Concrete Trait Types" begin - Test.@testset "WithAD" begin - Test.@testset "WithAD is exported" begin - Test.@test isdefined(Traits, :WithAD) - end - - Test.@testset "WithAD is concrete" begin - Test.@test !isabstracttype(Traits.WithAD) - end - - Test.@testset "WithAD instantiates" begin - with = Traits.WithAD() - Test.@test with isa Traits.WithAD - end - - Test.@testset "WithAD subtypes AbstractADTrait" begin - Test.@test Traits.WithAD <: Traits.AbstractADTrait - end - end - - Test.@testset "WithoutAD" begin - Test.@testset "WithoutAD is exported" begin - Test.@test isdefined(Traits, :WithoutAD) - end - - Test.@testset "WithoutAD is concrete" begin - Test.@test !isabstracttype(Traits.WithoutAD) - end - - Test.@testset "WithoutAD instantiates" begin - without = Traits.WithoutAD() - Test.@test without isa Traits.WithoutAD - end - - Test.@testset "WithoutAD subtypes AbstractADTrait" begin - Test.@test Traits.WithoutAD <: Traits.AbstractADTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Type Hierarchy - # ==================================================================== - - Test.@testset "UNIT TESTS - Type Hierarchy" begin - Test.@testset "All AD traits subtype AbstractTrait" begin - Test.@test Traits.WithAD <: Traits.AbstractTrait - Test.@test Traits.WithoutAD <: Traits.AbstractTrait - end - end - - # ==================================================================== - # UNIT TESTS - ad_trait function - # ==================================================================== - - Test.@testset "UNIT TESTS - ad_trait function" begin - Test.@testset "ad_trait default returns WithoutAD" begin - Test.@test Traits.ad_trait(42) === Traits.WithoutAD - Test.@test Traits.ad_trait("anything") === Traits.WithoutAD - Test.@test Traits.ad_trait(nothing) === Traits.WithoutAD - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported AD trait types" begin - for sym in (:AbstractADTrait, :WithAD, :WithoutAD) - Test.@test isdefined(Traits, sym) - end - end - - Test.@testset "Exported ad_trait function" begin - Test.@test isdefined(Traits, :ad_trait) - end - end - end -end - -end # module - -test_ad() = TestAD.test_ad() diff --git a/test/suite/traits/test_dynamics.jl b/test/suite/traits/test_dynamics.jl deleted file mode 100644 index cf4d3203..00000000 --- a/test/suite/traits/test_dynamics.jl +++ /dev/null @@ -1,129 +0,0 @@ -module TestDynamics - -import Test -import CTFlows.Traits - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -function test_dynamics() - Test.@testset "Dynamics Trait Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Abstract Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Abstract Types" begin - Test.@testset "AbstractDynamicsTrait" begin - Test.@testset "AbstractDynamicsTrait is exported" begin - Test.@test isdefined(Traits, :AbstractDynamicsTrait) - end - - Test.@testset "AbstractDynamicsTrait is abstract" begin - Test.@test isabstracttype(Traits.AbstractDynamicsTrait) - end - - Test.@testset "AbstractDynamicsTrait subtypes AbstractTrait" begin - Test.@test Traits.AbstractDynamicsTrait <: Traits.AbstractTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Concrete Trait Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Concrete Trait Types" begin - Test.@testset "StateDynamics" begin - Test.@testset "StateDynamics is exported" begin - Test.@test isdefined(Traits, :StateDynamics) - end - - Test.@testset "StateDynamics is concrete" begin - Test.@test !isabstracttype(Traits.StateDynamics) - end - - Test.@testset "StateDynamics instantiates" begin - st = Traits.StateDynamics() - Test.@test st isa Traits.StateDynamics - end - - Test.@testset "StateDynamics subtypes AbstractDynamicsTrait" begin - Test.@test Traits.StateDynamics <: Traits.AbstractDynamicsTrait - end - end - - Test.@testset "HamiltonianDynamics" begin - Test.@testset "HamiltonianDynamics is exported" begin - Test.@test isdefined(Traits, :HamiltonianDynamics) - end - - Test.@testset "HamiltonianDynamics is concrete" begin - Test.@test !isabstracttype(Traits.HamiltonianDynamics) - end - - Test.@testset "HamiltonianDynamics instantiates" begin - ham = Traits.HamiltonianDynamics() - Test.@test ham isa Traits.HamiltonianDynamics - end - - Test.@testset "HamiltonianDynamics subtypes AbstractDynamicsTrait" begin - Test.@test Traits.HamiltonianDynamics <: Traits.AbstractDynamicsTrait - end - end - - Test.@testset "AugmentedHamiltonianDynamics" begin - Test.@testset "AugmentedHamiltonianDynamics is exported" begin - Test.@test isdefined(Traits, :AugmentedHamiltonianDynamics) - end - - Test.@testset "AugmentedHamiltonianDynamics is concrete" begin - Test.@test !isabstracttype(Traits.AugmentedHamiltonianDynamics) - end - - Test.@testset "AugmentedHamiltonianDynamics instantiates" begin - aug = Traits.AugmentedHamiltonianDynamics() - Test.@test aug isa Traits.AugmentedHamiltonianDynamics - end - - Test.@testset "AugmentedHamiltonianDynamics subtypes AbstractDynamicsTrait" begin - Test.@test Traits.AugmentedHamiltonianDynamics <: Traits.AbstractDynamicsTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Type Hierarchy - # ==================================================================== - - Test.@testset "UNIT TESTS - Type Hierarchy" begin - Test.@testset "All dynamics traits subtype AbstractTrait" begin - Test.@test Traits.StateDynamics <: Traits.AbstractTrait - Test.@test Traits.HamiltonianDynamics <: Traits.AbstractTrait - Test.@test Traits.AugmentedHamiltonianDynamics <: Traits.AbstractTrait - end - - Test.@testset "Dynamics traits are distinct from mode traits" begin - Test.@test !(Traits.StateDynamics <: Traits.AbstractModeTrait) - Test.@test !(Traits.HamiltonianDynamics <: Traits.AbstractModeTrait) - Test.@test !(Traits.AugmentedHamiltonianDynamics <: Traits.AbstractModeTrait) - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported dynamics trait types" begin - for sym in (:AbstractDynamicsTrait, :StateDynamics, :HamiltonianDynamics, :AugmentedHamiltonianDynamics) - Test.@test isdefined(Traits, sym) - end - end - end - end -end - -end # module - -test_dynamics() = TestDynamics.test_dynamics() diff --git a/test/suite/traits/test_mode.jl b/test/suite/traits/test_mode.jl deleted file mode 100644 index b25a7fd2..00000000 --- a/test/suite/traits/test_mode.jl +++ /dev/null @@ -1,103 +0,0 @@ -module TestMode - -import Test -import CTFlows.Traits - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -function test_mode() - Test.@testset "Mode Trait Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Abstract Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Abstract Types" begin - Test.@testset "AbstractModeTrait" begin - Test.@testset "AbstractModeTrait is exported" begin - Test.@test isdefined(Traits, :AbstractModeTrait) - end - - Test.@testset "AbstractModeTrait is abstract" begin - Test.@test isabstracttype(Traits.AbstractModeTrait) - end - - Test.@testset "AbstractModeTrait subtypes AbstractTrait" begin - Test.@test Traits.AbstractModeTrait <: Traits.AbstractTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Concrete Trait Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Concrete Trait Types" begin - Test.@testset "EndPointMode" begin - Test.@testset "EndPointMode is exported" begin - Test.@test isdefined(Traits, :EndPointMode) - end - - Test.@testset "EndPointMode is concrete" begin - Test.@test !isabstracttype(Traits.EndPointMode) - end - - Test.@testset "EndPointMode instantiates" begin - pt = Traits.EndPointMode() - Test.@test pt isa Traits.EndPointMode - end - - Test.@testset "EndPointMode subtypes AbstractModeTrait" begin - Test.@test Traits.EndPointMode <: Traits.AbstractModeTrait - end - end - - Test.@testset "TrajectoryMode" begin - Test.@testset "TrajectoryMode is exported" begin - Test.@test isdefined(Traits, :TrajectoryMode) - end - - Test.@testset "TrajectoryMode is concrete" begin - Test.@test !isabstracttype(Traits.TrajectoryMode) - end - - Test.@testset "TrajectoryMode instantiates" begin - traj = Traits.TrajectoryMode() - Test.@test traj isa Traits.TrajectoryMode - end - - Test.@testset "TrajectoryMode subtypes AbstractModeTrait" begin - Test.@test Traits.TrajectoryMode <: Traits.AbstractModeTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Type Hierarchy - # ==================================================================== - - Test.@testset "UNIT TESTS - Type Hierarchy" begin - Test.@testset "All mode traits subtype AbstractTrait" begin - Test.@test Traits.EndPointMode <: Traits.AbstractTrait - Test.@test Traits.TrajectoryMode <: Traits.AbstractTrait - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported mode trait types" begin - for sym in (:AbstractModeTrait, :EndPointMode, :TrajectoryMode) - Test.@test isdefined(Traits, sym) - end - end - end - end -end - -end # module - -test_mode() = TestMode.test_mode() diff --git a/test/suite/traits/test_mutability.jl b/test/suite/traits/test_mutability.jl deleted file mode 100644 index 29967af5..00000000 --- a/test/suite/traits/test_mutability.jl +++ /dev/null @@ -1,179 +0,0 @@ -module TestMutability - -import Test -import CTBase.Exceptions -import CTFlows.Traits - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -# ============================================================================== -# Fake types for contract testing -# ============================================================================== - -""" -Fake type for testing mutability trait pattern with InPlace. -""" -struct FakeInPlace end - -Traits.has_mutability_trait(::FakeInPlace) = true -Traits.mutability(::FakeInPlace) = Traits.InPlace - -""" -Fake type for testing mutability trait pattern with OutOfPlace. -""" -struct FakeOutOfPlace end - -Traits.has_mutability_trait(::FakeOutOfPlace) = true -Traits.mutability(::FakeOutOfPlace) = Traits.OutOfPlace - -""" -Fake type for testing mutability trait without the trait. -""" -struct FakeNoMutability end - -function test_mutability() - Test.@testset "Mutability Trait Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Abstract Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Abstract Types" begin - Test.@testset "AbstractMutabilityTrait" begin - Test.@testset "AbstractMutabilityTrait is exported" begin - Test.@test isdefined(Traits, :AbstractMutabilityTrait) - end - - Test.@testset "AbstractMutabilityTrait is abstract" begin - Test.@test isabstracttype(Traits.AbstractMutabilityTrait) - end - - Test.@testset "AbstractMutabilityTrait subtypes AbstractTrait" begin - Test.@test Traits.AbstractMutabilityTrait <: Traits.AbstractTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Concrete Trait Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Concrete Trait Types" begin - Test.@testset "InPlace" begin - Test.@testset "InPlace is exported" begin - Test.@test isdefined(Traits, :InPlace) - end - - Test.@testset "InPlace is concrete" begin - Test.@test !isabstracttype(Traits.InPlace) - end - - Test.@testset "InPlace instantiates" begin - ip = Traits.InPlace() - Test.@test ip isa Traits.InPlace - end - - Test.@testset "InPlace subtypes AbstractMutabilityTrait" begin - Test.@test Traits.InPlace <: Traits.AbstractMutabilityTrait - end - end - - Test.@testset "OutOfPlace" begin - Test.@testset "OutOfPlace is exported" begin - Test.@test isdefined(Traits, :OutOfPlace) - end - - Test.@testset "OutOfPlace is concrete" begin - Test.@test !isabstracttype(Traits.OutOfPlace) - end - - Test.@testset "OutOfPlace instantiates" begin - oop = Traits.OutOfPlace() - Test.@test oop isa Traits.OutOfPlace - end - - Test.@testset "OutOfPlace subtypes AbstractMutabilityTrait" begin - Test.@test Traits.OutOfPlace <: Traits.AbstractMutabilityTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Type Hierarchy - # ==================================================================== - - Test.@testset "UNIT TESTS - Type Hierarchy" begin - Test.@testset "All mutability traits subtype AbstractTrait" begin - Test.@test Traits.InPlace <: Traits.AbstractTrait - Test.@test Traits.OutOfPlace <: Traits.AbstractTrait - end - end - - # ==================================================================== - # ERROR TESTS - Fallback Methods - # ==================================================================== - - Test.@testset "ERROR TESTS - Fallback Methods" begin - Test.@testset "has_mutability_trait throws IncorrectArgument" begin - obj = "not a trait object" - Test.@test_throws Exceptions.IncorrectArgument Traits.has_mutability_trait(obj) - end - - Test.@testset "mutability throws IncorrectArgument" begin - obj = "not a trait object" - Test.@test_throws Exceptions.IncorrectArgument Traits.mutability(obj) - end - end - - # ==================================================================== - # CONTRACT TESTS - Mutability Trait Pattern - # ==================================================================== - - Test.@testset "CONTRACT TESTS - Mutability Trait Pattern" begin - Test.@testset "FakeInPlace trait implementation" begin - obj = FakeInPlace() - Test.@test Traits.has_mutability_trait(obj) === true - Test.@test Traits.mutability(obj) === Traits.InPlace - Test.@test Traits.is_inplace(obj) === true - Test.@test Traits.is_outofplace(obj) === false - end - - Test.@testset "FakeOutOfPlace trait implementation" begin - obj = FakeOutOfPlace() - Test.@test Traits.has_mutability_trait(obj) === true - Test.@test Traits.mutability(obj) === Traits.OutOfPlace - Test.@test Traits.is_inplace(obj) === false - Test.@test Traits.is_outofplace(obj) === true - end - - Test.@testset "FakeNoMutability throws errors" begin - obj = FakeNoMutability() - Test.@test_throws Exceptions.IncorrectArgument Traits.is_inplace(obj) - Test.@test_throws Exceptions.IncorrectArgument Traits.mutability(obj) - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported mutability trait types" begin - for sym in (:AbstractMutabilityTrait, :InPlace, :OutOfPlace) - Test.@test isdefined(Traits, sym) - end - end - - Test.@testset "Exported mutability trait functions" begin - for sym in (:has_mutability_trait, :mutability, :is_inplace, :is_outofplace) - Test.@test isdefined(Traits, sym) - end - end - end - end -end - -end # module - -test_mutability() = TestMutability.test_mutability() diff --git a/test/suite/traits/test_time_dependence.jl b/test/suite/traits/test_time_dependence.jl deleted file mode 100644 index ace321e5..00000000 --- a/test/suite/traits/test_time_dependence.jl +++ /dev/null @@ -1,101 +0,0 @@ -module TestTimeDependence - -import Test -import CTBase.Exceptions -import CTFlows.Traits -import CTModels.Models - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -# ============================================================================== -# Fake types for contract testing -# ============================================================================== - -""" -Fake type for testing time-dependence trait pattern. -Implements both required methods: has_time_dependence_trait and time_dependence. -""" -struct FakeAutonomous end - -Traits.has_time_dependence_trait(::FakeAutonomous; kwargs...) = true -Traits.time_dependence(::FakeAutonomous) = Models.Autonomous - -""" -Fake type for testing time-dependence trait pattern with NonAutonomous. -""" -struct FakeNonAutonomous end - -Traits.has_time_dependence_trait(::FakeNonAutonomous) = true -Traits.time_dependence(::FakeNonAutonomous) = Models.NonAutonomous - -function test_time_dependence() - Test.@testset "Time Dependence Trait Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Trait Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Trait Types" begin - Test.@testset "TimeDependence abstract type" begin - Test.@test isdefined(Models, :TimeDependence) - Test.@test Models.Autonomous <: Models.TimeDependence - Test.@test Models.NonAutonomous <: Models.TimeDependence - end - end - - # ==================================================================== - # ERROR TESTS - Fallback Methods - # ==================================================================== - - Test.@testset "ERROR TESTS - Fallback Methods" begin - Test.@testset "has_time_dependence_trait throws IncorrectArgument" begin - obj = "not a trait object" - Test.@test_throws Exceptions.IncorrectArgument Traits.has_time_dependence_trait(obj) - end - - Test.@testset "time_dependence throws IncorrectArgument" begin - obj = "not a trait object" - Test.@test_throws Exceptions.IncorrectArgument Traits.time_dependence(obj) - end - end - - # ==================================================================== - # CONTRACT TESTS - Time-Dependence Trait Pattern - # ==================================================================== - - Test.@testset "CONTRACT TESTS - Time-Dependence Trait Pattern" begin - Test.@testset "FakeAutonomous trait implementation" begin - obj = FakeAutonomous() - Test.@test Traits.has_time_dependence_trait(obj) === true - Test.@test Traits.time_dependence(obj) === Models.Autonomous - Test.@test Models.is_autonomous(obj) === true - Test.@test Models.is_nonautonomous(obj) === false - end - - Test.@testset "FakeNonAutonomous trait implementation" begin - obj = FakeNonAutonomous() - Test.@test Traits.has_time_dependence_trait(obj) === true - Test.@test Traits.time_dependence(obj) === Models.NonAutonomous - Test.@test Models.is_autonomous(obj) === false - Test.@test Models.is_nonautonomous(obj) === true - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported time-dependence trait functions" begin - for sym in (:has_time_dependence_trait, :time_dependence) - Test.@test isdefined(Traits, sym) - end - end - end - end -end - -end # module - -test_time_dependence() = TestTimeDependence.test_time_dependence() diff --git a/test/suite/traits/test_traits_module.jl b/test/suite/traits/test_traits_module.jl deleted file mode 100644 index 833dfbb9..00000000 --- a/test/suite/traits/test_traits_module.jl +++ /dev/null @@ -1,210 +0,0 @@ -""" -# ============================================================================ -# Traits Module Exports Tests -# ============================================================================ -# This file tests the exports from the `Traits` module. It verifies that -# the expected types and functions are properly exported by -# `CTFlows.Traits` and readily accessible to the end user. -# -# Functionality tests are in separate files: -# - test_abstract_traits.jl for abstract trait types -# - test_ad.jl for AD traits -# - test_dynamics.jl for dynamics traits -# - test_mode.jl for mode traits -# - test_mutability.jl for mutability traits -# - test_time_dependence.jl for time dependence traits -# - test_variable_costate.jl for variable costate traits -# - test_variable_dependence.jl for variable dependence traits -""" - -module TestTraitsModule - -import Test -import CTFlows -import CTFlows.Traits -using CTFlows.Traits # For testing exported symbols - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -const CurrentModule = TestTraitsModule - -# ============================================================================ -# Hardcoded export lists -# ============================================================================ -# These lists define the expected public API of the Traits module. - -const EXPORTED_ABSTRACT_TYPES = ( - :AbstractTrait, - :AbstractModeTrait, - :AbstractDynamicsTrait, - :AbstractMutabilityTrait, - :AbstractADTrait, - :AbstractVariableCostateCapability, - :TimeDependence, - :VariableDependence, -) - -const EXPORTED_CONCRETE_TYPES = ( - :EndPointMode, - :TrajectoryMode, - :StateDynamics, - :HamiltonianDynamics, - :AugmentedHamiltonianDynamics, - :InPlace, - :OutOfPlace, - :WithAD, - :WithoutAD, - :SupportsVariableCostate, - :NoVariableCostate, - :Autonomous, - :NonAutonomous, - :Fixed, - :NonFixed, -) - -const EXPORTED_FUNCTIONS = ( - :ad_trait, - :variable_costate_trait, - :is_inplace, - :is_outofplace, - :has_time_dependence_trait, - :time_dependence, - :has_mutability_trait, - :mutability, - :has_variable_dependence_trait, - :variable_dependence, - :is_autonomous, - :is_nonautonomous, - :is_variable, - :is_nonvariable, - :has_variable, -) - -const PRIVATE_SYMBOLS = ( - :_caller_function_name, -) - -# ============================================================================ -# Helper functions (generic for reuse in other modules) -# ============================================================================ - -""" - test_exported_symbols(module_ref::Module, symbols::Tuple, test_module::Module) - -Test that symbols are exported from a module and available via `using`. -""" -function test_exported_symbols(module_ref::Module, symbols::Tuple, test_module::Module) - for sym in symbols - Test.@testset "$(sym)" begin - Test.@test isdefined(module_ref, sym) - Test.@test isdefined(test_module, sym) - end - end -end - -""" - test_internal_symbols(module_ref::Module, symbols::Tuple, test_module::Module) - -Test that symbols are defined in a module but NOT exported (not available via `using`). -Generic helper for modules with private symbols. -""" -function test_internal_symbols(module_ref::Module, symbols::Tuple, test_module::Module) - for sym in symbols - Test.@testset "$(sym)" begin - Test.@test isdefined(module_ref, sym) - Test.@test !isdefined(test_module, sym) - end - end -end - -# ============================================================================ -# Test function -# ============================================================================ - -function test_traits_module() - Test.@testset "Traits Module Exports" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # Module availability - # ==================================================================== - - Test.@testset "Module availability" begin - Test.@testset "Traits module exists" begin - Test.@test isdefined(CTFlows, :Traits) - Test.@test CTFlows.Traits isa Module - end - end - - # ==================================================================== - # Exported abstract types verification - # ==================================================================== - - Test.@testset "Exported abstract types" begin - test_exported_symbols(Traits, EXPORTED_ABSTRACT_TYPES, CurrentModule) - end - - # ==================================================================== - # Exported concrete types verification - # ==================================================================== - - Test.@testset "Exported concrete types" begin - test_exported_symbols(Traits, EXPORTED_CONCRETE_TYPES, CurrentModule) - end - - # ==================================================================== - # Exported functions verification - # ==================================================================== - - Test.@testset "Exported functions" begin - test_exported_symbols(Traits, EXPORTED_FUNCTIONS, CurrentModule) - end - - # ==================================================================== - # Private symbols (not exported) verification - # ==================================================================== - - Test.@testset "Private symbols (not exported)" begin - test_internal_symbols(Traits, PRIVATE_SYMBOLS, CurrentModule) - end - - # ==================================================================== - # Type hierarchy tests - # ==================================================================== - - Test.@testset "Type hierarchy" begin - Test.@testset "Abstract types are abstract" begin - Test.@test isabstracttype(Traits.AbstractTrait) - Test.@test isabstracttype(Traits.AbstractModeTrait) - Test.@test isabstracttype(Traits.AbstractDynamicsTrait) - Test.@test isabstracttype(Traits.AbstractMutabilityTrait) - Test.@test isabstracttype(Traits.AbstractADTrait) - Test.@test isabstracttype(Traits.AbstractVariableCostateCapability) - Test.@test isabstracttype(Traits.TimeDependence) - Test.@test isabstracttype(Traits.VariableDependence) - end - - Test.@testset "Concrete types inherit from abstract types" begin - Test.@test Traits.EndPointMode <: Traits.AbstractModeTrait - Test.@test Traits.TrajectoryMode <: Traits.AbstractModeTrait - Test.@test Traits.StateDynamics <: Traits.AbstractDynamicsTrait - Test.@test Traits.HamiltonianDynamics <: Traits.AbstractDynamicsTrait - Test.@test Traits.AugmentedHamiltonianDynamics <: Traits.AbstractDynamicsTrait - Test.@test Traits.InPlace <: Traits.AbstractMutabilityTrait - Test.@test Traits.OutOfPlace <: Traits.AbstractMutabilityTrait - Test.@test Traits.WithAD <: Traits.AbstractADTrait - Test.@test Traits.WithoutAD <: Traits.AbstractADTrait - Test.@test Traits.SupportsVariableCostate <: Traits.AbstractVariableCostateCapability - Test.@test Traits.NoVariableCostate <: Traits.AbstractVariableCostateCapability - Test.@test Traits.Autonomous <: Traits.TimeDependence - Test.@test Traits.NonAutonomous <: Traits.TimeDependence - Test.@test Traits.Fixed <: Traits.VariableDependence - Test.@test Traits.NonFixed <: Traits.VariableDependence - end - end - end -end - -end # module - -test_traits_module() = TestTraitsModule.test_traits_module() diff --git a/test/suite/traits/test_variable_costate.jl b/test/suite/traits/test_variable_costate.jl deleted file mode 100644 index af0d80e1..00000000 --- a/test/suite/traits/test_variable_costate.jl +++ /dev/null @@ -1,124 +0,0 @@ -module TestVariableCostate - -import Test -import CTFlows.Traits - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -function test_variable_costate() - Test.@testset "Variable Costate Trait Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Abstract Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Abstract Types" begin - Test.@testset "AbstractVariableCostateCapability" begin - Test.@testset "AbstractVariableCostateCapability is exported" begin - Test.@test isdefined(Traits, :AbstractVariableCostateCapability) - end - - Test.@testset "AbstractVariableCostateCapability is abstract" begin - Test.@test isabstracttype(Traits.AbstractVariableCostateCapability) - end - - Test.@testset "AbstractVariableCostateCapability subtypes AbstractTrait" begin - Test.@test Traits.AbstractVariableCostateCapability <: Traits.AbstractTrait - end - end - end - - # ==================================================================== - # UNIT TESTS - Concrete Trait Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Concrete Trait Types" begin - Test.@testset "SupportsVariableCostate" begin - Test.@testset "SupportsVariableCostate is exported" begin - Test.@test isdefined(Traits, :SupportsVariableCostate) - end - - Test.@testset "SupportsVariableCostate is concrete" begin - Test.@test !isabstracttype(Traits.SupportsVariableCostate) - end - - Test.@testset "SupportsVariableCostate instantiates" begin - svc = Traits.SupportsVariableCostate() - Test.@test svc isa Traits.SupportsVariableCostate - end - - Test.@testset "SupportsVariableCostate subtypes AbstractVariableCostateCapability" begin - Test.@test Traits.SupportsVariableCostate <: Traits.AbstractVariableCostateCapability - end - end - - Test.@testset "NoVariableCostate" begin - Test.@testset "NoVariableCostate is exported" begin - Test.@test isdefined(Traits, :NoVariableCostate) - end - - Test.@testset "NoVariableCostate is concrete" begin - Test.@test !isabstracttype(Traits.NoVariableCostate) - end - - Test.@testset "NoVariableCostate instantiates" begin - nvc = Traits.NoVariableCostate() - Test.@test nvc isa Traits.NoVariableCostate - end - - Test.@testset "NoVariableCostate subtypes AbstractVariableCostateCapability" begin - Test.@test Traits.NoVariableCostate <: Traits.AbstractVariableCostateCapability - end - end - end - - # ==================================================================== - # UNIT TESTS - Type Hierarchy - # ==================================================================== - - Test.@testset "UNIT TESTS - Type Hierarchy" begin - Test.@testset "All variable costate traits subtype AbstractTrait" begin - Test.@test Traits.SupportsVariableCostate <: Traits.AbstractTrait - Test.@test Traits.NoVariableCostate <: Traits.AbstractTrait - end - - Test.@testset "Variable costate traits subtype AbstractVariableCostateCapability" begin - Test.@test Traits.SupportsVariableCostate <: Traits.AbstractVariableCostateCapability - Test.@test Traits.NoVariableCostate <: Traits.AbstractVariableCostateCapability - end - end - - # ==================================================================== - # UNIT TESTS - variable_costate_trait function - # ==================================================================== - - Test.@testset "UNIT TESTS - variable_costate_trait function" begin - Test.@testset "variable_costate_trait default returns NoVariableCostate" begin - Test.@test Traits.variable_costate_trait(42) === Traits.NoVariableCostate - Test.@test Traits.variable_costate_trait("anything") === Traits.NoVariableCostate - Test.@test Traits.variable_costate_trait(nothing) === Traits.NoVariableCostate - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported variable costate trait types" begin - for sym in (:AbstractVariableCostateCapability, :SupportsVariableCostate, :NoVariableCostate) - Test.@test isdefined(Traits, sym) - end - end - - Test.@testset "Exported variable_costate_trait function" begin - Test.@test isdefined(Traits, :variable_costate_trait) - end - end - end -end - -end # module - -test_variable_costate() = TestVariableCostate.test_variable_costate() diff --git a/test/suite/traits/test_variable_dependence.jl b/test/suite/traits/test_variable_dependence.jl deleted file mode 100644 index 27144c54..00000000 --- a/test/suite/traits/test_variable_dependence.jl +++ /dev/null @@ -1,114 +0,0 @@ -module TestVariableDependence - -import Test -import CTBase.Exceptions -import CTFlows.Traits -import CTModels.Models - -const VERBOSE = isdefined(Main, :TestOptions) ? Main.TestOptions.VERBOSE : true -const SHOWTIMING = isdefined(Main, :TestOptions) ? Main.TestOptions.SHOWTIMING : true - -# ============================================================================== -# Fake types for contract testing -# ============================================================================== - -""" -Fake type for testing variable-dependence trait pattern. -Implements both required methods: has_variable_dependence_trait and variable_dependence. -""" -struct FakeFixed end - -Traits.has_variable_dependence_trait(::FakeFixed) = true -Traits.variable_dependence(::FakeFixed) = Traits.Fixed - -""" -Fake type for testing variable-dependence trait pattern with NonFixed. -""" -struct FakeNonFixed end - -Traits.has_variable_dependence_trait(::FakeNonFixed) = true -Traits.variable_dependence(::FakeNonFixed) = Traits.NonFixed - -function test_variable_dependence() - Test.@testset "Variable Dependence Trait Tests" verbose=VERBOSE showtiming=SHOWTIMING begin - - # ==================================================================== - # UNIT TESTS - Trait Types - # ==================================================================== - - Test.@testset "UNIT TESTS - Trait Types" begin - Test.@testset "VariableDependence abstract type" begin - Test.@test isdefined(Traits, :VariableDependence) - Test.@test Traits.Fixed <: Traits.VariableDependence - Test.@test Traits.NonFixed <: Traits.VariableDependence - end - - Test.@testset "Concrete trait types" begin - Test.@test Traits.Fixed() isa Traits.Fixed - Test.@test Traits.NonFixed() isa Traits.NonFixed - end - end - - # ==================================================================== - # ERROR TESTS - Fallback Methods - # ==================================================================== - - Test.@testset "ERROR TESTS - Fallback Methods" begin - Test.@testset "has_variable_dependence_trait throws IncorrectArgument" begin - obj = "not a trait object" - Test.@test_throws Exceptions.IncorrectArgument Traits.has_variable_dependence_trait(obj) - end - - Test.@testset "variable_dependence throws IncorrectArgument" begin - obj = "not a trait object" - Test.@test_throws Exceptions.IncorrectArgument Traits.variable_dependence(obj) - end - end - - # ==================================================================== - # CONTRACT TESTS - Variable-Dependence Trait Pattern - # ==================================================================== - - Test.@testset "CONTRACT TESTS - Variable-Dependence Trait Pattern" begin - Test.@testset "FakeFixed trait implementation" begin - obj = FakeFixed() - Test.@test Traits.has_variable_dependence_trait(obj) === true - Test.@test Traits.variable_dependence(obj) === Traits.Fixed - Test.@test Models.is_variable(obj) === false - Test.@test Models.is_nonvariable(obj) === true - Test.@test Models.has_variable(obj) === false - end - - Test.@testset "FakeNonFixed trait implementation" begin - obj = FakeNonFixed() - Test.@test Traits.has_variable_dependence_trait(obj) === true - Test.@test Traits.variable_dependence(obj) === Traits.NonFixed - Test.@test Models.is_variable(obj) === true - Test.@test Models.is_nonvariable(obj) === false - Test.@test Models.has_variable(obj) === true - end - end - - # ==================================================================== - # Exports Verification - # ==================================================================== - - Test.@testset "Exports Verification" begin - Test.@testset "Exported variable-dependence trait types" begin - for sym in (:VariableDependence, :Fixed, :NonFixed) - Test.@test isdefined(Traits, sym) - end - end - - Test.@testset "Exported variable-dependence trait functions" begin - for sym in (:has_variable_dependence_trait, :variable_dependence) - Test.@test isdefined(Traits, sym) - end - end - end - end -end - -end # module - -test_variable_dependence() = TestVariableDependence.test_variable_dependence()