[Tests] Corleone solve helper and ModelingToolkit test suite (smoke, equivalence, reference solution) (#308)
Maintainer antworten meist innerhalb von 1 Tag
@ocots arbeitet bereits daran.
Seit 08.11.2026.
Bewertung
Dieses Issue wurde noch nicht bewertet.
Beschreibung
Agents: read the guide for agents in #310 first (order, difficulty, how to claim an issue, working method). Read
AGENTS.mdand clone.ct-conventions(v0.11.0) and.ct-agents(v0.4.0). Specification: this description and #308.
Sub-issue of #308, part 2 of 3. Depends on #437 (ModelingToolkitBackend and continuous bryson_denham model).
Goal
Implement the Corleone-based solve helper in test/common/solve_modelingtoolkit.jl (keeping Corleone strictly in the test environment, outside the package extension), complete the test/suite/ModelingToolkit/ test suite (test_methods.jl, test_smoke.jl, test_equivalence.jl, test_reference_solution.jl), and promote bryson_denham from :draft to :valid for ModelingToolkit.
At the end of this issue, bryson_denham(ModelingToolkitBackend()) is solved with Corleone + Ipopt using the shared :init from metadata, cross-evaluated against OptimalControl, verified against the analytic reference solution (:reference_solution), marked :valid, and all suite/ModelingToolkit and suite/core tests pass.
Technical Findings (from #308 preliminary checks)
- Discretizing continuous path constraints
(b)forCorleone:
Corleone.CorleoneDynamicOptProblem(sys, ...)(Corleone/ext/MTKExtension/utils.jl:75) requires every signal callx(τ)inModelingToolkit.get_constraints(sys)to have a concrete finite real numberτ(time isa Real && isfinite(time)), throwingArgumentError("Signal times must be finite real numbers: x₁(t).")on symbolict = ModelingToolkit.get_iv(sys).
Intest/common/solve_modelingtoolkit.jl, before callingCorleoneDynamicOptProblem, inspectModelingToolkit.get_constraints(sys):- Keep point constraints (neither
lhsnorrhscontainsiv = ModelingToolkit.get_iv(sys)as a free variable, e.g.x₁(tf) ~ x1_tf) as-is. - Expand any path constraint (whose
lhsorrhscontainsiv, e.g.x₁(t) ≲ x1_max) bySymbolics.substitute(c, Dict(iv => τ))for eachτinconstraint_grid(filtering outt0if initial state is fixed), and rebuild aModelingToolkit.Systemwith the discretized constraints.
- Keep point constraints (neither
- Extracting
tspan = (t0, tf)fromsys:
Extract(t0, tf)from theSymbolics.Integraldomain inModelingToolkit.get_costs(sys)(DomainSets.infimum/supremumorinterval.left/interval.right). - Injecting shared
:init(#306) intomodel.ps:
Inmodel = Corleone.CorleoneDynamicOptProblem(sys_disc, tspan, ...; switches=control_grid[2:(end - 1)], shooting=shooting_grid, alg=OrdinaryDiffEqTsit5.Tsit5()):model.pshas fields(initialcondition = ..., parameter = ...).- Controls (
model.ps.parameter.parameters): forN = length(control_grid) - 1piecewise-constant intervals[t_k, t_{k+1}], evaluateinit.controlat the interval midpoints (or left endpoints) and write into each control's.psvector of lengthN. - States (
model.ps.initialcondition): in single shooting with fixed initial state (tunable = false),model.ps.initialconditionis empty; in multiple shooting, evaluateinit.stateat the shooting nodes and write intomodel.ps.initialcondition(or viaCorleone.custom_initialization). - Pass the updated
pstoOptimization.OptimizationProblem(model, Optimization.AutoForwardDiff(); ps=ps)soopt.u0uses our shared initial guess.
- Cross-evaluation (
test_equivalence.jl) with imposed parameters:
Corleoneexposes:Corleone.optimization_objective(model, ps, model.st)-> scalar objective $J$.Corleone.optimization_constraints(model, ps, model.st)-> constraint vector $c$, bounded bymodel.lconsandmodel.ucons. Constraint violation ismaximum(max.(model.lcons .- c, c .- model.ucons, 0.0); init=0.0).
Project the optimal control ofOptimalControl(or:reference_solution) onto Corleone's piecewise-constantcontrol_grid(using interval midpoints(t_k + t_{k+1}) / 2), evaluateoptimization_objectiveandoptimization_constraints, and verify that objective and constraint violation agree within a grid-step tolerance $O(h)$ / $O(h^2)$ where $h = (t_f - t_0)/N$.
Mandatory Rules & Conventions (ct-conventions v0.11.0, #310)
- Worktree per issue (
#310rule 3a): Never edit or switch branches in the main checkout. Use a dedicated worktree (git worktree add ../OptimalControlProblems-<issue> -b feat/<issue>-mtk-corleone-tests main). - Separation of modeling and solving:
Corleonemust not be added to the rootProject.tomlorext/ModelingToolkitModels.jl; it belongs only intest/suite/ModelingToolkit/Project.tomlandtest/common/solve_modelingtoolkit.jl. - Qualified imports only (
MOD3,MOD4): Always useusing Pkg: Pkg, sym. Never use bareusing Pkgorimport. - Fake types at module top-level (
TST3): Any helper structs in tests must be defined at module top-level, never inside@testsetor functions. - No hand-written problem lists (
test_no_handwritten_listintest/suite/core/test_consistency.jl): Never write:bryson_denhamor"bryson_denham"literals intest/! Always loop withMain.TestStatus.for_each_problem(..., OptimalControlProblems.ModelingToolkitBackend()).
Detailed Implementation Plan
Files to Create or Modify
| File | Action | Details |
|---|---|---|
test/suite/ModelingToolkit/Project.toml |
Modify | Add Corleone (compat = "2"), OrdinaryDiffEqTsit5 ("2"), Optimization ("5"), OptimizationMOI ("1"), Ipopt ("1"), ComponentArrays ("0.15"), ForwardDiff ("1"), OptimalControl ("2.2"), NLPModelsIpopt ("0.11"), Symbolics, SciMLBase. |
test/common/configs.jl |
Modify | Add ModelingToolkit = [(shooting=:single, solver=:ipopt)] to CONFIGS. |
test/common/status.jl |
Modify | Add "ModelingToolkit", "Corleone", "OrdinaryDiffEqTsit5" to KEY_DEPENDENCIES. |
test/common/solve_modelingtoolkit.jl |
Create | Module SolveModelingToolkit:- _extract_tspan(sys)- _build_grids(tspan; grid_size, shooting, control_grid, constraint_grid, shooting_grid)- _discretize_path_constraints(sys, constraint_grid)- _apply_initial_guess!(model, sys, init, control_grid, shooting_grid)- prepare(pb; shooting=:single, grid_size=nothing, ...)- solve(pb; shooting=:single, solver=:ipopt, grid_size=nothing, max_iter=1000, tol=1e-6, print_level=0, ...)- evaluate(pb, control_fn; state_fn=nothing, grid_size=nothing, shooting=:single) returning (; objective, constraint_violation, grid_step)- outcome(sol, model, reconstruct), settings(pb, cfg; grid_size=nothing), trajectory(sol, model, reconstruct, sys) |
test/suite/ModelingToolkit/test_methods.jl |
Create | Unit-test SolveModelingToolkit: _extract_tspan, _build_grids (single & multiple shooting), _discretize_path_constraints, _apply_initial_guess!, settings, outcome, trajectory. |
test/suite/ModelingToolkit/test_smoke.jl |
Create | Smoke test every problem in ModelingToolkitBackend() across CONFIGS.ModelingToolkit with grid_size = TestConfigs.SMALL_GRID (20) and max_iter = TestConfigs.SMOKE_MAX_ITER (10): check no exception and isfinite(objective). |
test/suite/ModelingToolkit/test_equivalence.jl |
Create | Cross-evaluation test: for each problem in ModelingToolkitBackend(), project the reference optimal control onto control_grid (midpoint sampling), call SolveModelingToolkit.evaluate, and assert that objective matches the reference objective within $O(h)$ and constraint_violation is within $O(h^2)$. |
test/suite/ModelingToolkit/test_reference_solution.jl |
Create | For each problem in ModelingToolkitBackend() with has_reference_solution(problem), solve with Corleone + Ipopt (grid_size=50, tol=1e-6) and check objective and state/control $L^\infty$ errors against reference_solution_data(problem). |
ext/MetaData/bryson_denham.jl |
Modify | Switch ModelingToolkit status from :draft to :valid. |
Verification Commands
julia --project=. -e 'using Pkg; Pkg.test(test_args=["suite/ModelingToolkit"])'
julia --project=. -e 'using Pkg; Pkg.test(test_args=["suite/core"])'
Done when
-
test/common/solve_modelingtoolkit.jldiscretizes continuous path constraints ontoconstraint_grid, injects shared:initintomodel.ps, and solves withCorleone+Ipopt. -
test_methods.jl,test_problem.jl,test_smoke.jl,test_equivalence.jl(cross-evaluation), andtest_reference_solution.jlall pass insuite/ModelingToolkit. -
bryson_denhamstatus forModelingToolkitis:validinext/MetaData/bryson_denham.jl. -
suite/corepasses (includingtest_consistency.jlandtest_no_handwritten_list).
Refs #308, #310
- Vorherrschende Sprache
- Julia
- Sterne
- 13
- Forks
- 1
- Ø Merge
- 3 Std. 33 Min.
- Gemergte PRs (30 T.)
- 55
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus control-toolbox/OptimalControlProblems.jl
-
[Cron/Doc] ModelingToolkit convergence cron, trajectories, and documentation (#308)Evtl. vergeben @ocots hat das heute übernommen. Offendocumentation feature
control-toolbox/OptimalControlProblems.jl#439 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
[Problems] ModelingToolkitBackend, extension ModelingToolkitModels, and continuous bryson_denham (#308)Evtl. vergeben @ocots hat das heute übernommen. Offenfeature
control-toolbox/OptimalControlProblems.jl#437 · 1 Kommentar · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
cron-convergence
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 32/100
control-toolbox/OptimalControlProblems.jl#436 · 3 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
[Cron] cron-failureOffencron-failure
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 35/100
control-toolbox/OptimalControlProblems.jl#435 · 5 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
[Dev] Expose the duals of the JuMP path, boundary and box constraints, aligned with signs.mdEvtl. vergeben @ocots hat das heute übernommen. Offen
control-toolbox/OptimalControlProblems.jl#430 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in control-toolbox/OptimalControlProblems.jl
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 73/100
Maintainer antworten meist innerhalb von 1 Tag
-
lux
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
JuliaGraphs/GraphNeuralNetworks.jl#732 ·
Maintainer antworten meist innerhalb von 2 Tagen
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
Maintainer antworten meist innerhalb von 1 Tag
-
erfinv(::Float16) and erfcinv(::Float16) are wrong for abs(x) <= 0.75 (erfinv(Float16(0)) == 0.2201)Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
JuliaMath/SpecialFunctions.jl#571 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 67/100