Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
17938c7
foo
ocots Jan 25, 2026
61fb4cd
feat: Phase 1 - Module Modelers with AbstractStrategy contract
ocots Jan 25, 2026
81a69b3
feat: Add DOCP module for Discretized Optimal Control Problems
ocots Jan 25, 2026
2db43e7
fix: Apply development standards to DOCP module
ocots Jan 25, 2026
9f4ef03
refactor: Phase 1 critical revisions - clean architecture
ocots Jan 26, 2026
9a06a93
refactor: Complete Phase 2 refonte - Architecture propre
ocots Jan 26, 2026
0add8c9
refactor: Comment legacy NLP imports - replaced by new modules
ocots Jan 26, 2026
8a157bc
refactor: Split model_api.jl into Optimization and DOCP modules
ocots Jan 26, 2026
e9ef846
refactor: Rename to building.jl and move solver_info to Optimization
ocots Jan 26, 2026
dba3197
test: Add comprehensive tests for Optimization and DOCP modules
ocots Jan 26, 2026
fe18b3d
fix: Correct ExaModels syntax in tests (partial)
ocots Jan 26, 2026
9121906
fix: Correct ExaModels syntax in all tests - ALL TESTS PASSING
ocots Jan 26, 2026
0ec6547
feat: Add error cases and integration tests
ocots Jan 26, 2026
0cf4da6
refactor: Restructure test suite into suite/ directory
ocots Jan 26, 2026
4e146af
fix: Include src/init/ in CTModels.jl
ocots Jan 26, 2026
d423e30
fix: Rename test_default() to test_defaults()
ocots Jan 26, 2026
ec55472
fix: Import builder functions and extract OptionValue in Modelers
ocots Jan 26, 2026
e66c8b0
fix: Resolve all remaining test failures
ocots Jan 26, 2026
f083569
feat: Restore full backend testing with proper option filtering
ocots Jan 26, 2026
b713c9b
refactor: Add explicit default value functions for modeler options
ocots Jan 26, 2026
34d4d33
refactor: Add extract_raw_options utility to eliminate code duplication
ocots Jan 26, 2026
61a81ab
feat: Introduce NotProvided type to disambiguate option defaults
ocots Jan 26, 2026
dee1d75
test: Update modelers test to reflect NotProvided behavior
ocots Jan 26, 2026
fcc11a5
fix: Replace nothing with NotStored sentinel for option filtering
ocots Jan 26, 2026
fdfc45b
fix: Restore proper KernelAbstractions.Backend type for ExaModeler
ocots Jan 26, 2026
d9154fe
test: Suppress overwriting bound warnings in test_model.jl
ocots Jan 26, 2026
adc4a64
docs: Add explanatory messages for intentional warnings in test_const…
ocots Jan 26, 2026
ddfba8b
test: Add comprehensive tests for MadNLP extension
ocots Jan 26, 2026
1a92d59
refactor: Split test_utils.jl into orthogonal test files
ocots Jan 26, 2026
d8a7b55
fix: Correct test failures in test_exports.jl and test_model.jl
ocots Jan 26, 2026
bec0aea
refactor: Modularize optimization test files
ocots Jan 26, 2026
ffb4671
refactor: Modularize strategies test files
ocots Jan 26, 2026
35fb57e
refactor: Modularize 8 ocp test files
ocots Jan 26, 2026
33e4461
refactor: Complete modularization of ocp test files
ocots Jan 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 26 additions & 21 deletions src/CTModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,28 @@ using KernelAbstractions
using NLPModels

# Modules
include("Options/Options.jl")
include(joinpath(@__DIR__, "Options", "Options.jl"))
using .Options

include("Strategies/Strategies.jl")
include(joinpath(@__DIR__, "Strategies", "Strategies.jl"))
using .Strategies

include("Orchestration/Orchestration.jl")
include(joinpath(@__DIR__, "Orchestration", "Orchestration.jl"))
using .Orchestration

# Optimization module provides general optimization types (AbstractOptimizationProblem, builders)
include(joinpath(@__DIR__, "Optimization", "Optimization.jl"))
using .Optimization

# Modelers module uses AbstractOptimizationProblem from Optimization (general)
include(joinpath(@__DIR__, "Modelers", "Modelers.jl"))
using .Modelers

# DOCP module provides concrete DOCP types (DiscretizedOptimalControlProblem)
# Loaded after Modelers since Modelers only need the general AbstractOptimizationProblem
include(joinpath(@__DIR__, "DOCP", "DOCP.jl"))
using .DOCP

# ============================================================================ #
# TYPES AND FOUNDATIONS
# ============================================================================ #
Expand All @@ -45,7 +58,7 @@ using .Orchestration

# 1. Type aliases (Dimension, ctNumber, Time, etc.) and export/import types
# These are the most basic types with no dependencies
include("types/types.jl")
include(joinpath(@__DIR__, "types", "types.jl"))

