Dev/dto issue 122 fixes - #124
Open
gennadiryan wants to merge 2 commits into
Open
Conversation
added 2 commits
August 2, 2026 03:09
Contributor
There was a problem hiding this comment.
⚠️ 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: e45a0e2 | Previous: 0cd7923 | Ratio |
|---|---|---|---|
xgate_convergence_ipopt_N51 [infidelity] |
7.749312302962608e-11 infidelity |
4.429490108037726e-11 infidelity |
1.75 |
xgate_convergence_madnlp_N51 [infidelity] |
2.4337198922808057e-12 infidelity |
3.086420008457935e-14 infidelity |
78.85 |
This comment was automatically generated by workflow using github-action-benchmark.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DirectTrajOpt — follow-up layer on #122
Refs: issue #122 ·
PR #123 (merged
2026-08-02, base
19e414e)Branch:
issue-122— two commits on top of the merged #123 tree(
1b4acb5"Spot fixes",e45a0e2"Updating CHANGELOG").What this is
#123 satisfied every acceptance criterion in #122: the single-Δt weighting across
value, gradient, full Hessian and Hessian structure, the N-invariance regression,
finite-difference parity at variable timestep, and the migration note. This layer sits
on top of it and covers three things found while reviewing that change — one a direct
extension of #122's own reasoning, two pre-existing and unrelated to the weighting.
Nothing here revisits the weighting decision.
Rstill means what #123 says it means.1.
hessian_structureover-declared the control–control blockR::Vector{Float64}is a vector of per-component weights, so∂²J/∂v² = Δt · diag(R)is diagonal — but the full
d × dblock was declared, reservingd(d-1)/2structural nonzeros per knot that can never be nonzero.
This is the same defect class as #122's AC4, which called out the Δt–Δt entry as "the
one a mechanical edit of the arithmetic would miss." AC4's rationale — do not declare
a structural nonzero that is always zero — applies verbatim to the off-diagonals, and
#123 left them declared while removing the Δt–Δt entry. Over-declaration is safe
(the evaluator only ever writes into declared entries, so the risk direction is
under-declaration) but it inflates the assembled sparsity for every consumer.
Measured on a 4-knot,
d = 3fixture: 48 → 24 declared nonzeros.get_full_hessiannow returnsdropzeros!(∂²J)so the emitted pattern and thedeclared pattern agree exactly.
2. Fixed-timestep trajectories — defensive guards (pre-existing)
gradient!,hessian_structureandget_full_hessianlooked uptraj.components[traj.timestep]unconditionally. With aFloat64timestep thatindexes a
NamedTuplewith a float — aMethodError.LinearRegularizeralreadyguarded this;
QuadraticRegularizerdid not, and ingradient!the use was guardedby
traj.timestep isa Symbolwhile the lookup above it was not.This is unreachable today.
NamedTrajectoriestypes the fieldtimestep::Symbol(
struct_named_trajectory.jl:67), so a fixed timestep is not representable and theguard constant-folds. It is filed under
### Internalin the changelog rather than### Fixedfor exactly that reason, and the corresponding test was dropped rather thanwritten against an unconstructible fixture —
test_utils.jl'snamed_trajectory_type_1(free_time = false)branch throws, and had no callers.Kept anyway because it costs nothing, restores symmetry with
LinearRegularizer, andmatches an assumption Piccolissimo's device backend already documents. Note the guard
must be partial: unlike
LinearRegularizer, this objective cannot return early,because
∂²J/∂v² = Δt·Ris nonzero whether or not Δt is a decision variable.3. Migration note was value-only
The docstring and changelog said the old behaviour is "reproduced exactly by passing
R * Δt". True for the value on a uniform grid, but not for∂J/∂Δtwhen thetimestep is free — old
Δt ΔvᵀRΔvversus substituted½Δt ΔvᵀRΔv. Since free-timeproblems are the common case downstream, both texts now say so explicitly.
Tests
#123structure test is extended from one-directional coverage(
structure ⊇ nonzeros(H)) to exact agreement in both directions, pinning thediagonal claim in §1. It uses a deterministic fixture with strictly nonzero
Randresiduals: with a zero weight or a zero residual component the entry is legitimately
declared but absent from
H, and the converse direction would flake against therandomly-initialised shared fixture.
Results: regularizer test items 36/36; evaluator test items 10/10 (the
integration-level check that §1's tightening did not under-declare).
Release
Project.tomlis unchanged at0.9.8and the changelog entry is still under[Unreleased], pending the 0.9.9 / 0.10.0 decision. Worth resolving beforerelease:
Rsilently changes meaning, which argues for the minor bump, though #122left the staging question ("plain fix with migration note" versus "temporary opt-in")
to the maintainer.
Out of scope
Retuning the
Rweights baked into downstream templates — explicitly out per #122'sScope section, and unchanged here. See
dto-122-piccolissimo.1.md: the retuningfallout is now measured, and it reaches Piccolissimo's own suite, not only Piccolo's
templates.