[Tests] Corleone solve helper and ModelingToolkit test suite (smoke, equivalence, reference solution) (#308)
Maintainer thường phản hồi trong vòng 1 ngày
@ocots đang làm issue này rồi.
Từ ngày 8/11/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
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
- Ngôn ngữ chính
- Julia
- Star
- 13
- Fork
- 1
- Merge trung bình
- 3 giờ 33 phút
- Pull request đã merge (30 ngày)
- 55
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của control-toolbox/OptimalControlProblems.jl
-
[Cron/Doc] ModelingToolkit convergence cron, trajectories, and documentation (#308)Có thể đã có người làm @ocots đã nhận hôm nay. Đang mởdocumentation feature
control-toolbox/OptimalControlProblems.jl#439 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Problems] ModelingToolkitBackend, extension ModelingToolkitModels, and continuous bryson_denham (#308)Có thể đã có người làm @ocots đã nhận hôm nay. Đang mởfeature
control-toolbox/OptimalControlProblems.jl#437 · 1 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
cron-convergence
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 32/100
control-toolbox/OptimalControlProblems.jl#436 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Cron] cron-failureĐang mởcron-failure
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
control-toolbox/OptimalControlProblems.jl#435 · 5 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Dev] Expose the duals of the JuMP path, boundary and box constraints, aligned with signs.mdCó thể đã có người làm @ocots đã nhận hôm nay. Đang mở
control-toolbox/OptimalControlProblems.jl#430 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của control-toolbox/OptimalControlProblems.jl
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
Maintainer thường phản hồi trong vòng 1 ngày
-
lux
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
JuliaGraphs/GraphNeuralNetworks.jl#732 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
erfinv(::Float16) and erfcinv(::Float16) are wrong for abs(x) <= 0.75 (erfinv(Float16(0)) == 0.2201)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
JuliaMath/SpecialFunctions.jl#571 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100