Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
7212d64
foo
ocots Feb 11, 2026
1ccb707
foo
ocots Feb 11, 2026
797b20a
Update compatibility versions in Project.toml
jbcaillau Feb 11, 2026
50366f4
Update compatibility versions in Project.toml
jbcaillau Feb 11, 2026
01ba7f1
Add CTDirect reexports and tests
ocots Feb 11, 2026
c66440c
Add CTFlows reexports and tests
ocots Feb 11, 2026
ee25ee9
Add comprehensive reexport tests and fix syntax errors
ocots Feb 11, 2026
5cd36f0
add save
ocots Feb 11, 2026
511cc60
foo
ocots Feb 11, 2026
45a131e
Add solve function and canonical solve tests
ocots Feb 11, 2026
a51f771
Update test_canonical.jl progress display
ocots Feb 11, 2026
fa81f41
workflows
ocots Feb 11, 2026
0a21ab6
gpu
ocots Feb 11, 2026
51d93c8
gpu
ocots Feb 11, 2026
9f51d29
v1.10 removed for CI
ocots Feb 11, 2026
8cd0145
Add GPU tests to test_canonical.jl
ocots Feb 11, 2026
aa12b01
foo
ocots Feb 11, 2026
3aeba37
Refactor solve.jl initial guess handling
ocots Feb 12, 2026
632414a
Add tests for builder options forwarding
ocots Feb 12, 2026
74530bd
fix: correct reexport behavior and test expectations
ocots Feb 13, 2026
19357aa
Update options forwarding tests for CTSolvers v0.2.5-beta
ocots Feb 14, 2026
8f95f35
feat: Add professional table-aligned display for solve tests
ocots Feb 14, 2026
5793ebf
foo
ocots Feb 14, 2026
4470bda
foo
ocots Feb 14, 2026
3d8f176
fix: Translate French comments to English in test_print_utils.jl
ocots Feb 14, 2026
6cdbb9e
refactor: Move test_print_utils.jl to test/helpers/ directory
ocots Feb 14, 2026
c1a4b17
feat: Add Type column for CPU/GPU distinction in test output
ocots Feb 14, 2026
90c1ce7
feat: add options function to CTSolvers imports
ocots Feb 14, 2026
c9ff1f1
feat: add improved display function test suite
ocots Feb 14, 2026
39dfb6d
Finalize display helper integration and fix tests
ocots Feb 16, 2026
5fe16cd
Update imports and reexports for CTBase v0.18.1-beta compatibility
ocots Feb 16, 2026
c15c35c
Add strategy registry and available methods helpers
ocots Feb 17, 2026
8885f81
WIP: pending changes
ocots Feb 17, 2026
bbd199d
Add component completeness helper
ocots Feb 17, 2026
0eb3fcd
Add solve_explicit with contract tests and mock routing
ocots Feb 17, 2026
4113b76
Add strategy symbol extraction helper
ocots Feb 17, 2026
630867c
Add strategy completion helper using CTBase.complete
ocots Feb 17, 2026
a2d1fec
Add generic strategy builder with provided path
ocots Feb 17, 2026
a044cde
Task 08: Implement component completion orchestrating R3 helpers
ocots Feb 17, 2026
4e17abb
Task 09: Add comprehensive integration tests with real strategies
ocots Feb 17, 2026
bb6fa0e
Task 09: Complete comprehensive integration tests with method coverage
ocots Feb 17, 2026
1df7df9
Reorganize helpers and rename available_methods to Base.methods
ocots Feb 17, 2026
9cdedc9
Add MadNCL solver to registry and methods
ocots Feb 17, 2026
de67500
Standardize test suite imports and fix CTSolvers references
ocots Feb 17, 2026
cb1bf0a
Update print.jl docstrings to English following Julia standards
ocots Feb 17, 2026
89acf8c
Refactor solve_explicit to follow SOLID principles and DRY
ocots Feb 17, 2026
1ad1119
Refactor strategy_builders.jl: multiple dispatch + improved docs
ocots Feb 18, 2026
3e1874d
Complete solve_explicit implementation with comprehensive integration…
ocots Feb 18, 2026
9ad8b07
add reports to store
ocots Feb 18, 2026
e95b018
feat: implement SolveMode types and _extract_kwarg helper
ocots Feb 19, 2026
1ec1080
fix: correct workflow violations for tasks 01-03
ocots Feb 19, 2026
a49bd54
feat: implement _solve dispatch methods (Option C asymmetric signatures)
ocots Feb 19, 2026
b6b2d8f
refactor: reorganize solve files to avoid name redundancy
ocots Feb 19, 2026
ca254e2
refactor(solve): Option B - rename _solve dispatch to solve_explicit/…
ocots Feb 19, 2026
330d4c2
test(solve): cleanup and improve tests for Option B
ocots Feb 19, 2026
b21ebfb
style(tests): reduce Modeler column width in test table
ocots Feb 19, 2026
19e47ce
feat(solve): allow registry injection in dispatch and add mock dispat…
ocots Feb 19, 2026
18b3dac
feat(solve): implement solve_descriptive with strict option routing
ocots Feb 19, 2026
f1b20aa
test(solve): add test_solve_modes.jl for integration testing of solve…
ocots Feb 19, 2026
b0a3f27
Add design report for bypass option mechanism
ocots Feb 19, 2026
057ed35
Add descriptive comments to all test files
ocots Feb 20, 2026
2e539dc
Add bypass mechanism integration tests
ocots Feb 20, 2026
e38616b
foo
ocots Feb 20, 2026
a618ca5
foo
ocots Feb 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 11 additions & 0 deletions .extras/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[deps]
ADNLPModels = "54578032-b7ea-4c30-94aa-7cbd1cce6c9a"
CTBase = "54762871-cc72-4466-b8e8-f6c8b58076cd"
CTDirect = "790bbbee-bee9-49ee-8912-a9de031322d5"
CTModels = "34c4fa32-2049-4079-8329-de33c2a22e2d"
CTSolvers = "d3e8d392-8e4b-4d9b-8e92-d7d4e3650ef6"
ExaModels = "1037b233-b668-4ce9-9b63-f9f681f55dd2"
MadNLP = "2621e9c9-9eb4-46b1-8089-e8c72242dfb6"
MadNLPMumps = "3b83494e-c0a4-4895-918b-9157a7a085a1"
NLPModelsIpopt = "f4238b75-b362-5c4c-b852-0801c9a21d71"
OptimalControl = "5f98b655-cc9a-415a-b60e-744165666948"
363 changes: 363 additions & 0 deletions .extras/test_display.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
try
using Revise
catch
println("🔧 Revise not found - continuing without hot reload")
end

