-
Notifications
You must be signed in to change notification settings - Fork 430
feat: Add Dinic's Maximum Flow Algorithm #739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
As mentioned in PR 740, by @starovoid, the algorithm does not seem to be improving upon the existing implementation when running the benchmarks. Indeed it seems to be performing worse. This may be because the graphs from the benchmark have the same number of nodes as edges. However, in such a setting, Ford Fulkerson and Dinics should actually perform similarly. The results on my PC are however as follows: Which shows the decrease in performance. I also added a similar benchmark for both algorithms for an increased number of edges, where on can observe that this implementation of Dinic performs similarly poor. The bench setup is as follows: #[bench]
fn dinics_bench_many_edges(bench: &mut Bencher) {
static NODE_COUNT: usize = 1_001;
let mut g: Graph<usize, usize> = Graph::new();
let nodes: Vec<NodeIndex<_>> = (0..NODE_COUNT).map(|i| g.add_node(i)).collect();
for j in [1, 2, 4, 5, 10, 20, 25, 50] {
for i in 0..(NODE_COUNT - 1) / j {
g.add_edge(nodes[i], nodes[(i + 1) * j], 1);
}
}
bench.iter(|| {
let _flow = dinics(
&g,
NodeIndex::from(0),
NodeIndex::from(g.node_count() as u32 - 1),
);
});
}And the results are: |
This reverts commit d3170dc.
6643b23 to
87ceccb
Compare
|
Hi @RaoulLuque , thanks for pointing out the benchmark and for providing a larger bench test. I reimplemented some parts of the algorithm and got it to work a lot better. The Dinics and Ford Fulkerson benches that were being compared contained graph instances that favored a Ford Fulkerson method, so I added some others that favors Dinics. I added the benchmark results in the PR description. I'll also check the Maximum Bipartite Matching PR soon. |
|
Hi, thanks for reviewing the code and improving it :) Those results look really promising ! Ah, I didn't know that they were more favorable for Ford Fulkerson, I'll look into that interesting. Thanks for pointing that out 😁 I'll have a look at the new code prob next week if that's okay, because I currently don't have a lot of time unfortunately :) (If someone else wants to have a look, that is also great of course 😁) |
|
(one thing I can already say tho is that a docstring in the algo docs format should be added :) ) |
|
Sry for the additional comment, but since you seem to be quite knowledgable when it comes to the different use-cases of Dinics/Ford Fulkerson (Edmonds Karp), I think it would be a good idea to document when to use which function. We could use the (You can use |
good idea, added in latest commit |
|
Okay, so if you adjust the docstring of dinics to document the possibility to panic as stated in #739 (comment), I think this Pr would be ready to merge, thanks a lot again 🌟 Just one more comment I have, just below. Note that you can also accept suggestions right here on GitHub, this way the reviewers will be credited in Git for their suggestions :) |
Co-authored-by: Raoul Luqué <125205120+RaoulLuque@users.noreply.github.com>
…etgraph#849) The function 'zip' was introduced in petgraph#747 as a part of adding `no_std` support. However, there is already such a function in `core::iter`. The MSRV stated in the description of petgraph#747 was 1.64 at minimum, but the function in `core` is stable since Rust 1.59. Thus, it is an unnecessary duplication and can be removed without consequences. <!-- -- Thanks for contributing to `petgraph`! -- -- We require PR titles to follow the Conventional Commits specification, -- https://www.conventionalcommits.org/en/v1.0.0/. This helps us generate -- changelogs and follow semantic versioning. -- -- Start the PR title with one of the following: -- * `feat:` for new features -- * `fix:` for bug fixes -- * `refactor:` for code refactors -- * `docs:` for documentation changes -- * `test:` for test changes -- * `perf:` for performance improvements -- * `revert:` for reverting changes -- * `ci:` for CI/CD changes -- * `chore:` for changes that don't fit in any of the above categories -- The last two categories will not be included in the changelog. -- -- If your PR includes a breaking change, please add a `!` after the type -- and include a `BREAKING CHANGE:` line in the body of the PR describing -- the necessary changes for users to update their code. -- --> Co-authored-by: cactusdualcore <cactusdualcore@noreply.codeberg.org>
|
Looks great, thanks for all your patience with my review |
Co-authored-by: Raoul Luqué <125205120+RaoulLuque@users.noreply.github.com>
Co-authored-by: Raoul Luqué <125205120+RaoulLuque@users.noreply.github.com>
thanks |
See also petgraph#740 and petgraph#847 # Add Dinic's Maximum Flow Algorithm Computes the maximum flow of a weighted directed graph. Implementation inspired by existing [Ford Fulkerson](https://github.com/petgraph/petgraph/blob/9f778ec11b218ef6d1dfaaa51467b24c8c939fca/src/algo/maximum_flow/ford_fulkerson.rs) in Petgraph. Also, creates a `maximum_flow` submodule inside `algo` module to group flow network algorithms. References: * https://en.wikipedia.org/wiki/Dinic%27s_algorithm * https://cp-algorithms.com/graph/dinic.html I also added some more benches that build graphs where Dinics strongly outperforms Ford Fulkerson, as the graph built in the existent bench in the library favored Ford Fulkerson method. * Dinics ``` > cargo bench --bench dinics running 5 tests test dinics_bench ... bench: 52,870.19 ns/iter (+/- 5,405.82) test dinics_bench_dense_middle ... bench: 680,920.00 ns/iter (+/- 120,617.64) test dinics_bench_dense_middle_varying_weights ... bench: 1,527,980.00 ns/iter (+/- 281,240.50) test dinics_bench_many_edges ... bench: 335,548.12 ns/iter (+/- 59,469.62) test dinics_bench_wide ... bench: 163,606.25 ns/iter (+/- 4,729.17) test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured; 0 filtered out; finished in 18.47s ``` * Ford Fulkerson ``` > cargo bench --bench ford_fulkerson running 5 tests test ford_fulkerson_bench ... bench: 15,360.68 ns/iter (+/- 3,189.80) test ford_fulkerson_bench_dense_middle ... bench: 1,129,970.00 ns/iter (+/- 194,473.25) test ford_fulkerson_bench_dense_middle_varying_weights ... bench: 14,432,700.00 ns/iter (+/- 1,127,474.00) test ford_fulkerson_bench_many_edges ... bench: 153,336.25 ns/iter (+/- 20,860.00) test ford_fulkerson_bench_wide ... bench: 3,733,340.00 ns/iter (+/- 957,471.00) test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured; 0 filtered out; finished in 15.93s``` ``` --------- Co-authored-by: Raoul Luqué <125205120+RaoulLuque@users.noreply.github.com> Co-authored-by: Paul Buehne <64769435+cactusdualcore@users.noreply.github.com> Co-authored-by: cactusdualcore <cactusdualcore@noreply.codeberg.org>
See also petgraph#740 and petgraph#847 # Add Dinic's Maximum Flow Algorithm Computes the maximum flow of a weighted directed graph. Implementation inspired by existing [Ford Fulkerson](https://github.com/petgraph/petgraph/blob/9f778ec11b218ef6d1dfaaa51467b24c8c939fca/src/algo/maximum_flow/ford_fulkerson.rs) in Petgraph. Also, creates a `maximum_flow` submodule inside `algo` module to group flow network algorithms. References: * https://en.wikipedia.org/wiki/Dinic%27s_algorithm * https://cp-algorithms.com/graph/dinic.html I also added some more benches that build graphs where Dinics strongly outperforms Ford Fulkerson, as the graph built in the existent bench in the library favored Ford Fulkerson method. * Dinics ``` > cargo bench --bench dinics running 5 tests test dinics_bench ... bench: 52,870.19 ns/iter (+/- 5,405.82) test dinics_bench_dense_middle ... bench: 680,920.00 ns/iter (+/- 120,617.64) test dinics_bench_dense_middle_varying_weights ... bench: 1,527,980.00 ns/iter (+/- 281,240.50) test dinics_bench_many_edges ... bench: 335,548.12 ns/iter (+/- 59,469.62) test dinics_bench_wide ... bench: 163,606.25 ns/iter (+/- 4,729.17) test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured; 0 filtered out; finished in 18.47s ``` * Ford Fulkerson ``` > cargo bench --bench ford_fulkerson running 5 tests test ford_fulkerson_bench ... bench: 15,360.68 ns/iter (+/- 3,189.80) test ford_fulkerson_bench_dense_middle ... bench: 1,129,970.00 ns/iter (+/- 194,473.25) test ford_fulkerson_bench_dense_middle_varying_weights ... bench: 14,432,700.00 ns/iter (+/- 1,127,474.00) test ford_fulkerson_bench_many_edges ... bench: 153,336.25 ns/iter (+/- 20,860.00) test ford_fulkerson_bench_wide ... bench: 3,733,340.00 ns/iter (+/- 957,471.00) test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured; 0 filtered out; finished in 15.93s``` ``` --------- Co-authored-by: Raoul Luqué <125205120+RaoulLuque@users.noreply.github.com> Co-authored-by: Paul Buehne <64769435+cactusdualcore@users.noreply.github.com> Co-authored-by: cactusdualcore <cactusdualcore@noreply.codeberg.org>
## 🤖 New release * `petgraph`: 0.8.2 -> 0.8.3 (✓ API compatible changes) <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [0.8.3](https://github.com/petgraph/petgraph/compare/petgraph@v0.8.2...petgraph@v0.8.3) - 2025-09-28 ### Bug Fixes - Infinite `subgraph_isomorphisms_iter` for empty isomorphisms ([#780](#780)) - Algos don't work on `UndirectedAdaptor` ([#870](#870)) ([#871](#871)) - use a queue for SPFA ([#893](#893)) - `StableGraph::reverse` breaks free lists ([#890](#890)) ### Documentation - Fix examples link in README and unify typesetting of one word ([#823](#823)) - Add link to multigraph definition to isomorphism algos ([#824](#824)) - Fix auxiliary space (and time) complexity of bron-kerbosch ([#825](#825)) - Fix Typo in Operator Module Documentation ([#831](#831)) - Sync the crate feature flags in the README and docs ([#832](#832)) - Remove all \[Generic\] tags from algo docstrings ([#835](#835)) - Fix typos in comments ([#836](#836)) - Revamp CONTRIBUTING.md ([#833](#833)) - Update `GraphMap` link in README ([#857](#857)) - Add doc comment for `Dot::with_attr_getters` ([#850](#850)) - Specify iteration order for neighbors and edges and their variants ([#790](#790)) - Collection of Doc fixes ([#856](#856)) ### New Features - Add `into_nodes_edges_iters` to `StableGraph` ([#841](#841)) - Add methods to reserve & shrink `StableGraph` capacity ([#846](#846)) - Add Dinic's Maximum Flow Algorithm ([#739](#739)) - make Csr::from_sorted_edges generic over edge type and properly increase edge_count in Csr::from_sorted_edges ([#861](#861)) - Add `map_owned` and `filter_map_owned` for `Graph` and `StableGraph` ([#863](#863)) - Add dijkstra::with_dynamic_goal ([#855](#855)) - Fix self-loop bug in all_simple_paths and enable multiple targets ([#865](#865)) - mark petgraph::dot::Dot::graph_fmt as public ([#866](#866)) - Add bidirectional Dijkstra algorithm ([#782](#782)) ### Performance - Make A* tie break on lower h-values ([#882](#882)) ### Refactor - add examples for scc algorithms and reorganize into dedicated module ([#830](#830)) - Remove unnecessary trait bounds from impls/methods ([#828](#828)) - replace uses of 'crate::util::zip' with 'core::iter::zip' ([#849](#849)) - Fix clippy (and other) lints ([#851](#851)) - Cleanup repo ([#854](#854)) - replace crate::util::enumerate with Iterator::enumerate ([#881](#881)) ### Testing - Add dependency list for 'quickcheck' feature ([#822](#822)) - Fix feature cfg capitalization in doctest ([#852](#852)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Egor Starovoitov <52821033+starovoid@users.noreply.github.com>
See also #740 and #847
Add Dinic's Maximum Flow Algorithm
Computes the maximum flow of a weighted directed graph.
Implementation inspired by existing Ford Fulkerson in Petgraph.
Also, creates a
maximum_flowsubmodule insidealgomodule to group flow network algorithms.References:
I also added some more benches that build graphs where Dinics strongly outperforms Ford Fulkerson, as the graph built in the existent bench in the library favored Ford Fulkerson method.