Skip to content
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

PageRank Args, is_self_loop on edge, remove all option<bool>, added bincode version on graph, fix all warns, #1499

Merged
merged 13 commits into from
Feb 22, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ fn main() {

// page rank with time
now = Instant::now();
let _page_rank = unweighted_page_rank(&g, 1000, None, None, true);
let _page_rank = unweighted_page_rank(&g, Some(1000), None, None, true, None);
println!("Page rank: {} seconds", now.elapsed().as_secs_f64());

// connected community_detection with time
Expand Down
2 changes: 1 addition & 1 deletion examples/rust/src/bin/bench/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,6 @@ fn main() {
g
};
println!("Data loaded\nPageRanking");
unweighted_page_rank(&graph, 25, Some(8), None, true);
unweighted_page_rank(&graph, Some(25), Some(8), None, true, None);
println!("Done PR");
}
6 changes: 3 additions & 3 deletions examples/rust/src/bin/crypto/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ fn main() {

println!("Pagerank");
let now = Instant::now();
let _ = unweighted_page_rank(&g, 20, None, None, true);
let _ = unweighted_page_rank(&g, Some(20), None, None, true, None);
println!("Time taken: {} secs", now.elapsed().as_secs());

let now = Instant::now();

let _ = unweighted_page_rank(&g, 20, None, None, true);
let _ = unweighted_page_rank(&g, Some(20), None, None, true, None);
println!("Time taken: {} secs", now.elapsed().as_secs());

let now = Instant::now();
let _ = unweighted_page_rank(&g.layers("USDT").unwrap(), 20, None, None, true);
let _ = unweighted_page_rank(&g.layers("USDT").unwrap(), Some(20), None, None, true, None);
println!("Time taken: {} secs", now.elapsed().as_secs());

println!("Generic taint");
Expand Down
2 changes: 1 addition & 1 deletion examples/rust/src/bin/pokec/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn main() {

let now = Instant::now();

unweighted_page_rank(&g, 100, None, Some(0.00000001), true);
unweighted_page_rank(&g, Some(100), None, Some(0.00000001), true, None);

println!("PageRank took {} millis", now.elapsed().as_millis());

Expand Down
8 changes: 8 additions & 0 deletions python/tests/test_graphdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,14 @@ def test_node_types_change():
a.set_node_type("YO")
assert a.node_type == "YO"

def test_is_self_loop():
g = Graph()
g.add_node(0, "A", None, None)
e = g.add_edge(0, "A", "A", None, None)
assert e.is_self_loop()
g.add_node(0, "B", None, None)
ee = g.add_edge(0, "A", "B", None, None)
assert not ee.is_self_loop()

def test_fuzzy_search():
g = Graph()
Expand Down
2 changes: 1 addition & 1 deletion raphtory-benchmark/benches/algobench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub fn graphgen_large_pagerank(c: &mut Criterion) {
&graph,
|b, graph| {
b.iter(|| {
let result = unweighted_page_rank(graph, 100, None, None, true);
let result = unweighted_page_rank(graph, Some(100), None, None, true, None);
black_box(result);
});
},
Expand Down
14 changes: 13 additions & 1 deletion raphtory-graphql/src/model/algorithms/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,19 @@ fn apply_pagerank<'b>(
let threads = ctx.args.get("threads").map(|v| v.u64()).transpose()?;
let threads = threads.map(|v| v as usize);
let tol = ctx.args.get("tol").map(|v| v.f64()).transpose()?;
let binding = unweighted_page_rank(&entry_point.graph, iter_count, threads, tol, true);
let damping_factor = ctx
.args
.get("damping_factor")
.map(|v| v.f64())
.transpose()?;
let binding = unweighted_page_rank(
&entry_point.graph,
Some(iter_count),
threads,
tol,
true,
damping_factor,
);
let result = binding
.get_all_with_names()
.into_iter()
Expand Down
4 changes: 4 additions & 0 deletions raphtory-graphql/src/model/graph/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,8 @@ impl Edge {
async fn is_deleted(&self) -> bool {
self.ee.is_deleted()
}

async fn is_self_loop(&self) -> bool {
self.ee.is_self_loop()
}
}
17 changes: 10 additions & 7 deletions raphtory/src/algorithms/centrality/pagerank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,27 @@ impl PageRankState {
/// * `threads`: Number of threads to use for parallel execution
/// * `tol`: The tolerance value for convergence
/// * `use_l2_norm`: Whether to use L2 norm for convergence
/// * `damping_factor`: Probability of likelihood the spread will continue
///
/// Result:
///
/// * An AlgorithmResult object containing the mapping from node ID to the PageRank score of the node
///
pub fn unweighted_page_rank<G: StaticGraphViewOps>(
g: &G,
iter_count: usize,
iter_count: Option<usize>,
threads: Option<usize>,
tol: Option<f64>,
use_l2_norm: bool,
damping_factor: Option<f64>,
) -> AlgorithmResult<G, f64, OrderedFloat<f64>> {
let n = g.count_nodes();

let mut ctx: Context<G, ComputeStateVec> = g.into();

let tol: f64 = tol.unwrap_or_else(|| 0.000001f64);
let damp = 0.85;
let damp = damping_factor.unwrap_or(0.85);
let iter_count = iter_count.unwrap_or(20);
let teleport_prob = (1f64 - damp) / n as f64;
let factor = damp / n as f64;

Expand Down Expand Up @@ -211,7 +214,7 @@ mod page_rank_tests {
fn test_page_rank() {
let graph = load_graph();

let results = unweighted_page_rank(&graph, 1000, Some(1), None, true);
let results = unweighted_page_rank(&graph, Some(1000), Some(1), None, true, None);

assert_eq_f64(results.get("1"), Some(&0.38694), 5);
assert_eq_f64(results.get("2"), Some(&0.20195), 5);
Expand Down Expand Up @@ -253,7 +256,7 @@ mod page_rank_tests {
graph.add_edge(t, src, dst, NO_PROPS, None).unwrap();
}

let results = unweighted_page_rank(&graph, 1000, Some(4), None, true);
let results = unweighted_page_rank(&graph, Some(1000), Some(4), None, true, None);

assert_eq_f64(results.get("10"), Some(&0.072082), 5);
assert_eq_f64(results.get("8"), Some(&0.136473), 5);
Expand All @@ -278,7 +281,7 @@ mod page_rank_tests {
graph.add_edge(t as i64, src, dst, NO_PROPS, None).unwrap();
}

let results = unweighted_page_rank(&graph, 1000, Some(4), None, false);
let results = unweighted_page_rank(&graph, Some(1000), Some(4), None, false, None);

assert_eq_f64(results.get("1"), Some(&0.5), 3);
assert_eq_f64(results.get("2"), Some(&0.5), 3);
Expand All @@ -294,7 +297,7 @@ mod page_rank_tests {
graph.add_edge(t as i64, src, dst, NO_PROPS, None).unwrap();
}

let results = unweighted_page_rank(&graph, 10, Some(4), None, false);
let results = unweighted_page_rank(&graph, Some(10), Some(4), None, false, None);

assert_eq_f64(results.get("1"), Some(&0.303), 3);
assert_eq_f64(results.get("2"), Some(&0.393), 3);
Expand Down Expand Up @@ -330,7 +333,7 @@ mod page_rank_tests {
graph.add_edge(t, src, dst, NO_PROPS, None).unwrap();
}

let results = unweighted_page_rank(&graph, 1000, Some(4), None, true);
let results = unweighted_page_rank(&graph, Some(1000), Some(4), None, true, None);

assert_eq_f64(results.get("1"), Some(&0.055), 3);
assert_eq_f64(results.get("2"), Some(&0.079), 3);
Expand Down
7 changes: 7 additions & 0 deletions raphtory/src/db/api/view/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@
/// Check that the latest status of the edge is deleted (i.e., not valid)
fn is_deleted(&self) -> Self::ValueType<bool>;

/// If the edge is a loop then returns true, else false
fn is_self_loop(&self) -> Self::ValueType<bool>;

/// Return a view of the properties of the edge
fn properties(&self) -> Self::ValueType<Properties<Self::PropType>>;
/// Returns the source node of the edge.
Expand Down Expand Up @@ -167,6 +170,10 @@
self.map(|g, e| !g.edge_is_valid(e, g.layer_ids().constrain_from_edge(e)))
}

fn is_self_loop(&self) -> Self::ValueType<bool> {
self.map(|g, e| e.src() == e.dst())

Check warning on line 174 in raphtory/src/db/api/view/edge.rs

View workflow job for this annotation

GitHub Actions / Run benchmarks / Rust Benchmark (ubuntu-latest)

unused variable: `g`

Check warning on line 174 in raphtory/src/db/api/view/edge.rs

View workflow job for this annotation

GitHub Actions / Run Python tests / Python Tests (3.8, ubuntu-latest)

unused variable: `g`

Check warning on line 174 in raphtory/src/db/api/view/edge.rs

View workflow job for this annotation

GitHub Actions / Run Python tests / Python Tests (3.8, macos-latest)

unused variable: `g`

Check warning on line 174 in raphtory/src/db/api/view/edge.rs

View workflow job for this annotation

GitHub Actions / Run Python tests / Python Tests (3.8, windows-latest)

unused variable: `g`
}

/// Return a view of the properties of the edge
fn properties(&self) -> Self::ValueType<Properties<Self::PropType>> {
self.as_props()
Expand Down
5 changes: 5 additions & 0 deletions raphtory/src/python/graph/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ impl PyEdge {
self.edge.is_deleted()
}

/// Check if the edge is on the same node
pub fn is_self_loop(&self) -> bool {
self.edge.is_self_loop()
}

/// Returns a view of the properties of the edge.
///
/// Returns:
Expand Down
12 changes: 12 additions & 0 deletions raphtory/src/python/graph/edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ impl PyEdges {
(move || edges.is_valid()).into()
}

/// Check if the edges are on the same node
fn is_self_loop(&self) -> BoolIterable {
let edges = self.edges.clone();
(move || edges.is_self_loop()).into()
}

/// Check if the edges are deleted
fn is_deleted(&self) -> BoolIterable {
let edges = self.edges.clone();
Expand Down Expand Up @@ -380,6 +386,12 @@ impl PyNestedEdges {
(move || edges.is_valid()).into()
}

/// Check if the edges are on the same node
fn is_self_loop(&self) -> NestedBoolIterable {
let edges = self.edges.clone();
(move || edges.is_self_loop()).into()
}

/// Check if edges are deleted
fn is_deleted(&self) -> NestedBoolIterable {
let edges = self.edges.clone();
Expand Down
13 changes: 11 additions & 2 deletions raphtory/src/python/packages/algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,22 @@ pub fn out_components(g: &PyGraphView) -> AlgorithmResult<DynamicGraph, Vec<u64>
/// Returns:
/// AlgorithmResult : AlgorithmResult with string keys and float values mapping node names to their pagerank value.
#[pyfunction]
#[pyo3(signature = (g, iter_count=20, max_diff=None))]
#[pyo3(signature = (g, iter_count=20, max_diff=None, use_l2_norm=true, damping_factor=0.85))]
pub fn pagerank(
g: &PyGraphView,
iter_count: usize,
max_diff: Option<f64>,
use_l2_norm: bool,
damping_factor: Option<f64>,
) -> AlgorithmResult<DynamicGraph, f64, OrderedFloat<f64>> {
unweighted_page_rank(&g.graph, iter_count, None, max_diff, true)
unweighted_page_rank(
&g.graph,
Some(iter_count),
None,
max_diff,
use_l2_norm,
damping_factor,
)
}

/// Temporally reachable nodes -- the nodes that are reachable by a time respecting path followed out from a set of seed nodes at a starting time.
Expand Down
Loading