Skip to content

[AI] Use declared inputs for input-aware codegen on compiled systems#4702

Merged
AayushSabharwal merged 3 commits into
SciML:masterfrom
SebastianM-C:smc/codegen_input_defaults
Jul 3, 2026
Merged

[AI] Use declared inputs for input-aware codegen on compiled systems#4702
AayushSabharwal merged 3 commits into
SciML:masterfrom
SebastianM-C:smc/codegen_input_defaults

Conversation

@SebastianM-C

@SebastianM-C SebastianM-C commented Jul 2, 2026

Copy link
Copy Markdown
Member

unbound_inputs classifies an input as bound if it appears in an equation together with variables from another namespace. That heuristic is only meaningful before flattening: after mtkcompile, connection/output equations are eliminated, so any effective input co-occurs with variables from other components — unbound_inputs is empty for every compiled hierarchical system.

Three codegen entry points still use it as their default input set and silently degrade on compiled hierarchical systems:

  • generate_control_function warns "No unbound inputs were found in system." and generates dynamics with the controls bound at their operating-point values
  • BVProblem computes n_controls = 0, mis-shaping f_prototype
  • calculate_control_jacobian returns an empty jacobian

(We hit the first one through JuMPDynamicOptProblem on a hierarchical vehicle model: the NLP ended up with control-free dynamics and Ipopt "converged" in a handful of iterations to a pseudo-optimal constant-input trajectory.)

This PR adds default_codegen_inputs(sys)inputs(sys) for scheduled systems, where the declared inputs are the contract mtkcompile was built around (stored in the inputs field), falling back to the unbound_inputs heuristic for unscheduled hierarchies — and uses it at those three sites. ODEInputFunction, already fixed to inputs(sys) in #4406, is switched to the same helper for consistency.

Includes a regression test with a minimal two-component system whose input is eliminated into a cross-namespace equation, covering the ODEInputFunction default and calculate_control_jacobian.

Also included: repairs to make the Optimization test group runnable again

The Optimization test group could not resolve or pass on current registry state, so two additional commits fix that (verified locally: the full dynamic_optimization.jl file passes, including the CasADi paths):

  1. Migrate off DiffEqDevTools tableaus. DiffEqDevTools v3 removed the construct* tableau functions (moved to OrdinaryDiffEqExplicitTableaus / OrdinaryDiffEqImplicitTableaus), and v2's DiffEqBase cap conflicts with MTKBase's DiffEqBase ≥ 7.2 requirement, making the test env unresolvable either way.
  2. Fix DynamicOptProblem reconstruction under remake/setproperties. The problem structs collected kwargs as positional varargs (storing a Tuple); current SciMLBase remake asserts values(prob.kwargs)::NamedTuple and reconstructs via keyword call, and ConstructionBase setproperties reconstructs with all six fields positionally. This broke solveremake(prob, p = new_p) for problems with tunable parameters (the parameter estimation tests).

🤖 Generated with Claude Code

SebastianM-C and others added 3 commits July 2, 2026 19:48
unbound_inputs classifies an input as bound if it appears in an equation
together with variables from another namespace. That connection-structure
heuristic is only meaningful before flattening: after mtkcompile,
connection and output equations are eliminated, so any effective input
co-occurs with variables from other components and unbound_inputs is
empty for every compiled hierarchical system.

Three codegen entry points still use unbound_inputs(sys) as their
default input set and silently degrade on compiled hierarchical systems:
- generate_control_function warns "No unbound inputs were found" and
  binds the inputs at their operating-point values when handed an
  already-scheduled system, generating input-free dynamics
- BVProblem computes n_controls = 0 and mis-shapes f_prototype
- calculate_control_jacobian returns an empty jacobian

Add default_codegen_inputs(sys), which returns the inputs declared to
mtkcompile for scheduled systems (stored in the inputs field) and falls
back to the unbound_inputs heuristic for unscheduled hierarchies. Use it
at those three sites, and switch ODEInputFunction (already fixed to
inputs(sys) in SciML#4406) to the same helper for consistency.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DiffEqDevTools v3 removed the construct* tableau functions (moved to
OrdinaryDiffEqExplicitTableaus / OrdinaryDiffEqImplicitTableaus when it
joined the OrdinaryDiffEq monorepo), and DiffEqDevTools v2's DiffEqBase
cap conflicts with ModelingToolkitBase's DiffEqBase >= 7.2 requirement,
making the whole Optimization test group unresolvable.

Depend on the two tableau packages instead and use the new names
(constructRK4() -> ExplicitTableaus.RK4(), etc.). Return types are
unchanged (DiffEqBase.ExplicitRKTableau), so no source changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dynamic optimization problem structs collected kwargs as positional
varargs, storing a Tuple in the kwargs field. Current SciMLBase remake
asserts values(prob.kwargs)::NamedTuple and reconstructs the problem
with T(f, u0, tspan, p, wrapped_model; kwargs...), and ConstructionBase
setproperties (used by remake internals) reconstructs with all six
fields positionally — both of which the varargs form breaks. This
surfaces as a TypeError from solve() -> remake(prob, p = new_p) for any
problem with tunable parameters, e.g. the parameter estimation tests.

Give each problem struct an exact six-argument positional constructor
(for setproperties) and a keyword-varargs constructor (for remake), and
pass kwargs through process_DynamicOptProblem as keywords.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AayushSabharwal AayushSabharwal merged commit 77047c8 into SciML:master Jul 3, 2026
73 of 89 checks passed
@SebastianM-C SebastianM-C deleted the smc/codegen_input_defaults branch July 3, 2026 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants