pub struct VamanaNode {
pub id: u64,
pub neighbors: Vec<u32>,
}
pub struct VamanaGraph {
pub dim: usize,
pub r: usize,
pub alpha: f32,
pub entry: usize,
nodes: Vec<VamanaNode>,
}
impl VamanaGraph {
pub fn new(dim: usize, r: usize, alpha: f32) -> Self {
Self {
dim,
r,
alpha,
entry: 0,
nodes: Vec::new(),
}
}
pub fn len(&self) -> usize {
self.nodes.len()
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
pub fn add_node(&mut self, id: u64) -> usize {
let idx = self.nodes.len();
self.nodes.push(VamanaNode {
id,
neighbors: Vec::new(),
});
idx
}
pub fn set_neighbors(&mut self, idx: usize, mut neighbors: Vec<u32>) {
neighbors.truncate(self.r);
self.nodes[idx].neighbors = neighbors;
}
pub fn neighbors(&self, idx: usize) -> &[u32] {
&self.nodes[idx].neighbors
}
pub fn external_id(&self, idx: usize) -> u64 {
self.nodes[idx].id
}
pub fn iter(&self) -> impl Iterator<Item = (usize, &VamanaNode)> {
self.nodes.iter().enumerate()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_nodes_len_matches() {
let mut g = VamanaGraph::new(8, 4, 1.2);
assert_eq!(g.len(), 0);
assert!(g.is_empty());
let i0 = g.add_node(100);
let i1 = g.add_node(200);
let i2 = g.add_node(300);
assert_eq!(g.len(), 3);
assert!(!g.is_empty());
assert_eq!(i0, 0);
assert_eq!(i1, 1);
assert_eq!(i2, 2);
}
#[test]
fn set_and_get_neighbors() {
let mut g = VamanaGraph::new(8, 4, 1.2);
g.add_node(10);
g.add_node(20);
g.add_node(30);
g.set_neighbors(0, vec![1, 2]);
assert_eq!(g.neighbors(0), &[1, 2]);
assert_eq!(g.neighbors(1), &[] as &[u32]);
}
#[test]
fn set_neighbors_respects_degree_bound() {
let r = 3;
let mut g = VamanaGraph::new(4, r, 1.2);
for id in 0..10 {
g.add_node(id);
}
g.set_neighbors(0, vec![1, 2, 3, 4, 5]);
assert_eq!(g.neighbors(0).len(), r);
}
#[test]
fn external_id_roundtrip() {
let mut g = VamanaGraph::new(4, 8, 1.2);
g.add_node(9999);
assert_eq!(g.external_id(0), 9999);
}
}