use rayon::prelude::*;
use std::collections::HashMap;
use crate::core::types::{BaseGraph, GraphConstructor, NodeId};
use petgraph::EdgeType;
pub fn degrees_parallel<A, W, Ty>(graph: &BaseGraph<A, W, Ty>) -> HashMap<NodeId, usize>
where
A: Sync,
W: Sync,
Ty: GraphConstructor<A, W> + EdgeType + Sync,
{
let nodes: Vec<NodeId> = graph.node_ids().collect();
nodes
.par_iter()
.map(|&node| {
let degree = graph.degree(node).unwrap_or(0);
(node, degree)
})
.collect()
}
#[cfg(test)]
mod tests {
#[test]
fn test_parallel_vs_sequential_consistency() {
use crate::core::types::Graph;
use crate::parallel::degrees_parallel;
let mut g = Graph::<i32, f64>::new();
let nodes: Vec<_> = (0..100).map(|i| g.add_node(i)).collect();
for i in 0..100 {
for j in (i + 1)..100 {
if (i * j) % 7 == 0 {
g.add_edge(nodes[i], nodes[j], 1.0);
}
}
}
let parallel_degrees = degrees_parallel(&g);
let sequential_degrees: std::collections::HashMap<_, _> = g
.nodes()
.map(|(id, _)| (id, g.degree(id).unwrap()))
.collect();
for (node, deg) in &sequential_degrees {
assert_eq!(parallel_degrees.get(node), Some(deg));
}
}
use super::*;
use crate::core::types::Graph;
#[test]
fn test_degrees_parallel() {
let mut g = Graph::<i32, f64>::new();
let n1 = g.add_node(1);
let n2 = g.add_node(2);
let n3 = g.add_node(3);
g.add_edge(n1, n2, 1.0);
g.add_edge(n2, n3, 1.0);
let degrees = degrees_parallel(&g);
assert_eq!(degrees[&n1], 1);
assert_eq!(degrees[&n2], 2);
assert_eq!(degrees[&n3], 1);
}
}