• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vigna / webgraph-rs / 25054814280

28 Apr 2026 01:11PM UTC coverage: 69.158% (-0.04%) from 69.201%
25054814280

push

github

vigna
Further cleanup of method names; sorted symmetrization now uses IntoParLenders, too

24 of 59 new or added lines in 12 files covered. (40.68%)

761 existing lines in 28 files now uncovered.

7505 of 10852 relevant lines covered (69.16%)

50040578.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/cli/src/transform/transpose.rs
1
/*
2
 * SPDX-FileCopyrightText: 2023 Inria
3
 * SPDX-FileCopyrightText: 2023 Tommaso Fontana
4
 * SPDX-FileCopyrightText: 2026 Sebastiano Vigna
5
 *
6
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7
 */
8

9
use crate::*;
10
use anyhow::Result;
11
use dsi_bitstream::{dispatch::factory::CodesReaderFactoryHelper, prelude::*};
12
use dsi_progress_logger::prelude::*;
13
use std::path::PathBuf;
14
use tempfile::Builder;
15
use webgraph::prelude::*;
16

17
#[derive(Parser, Debug)]
18
#[command(name = "transpose", about = "Transposes a graph in the BV format.", long_about = None, next_line_help = true)]
19
pub struct CliArgs {
20
    /// The basename of the graph.​
21
    pub src: PathBuf,
22
    /// The basename of the transposed graph.​
23
    pub dst: PathBuf,
24

25
    #[arg(short, long)]
26
    /// Uses the sequential algorithm (does not need offsets).​
27
    pub sequential: bool,
28

29
    #[clap(flatten)]
30
    pub num_threads: NumThreadsArg,
31

32
    #[clap(flatten)]
33
    pub memory_usage: MemoryUsageArg,
34

35
    #[arg(long, conflicts_with = "sequential")]
36
    /// Uses the degree cumulative function to balance work by arcs rather than
37
    /// by nodes; the DCF must have been pre-built with `webgraph build dcf`.​
38
    pub dcf: bool,
39

40
    #[clap(flatten)]
41
    pub ca: CompressArgs,
42

43
    #[clap(flatten)]
44
    pub log_interval: LogIntervalArg,
45
}
46

UNCOV
47
pub fn main(args: CliArgs) -> Result<()> {
×
48
    create_parent_dir(&args.dst)?;
×
49

50
    match get_endianness(&args.src)?.as_str() {
×
51
        #[cfg(feature = "be_bins")]
52
        BE::NAME => {
×
UNCOV
53
            if args.sequential {
×
NEW
54
                transpose_seq::<BE>(args)
×
55
            } else {
NEW
56
                transpose_par::<BE>(args)
×
57
            }
58
        }
59
        #[cfg(feature = "le_bins")]
60
        LE::NAME => {
×
UNCOV
61
            if args.sequential {
×
NEW
62
                transpose_seq::<LE>(args)
×
63
            } else {
NEW
64
                transpose_par::<LE>(args)
×
65
            }
66
        }
67
        e => panic!("Unknown endianness: {}", e),
×
68
    }
69
}
70

71
/// Sequential version of [`transpose_par`].
NEW
72
pub fn transpose_seq<E: Endianness>(args: CliArgs) -> Result<()>
×
73
where
74
    MmapHelper<u32>: CodesReaderFactoryHelper<E>,
75
{
UNCOV
76
    let thread_pool = crate::get_thread_pool(args.num_threads.num_threads);
×
77

78
    // TODO!: speed it up by using random access graph if possible
UNCOV
79
    let seq_graph = webgraph::graphs::bvgraph::sequential::BvGraphSeq::with_basename(&args.src)
×
80
        .endianness::<E>()
81
        .load()?;
82

83
    // transpose the graph
84
    let mut pl = progress_logger![
×
85
        display_memory = true,
×
86
        log_interval = args.log_interval.log_interval
×
87
    ];
88
    let sorted =
×
UNCOV
89
        webgraph::transform::transpose(&seq_graph, args.memory_usage.memory_usage, &mut pl)?;
×
90

91
    let target_endianness = args.ca.endianness.clone().unwrap_or_else(|| E::NAME.into());
×
UNCOV
92
    let dir = Builder::new().prefix("transform_transpose_").tempdir()?;
×
UNCOV
93
    let chunk_size = args.ca.chunk_size;
×
UNCOV
94
    let bvgraphz = args.ca.bvgraphz;
×
UNCOV
95
    let mut builder = BvCompConf::new(&args.dst)
×
96
        .comp_flags(args.ca.into())
×
UNCOV
97
        .tmp_dir(&dir);
×
98

UNCOV
99
    if bvgraphz {
×
UNCOV
100
        builder = builder.chunk_size(chunk_size);
×
101
    }
102

103
    // Use uniform cutpoints for compression of the transposed graph
104
    // (the source DCF does not match the transpose's degree distribution)
UNCOV
105
    let mut builder = builder.progress_logger(&mut pl);
×
106
    thread_pool.install(|| par_comp!(builder, sorted, target_endianness))?;
×
107

108
    Ok(())
×
109
}
110

111
/// Parallel version of [`transpose_seq`].
NEW
112
pub fn transpose_par<E: Endianness>(args: CliArgs) -> Result<()>
×
113
where
114
    MmapHelper<u32>: CodesReaderFactoryHelper<E>,
115
    for<'a> LoadModeCodesReader<'a, E, Mmap>: BitSeek + Clone + Send + Sync,
116
{
UNCOV
117
    let thread_pool = crate::get_thread_pool(args.num_threads.num_threads);
×
118

119
    let graph = webgraph::graphs::bvgraph::BvGraph::with_basename(&args.src)
×
120
        .endianness::<E>()
121
        .load()?;
122

123
    let num_nodes = graph.num_nodes();
×
124
    let num_arcs_hint = graph.num_arcs_hint();
×
125
    let cp = crate::cutpoints(&args.src, num_nodes, num_arcs_hint, args.dcf)?;
×
126

127
    // transpose the graph
UNCOV
128
    let par_graph = webgraph::graphs::par_graphs::ParGraph::with_cutpoints(graph, cp);
×
129
    let mut pl = progress_logger![
×
130
        display_memory = true,
×
UNCOV
131
        log_interval = args.log_interval.log_interval
×
132
    ];
133
    let sorted =
×
NEW
134
        webgraph::transform::transpose_par(&par_graph, args.memory_usage.memory_usage, &mut pl)?;
×
135

UNCOV
136
    let target_endianness = args.ca.endianness.clone().unwrap_or_else(|| E::NAME.into());
×
UNCOV
137
    let dir = Builder::new().prefix("transform_transpose_").tempdir()?;
×
UNCOV
138
    let chunk_size = args.ca.chunk_size;
×
UNCOV
139
    let bvgraphz = args.ca.bvgraphz;
×
UNCOV
140
    let mut builder = BvCompConf::new(&args.dst)
×
UNCOV
141
        .comp_flags(args.ca.into())
×
UNCOV
142
        .tmp_dir(&dir);
×
143

UNCOV
144
    if bvgraphz {
×
UNCOV
145
        builder = builder.chunk_size(chunk_size);
×
146
    }
147

UNCOV
148
    let mut builder = builder.progress_logger(&mut pl);
×
UNCOV
149
    thread_pool.install(|| par_comp!(builder, sorted, target_endianness))?;
×
UNCOV
150
    Ok(())
×
151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc