webgraph_algo/sccs/
symm_par.rs1use crate::prelude::*;
9use crossbeam_utils::CachePadded;
10use dsi_progress_logger::ConcurrentProgressLog;
11use no_break::NoBreak;
12use std::{
13 mem::MaybeUninit,
14 ops::ControlFlow::Continue,
15 sync::atomic::{AtomicUsize, Ordering},
16};
17use sync_cell_slice::SyncSlice;
18use webgraph::traits::RandomAccessGraph;
19use webgraph::visits::{
20 Parallel,
21 breadth_first::{EventNoPred, ParFairNoPred},
22};
23
24pub fn symm_par(graph: impl RandomAccessGraph + Sync, pl: &mut impl ConcurrentProgressLog) -> Sccs {
26 let num_nodes = graph.num_nodes();
29 pl.item_name("node");
30 pl.expected_updates(Some(num_nodes));
31 pl.start("Computing strongly connected components...");
32
33 let mut visit = ParFairNoPred::new(&graph);
34 let mut component = Box::new_uninit_slice(num_nodes);
35
36 let number_of_components = CachePadded::new(AtomicUsize::new(0));
37 let slice = component.as_sync_slice();
38
39 for node in 0..num_nodes {
40 visit
41 .par_visit_with([node], pl.clone(), |pl, event| {
42 match event {
43 EventNoPred::Init { .. } => {}
44 EventNoPred::Visit { node, .. } => {
45 pl.light_update();
46 unsafe {
47 slice[node].set(MaybeUninit::new(
48 number_of_components.load(Ordering::Relaxed),
49 ))
50 };
51 }
52 EventNoPred::Done { .. } => {
53 number_of_components.fetch_add(1, Ordering::Relaxed);
54 }
55 _ => (),
56 }
57 Continue(())
58 })
59 .continue_value_no_break();
60 }
61
62 let component = unsafe { component.assume_init() };
63
64 pl.done();
65
66 Sccs::new(number_of_components.load(Ordering::Relaxed), component)
67}