# 2. OCP defaults (functions returning default values)
# Depends on: type aliases (uses Dimension, ctVector, etc.)
Expand All @@ -56,18 +69,18 @@ include(joinpath(@__DIR__, "ocp", "defaults.jl"))
# Must be loaded before OCP types because @ensure macro is used in OCP types
include(joinpath(@__DIR__, "utils", "utils.jl"))

# 4. OCP type definitions (components, model, solution)
# 4. Initial guess types
# Depends on: type aliases
include(joinpath(@__DIR__, "init", "types.jl"))

# 5. OCP type definitions (components, model, solution)
# Depends on: type aliases, defaults, and utils (@ensure macro)
include(joinpath(@__DIR__, "ocp", "types", "components.jl"))
include(joinpath(@__DIR__, "ocp", "types", "model.jl"))
include(joinpath(@__DIR__, "ocp", "types", "solution.jl"))

# 5. NLP types (backends, builders, modelers)
# Depends on: OCP types (uses AbstractModel, AbstractSolution)
include(joinpath(@__DIR__, "nlp", "types.jl"))

# 6. Export/import functions (require OCP types)
# Depends on: OCP types (uses AbstractModel, AbstractSolution)
# # 6. Export/import functions (require OCP types)
# # Depends on: OCP types (uses AbstractModel, AbstractSolution)
include(joinpath(@__DIR__, "types", "export_import_functions.jl"))

# ============================================================================ #
Expand Down Expand Up @@ -99,16 +112,8 @@ const AbstractOptimalControlSolution = CTModels.AbstractSolution
# Depends on: all OCP types
include(joinpath(@__DIR__, "ocp", "ocp.jl"))

# 7. NLP implementations (problem core, backends, discretization)
# Depends on: OCP and NLP types
include(joinpath(@__DIR__, "nlp", "problem_core.jl"))
include(joinpath(@__DIR__, "nlp", "nlp_backends.jl"))
include(joinpath(@__DIR__, "nlp", "extract_solver_infos.jl"))
include(joinpath(@__DIR__, "nlp", "discretized_ocp.jl"))
include(joinpath(@__DIR__, "nlp", "model_api.jl"))
# 8. Initialization (types and functions for initial guesses)
# Depends on: OCP types (uses AbstractModel, AbstractSolution)
include(joinpath(@__DIR__, "init", "types.jl"))
# 7. Initial guess implementations
# Depends on: OCP types (uses AbstractOptimalControlProblem)
include(joinpath(@__DIR__, "init", "initial_guess.jl"))

end
32 changes: 32 additions & 0 deletions src/Modelers/Modelers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Modelers Module
#
# This module provides strategy-based modelers for converting discretized optimal
# control problems to NLP backend models using the new AbstractStrategy contract.
#
# Author: CTModels Development Team
# Date: 2026-01-25

module Modelers

using CTBase: CTBase
using DocStringExtensions
using SolverCore
using ADNLPModels
using ExaModels
using KernelAbstractions
using ..CTModels.Options
using ..CTModels.Strategies
using ..CTModels.Optimization: AbstractOptimizationProblem,
get_adnlp_model_builder, get_exa_model_builder,
get_adnlp_solution_builder, get_exa_solution_builder

# Include submodules
include(joinpath(@__DIR__, "abstract_modeler.jl"))
include(joinpath(@__DIR__, "adnlp_modeler.jl"))
include(joinpath(@__DIR__, "exa_modeler.jl"))

# Public API
export AbstractOptimizationModeler
export ADNLPModeler, ExaModeler

end # module Modelers
93 changes: 93 additions & 0 deletions src/Modelers/abstract_modeler.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Abstract Optimization Modeler
#
# Defines the AbstractOptimizationModeler strategy contract for all modeler strategies.
# This extends the AbstractStrategy contract with modeler-specific interfaces.
#
# Author: CTModels Development Team
# Date: 2026-01-25

"""
AbstractOptimizationModeler

Abstract base type for all modeler strategies.

Modeler strategies are responsible for converting discretized optimal control
problems (AbstractOptimizationProblem) into NLP backend models. They implement
the `AbstractStrategy` contract and provide modeler-specific interfaces for
model and solution building.

# Implementation Requirements
All concrete modeler strategies must:
- Implement the `AbstractStrategy` contract (see Strategies module)
- Provide callable interfaces for model building from AbstractOptimizationProblem
- Provide callable interfaces for solution building
- Define strategy metadata with option specifications

# Example
```julia
struct MyModeler <: AbstractOptimizationModeler
options::Strategies.StrategyOptions
end

Strategies.id(::Type{<:MyModeler}) = :my_modeler

function (modeler::MyModeler)(
prob::AbstractOptimizationProblem,
initial_guess
)
# Build NLP model from problem and initial guess
return nlp_model
end
```
"""
abstract type AbstractOptimizationModeler <: Strategies.AbstractStrategy end

