use std::collections::HashMap;
pub type NodeId = u64;
pub struct GraphView {
pub node_count: usize,
pub index_to_node: Vec<NodeId>,
pub node_to_index: HashMap<NodeId, usize>,
pub out_offsets: Vec<usize>,
pub out_targets: Vec<usize>,
pub in_offsets: Vec<usize>,
pub in_sources: Vec<usize>,
pub weights: Option<Vec<f64>>,
}
impl GraphView {
pub fn out_degree(&self, idx: usize) -> usize {
self.out_offsets[idx + 1] - self.out_offsets[idx]
}
pub fn in_degree(&self, idx: usize) -> usize {
self.in_offsets[idx + 1] - self.in_offsets[idx]
}
pub fn successors(&self, idx: usize) -> &[usize] {
let start = self.out_offsets[idx];
let end = self.out_offsets[idx + 1];
&self.out_targets[start..end]
}
pub fn predecessors(&self, idx: usize) -> &[usize] {
let start = self.in_offsets[idx];
let end = self.in_offsets[idx + 1];
&self.in_sources[start..end]
}
pub fn weights(&self, idx: usize) -> Option<&[f64]> {
self.weights.as_ref().map(|w| {
let start = self.out_offsets[idx];
let end = self.out_offsets[idx + 1];
&w[start..end]
})
}
pub fn from_adjacency_list(
node_count: usize,
index_to_node: Vec<NodeId>,
node_to_index: HashMap<NodeId, usize>,
outgoing: Vec<Vec<usize>>,
incoming: Vec<Vec<usize>>,
weights: Option<Vec<Vec<f64>>>,
) -> Self {
let mut out_offsets = Vec::with_capacity(node_count + 1);
let mut out_targets = Vec::new();
let mut in_offsets = Vec::with_capacity(node_count + 1);
let mut in_sources = Vec::new();
let mut flat_weights = if weights.is_some() { Some(Vec::new()) } else { None };
out_offsets.push(0);
for (i, neighbors) in outgoing.into_iter().enumerate() {
out_targets.extend(neighbors);
out_offsets.push(out_targets.len());
if let Some(ref mut w_flat) = flat_weights {
if let Some(w_row) = weights.as_ref().map(|w| &w[i]) {
w_flat.extend(w_row.iter());
}
}
}
in_offsets.push(0);
for sources in incoming {
in_sources.extend(sources);
in_offsets.push(in_sources.len());
}
GraphView {
node_count,
index_to_node,
node_to_index,
out_offsets,
out_targets,
in_offsets,
in_sources,
weights: flat_weights,
}
}
}