Skip to content

Commit

Permalink
Add release notes and universal functions for `floyd_warshall_success…
Browse files Browse the repository at this point in the history
…or_and_distance` (#1049)

Follow up of #1040

This adds the release notes, universal function, and shortens the name of the new floyd_warshall_successor_and_distance

* Save next nodes in Floyd-Warshall numpy variants

* Create `graph_floyd_warshall_successor_and_distance_numpy`

* Reformat

* Split a function by by `generate_successors`

* Add testcases

* Add the functions to docs

* Add docstring to Rust code

* Change name and add universal function

* Add release notes

---------

Co-authored-by: maleicacid <maleicacid824+dev@gmail.com>
  • Loading branch information
IvanIsCoding and kazuki0824 committed Jan 8, 2024
1 parent e4ff44e commit ab23043
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 10 deletions.
1 change: 1 addition & 0 deletions docs/source/api/algorithm_functions/shortest_paths.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Shortest Paths
rustworkx.distance_matrix
rustworkx.floyd_warshall
rustworkx.floyd_warshall_numpy
rustworkx.floyd_warshall_successor_and_distance
rustworkx.astar_shortest_path
rustworkx.k_shortest_path_lengths
rustworkx.num_shortest_paths_unweighted
Expand Down
2 changes: 1 addition & 1 deletion docs/source/api/pydigraph_api_functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ the functions from the explicitly typed based on the data type.
rustworkx.digraph_distance_matrix
rustworkx.digraph_floyd_warshall
rustworkx.digraph_floyd_warshall_numpy
rustworkx.digraph_floyd_warshall_successor_and_distance_numpy
rustworkx.digraph_floyd_warshall_successor_and_distance
rustworkx.digraph_adjacency_matrix
rustworkx.digraph_all_simple_paths
rustworkx.digraph_all_pairs_all_simple_paths
Expand Down
2 changes: 1 addition & 1 deletion docs/source/api/pygraph_api_functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ typed API based on the data type.
rustworkx.graph_distance_matrix
rustworkx.graph_floyd_warshall
rustworkx.graph_floyd_warshall_numpy
rustworkx.graph_floyd_warshall_successor_and_distance_numpy
rustworkx.graph_floyd_warshall_successor_and_distance
rustworkx.graph_adjacency_matrix
rustworkx.graph_all_simple_paths
rustworkx.graph_all_pairs_all_simple_paths
Expand Down
7 changes: 7 additions & 0 deletions releasenotes/notes/add-fw-successor-80c09cb300c137f0.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
features:
- |
Added a new algorithm function,
:func:`rustworkx.floyd_warshall_successor_and_distance`, that calculates
the shortest path distance and the successor nodes for all node pairs in
:class:`~rustworkx.PyGraph` and :class:`~rustworkx.PyDiGraph` graphs.
69 changes: 69 additions & 0 deletions rustworkx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2102,3 +2102,72 @@ def is_bipartite(graph):

is_bipartite.register(PyDiGraph, digraph_is_bipartite)
is_bipartite.register(PyGraph, graph_is_bipartite)


@functools.singledispatch
def floyd_warshall_successor_and_distance(
graph,
weight_fn=None,
default_weight=1.0,
parallel_threshold=300,
):
"""
Find all-pairs shortest path lengths using Floyd's algorithm.
Floyd's algorithm is used for finding shortest paths in dense graphs
or graphs with negative weights (where Dijkstra's algorithm fails).
This function is multithreaded and will launch a pool with threads equal
to the number of CPUs by default if the number of nodes in the graph is
above the value of ``parallel_threshold`` (it defaults to 300).
You can tune the number of threads with the ``RAYON_NUM_THREADS``
environment variable. For example, setting ``RAYON_NUM_THREADS=4`` would
limit the thread pool to 4 threads if parallelization was enabled.
:param PyDiGraph graph: The directed graph to run Floyd's algorithm on
:param weight_fn: A callable object (function, lambda, etc) which
will be passed the edge object and expected to return a ``float``. This
tells rustworkx/rust how to extract a numerical weight as a ``float``
for edge object. Some simple examples are::
floyd_warshall_successor_and_distance(graph, weight_fn=lambda _: 1)
to return a weight of 1 for all edges. Also:
floyd_warshall_successor_and_distance(graph, weight_fn=float)
to cast the edge object as a float as the weight.
:param as_undirected: If set to true each directed edge will be treated as
bidirectional/undirected.
:param int parallel_threshold: The number of nodes to execute
the algorithm in parallel at. It defaults to 300, but this can
be tuned
:returns: A tuple of two matrices.
First one is a matrix of shortest path distances between nodes. If there is no
path between two nodes then the corresponding matrix entry will be
``np.inf``.
Second one is a matrix of **next** nodes for given source and target. If there is no
path between two nodes then the corresponding matrix entry will be the same as
a target node. To reconstruct the shortest path among nodes::
def reconstruct_path(source, target, successors):
path = []
if source == target:
return path
curr = source
while curr != target:
path.append(curr)
curr = successors[curr, target]
path.append(target)
return path
:rtype: (numpy.ndarray, numpy.ndarray)
"""
raise TypeError("Invalid Input Type %s for graph" % type(graph))


floyd_warshall_successor_and_distance.register(
PyDiGraph, digraph_floyd_warshall_successor_and_distance
)
floyd_warshall_successor_and_distance.register(PyGraph, graph_floyd_warshall_successor_and_distance)
4 changes: 2 additions & 2 deletions rustworkx/shortest_path.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,15 @@ def graph_floyd_warshall_numpy(
default_weight: float | None = ...,
parallel_threshold: int | None = ...,
) -> np.ndarray: ...
def digraph_floyd_warshall_successor_and_distance_numpy(
def digraph_floyd_warshall_successor_and_distance(
graph: PyDiGraph[_S, _T],
/,
weight_fn: Callable[[_T], float] | None = ...,
as_undirected: bool | None = ...,
default_weight: float | None = ...,
parallel_threshold: int | None = ...,
) -> tuple[np.ndarray, np.ndarray]: ...
def graph_floyd_warshall_successor_and_distance_numpy(
def graph_floyd_warshall_successor_and_distance(
graph: PyGraph[_S, _T],
/,
weight_fn: Callable[[_T], float] | None = ...,
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,10 @@ fn rustworkx(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(graph_floyd_warshall_numpy))?;
m.add_wrapped(wrap_pyfunction!(digraph_floyd_warshall_numpy))?;
m.add_wrapped(wrap_pyfunction!(
graph_floyd_warshall_successor_and_distance_numpy
graph_floyd_warshall_successor_and_distance
))?;
m.add_wrapped(wrap_pyfunction!(
digraph_floyd_warshall_successor_and_distance_numpy
digraph_floyd_warshall_successor_and_distance
))?;
m.add_wrapped(wrap_pyfunction!(collect_runs))?;
m.add_wrapped(wrap_pyfunction!(collect_bicolor_runs))?;
Expand Down
4 changes: 2 additions & 2 deletions src/shortest_path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ pub fn graph_floyd_warshall_numpy(
signature=(graph, weight_fn=None, default_weight=1.0, parallel_threshold=300),
text_signature = "(graph, /, weight_fn=None, default_weight=1.0, parallel_threshold=300)"
)]
pub fn graph_floyd_warshall_successor_and_distance_numpy(
pub fn graph_floyd_warshall_successor_and_distance(
py: Python,
graph: &graph::PyGraph,
weight_fn: Option<PyObject>,
Expand Down Expand Up @@ -1242,7 +1242,7 @@ pub fn digraph_floyd_warshall_numpy(
signature=(graph, weight_fn=None, as_undirected=false, default_weight=1.0, parallel_threshold=300),
text_signature = "(graph, /, weight_fn=None, as_undirected=False, default_weight=1.0, parallel_threshold=300)"
)]
pub fn digraph_floyd_warshall_successor_and_distance_numpy(
pub fn digraph_floyd_warshall_successor_and_distance(
py: Python,
graph: &digraph::PyDiGraph,
weight_fn: Option<PyObject>,
Expand Down
2 changes: 1 addition & 1 deletion tests/rustworkx_tests/digraph/test_floyd_warshall.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def test_floyd_warshall_successors_numpy(self):
graph.add_edges_from_no_data(
[(1, 2), (1, 7), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (0, 8)]
)
dist, succ = rustworkx.digraph_floyd_warshall_successor_and_distance_numpy(
dist, succ = rustworkx.floyd_warshall_successor_and_distance(
graph, default_weight=2, parallel_threshold=self.parallel_threshold
)
self.assertEqual(succ[1, 1], 1)
Expand Down
2 changes: 1 addition & 1 deletion tests/rustworkx_tests/graph/test_floyd_warshall.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def test_floyd_warshall_successors_numpy(self):
graph.add_edges_from_no_data(
[(1, 2), (1, 7), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (0, 8)]
)
dist, succ = rustworkx.graph_floyd_warshall_successor_and_distance_numpy(
dist, succ = rustworkx.floyd_warshall_successor_and_distance(
graph, default_weight=2, parallel_threshold=self.parallel_threshold
)
self.assertEqual(succ[1, 1], 1)
Expand Down

0 comments on commit ab23043

Please sign in to comment.