"""
(modeler::AbstractOptimizationModeler)(prob::AbstractOptimizationProblem, initial_guess)

Build an NLP model from a discretized optimal control problem and initial guess.

# Arguments
- `modeler::AbstractOptimizationModeler`: The modeler strategy instance
- `prob::AbstractOptimizationProblem`: The discretized optimal control problem
- `initial_guess`: Initial guess for optimization variables

# Returns
- An NLP model compatible with the target backend (e.g., ADNLPModel, ExaModel)

# Throws
- `CTBase.NotImplemented`: If not implemented by concrete type
"""
function (modeler::AbstractOptimizationModeler)(
::AbstractOptimizationProblem,
initial_guess
)
throw(CTBase.NotImplemented(
"Model building not implemented for $(typeof(modeler))"
))
end

"""
(modeler::AbstractOptimizationModeler)(prob::AbstractOptimizationProblem, nlp_solution)

Build a solution object from a discretized optimal control problem and NLP solution.

# Arguments
- `modeler::AbstractOptimizationModeler`: The modeler strategy instance
- `prob::AbstractOptimizationProblem`: The discretized optimal control problem
- `nlp_solution::SolverCore.AbstractExecutionStats`: Solution from NLP solver

# Returns
- A solution object appropriate for the problem type

# Throws
- `CTBase.NotImplemented`: If not implemented by concrete type
"""
function (modeler::AbstractOptimizationModeler)(
::AbstractOptimizationProblem,
::SolverCore.AbstractExecutionStats
)
throw(CTBase.NotImplemented(
"Solution building not implemented for $(typeof(modeler))"
))
end
108 changes: 108 additions & 0 deletions src/Modelers/adnlp_modeler.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# ADNLP Modeler
#
# Implementation of ADNLPModeler using the AbstractStrategy contract.
# This modeler converts discretized optimal control problems to ADNLPModels.
#
# Author: CTModels Development Team
# Date: 2026-01-25

# Default option values
"""
$(TYPEDSIGNATURES)

Return the default value for the `show_time` option of [`ADNLPModeler`](@ref).

Default is `false`.
"""
__adnlp_model_show_time() = false

"""
$(TYPEDSIGNATURES)

Return the default automatic differentiation backend for [`ADNLPModeler`](@ref).

Default is `:optimized`.
"""
__adnlp_model_backend() = :optimized

"""
ADNLPModeler

Modeler for building ADNLPModels from discretized optimal control problems.

This modeler uses the ADNLPModels.jl package to create NLP models with
automatic differentiation support. It provides configurable options for
timing information and AD backend selection.

# Options
- `show_time::Bool`: Whether to show timing information (default: `false`)
- `backend::Symbol`: AD backend to use (default: `:optimized`)

# Example
```julia
modeler = ADNLPModeler(show_time=true, backend=:forwarddiff)
nlp_model = modeler(problem, initial_guess)
```
"""
struct ADNLPModeler <: AbstractOptimizationModeler
options::Strategies.StrategyOptions
end

# Strategy identification
Strategies.id(::Type{<:ADNLPModeler}) = :adnlp

# Strategy metadata with option definitions
function Strategies.metadata(::Type{<:ADNLPModeler})
return Strategies.StrategyMetadata(
Strategies.OptionDefinition(;
name=:show_time,
type=Bool,
default=__adnlp_model_show_time(),
description="Whether to show timing information while building the ADNLP model"
),
Strategies.OptionDefinition(;
name=:backend,
type=Symbol,
default=__adnlp_model_backend(),
description="Automatic differentiation backend used by ADNLPModels"
)
)
end

# Constructor with option validation
function ADNLPModeler(; kwargs...)
opts = Strategies.build_strategy_options(
ADNLPModeler; kwargs...
)
return ADNLPModeler(opts)
end

# Access to strategy options
Strategies.options(m::ADNLPModeler) = m.options

# Model building interface
function (modeler::ADNLPModeler)(
prob::AbstractOptimizationProblem,
initial_guess
)::ADNLPModels.ADNLPModel
opts = Strategies.options(modeler)

# Get the appropriate builder for this problem type
builder = get_adnlp_model_builder(prob)

# Extract raw values from OptionValue wrappers and filter out nothing values
raw_opts = Options.extract_raw_options(opts.options)

# Build the ADNLP model passing all options generically
return builder(initial_guess; raw_opts...)
end

# Solution building interface
function (modeler::ADNLPModeler)(
prob::AbstractOptimizationProblem,
nlp_solution::SolverCore.AbstractExecutionStats
)
# Get the appropriate solution builder for this problem type
builder = get_adnlp_solution_builder(prob)
return builder(nlp_solution)
end
Loading
Loading