webgraph_cli/dist/ess/
mod.rs1use crate::{GlobalArgs, NumThreadsArg};
8use anyhow::{Result, ensure};
9use clap::{Parser, ValueEnum};
10use dsi_bitstream::prelude::*;
11use dsi_progress_logger::{ProgressLog, concurrent_progress_logger};
12use std::path::PathBuf;
13use webgraph::{graphs::bvgraph::get_endianness, prelude::BvGraph};
14use webgraph_algo::distances::exact_sum_sweep::{
15 All, AllForward, Diameter, Level, Radius, RadiusDiameter,
16};
17
18#[derive(Parser, Debug)]
19#[command(name = "exactsumsweep", about = "Compute radius, diameter, and possibly eccentricities using the ExactSumSweep algorithm. (WORK IN PROGRESS)", long_about = None)]
20pub struct CliArgs {
21 pub basename: PathBuf,
23
24 pub transposed: Option<PathBuf>,
26
27 #[arg(short, long = "symm")]
28 pub symmetric: bool,
30
31 #[arg(short, long)]
33 pub forward: Option<PathBuf>,
34
35 #[arg(short, long)]
37 pub backward: Option<PathBuf>,
38
39 #[arg(long, value_enum)]
40 pub level: LevelArg,
41
42 #[clap(flatten)]
43 pub num_threads: NumThreadsArg,
44}
45
46#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
47pub enum LevelArg {
49 Radius,
50 Diameter,
51 #[clap(name = "radius-diameter")]
52 RadiusDiameter,
53 #[clap(name = "all-forward")]
54 AllForward,
55 All,
56}
57
58pub fn main(global_args: GlobalArgs, args: CliArgs) -> Result<()> {
59 println!("{:#4?}", args);
60 ensure!(
61 args.symmetric || args.transposed.is_some(),
62 "You have to either pass --transposed with with the basename of the transposed graph or --symm if the graph is symmetric."
63 );
64 ensure!(
65 !(args.symmetric && args.transposed.is_some()),
66 "--transposed is needed only if the graph is not symmetric."
67 );
68 ensure!(
69 args.forward.is_none() || matches!(args.level, LevelArg::All | LevelArg::AllForward),
70 "You cannot only pass --forward with --level=all or --level=all-forward as the forward eccentricities won't be computed otherwise."
71 );
72 ensure!(
73 !(args.forward.is_none() && matches!(args.level, LevelArg::All | LevelArg::AllForward)),
74 "If --level=all or --level=all-forward, you should pass --forward to store the computed eccentricities."
75 );
76 ensure!(
77 !(args.backward.is_some() && args.level != LevelArg::All),
78 "You cannot only pass --backward with --level=all as the backward eccentricities won't be computed otherwise."
79 );
80 ensure!(
81 !(args.level == LevelArg::All && args.symmetric && args.backward.is_some()),
82 "You cannot pass --backward with --symm and --level=all as the eccentricities of a symmetric graph are the same in both directions."
83 );
84
85 match get_endianness(&args.basename)?.as_str() {
86 #[cfg(feature = "be_bins")]
87 BE::NAME => exact_sum_sweep::<BE>(global_args, args),
88 #[cfg(feature = "le_bins")]
89 LE::NAME => exact_sum_sweep::<LE>(global_args, args),
90 e => panic!("Unknown endianness: {}", e),
91 }
92}
93
94pub fn exact_sum_sweep<E: Endianness>(global_args: GlobalArgs, args: CliArgs) -> Result<()> {
95 match args.level {
96 LevelArg::Radius => {
97 exact_sum_sweep_level::<E, Radius>(global_args, args)?;
98 }
99 LevelArg::Diameter => {
100 exact_sum_sweep_level::<E, Diameter>(global_args, args)?;
101 }
102 LevelArg::RadiusDiameter => {
103 exact_sum_sweep_level::<E, RadiusDiameter>(global_args, args)?;
104 }
105 LevelArg::AllForward => {
106 exact_sum_sweep_level::<E, AllForward>(global_args, args)?;
107 }
108 LevelArg::All => {
109 exact_sum_sweep_level::<E, All>(global_args, args)?;
110 }
111 }
112 Ok(())
113}
114
115pub fn exact_sum_sweep_level<E: Endianness, L: Level>(
116 global_args: GlobalArgs,
117 args: CliArgs,
118) -> Result<()> {
119 let graph = BvGraph::with_basename(&args.basename).load()?;
120
121 let thread_pool = crate::get_thread_pool(args.num_threads.num_threads);
122 let mut pl = concurrent_progress_logger![];
123 if let Some(log_interval) = global_args.log_interval {
124 pl.log_interval(log_interval);
125 }
126
127 if args.symmetric {
128 let _out = thread_pool.install(|| L::run_symm(graph, &mut pl));
129 } else {
130 let transpose_path = args
131 .transposed
132 .as_ref()
133 .expect("You have to pass the transposed graph if the graph is not symmetric.");
134 let transpose = BvGraph::with_basename(transpose_path).load()?;
135 let _out = thread_pool.install(|| L::run(graph, transpose, None, &mut pl));
136 }
137
138 todo!("print out and serialize the eccentricities if present");
139}