using Pkg
Pkg.activate(@__DIR__)

# Add OptimalControl in development mode
if !haskey(Pkg.project().dependencies, "OptimalControl")
Pkg.develop(path=joinpath(@__DIR__, ".."))
end

using OptimalControl
using NLPModelsIpopt
import MadNLP
import MadNLPMumps

# Include shared test problems via TestProblems module
# include(joinpath(@__DIR__, "..", "test", "problems", "TestProblems.jl"))
# using .TestProblems

# Create test arguments similar to test_canonical.jl
function create_test_components()
# Discretizer
discretizer = OptimalControl.Collocation(grid_size=100, scheme=:midpoint)

# Modeler
modeler = OptimalControl.ADNLP()

# Solver - use real Ipopt solver
solver = OptimalControl.Ipopt(print_level=0)

# Method tuple
method = (:collocation, :adnlp, :ipopt)

return method, discretizer, modeler, solver
end

# Create additional test configurations
function create_test_variants()
variants = []

# Variant 1: Different discretizer
discretizer1 = OptimalControl.Collocation(grid_size=50, scheme=:trapeze)
modeler1 = OptimalControl.ADNLP()
solver1 = OptimalControl.Ipopt(print_level=0)
method1 = (:collocation, :ipopt, :adnlp)
push!(variants, ("Trapezoidal Grid", method1, discretizer1, modeler1, solver1))

# Variant 2: Different modeler
discretizer2 = OptimalControl.Collocation(grid_size=75, scheme=:midpoint)
modeler2 = OptimalControl.Exa()
solver2 = OptimalControl.Ipopt(print_level=0)
method2 = (:exa, :collocation, :cpu, :ipopt)
push!(variants, ("Exa", method2, discretizer2, modeler2, solver2))

