Skip to content

fix(integrators): restore the multi-state BilinearIntegrator constructor - #139

Merged
aarontrowbridge merged 2 commits into
mainfrom
138-bug-restore-the-multi-state-bilinearintegrator-constructor-dropped-in-c9fdeb7-unblocks-piccolo-300
Aug 21, 2026
Merged

fix(integrators): restore the multi-state BilinearIntegrator constructor#139
aarontrowbridge merged 2 commits into
mainfrom
138-bug-restore-the-multi-state-bilinearintegrator-constructor-dropped-in-c9fdeb7-unblocks-piccolo-300

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

Fixes #138. Unblocks Piccolo #300.

What

The c9fdeb7 refactor dropped BilinearIntegrator(G, traj, xs::AbstractVector{Symbol}, u); today's only constructor took a single x::Symbol, so stacked-state callers — Piccolo's exported VariationalKetIntegrator/VariationalUnitaryIntegrator, which pass vcat(ψ̃, ψ̃_variations...) — threw MethodError on every call (silent: zero callers ecosystem-wide until the Piccolo coverage campaign found it).

How (additive, following the codebase's existing x_names convention)

  • Struct gains x_names::Vector{Symbol}; x_name::Symbol stays as the primary (first) name — existing field access and Base.show keep working.
  • New BilinearIntegrator(G, xs, u, traj); the single-name constructor delegates via [x].
  • evaluate!/eval_jacobian/eval_hessian_of_lagrangian gather the stacked state across all names (component ranges hoisted out of the ForwardDiff closures — one lookup per call instead of per-FD-eval).
  • get_nonlinear_constraints: x_names checked before x_name, so an integrator carrying both fields sums the whole stack. Single-name behavior unchanged (x_names = [x]). Branch coverage preserved via a new x_name-only mock.

Verification

  • New testitem: a split-component trajectory (:a, :b occupying the same flat slots as the reference :x) vs. the single-component reference — identical residuals, Jacobians, and Lagrangian Hessians on coinciding flat data, plus test_integrator gates and get_nonlinear_constraints length parity.
  • Full local suite green (Pkg.test, 2026-08-21).
  • Formatter: 2.12.6-clean (CI's pinned-by-latest arbiter).

Notes for reviewers

  • The generic eval_jacobian(::AbstractBilinearIntegrator) now requires x_names; every existing subtype (TimeDependentBilinearIntegrator, Piccolissimo's exponential family) overrides these methods, so no behavioral change reaches them.
  • Versioning: 0.10.1 — additive constructor + new field; .x_name still present. Piccolo 2.0.3 follows with the variational integrator tests (Piccolo #300).

The c9fdeb7 integrator refactor dropped the historical xs::AbstractVector{Symbol}
constructor, leaving every stacked-state caller — concretely Piccolo's exported
VariationalKetIntegrator/VariationalUnitaryIntegrator (Piccolo #300) — with a
MethodError on construction.

Additive restore following the codebase's existing multi-name convention
(get_nonlinear_constraints already dispatches on x_names; Piccolissimo's
exponential family carries it):

- struct gains x_names::Vector{Symbol}; x_name::Symbol stays as the primary
  (first) name, so existing field access keeps working
- BilinearIntegrator(G, xs, u, traj) constructor; the single-name form
  delegates via [x]
- evaluate!/eval_jacobian/eval_hessian_of_lagrangian gather the stacked
  state across all names (component ranges hoisted out of the ForwardDiff
  closures)
- get_nonlinear_constraints checks x_names before x_name so an integrator
  carrying both fields sums the whole stack
- test: split-component trajectory vs single-component reference — identical
  residuals/Jacobians/Hessians on coinciding flat data + branch coverage

Fixes #138. Unblocks Piccolo #300 (variational integrator tests ride 2.0.3).
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…Stats)

The rev-pinned c38418c pin (compat DirectTrajOpt = 0.9 only) made both
benchmark CI suites unsatisfiable the moment DTO 0.10.0 hit General —
on this very PR, since its Project.toml declares 0.10. v0.2.1 widens
compat to 0.9/0.10 and wires the SolveStats return into
benchmark_solve!'s iteration counts (harmoniqs/HarmoniqsBenchmarks.jl#18).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'DirectTrajOpt.jl convergence'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.

Benchmark suite Current: f29bb9a Previous: 0cd7923 Ratio
xgate_convergence_ipopt_N51 [infidelity] 7.749323405192854e-11 infidelity 4.429490108037726e-11 infidelity 1.75
xgate_convergence_madnlp_N51 [infidelity] 2.4334978476758806e-12 infidelity 3.086420008457935e-14 infidelity 78.85

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'DirectTrajOpt.jl benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.

Benchmark suite Current: f29bb9a Previous: 134c3ac Ratio
bilinear_N51_ipopt [wall] 1.594580896 s 0.564104588 s 2.83
bilinear_N51_ipopt [alloc] 4318456168 bytes 1432053240 bytes 3.02
bilinear_N51_madnlp [wall] 2.498824858 s 0.363166886 s 6.88
bilinear_N51_madnlp [alloc] 6699092272 bytes 980944936 bytes 6.83
scaling_N101_d4_ipopt [wall] 2.358249771 s 1.054411922 s 2.24
scaling_N101_d4_ipopt [alloc] 6944397408 bytes 2467082832 bytes 2.81
scaling_N25_d16_ipopt [wall] 13.351560731 s 3.044575574 s 4.39
scaling_N25_d16_ipopt [alloc] 51122805800 bytes 5664718144 bytes 9.02
scaling_N25_d8_ipopt [wall] 0.174621301 s 0.012267772 s 14.23
scaling_N25_d8_ipopt [alloc] 644871656 bytes 22826992 bytes 28.25
scaling_N51_d16_ipopt [alloc] 57108354040 bytes 39827022448 bytes 1.43
scaling_N51_d8_ipopt [wall] 2.330262973 s 1.405805628 s 1.66
scaling_N51_d8_ipopt [alloc] 9103164104 bytes 2731535776 bytes 3.33

This comment was automatically generated by workflow using github-action-benchmark.

@aarontrowbridge
aarontrowbridge marked this pull request as ready for review August 21, 2026 16:55
@aarontrowbridge
aarontrowbridge merged commit 110708d into main Aug 21, 2026
10 of 11 checks passed
@aarontrowbridge
aarontrowbridge deleted the 138-bug-restore-the-multi-state-bilinearintegrator-constructor-dropped-in-c9fdeb7-unblocks-piccolo-300 branch August 21, 2026 16:55
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.

BUG: restore the multi-state BilinearIntegrator constructor dropped in c9fdeb7 (unblocks Piccolo #300)

1 participant