Fixed and lossy equal-balanced placement, reverse SPF (0.9.0) - #9
Conversation
Two equal-balanced placement modes for hop-by-hop ECMP with a load-blind forwarding table: EQUAL_BALANCED_FIXED admits losslessly over the topology's next-hop set (a member filled since the DAG was computed drives the scale to 0), EQUAL_BALANCED_LOSSY forwards best-effort and reports the dropped volume per edge via FlowGraph.place_with_drops. FlowPolicy treats both as equal-balanced but skips the equalizing rebalance for the lossy mode, so pinned routes carry what fits. shortest_paths_to / Algorithms.spf_to runs Dijkstra over the in-adjacency and returns distances to one destination plus a forward-oriented PredDAG valid for placement from any node, with optional forced fan-out edges for an origin whose first hop is a traffic split rather than a routing choice. A cost-only FlowPolicy (require_capacity=false) no longer passes the residual to SPF when an equal-balanced per-flow target is set; a residual forces capacity-aware selection, so such policies routed around saturated edges instead of following costs. Version 0.9.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 480e7977fc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (ent_edge[static_cast<std::size_t>(i)] == e_raw) { present = true; break; } | ||
| } | ||
| if (present) continue; | ||
| succ_append(static_cast<std::size_t>(u), v, e_raw); |
There was a problem hiding this comment.
Validate cycles after appending forced fan-out edges
The acyclicity check only considers entries produced by SPF, so a forced edge can itself introduce a cycle. For example, on a graph containing 0->1 and a higher-cost self-loop 0->0, passing the self-loop in fanout_edges reaches this append because node 0 has no incoming SPF entry, producing a cyclic PredDAG; a reproduced 10-unit EqualBalancedFixed placement then reported 8 units placed while allocating 10 units on both edges. Multiple forced edges between otherwise root nodes can similarly form cycles, so reject self-loops and validate the accumulated forced-edge graph before returning it.
AGENTS.md reference: AGENTS.md:L12-L12
Useful? React with 👍 / 👎.
Summary
EQUAL_BALANCED_FIXED: lossless hash-ECMP admission over the topology's next-hop set; a member filled by an earlier placement blocks later ones (scale 0).EQUAL_BALANCED_LOSSY: best-effort fill-and-drop; placed is the delivered volume,FlowGraph.place_with_dropsreports dropped volume per edge. FlowPolicy skips the equalizing rebalance for this mode so pinned routes carry what fits.shortest_paths_to/Algorithms.spf_to: reverse SPF returning distances to a destination and a forward-oriented DAG usable from any node, with optional forced fan-out edges.NetGraph 0.23.0 depends on this release (
netgraph-core>=0.9.0).Test plan
make cpp-test)make lint,pytest tests/py)dev/check_core_integration.shagainst this branch (1274 tests)🤖 Generated with Claude Code