Skip to content

perf(edmonds-karp): stop repeating work that is already done - #819

Open
tachsin wants to merge 1 commit into
evenfurther:mainfrom
tachsin:perf/edmonds-karp-redundant-work
Open

perf(edmonds-karp): stop repeating work that is already done#819
tachsin wants to merge 1 commit into
evenfurther:mainfrom
tachsin:perf/edmonds-karp-redundant-work

Conversation

@tachsin

@tachsin tachsin commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Closes #816.

Builds the flow list once in augment and reads the cut off it, iterates the sparse map by reference instead of cloning it, indexes reachability by node number rather than through a BTreeSet, and uses windows(2) for the path pairs in cancel_flow.

update_flows changes return type, but it belongs to the private EdmondsKarpInternal trait and does not escape the module.

Checking

No change to the flows, the value or the cut, all of which the existing tests check exactly, including the two Code Jam ones. 290 tests pass, clippy and rustfmt clean.

Measured against this branch's parent, ten passes with the order of the two binaries swapped on alternate passes:

edmonds_karp, dense, 122-node layered network:   about 12% off
edmonds_karp, sparse, 122-node layered network:  about 17% off

Measured on Windows 11, Intel Core Ultra 7 265K, 64 GB RAM.

This touches the same file as #820 but not the same lines; I checked they merge in either order.

Three things in the augmentation path are done twice or more:

- `augment` calls `flows()` once to derive the cut and again for the value it
  returns. Building that list walks the whole capacity structure, which for
  `DenseCapacity` means the entire size-by-size matrix. Build it once and read
  the cut off it.
- `SparseCapacity::flows` clones the whole nested `BTreeMap` before iterating
  it, allocating a copy of every flow to read every flow. Iterate by reference.
- `update_flows` records the nodes the source can still reach in a
  `BTreeSet<usize>`, cleared and refilled on every augmentation. Nodes here are
  numbered from zero, so a `Vec<bool>` indexes directly. The set never escapes
  the private trait.

Also `cancel_flow` cloned a path to zip it with itself; `windows(2)` gives the
same pairs.

No change to the flows, the value, or the cut, all of which the existing tests
check exactly, including the two Code Jam ones.

On a layered 122-node network, measured against this branch's parent: about 6%
off the dense representation and 16% off the sparse one, which does the most
copying.
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.

edmonds_karp builds the flow list twice and clones the sparse map to read it

1 participant