Skip to content

api: /maxflow?trace=true ships the whole trace statelessly (closes #36) - #58

Closed
bgent19 wants to merge 2 commits into
classdemosfrom
worktree-issue-36-maxflow-trace-api
Closed

api: /maxflow?trace=true ships the whole trace statelessly (closes #36)#58
bgent19 wants to merge 2 commits into
classdemosfrom
worktree-issue-36-maxflow-trace-api

Conversation

@bgent19

@bgent19 bgent19 commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Implements #36. Based on classdemos (not main) because it stacks on #35's api.py changes.

GET /maxflow gains trace: bool = False. When true the whole Edmonds–Karp trace ships as one array — every augmentation, complete enough to draw, with no server-side cursor.

What changed

  • Each step is a complete snapshot, never a delta, so backward stepping is an index decrement. EdmondsKarp._snapshot states the entire residual graph and every arc's flow each time.
  • Step 0 is prepended — empty path, zero bottleneck, initial residuals — so the uniform residuals from k−1, path from k render rule has a before-state for iteration 1 without building residual graphs in the browser.
  • The data layer stopped filtering; the CLI started. Terminals are named __source__ / __sink__ and retained; unbounded residuals ship as null and stay in place, so lane_residuals is one term per hop and a min(...) term can be anchored to its lane. cli.cmd_maxflow narrows at print time.
  • flows states every arc, zeros included, closing the trap where a saturated lane was indistinguishable from an absent one. Server-computed, not cap − residual in JS.
  • MaxFlowResponse / TraceStepOut document the shape at /docs. trace=false keeps all four existing fields and their values, adding an empty trace array.

Edge identity is deliberately not threaded through the arc generator, per the issue.

Verification

  • tests/golden/ pins the --trace lecture text character for character. The goldens were generated from the CLI before the split existed, so they are evidence the narrowing is exact rather than approximately right — a reviewer independently checked out the pre-change commit and diffed; both datasets came back empty.
  • New contract-test section covers step 0, the full field set, len(lane_residuals) == max(len(path) - 1, 0) (the spec's formula, guarded for step 0's empty path), terminal retention, null-never-Infinity (parsed with parse_constant so a browser-breaking Infinity cannot slip through), flow coverage of saturated lanes, statelessness, and the /docs schema.
  • Two pre-existing core tests in test_maxflow_interdiction.py asserted the old filtered shape and were updated to the new contract, keeping their intent — including the load-bearing edge-order assertions that select which cancellation trace students see.
  • Full suite: 203 passed.

🤖 Generated with Claude Code

Day 2 steps through Edmonds-Karp with the arrow keys, so the entire trace
ships as one array in one call and backward stepping is an index decrement.
Each entry is a complete snapshot, never a delta, which is what makes that
possible -- a server-side cursor would have broken the API's own no-leaked-
state promise for no gain.

The data layer stops filtering and the CLI starts. Two filters existed purely
to tidy CLI output and both damaged a drawing consumer: stripping the synthetic
terminals made a route appear to begin mid-graph, and dropping unbounded terms
de-aligned lane_residuals from path so a min(...) term could not be anchored to
its lane. Both now ship complete -- terminals named __source__/__sink__,
unbounded residuals as null -- and cli.cmd_maxflow narrows at print time.

The solver also states per-arc flows on every step, zeros included, closing the
trap where a saturated lane was indistinguishable from an absent one. Computed
server-side rather than as cap - residual in the browser.

Adds a step 0: the graph before the first push, so the frontend's uniform
"residuals from k-1, path from k" render rule has a before-state for
iteration 1 without building residual graphs in JavaScript.

tests/golden/ pins the --trace lecture text character for character. The
goldens were generated from the CLI before the split existed, so they are
evidence the narrowing is exact rather than approximately right.
The display helper sniffed tuple length to accept both (u, v) pairs and
(u, v, residual) triples; it is now two named helpers, one per shape. The
None-residual guard is redundant today -- only terminal arcs are unbounded, and
dropping the synthetic endpoints already drops them -- and is kept because the
alternative is a TypeError mid-lecture if that stops being true.

_snapshot's bottleneck and total are the same type and adjacent, so transposing
them would be a silent wrong number on the projector. Keyword-only.
@bgent19 bgent19 closed this Aug 13, 2026
@bgent19
bgent19 deleted the worktree-issue-36-maxflow-trace-api branch August 13, 2026 22:53
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.

1 participant