-
Notifications
You must be signed in to change notification settings - Fork 430
feat: Add Johnson's algorithm #741
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
RaoulLuque
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a useful addition to Petgraph :)
Was wondering a few things:
I saw that this is similar with Floyd Warshall, but why do we not return the actual paths that are computed in some way? Of course changing this for Floyd Warshall would be an API change, but we could do it from the start with Johnson's?
Probably this would be a performance drawback, but would it maybe be possible to discard the "path map" immediately as a user in which case the compiler might optimize the performance slowdown away?
I.e. something like let (res, _) = johnson(...).unwrap(), where the _ would be throwing away the "path map" returned by johnson. Not sure if this works, especially with the Result return type, but might be worth looking into 🤔
| /// **Note**: If the graph is sparse (the number of edges is quite small), | ||
| /// consider using the [`johnson`](fn@crate::algo::johnson), which is likely to show better performance. | ||
| /// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Judging by the benchmarks, parallel Johnson might be worth considering instead of Floyd Warshall, even on dense graphs. So maybe add a line about that as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be a pretty bold statement, since in addition to the absolute operating time, resource consumption is often also taken into account, which will be much more economical when using floyd_warshall for dense graphs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are definitely right that one has to take into account the resource consumption, but it still might be interesting to users, to know that parallelized johnson might run faster (not necessarily more efficient) than normal floyd warshall, even on general graphs. But I also see your point, so feel free to include a comment about the runtime/resource trade-off or not 👍
Because it will also require changing/adding a new version of Secondly, significant refactoring and generalization of shortest path algorithms is expected in the future, and then I hope we will be able to develop a uniform API for both versions of all algorithms without paying extra for unused functionality. Some work has already been done previously in the |
Oh, I didn't see that |
Work on |
|
LGTM now :) |
## 🤖 New release * `petgraph`: 0.8.1 -> 0.8.2 (✓ API compatible changes) <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [0.8.2](https://github.com/petgraph/petgraph/compare/petgraph@v0.8.1...petgraph@v0.8.2) - 2025-06-06 ### Bug Fixes - Ford Fulkerson sometimes Panics on StableGraphs ([#793](#793)) - Run Maximal Cliques Quickcheck only on Digraphs which are symmetrical ([#800](#800)) - Run Steiner Tree Quickcheck on the connected components to properly support disconnected graphs ([#801](#801)) - Quickcheck random01 function only outputs 0 ([#798](#798)) ### Documentation - Specify that Acyclic::try_udpate_edge may add an edge ([#770](#770)) - Update remove_node doc comment in graphmap.rs ([#663](#663)) - Add examples to minimum spanning tree functions ([#808](#808)) - Minimal typo fix in comments ([#803](#803)) - Update docs.rs ([#807](#807)) - Add note about `StableGraph::edge_indices` behaviour ([#812](#812)) - Clarification of references to nodes and V (refresh #358) ([#814](#814)) - Fix link and mention Dfs and Bfs as special case in examples ([#816](#816)) - Unify algo docs ([#815](#815)) ### New Features - *(parser)* allow parsing graphs from Dot/Graphviz files ([#653](#653)) - Implement `DataMap` for `GraphMap` graphs ([#776](#776)) - Add Johnson's algorithm ([#741](#741)) - Add algorithm to find bridge edges ([#590](#590)) ### Performance - Reuse queue allocation in `maximum_matching` main loop ([#817](#817)) ### Refactor - Fix new clippy warnings ([#791](#791)) </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: starovoid <prototyperailgun@gmail.com>
## 🤖 New release * `petgraph`: 0.8.1 -> 0.8.2 (✓ API compatible changes) <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [0.8.2](https://github.com/petgraph/petgraph/compare/petgraph@v0.8.1...petgraph@v0.8.2) - 2025-06-06 ### Bug Fixes - Ford Fulkerson sometimes Panics on StableGraphs ([petgraph#793](petgraph#793)) - Run Maximal Cliques Quickcheck only on Digraphs which are symmetrical ([petgraph#800](petgraph#800)) - Run Steiner Tree Quickcheck on the connected components to properly support disconnected graphs ([petgraph#801](petgraph#801)) - Quickcheck random01 function only outputs 0 ([petgraph#798](petgraph#798)) ### Documentation - Specify that Acyclic::try_udpate_edge may add an edge ([petgraph#770](petgraph#770)) - Update remove_node doc comment in graphmap.rs ([petgraph#663](petgraph#663)) - Add examples to minimum spanning tree functions ([petgraph#808](petgraph#808)) - Minimal typo fix in comments ([petgraph#803](petgraph#803)) - Update docs.rs ([petgraph#807](petgraph#807)) - Add note about `StableGraph::edge_indices` behaviour ([petgraph#812](petgraph#812)) - Clarification of references to nodes and V (refresh petgraph#358) ([petgraph#814](petgraph#814)) - Fix link and mention Dfs and Bfs as special case in examples ([petgraph#816](petgraph#816)) - Unify algo docs ([petgraph#815](petgraph#815)) ### New Features - *(parser)* allow parsing graphs from Dot/Graphviz files ([petgraph#653](petgraph#653)) - Implement `DataMap` for `GraphMap` graphs ([petgraph#776](petgraph#776)) - Add Johnson's algorithm ([petgraph#741](petgraph#741)) - Add algorithm to find bridge edges ([petgraph#590](petgraph#590)) ### Performance - Reuse queue allocation in `maximum_matching` main loop ([petgraph#817](petgraph#817)) ### Refactor - Fix new clippy warnings ([petgraph#791](petgraph#791)) </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: starovoid <prototyperailgun@gmail.com>
Brief
Add Johnson algorithm for all pairs shortest path problem.
About algorithm & implementation
Johnson's algorithm is based on Dijkstra's algorithm, calling it for each vertex after some preparation using SPFA.
In this way we can find all pair shortest paths in O(VD + VE) time (D is the Dijksta's time complexity).
In the current implementation, we have a time complexity O(VElog(V) + V^2log(V)), which is preferable for non-dense graphs, compared to the Floyd-Warshall algorithm.
Instead of SPFA, it would also be possible to use the existing
bellman_fordimplementation, but SPFA usage additionally speeds up the algorithm on sparse graphs, and there is an unconfirmed estimate that SPFA works on average in O(E) time.Becnhmarks
I have conducted small comparative tests that confirm the statement that Johnson's algorithm is preferable on sparse graphs (almost five times faster than
floyd_warshall), but it also naturally loses on dense graphs.The benchmark code has also been added to this PR in order to be able to compare the performance of certain algorithms in the future.
parallel_johnsonA version of the algorithm that parallels
dijkstracalls is available under therayonfeature.The benchmarks show the following performance on PC with Ryzen 9 7950X:
and
on laptop with 12th Intel(R) i7-12700H