# Variant 3: Different solver
discretizer3 = OptimalControl.Collocation(grid_size=80, scheme=:midpoint)
modeler3 = OptimalControl.ADNLP()
solver3 = OptimalControl.MadNLP(print_level=MadNLP.ERROR)
method3 = (:collocation, :optimized, :adnlp, :gpu, :madnlp)
push!(variants, ("MadNLP Solver", method3, discretizer3, modeler3, solver3))

return variants
end

# Copy the ORIGINAL display function from solve.jl
function original_display_ocp_method(
io::IO,
method::Tuple,
discretizer,
modeler,
solver;
display::Bool,
)
display || return nothing

version_str = string(Base.pkgversion(OptimalControl))

print(io, "▫ This is OptimalControl version v", version_str, " running with: ")
for (i, m) in enumerate(method)
sep = i == length(method) ? ".\n\n" : ", "
printstyled(io, string(m) * sep; color=:cyan, bold=true)
end

# Package information using id()
model_pkg = OptimalControl.id(typeof(modeler))
solver_pkg = OptimalControl.id(typeof(solver))

println(
io,
" ┌─ The NLP is modelled with ",
model_pkg,
" and solved with ",
solver_pkg,
".",
)
println(io, " │")

# Options section
disc_opts = OptimalControl.options(discretizer)
mod_opts = OptimalControl.options(modeler)
sol_opts = OptimalControl.options(solver)

has_disc = !isempty(propertynames(disc_opts))
has_mod = !isempty(propertynames(mod_opts))
has_sol = !isempty(propertynames(sol_opts))

if has_disc || has_mod || has_sol
println(io, " Options:")

if has_disc
println(io, " ├─ Discretizer:")
for name in propertynames(disc_opts)
println(io, " │ ", name, " = ", getproperty(disc_opts, name))
end
end

if has_mod
println(io, " ├─ Modeler:")
for name in propertynames(mod_opts)
println(io, " │ ", name, " = ", getproperty(mod_opts, name))
end
end

if has_sol
println(io, " └─ Solver:")
for name in propertynames(sol_opts)
println(io, " ", name, " = ", getproperty(sol_opts, name))
end
end
end

println(io)
return nothing
end

function original_display_ocp_method(
method,
discretizer,
modeler,
solver;
display::Bool,
)
return original_display_ocp_method(
stdout, method, discretizer, modeler, solver; display=display
)
end

# Copy the display function here for testing and improvement
function improved_display_ocp_method(
io::IO,
method::Tuple,
discretizer,
modeler,
solver;
display::Bool,
show_options::Bool=true,
show_sources::Bool=false,
)
display || return nothing

# Get version info
version_str = string(Base.pkgversion(OptimalControl))

# Header with method
print(io, "▫ OptimalControl v", version_str, " solving with: ")

# First, get the strategy IDs from the actual components
discretizer_id = OptimalControl.id(typeof(discretizer))
modeler_id = OptimalControl.id(typeof(modeler))
solver_id = OptimalControl.id(typeof(solver))

# Always show: discretizer → modeler → solver using IDs
printstyled(io, discretizer_id; color=:cyan, bold=true)
print(io, " → ")
printstyled(io, modeler_id; color=:cyan, bold=true)
print(io, " → ")
printstyled(io, solver_id; color=:cyan, bold=true)

# Clean the method by removing strategy IDs and show remaining options
cleaned_method = CTBase.remove(method, (discretizer_id, modeler_id, solver_id))
if !isempty(cleaned_method)
print(io, " (")
for (i, m) in enumerate(cleaned_method)
sep = i == length(cleaned_method) ? "" : ", "
printstyled(io, string(m) * sep; color=:cyan, bold=true)
end
print(io, ")")
end

println(io)

# Combined configuration + options (Proposition 3)
println(io, "")
println(io, " 📦 Configuration:")

discretizer_pkg = OptimalControl.id(typeof(discretizer))
model_pkg = OptimalControl.id(typeof(modeler))
solver_pkg = OptimalControl.id(typeof(solver))

disc_opts = show_options ? OptimalControl.options(discretizer) : nothing
mod_opts = show_options ? OptimalControl.options(modeler) : nothing
sol_opts = show_options ? OptimalControl.options(solver) : nothing

