Skip to content

Commit

Permalink
Add PageRank (#788)
Browse files Browse the repository at this point in the history
Related to #315

Adds an implementation of the PageRank algorithm using sparse matrices. It uses the sprs crate combined with ndarray to implement a Power Method approach of finding the PageRank.

Also, we test this implementation against NetworkX's implementation of the PageRank. We accept all the arguments that NetworkX accepts: tolerance, max_iter, personalization, dangling, etc.

* Add the sketch of PageRank

* More progress towards pagerank

* Use CentralityMapping and FailedToConverge

* Finalize PageRank

* First test does not run

* Remove unwanted triplet

* Fix clippy warning

* Handle personalization correctly

* Add more tests

* Cargo fmt

* Add scipy to test requirements

* Skip SciPy tests in case architecture does not have it

* Ignore flake8 errors that do not help

* Flake8

* Handle dangling weights

* Add more tests

* Add nstart argument

* Cargo Clippy

* Documentation

* Fix typo in URL

* Update releasenotes/notes/add-pagerank-bef0de7d46026071.yaml

Co-authored-by: Matthew Treinish <[email protected]>

* Tweak pyfunction signature

* Add scipy to aarch64 test requirements

* Address comments from code review

* Clippy is always right

---------

Co-authored-by: Matthew Treinish <[email protected]>
  • Loading branch information
IvanIsCoding and mtreinish authored May 26, 2023
1 parent 09d5707 commit afc3627
Show file tree
Hide file tree
Showing 10 changed files with 597 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ jobs:
- name: Download grcov
run: curl -L https://github.com/mozilla/grcov/releases/download/v0.8.7/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf -
- name: Install deps
run: pip install -U setuptools-rust networkx testtools fixtures
run: pip install -U setuptools-rust networkx scipy testtools fixtures
- name: Build retworkx
run: python setup.py develop
env:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
CIBW_MANYLINUX_I686_IMAGE: quay.io/pypa/manylinux2014_i686:latest
CIBW_SKIP: cp36-* pp* *win32 *musl*
CIBW_BEFORE_BUILD: pip install -U setuptools-rust
CIBW_TEST_REQUIRES: networkx testtools fixtures
CIBW_TEST_REQUIRES: networkx scipy testtools fixtures
CIBW_TEST_COMMAND: python -m unittest discover {project}/tests/rustworkx_tests
- uses: actions/upload-artifact@v3
with:
Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:
CIBW_MANYLINUX_I686_IMAGE: quay.io/pypa/manylinux2014_i686:latest
CIBW_SKIP: cp36-* pp* *win32 *musl*
CIBW_BEFORE_BUILD: pip install -U setuptools-rust
CIBW_TEST_REQUIRES: networkx testtools fixtures
CIBW_TEST_REQUIRES: networkx scipy testtools fixtures
CIBW_TEST_COMMAND: python -m unittest discover {project}/tests/rustworkx_tests
CIBW_ARCHS_LINUX: aarch64
- uses: actions/upload-artifact@v3
Expand Down
86 changes: 82 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ rayon = "1.6"
num-traits = "0.2"
num-bigint = "0.4"
num-complex = "0.4"
ndarray-stats = "0.5.1"
quick-xml = "0.28"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand All @@ -50,6 +51,10 @@ features = ["rayon"]
version = "1.9"
features = ["rayon"]

[dependencies.sprs]
version = "^0.11"
features = ["multi_thread"]

[profile.release]
lto = 'fat'
codegen-units = 1
10 changes: 10 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ Centrality
rustworkx.eigenvector_centrality
rustworkx.closeness_centrality

.. _link-analysis:

Link Analysis
--------------

.. autosummary::
:toctree: apiref

rustworkx.pagerank

.. _traversal:

Traversal
Expand Down
29 changes: 29 additions & 0 deletions releasenotes/notes/add-pagerank-bef0de7d46026071.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
features:
- |
Added a new function, :func:`~.pagerank` which is used to
compute the PageRank score for all nodes in a given directed graph.
For example:
.. jupyter-execute::
import rustworkx as rx
from rustworkx.visualization import mpl_draw
graph = rx.generators.directed_hexagonal_lattice_graph(2, 2)
ranks = rx.pagerank(graph)
# Generate a color list
colors = []
for node in graph.node_indices():
pagerank_score = ranks[node]
graph[node] = pagerank_score
colors.append(pagerank_score)
mpl_draw(
graph,
with_labels=True,
node_color=colors,
node_size=650,
labels=lambda x: "{0:.2f}".format(x)
)
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod isomorphism;
mod iterators;
mod json;
mod layout;
mod link_analysis;
mod matching;
mod planar;
mod random_graph;
Expand All @@ -47,6 +48,8 @@ use graphml::*;
use isomorphism::*;
use json::*;
use layout::*;
use link_analysis::*;

use matching::*;
use planar::*;
use random_graph::*;
Expand Down Expand Up @@ -485,6 +488,7 @@ fn rustworkx(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(read_graphml))?;
m.add_wrapped(wrap_pyfunction!(digraph_node_link_json))?;
m.add_wrapped(wrap_pyfunction!(graph_node_link_json))?;
m.add_wrapped(wrap_pyfunction!(pagerank))?;
m.add_class::<digraph::PyDiGraph>()?;
m.add_class::<graph::PyGraph>()?;
m.add_class::<toposort::TopologicalSorter>()?;
Expand Down
Loading

0 comments on commit afc3627

Please sign in to comment.