docs: flows — indirect methods, simulation, and inspection - #868
Open
ocots wants to merge 11 commits into
Open
Conversation
…eld and the four get_*_gradient functions These were exported by CTFlows.Systems but not re-exported by OptimalControl, unlike their siblings control_law/pseudo_hamiltonian — an inconsistency flows/accessors.md (docs: flows, PR 8) can't document honestly without fixing. Zero naming collisions confirmed against CTBase/CTModels/CTSolvers/CTDirect's own re-exports. system/integrator stay deliberately unexported (too generic for a DSL surface); reach them as CTFlows.Flows.system(f)/.integrator(f). Adds the matching reexports() testset to test_ctflows.jl and updates docs/reports/99-api-coverage.md §8/§14. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Map of the section: why flows vs direct methods, the PMP recap, the three jobs (indirect solving, simulation, inspection), and the integrator prerequisite. Corrects the spec's own claim that a flow without an integrator loaded fails with a bare MethodError — verified live it's actually a clean ExtensionError. Also corrects method=:cpu/ :gpu to be a construction-time keyword, not a call-time one (spec's outline implied otherwise). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports attic/manual-flow-ocp.md's basic-usage/non-autonomous/variable/ augment material (concatenation and state-constraints split out to multi-phase.md and constrained-arcs.md per spec). Fixes all four spec-flagged stale patterns (Flow(x->x), positional Flow(ocp,u,g,μ), augment=true, OptimalControl.Hamiltonian). Harvests test_hamiltonian_type.jl's non-stationary-law example for the total-vs-partial Hamiltonian section rather than inventing one — already tested, already correct. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Full page from a 108-line skeleton, one section per constructor (VectorField, Hamiltonian, HamiltonianVectorField, PseudoHamiltonian + law, PseudoHamiltonianVectorField + law, SciML ODEFunction/ ODEProblem), each verified live with real return types. Fixes the stale autonomous=false keyword (now is_autonomous=) and the hand-rolled pseudo-Hamiltonian-via-dispatch pattern. New trap found: SciML-backed flows are always NonFixed, need variable=nothing even with no real free variable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
No predecessor on the old site. Covers ControlledVectorField + OpenLoop/ClosedLoop, and Flow(ocp, OpenLoop(u)) which — unlike a plain ControlledVectorField flow — carries an objective. Corrects the framing of OpenLoop's non-autonomy: a zero-arg closure builds without error and only fails on first call, a bare MethodError far from the mistake — not rejected at construction as one might assume. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The whole point of this page is the availability table (which accessor works on which flow kind) — verified cell-by-cell live, correcting one spec cell (hamiltonian(f) genuinely fails, IncorrectArgument, on a HamiltonianVectorField-built flow — an earlier check had this backwards) and noting the failure mode isn't uniform: some unavailable accessors throw IncorrectArgument, others a plain MethodError, a real API inconsistency stated honestly rather than papered over. Also works around a reproducible Documenter build quirk: `using OptimalControl` inside Documenter's @example sandbox (a bare `module`, not a regular one) fails to bind hamiltonian/hamiltonian_vector_field/ vector_field/the four get_*_gradient functions specifically, while Flow/Hamiltonian/control_law/pseudo_hamiltonian (reexported the exact same way, from the same CTFlows.Systems module) bind fine — isolated via extensive bisection (bare 1-hop import works, the two-hop reexport-through-OptimalControl chain doesn't, only inside a baremodule). Root cause not fully identified; a redundant, hidden (`# hide`) direct import right after `using OptimalControl` in the page's setup block fixes the sandbox without affecting what a normal user sees or needs to do — confirmed real users hitting `using OptimalControl` normally get the correct binding every time. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Concatenation (Base.:*), jumps as functions/nothing/plain-Vector (the Vector form confirmed live, an extra flexibility beyond callable-or- nothing), inspection accessors (already fully reexported, no gap here). Worked example is the bang-bang time-optimal double integrator from test/problems/double_integrator.jl's _di_time_shoot_builder fixture, matching the spec's own choice and confirmed against its reference solution (p0=[1,1], one switch at t=1, tf=2). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports attic/manual-flow-ocp.md's state-constraint material with the positional-to-keyword fix. Confirms and documents a real subtlety found live: the Symbol constraint spelling (constraint=:label) pulls the constraint straight from the OCP's own sign convention, which is not guaranteed to numerically agree with a hand-derived shooting g/μ pair using a different convention — stated as a warning rather than silently assumed interchangeable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Assembled from example-double-integrator-time.md and tutorial.md's indirect section, cross-checked against the CI-tested fixtures in test/problems/double_integrator.jl and test/helpers/shooting.jl rather than trusted at face value. The harvested in-place shooting example needed exactly one fix — a missing variable=tf on two flow calls in a NonFixed problem — everything else already worked. unsafe=true demonstrated with a genuine synthetic blow-up ODE (the double-integrator problem itself is too well-behaved to blow up even under a wild guess, so it wasn't a useful demo case for that one). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rk board Full julia --project=docs docs/make.jl + npx vitepress build rebuild, clean: 0 undefined-binding/no-docs/duplicate-docs warnings, all eight flows/ pages' @example blocks execute, 0 unresolved @refs from them. test/suite/flows/test_flow_api.jl + test/suite/problems/test_hamiltonian_type.jl re-run (89/89 passed). test/suite/reexport/test_ctflows.jl re-run (73/73 passed). typos clean. All 8 acceptance criteria ticked against that build. Findings beyond the checklist recorded in the report: the Documenter @example baremodule binding quirk (isolated, worked around, not fully root-caused), the corrected ExtensionError-not-MethodError claim on overview.md, and the method=:cpu/:gpu construction-time correction. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Summary
Stacked on #866 (
docs/solve, not yet merged) — base branch isdocs/solve, notmain, since PR 8 depends on PR 6 per the work board (sibling of #867, not stacked on it). Rebase ontomainonce #866 merges.The largest section of the rewrite: 8 pages under
docs/src/flows/, replacing the PR-2 stubs, covering the three jobsFlowdoes — indirect optimal control (PMP flow + shooting), simulation (integrate under a given control), and inspection (pull the Hamiltonian/vector field/control law back out of a flow).simulation.mdandaccessors.mdhave no predecessor on the old site;accessors.mdwas explicitly requested by the maintainer.overview.md(new): map of the section + PMP recap. Corrects the spec's own claim that a flow without an integrator loaded fails with a bareMethodError— verified live it's a cleanExtensionError. Correctsmethod=:cpu/:gputo be a construction-time keyword, not call-time.from-ocp.md: the main path. Fixes all four spec-flagged stale patterns (Flow(x->x), positionalFlow(ocp,u,g,μ),augment=true,OptimalControl.Hamiltonian). Harveststest/suite/problems/test_hamiltonian_type.jl's non-stationary-law example for the total-vs-partial Hamiltonian section — already tested, better than anything in the attic.from-hamiltonians.md: full page from a 108-line skeleton, one section per constructor, all six verified live with real return types.simulation.md(new):ControlledVectorField+OpenLoop/ClosedLoop. Corrects the framing ofOpenLoop's non-autonomy — a zero-arg closure builds without error, only fails on first call, not rejected at construction as one might assume.accessors.md(new, user-requested): the availability table is the whole point — verified cell-by-cell live, correcting one spec cell (hamiltonian(f)genuinely throws on aHamiltonianVectorField-built flow) and noting the failure mode isn't uniform (IncorrectArgumentin some cells, plainMethodErrorin others — a real API inconsistency stated honestly). Carries the PR's one code change: re-exportinghamiltonian/hamiltonian_vector_field/vector_field/the fourget_*_gradientfunctions insrc/imports/ctflows.jl(zero naming collisions confirmed), with the matchingtest/suite/reexport/test_ctflows.jltestset anddocs/reports/99-api-coverage.mdupdate.multi-phase.md(new, split out): worked example is the bang-bang time-optimal double integrator fromtest/problems/double_integrator.jl's tested_di_time_shoot_builderfixture, matching the spec's own choice.constrained-arcs.md: fixes the positional-to-keyword constraint syntax. Documents a real subtlety found live: theconstraint=:label(Symbol) spelling uses the OCP's own sign convention, not guaranteed to numerically agree with a hand-derived shootingg/μpair — stated as a warning rather than assumed interchangeable.shooting.md(new): cross-checked the harvested attic material against the CI-tested fixtures intest/problems/double_integrator.jlandtest/helpers/shooting.jlrather than trusting it at face value — needed exactly one fix (a missingvariable=tf).unsafe=truedemonstrated with a genuine synthetic blow-up ODE, since the double-integrator problem itself is too well-behaved to ever blow up.A genuine Documenter build quirk found and worked around (recorded in detail in
docs/reports/05-flows-indirect.md): inside Documenter's@examplesandbox (abaremodule, not a regularmodule),using OptimalControlfails to bindhamiltonian/hamiltonian_vector_field/vector_field/the fourget_*_gradientfunctions specifically — whileFlow/control_law/pseudo_hamiltonian(re-exported the same way, from the sameCTFlows.Systemsmodule) bind fine. Isolated via extensive bisection (a direct 1-hop import works; the two-hop reexport-through-OptimalControl chain doesn't, only inside abaremodule); root cause not fully identified despite that investigation. Confirmed this does not affect real usage — a normalusing OptimalControlin an ordinary session or module gets the correct binding every time. Worked around with a hidden (# hide), redundant direct import inaccessors.md's own setup block, invisible to readers and not something a real user needs.Test plan
julia --project=docs docs/make.jl— full rebuild, clean: 0 undefined-binding/no-docs/duplicate-docs warnings, all eight pages'@exampleblocks execute, 0 unresolved@refs from them.npx vitepress buildon the Documenter output — site builds; spot-checked cross-links into docs: modelling — describe an optimal control problem #865/docs: solve — direct methods, choosing and configuring them #866/docs: results — reading, plotting, and persisting a solution #867's already-built anchors resolve in the built HTML.test/suite/flows/test_flow_api.jl+test/suite/problems/test_hamiltonian_type.jl— 89/89 passed.test/suite/reexport/test_ctflows.jl(with the new testset) — 73/73 passed.typos— clean.docs/reports/05-flows-indirect.mdacceptance criteria re-checked against the real build (8/8 ticked, deviations/findings recorded explicitly rather than silently).🤖 Generated with Claude Code