function print_component(line_prefix, label, pkg, opts)
print(io, line_prefix)
printstyled(io, label; bold=true)
print(io, ": ")
printstyled(io, pkg; color=:cyan, bold=true)
if show_options && opts !== nothing
user_items = Tuple{Symbol, Any}[]
for (key, opt) in pairs(opts.options)
if OptimalControl.is_user(opts, key)
push!(user_items, (key, opt))
end
end
sort!(user_items, by = x -> string(x[1]))
n = length(user_items)
if n == 0
print(io, " (no user options)")
elseif n <= 2
print(io, " (")
for (i, (key, opt)) in enumerate(user_items)
sep = i == n ? "" : ", "
src = show_sources ? " [" * string(opt.source) * "]" : ""
print(io, string(key), " = ", opt.value, src, sep)
end
print(io, ")")
else
# Multiline with truncation after 3 items
print(io, "\n ")
shown = first(user_items, 3)
for (i, (key, opt)) in enumerate(shown)
sep = i == length(shown) ? "" : ", "
src = show_sources ? " [" * string(opt.source) * "]" : ""
print(io, string(key), " = ", opt.value, src, sep)
end
remaining = n - length(shown)
if remaining > 0
print(io, ", … (+", remaining, ")")
end
end
end
println(io)
end

print_component(" ├─ ", "Discretizer", discretizer_pkg, disc_opts)
print_component(" ├─ ", "Modeler", model_pkg, mod_opts)
print_component(" └─ ", "Solver", solver_pkg, sol_opts)

println(io)
#println(io, "🎯 Ready to solve!")
return nothing
end

function improved_display_ocp_method(
method,
discretizer,
modeler,
solver;
display::Bool,
kwargs...
)
return improved_display_ocp_method(
stdout, method, discretizer, modeler, solver; display=display, kwargs...
)
end

# Simple fallback for original display testing
function test_display_ocp_method(
method,
discretizer,
modeler,
solver;
display::Bool,
)
display || return nothing

println("▫ Original display (simplified):")
println(" Method: ", method)
println(" Discretizer: ", typeof(discretizer))
println(" Modeler: ", typeof(modeler))
println(" Solver: ", typeof(solver))
return nothing
end

# Create simple test problem
struct SimpleProblem
x0::Vector{Float64}
xf::Vector{Float64}
end

# Test problem
problem = SimpleProblem([0.0, 0.0], [1.0, 1.0])

# Create components
method, discretizer, modeler, solver = create_test_components()
variants = create_test_variants()

println("🧪 Testing ORIGINAL vs IMPROVED display functions:")
println("=" ^ 60)

println("\n📋 ORIGINAL DISPLAY:")
println("-" ^ 30)
# Call the ORIGINAL display function
original_display_ocp_method(
method, discretizer, modeler, solver; display=true
)

println("\n📋 IMPROVED DISPLAY:")
println("-" ^ 30)
# Call the IMPROVED display function
improved_display_ocp_method(
method, discretizer, modeler, solver; display=true
)

println("\n📋 IMPROVED DISPLAY (minimal):")
println("-" ^ 30)
# Call with minimal options
improved_display_ocp_method(
method, discretizer, modeler, solver; display=true, show_options=false
)

println("\n📋 NEW display_ocp_configuration (default):")
println("-" ^ 30)
# Call the NEW display function with default parameters
OptimalControl.display_ocp_configuration(
discretizer, modeler, solver; display=true
)

println("\n📋 NEW display_ocp_configuration (with sources):")
println("-" ^ 30)
# Call the NEW display function with sources shown
OptimalControl.display_ocp_configuration(
discretizer, modeler, solver; display=true, show_sources=true
)

println("\n📋 NEW display_ocp_configuration (minimal):")
println("-" ^ 30)
# Call the NEW display function without options
OptimalControl.display_ocp_configuration(
discretizer, modeler, solver; display=true, show_options=false
)

println("\n📋 TESTING DIFFERENT CONFIGURATIONS:")
println("-" ^ 30)
for (name, meth, disc, mod, solv) in variants
println("\n🔸 Configuration: ", name)
improved_display_ocp_method(
meth, disc, mod, solv; display=true, show_options=true
)

println("\n🔸 Configuration: ", name, " (NEW display_ocp_configuration)")
OptimalControl.display_ocp_configuration(
disc, mod, solv; display=true
)
end

println("=" ^ 60)
println("✅ Display comparison completed!")
Loading
Loading