Skip to content

Control-segment splitting and sequential intra-node solve #97

Description

@AlCap23

What to build

Extend the single-segment path (#96) to handle piecewise-constant controls within one shooting node. Given one coarse TrajectoryInterval (a node's tspan) and the node's active ControlParameters (#92), split it into a Vector{TrajectoryInterval} at the union of all active controls' breakpoints falling inside that tspan — purely structurally, recomputed from the controls' own time grids on every call rather than cached in st (so the layer stays reusable if the controls structure varies between calls).

Each fine segment's p is built by writing in every control active at that segment's start (if control A switches at t=2 and B at t=2.5, segment [2,2.5) needs both A's and B's current values merged in — same semantics as today's build_index_grid union-of-breakpoints logic, re-expressed as repeated named writes via remake instead of an indicator-matrix multiply).

Solve the resulting vector sequentially: each segment's ic is the previous segment's output endpoint, built via a non-mutating reduction (e.g. accumulate/mapfoldl-style, not a push! loop), since reverse-mode AD must work through this (per #96).

The breakpoint/index lookup logic (searchsortedlast-style determination of which control segment is active) has no derivative — mark it non-differentiable via ChainRulesCore so Zygote doesn't try to push gradients through it.

Acceptance criteria

  • Splitting a coarse TrajectoryInterval + a set of ControlParameters produces the correct Vector{TrajectoryInterval} breakpoints (union of all active controls' grids, clipped to the node's tspan)
  • Each fine segment's p correctly merges every control active at that segment, including overlapping/non-aligned breakpoints across multiple controls
  • Sequential intra-node solve matches a manually-stepped reference solve (segment-by-segment solve with continuity)
  • Built via non-mutating reduction (no push!/in-place Vector mutation)
  • Breakpoint/index determination logic marked ChainRulesCore.@non_differentiable (or wrapped in ignore_derivatives)
  • Reverse-mode (Zygote) gradient of a scalar loss w.r.t. ps.controls matches a forward-mode/finite-difference reference

Blocked by

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions