webgraph_cli/dist/ess/
mod.rs1use crate::{GlobalArgs, NumThreadsArg};
8use anyhow::{ensure, Result};
9use clap::{Parser, ValueEnum};
10use dsi_bitstream::prelude::*;
11use dsi_progress_logger::{concurrent_progress_logger, ProgressLog};
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!(args.symmetric || args.transposed.is_some(), "You have to either pass --transposed with with the basename of the transposed graph or --symm if the graph is symmetric.");
61 ensure!(
62 !(args.symmetric && args.transposed.is_some()),
63 "--transposed is needed only if the graph is not symmetric."
64 );
65 ensure!(args.forward.is_none() || matches!(args.level, LevelArg::All | LevelArg::AllForward), "You cannot only pass --forward with --level=all or --level=all-forward as the forward eccentricities won't be computed otherwise.");
66 ensure!(!(args.forward.is_none() && matches!(args.level, LevelArg::All | LevelArg::AllForward)), "If --level=all or --level=all-forward, you should pass --forward to store the computed eccentricities.");
67 ensure!(!(args.backward.is_some() && args.level != LevelArg::All), "You cannot only pass --backward with --level=all as the backward eccentricities won't be computed otherwise.");
68 ensure!(!(args.level == LevelArg::All && args.symmetric && args.backward.is_some()), "You cannot pass --backward with --symm and --level=all as the eccentricities of a symmetric graph are the same in both directions.");
69
70 match get_endianness(&args.basename)?.as_str() {
71 #[cfg(feature = "be_bins")]
72 BE::NAME => exact_sum_sweep::<BE>(global_args, args),
73 #[cfg(feature = "le_bins")]
74 LE::NAME => exact_sum_sweep::<LE>(global_args, args),
75 e => panic!("Unknown endianness: {}", e),
76 }
77}
78
79pub fn exact_sum_sweep<E: Endianness>(global_args: GlobalArgs, args: CliArgs) -> Result<()> {
80 match args.level {
81 LevelArg::Radius => {
82 exact_sum_sweep_level::<E, Radius>(global_args, args)?;
83 }
84 LevelArg::Diameter => {
85 exact_sum_sweep_level::<E, Diameter>(global_args, args)?;
86 }
87 LevelArg::RadiusDiameter => {
88 exact_sum_sweep_level::<E, RadiusDiameter>(global_args, args)?;
89 }
90 LevelArg::AllForward => {
91 exact_sum_sweep_level::<E, AllForward>(global_args, args)?;
92 }
93 LevelArg::All => {
94 exact_sum_sweep_level::<E, All>(global_args, args)?;
95 }
96 }
97 Ok(())
98}
99
100pub fn exact_sum_sweep_level<E: Endianness, L: Level>(
101 global_args: GlobalArgs,
102 args: CliArgs,
103) -> Result<()> {
104 let graph = BvGraph::with_basename(&args.basename).load()?;
105
106 let thread_pool = crate::get_thread_pool(args.num_threads.num_threads);
107 let mut pl = concurrent_progress_logger![];
108 if let Some(log_interval) = global_args.log_interval {
109 pl.log_interval(log_interval);
110 }
111
112 if args.symmetric {
113 let _out = L::run_symm(graph, &thread_pool, &mut pl);
114 } else {
115 let transpose_path = args
116 .transposed
117 .as_ref()
118 .expect("You have to pass the transposed graph if the graph is not symmetric.");
119 let transpose = BvGraph::with_basename(transpose_path).load()?;
120 let _out = L::run(graph, transpose, None, &thread_pool, &mut pl);
121 }
122
123 todo!("print out and serialize the eccentricities if present");
124}