#![feature(augmented_assignments)]
#![feature(op_assign_traits)]
use std::fmt::Debug;
use std::collections::BTreeMap;
use std::ops::AddAssign;
use std::ops::Neg;
pub trait NthEdge: Clone {
fn edge_index(&self, num_edges: usize, offset: usize) -> Option<usize>;
}
#[derive(Debug, Clone, Copy)]
pub struct NthEdgeI(pub u32);
#[derive(Debug, Clone, Copy)]
pub struct NthEdgeF(pub f32);
impl NthEdge for NthEdgeI {
fn edge_index(&self, num_edges: usize, offset: usize) -> Option<usize> {
if num_edges > 0 {
Some((self.0 as usize + offset) % num_edges)
} else {
None
}
}
}
impl NthEdge for NthEdgeF {
fn edge_index(&self, num_edges: usize, offset: usize) -> Option<usize> {
debug_assert!(self.0 >= 0.0 && self.0 < 1.0);
if num_edges > 0 {
let edge = (self.0 * num_edges as f32) as usize;
debug_assert!(edge < num_edges);
Some((edge + offset) % num_edges)
} else {
None
}
}
}
#[test]
fn test_nthedge() {
let n = NthEdgeI(3);
assert_eq!(Some(3), n.edge_index(4, 0));
assert_eq!(Some(0), n.edge_index(3, 0));
assert_eq!(None, n.edge_index(0, 0));
assert_eq!(Some(0), NthEdgeF(0.0).edge_index(10, 0));
assert_eq!(Some(0), NthEdgeF(0.09).edge_index(10, 0));
assert_eq!(Some(1), NthEdgeF(0.1).edge_index(10, 0));
assert_eq!(Some(2), NthEdgeF(0.2).edge_index(10, 0));
assert_eq!(Some(3), NthEdgeF(0.3).edge_index(10, 0));
assert_eq!(Some(9), NthEdgeF(0.9).edge_index(10, 0));
assert_eq!(Some(9), NthEdgeF(0.999).edge_index(10, 0));
assert_eq!(Some(9), NthEdgeF(0.999).edge_index(10, 10));
}
#[derive(Debug, Clone)]
pub enum EdgeOperation<W: Clone, N: Clone, NT: Clone> {
IncreaseWeight {
weight: W,
},
DecreaseWeight {
weight: W,
},
Duplicate {
weight: W,
},
Split {
weight: W,
},
Loop {
weight: W,
},
Output {
weight: W,
},
Merge {
n: NT,
},
Next {
n: NT,
},
Parent {
n: NT,
},
SetNodeFunction {
function: N,
},
Reverse,
Save,
Restore,
}
#[derive(Debug, Clone)]
struct Edge<W: Debug + Clone> {
src: usize,
dst: usize,
weight: W,
}
impl<W: Debug + Clone + Default> Edge<W> {
fn new(src: usize, dst: usize, weight: W) -> Edge<W> {
Edge {
src: src,
dst: dst,
weight: weight,
}
}
}
#[derive(Debug, Clone)]
struct Node<N: Clone + Default + Debug> {
in_edges: Vec<usize>,
out_edges: Vec<usize>,
node_fn: N,
}
impl<N: Default + Clone + Debug> Node<N> {
fn new() -> Node<N> {
Node {
in_edges: Vec::new(),
out_edges: Vec::new(),
node_fn: N::default(),
}
}
fn is_empty(&self) -> bool {
self.in_edges.is_empty() && self.out_edges.is_empty()
}
}
#[derive(Debug, Clone)]
struct State {
from_node: usize,
to_node: usize,
link_in_to_node: usize,
}
#[derive(Debug)]
pub struct GraphBuilder<W: Debug + Default + Clone, N: Debug + Default + Clone> {
edges: BTreeMap<usize, Edge<W>>,
nodes: Vec<Node<N>>,
next_edge_id: usize,
current_state: State,
states: Vec<State>,
}
impl<W: Debug + Default + Clone + AddAssign<W>, N: Debug + Default + Clone> GraphBuilder<W, N> {
pub fn new() -> GraphBuilder<W, N> {
GraphBuilder {
edges: BTreeMap::new(),
nodes: vec![Node::new()],
next_edge_id: 0,
current_state: State {
from_node: 0,
to_node: 0,
link_in_to_node: 0,
},
states: Vec::new(),
}
}
pub fn save(&mut self) {
let state = self.get_state();
self.states.push(state);
}
pub fn restore(&mut self) -> bool {
if let Some(state) = self.states.pop() {
self.set_state(state);
true
} else {
false
}
}
fn get_state(&self) -> State {
self.current_state.clone()
}
fn set_state(&mut self, state: State) {
self.current_state = state;
}
pub fn count_nodes(&self) -> usize {
let mut count = 0;
self.visit_nodes(|_, _| count += 1);
count
}
#[inline]
pub fn visit_nodes<F: FnMut(usize, &N)>(&self, mut callback: F) {
for (i, node) in self.nodes.iter().enumerate() {
if !node.is_empty() {
callback(i, &node.node_fn);
}
}
}
#[inline]
pub fn visit_edges<F: FnMut((usize, usize), &W)>(&self, mut callback: F) {
for (i, node) in self.nodes.iter().enumerate() {
if !node.is_empty() {
for out_edge in node.out_edges.iter() {
let edge = &self.edges[out_edge];
debug_assert!(edge.src == i);
callback((edge.src, edge.dst), &edge.weight);
}
}
}
}
pub fn to_edge_list(&self) -> Vec<Option<(N, Vec<(usize, W)>)>> {
self.nodes
.iter()
.map(|n| {
if n.is_empty() {
None
} else {
Some((n.node_fn.clone(),
n.out_edges
.iter()
.map(|oe| {
let edge = &self.edges[oe];
(edge.dst, edge.weight.clone())
})
.collect()))
}
})
.collect()
}
pub fn apply_operation<NT: NthEdge>(&mut self, op: EdgeOperation<W, N, NT>)
where W: Neg<Output = W>
{
match op {
EdgeOperation::IncreaseWeight {weight: w} => self.update_edge_weight(w),
EdgeOperation::DecreaseWeight {weight: w} => self.update_edge_weight(-w),
EdgeOperation::Duplicate {weight: w} => self.duplicate(w),
EdgeOperation::Split {weight: w} => self.split(w),
EdgeOperation::Loop {weight: w} => self.add_self_loop(w),
EdgeOperation::Output {weight: w} => self.output(w),
EdgeOperation::Merge {n} => self.merge(n),
EdgeOperation::Next {n} => self.next(n),
EdgeOperation::Parent {n} => self.parent(n),
EdgeOperation::SetNodeFunction {function: f} => self.set_node_function(f),
EdgeOperation::Reverse => self.reverse(),
EdgeOperation::Save => self.save(),
EdgeOperation::Restore => {
let _ = self.restore();
}
}
}
fn output(&mut self, weight: W) {
let from = self.current_state.from_node;
let output_node = self.new_node();
let edge_idx = self.create_new_edge_with_weight(from, output_node, weight);
self.insert_edge(edge_idx);
}
fn set_node_function(&mut self, node_fn: N) {
self.nodes[self.current_state.to_node].node_fn = node_fn;
}
fn get_current_edge(&self) -> Option<usize> {
let to_node = &self.nodes[self.current_state.to_node];
if let Some(&edge_idx) = to_node.in_edges.get(self.current_state.link_in_to_node) {
let edge = &self.edges[&edge_idx];
if edge.src == self.current_state.from_node && edge.dst == self.current_state.to_node {
Some(edge_idx)
} else {
None
}
} else {
None
}
}
pub fn update_edge_weight(&mut self, weight: W) {
let (from, to) = (self.current_state.from_node, self.current_state.to_node);
let cur_edge = self.get_current_edge();
if let Some(edge_idx) = cur_edge {
let e = self.get_mut_edge(edge_idx);
assert!(e.src == from);
assert!(e.dst == to);
e.weight += weight;
} else {
let edge_idx = self.create_new_edge_with_weight(from, to, weight);
self.current_state.link_in_to_node = self.nodes[to].in_edges.len();
self.insert_edge(edge_idx);
}
}
pub fn add_self_loop(&mut self, weight: W) {
let to = self.current_state.to_node;
let edge_idx = self.create_new_edge_with_weight(to, to, weight);
self.current_state.link_in_to_node = self.nodes[to].in_edges.len();
self.current_state.from_node = to;
self.insert_edge(edge_idx);
}
fn get_mut_edge(&mut self, edge_idx: usize) -> &mut Edge<W> {
self.edges.get_mut(&edge_idx).unwrap()
}
pub fn next<NT: NthEdge>(&mut self, n: NT) {
let to_node = &self.nodes[self.current_state.to_node];
if let Some(new_n) = n.edge_index(to_node.in_edges.len(),
self.current_state.link_in_to_node) {
let sibling_edge = to_node.in_edges[new_n];
let new_from = self.edges[&sibling_edge].src;
self.current_state.from_node = new_from;
self.current_state.link_in_to_node = new_n;
}
}
pub fn parent<NT: NthEdge>(&mut self, n: NT) {
let from = self.current_state.from_node;
let edge_idx = n.edge_index(self.nodes[from].in_edges.len(), 0);
if let Some(idx) = edge_idx {
let new_from = self.edges[&self.nodes[from].in_edges[idx]].src;
self.current_state.from_node = new_from;
self.current_state.link_in_to_node = idx;
} else {
return;
}
}
fn merge<NT: NthEdge>(&mut self, n: NT) {
let (from, to) = (self.current_state.from_node, self.current_state.to_node);
if let Some(edge_idx) = self.get_current_edge() {
let edge = self.edges.remove(&edge_idx).unwrap();
debug_assert!(edge.src == from);
debug_assert!(edge.dst == to);
self.nodes[from].out_edges.retain(|&i| i != edge_idx);
self.nodes[to].in_edges.retain(|&i| i != edge_idx);
}
if from == to {
return;
}
let mut new_out_edges = Vec::new();
for &out_edge in self.nodes[from].out_edges.iter() {
let edge = self.edges.get_mut(&out_edge).unwrap();
debug_assert!(edge.src == from);
edge.src = to;
new_out_edges.push(out_edge);
}
self.nodes[to].out_edges.extend(new_out_edges);
let mut new_in_edges = Vec::new();
for &in_edge in self.nodes[from].in_edges.iter() {
let edge = self.edges.get_mut(&in_edge).unwrap();
debug_assert!(edge.dst == from);
edge.dst = to;
new_in_edges.push(in_edge);
}
self.nodes[to].in_edges.extend(new_in_edges);
self.nodes[from].out_edges.clear();
self.nodes[from].in_edges.clear();
let edges = &self.nodes[to].in_edges;
if let Some(idx) = n.edge_index(edges.len(), 0) {
self.current_state.link_in_to_node = edges[idx];
self.current_state.from_node = self.edges[&self.current_state.link_in_to_node].src;
debug_assert!(self.edges[&self.current_state.link_in_to_node].dst == to);
} else {
self.current_state.link_in_to_node = 0;
self.current_state.from_node = to;
}
}
fn split(&mut self, weight: W) {
let (from, to) = (self.current_state.from_node, self.current_state.to_node);
let middle_node = self.new_node();
let cur_edge = self.get_current_edge();
if let Some(edge_idx) = cur_edge {
self.get_mut_edge(edge_idx).dst = middle_node;
self.nodes[to].in_edges.retain(|&i| i != edge_idx);
self.nodes[middle_node].in_edges.push(edge_idx);
} else {
let edge_idx = self.create_new_edge_with_weight(from, middle_node, W::default());
self.insert_edge(edge_idx);
}
let edge_idx = self.create_new_edge_with_weight(middle_node, to, weight);
self.current_state.link_in_to_node = self.insert_edge(edge_idx);
self.current_state.from_node = middle_node;
}
fn duplicate(&mut self, weight: W) {
let (from, to) = (self.current_state.from_node, self.current_state.to_node);
let edge_idx = self.create_new_edge_with_weight(from, to, weight);
self.current_state.link_in_to_node = self.insert_edge(edge_idx);
}
fn reverse(&mut self) {
let (from, to) = (self.current_state.from_node, self.current_state.to_node);
let cur_edge = self.get_current_edge();
let orig_weight = if let Some(edge_idx) = cur_edge {
let edge = self.edges.remove(&edge_idx).unwrap();
self.nodes[from].out_edges.retain(|&i| i != edge_idx);
self.nodes[to].in_edges.retain(|&i| i != edge_idx);
edge.weight
} else {
W::default()
};
let edge_idx = self.create_new_edge_with_weight(to, from, orig_weight);
let new_state = State {
link_in_to_node: self.insert_edge(edge_idx),
to_node: from,
from_node: to,
};
self.current_state = new_state;
}
fn insert_edge(&mut self, edge_idx: usize) -> usize {
let edge = self.edges.get(&edge_idx).unwrap().clone(); self.nodes[edge.src].out_edges.push(edge_idx);
let idx = self.nodes[edge.dst].in_edges.len();
self.nodes[edge.dst].in_edges.push(edge_idx);
idx
}
fn create_new_edge_with_weight(&mut self, from: usize, to: usize, weight: W) -> usize {
let edge_id = self.next_edge_id;
let edge = Edge::new(from, to, weight);
self.next_edge_id += 1;
self.edges.insert(edge_id, edge);
return edge_id;
}
fn new_node(&mut self) -> usize {
let node_id = self.nodes.len();
let node = Node::new();
self.nodes.push(node);
return node_id;
}
}
#[cfg(test)]
fn edge_list<W: Debug + Default + Clone + AddAssign<W>, N: Debug + Default + Clone>
(builder: &GraphBuilder<W, N>)
-> Vec<Vec<(usize, W)>> {
builder.to_edge_list()
.into_iter()
.map(|n| {
match n {
Some((_, b)) => b,
None => vec![],
}
})
.collect()
}
#[test]
fn test_empty() {
let builder: GraphBuilder<f32, usize> = GraphBuilder::new();
let v: Vec<Vec<(usize, f32)>> = vec![vec![]];
assert_eq!(v, edge_list(&builder));
}
#[test]
fn test_split() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.split(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
builder.split(2.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(0, 2.0)]],
edge_list(&builder));
builder.split(3.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0)]],
edge_list(&builder));
}
#[test]
fn test_duplicate() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.duplicate(1.0);
assert_eq!(vec![vec![(0, 0.0), (0, 1.0)]], edge_list(&builder));
builder.split(0.25);
assert_eq!(vec![vec![(0, 0.0), (1, 1.0)], vec![(0, 0.25)]],
edge_list(&builder));
builder.duplicate(2.0);
assert_eq!(vec![vec![(0, 0.0), (1, 1.0)], vec![(0, 0.25), (0, 2.0)]],
edge_list(&builder));
}
#[test]
fn test_reverse() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.split(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
builder.reverse();
assert_eq!(vec![vec![(1, 0.0), (1, 1.0)], vec![]], edge_list(&builder));
}
#[test]
fn test_update_edge_weight() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.update_edge_weight(4.0);
assert_eq!(vec![vec![(0, 4.0)]], edge_list(&builder));
builder.update_edge_weight(-4.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
}
#[test]
fn test_add_self_loop() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.add_self_loop(1.0);
assert_eq!(vec![vec![(0, 0.0), (0, 1.0)]], edge_list(&builder));
}
#[test]
fn test_next() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.split(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
builder.split(2.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(0, 2.0)]],
edge_list(&builder));
builder.split(3.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0)]],
edge_list(&builder));
builder.next(NthEdgeI(1));
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0)]],
edge_list(&builder));
builder.duplicate(5.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0), (0, 5.0)]],
edge_list(&builder));
builder.update_edge_weight(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0), (0, 6.0)]],
edge_list(&builder));
builder.next(NthEdgeI(0));
builder.update_edge_weight(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0), (0, 7.0)]],
edge_list(&builder));
builder.next(NthEdgeI(1));
builder.update_edge_weight(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 4.0), (0, 7.0)]],
edge_list(&builder));
builder.next(NthEdgeI(2));
builder.update_edge_weight(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 5.0), (0, 7.0)]],
edge_list(&builder));
}
#[test]
fn test_parent() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.parent(NthEdgeI(0));
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.parent(NthEdgeI(3));
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.split(1.0);
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
builder.parent(NthEdgeI(0));
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
}
#[test]
fn test_merge_self_loop() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.merge(NthEdgeI(1));
let v: Vec<Vec<(usize, f32)>> = vec![vec![]];
assert_eq!(v, edge_list(&builder));
let mut nodes = vec![];
builder.visit_nodes(|i, _| nodes.push(i));
assert!(nodes.is_empty());
assert_eq!(0, builder.count_nodes());
let mut edges = vec![];
builder.visit_edges(|(i, j), _w| edges.push((i, j)));
let res: Vec<(usize, usize)> = vec![];
assert_eq!(res, edges);
}
#[test]
fn test_merge_self_loop2() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.add_self_loop(1.0);
assert_eq!(vec![vec![(0, 0.0), (0, 1.0)]], edge_list(&builder));
builder.merge(NthEdgeI(1));
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
}
#[test]
fn test_graph_paper() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.25);
assert_eq!(vec![vec![(0, 0.25)]], edge_list(&builder));
builder.split(0.8);
assert_eq!(vec![vec![(1, 0.25)], vec![(0, 0.8)]], edge_list(&builder));
builder.duplicate(3.0);
assert_eq!(vec![vec![(1, 0.25)], vec![(0, 0.8), (0, 3.0)]],
edge_list(&builder));
builder.reverse();
assert_eq!(vec![vec![(1, 0.25), (1, 3.0)], vec![(0, 0.8)]],
edge_list(&builder));
builder.split(0.8);
builder.duplicate(2.0);
builder.reverse();
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)], vec![(0, 0.8), (2, 2.0)], vec![(1, 0.8)]],
edge_list(&builder));
builder.add_self_loop(1.0);
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)], vec![(0, 0.8), (2, 2.0)], vec![(1, 0.8), (2, 1.0)]],
edge_list(&builder));
builder.split(0.6);
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
vec![(0, 0.8), (2, 2.0)],
vec![(1, 0.8), (3, 1.0)],
vec![(2, 0.6)]],
edge_list(&builder));
builder.duplicate(0.4);
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
vec![(0, 0.8), (2, 2.0)],
vec![(1, 0.8), (3, 1.0)],
vec![(2, 0.6), (2, 0.4)]],
edge_list(&builder));
builder.split(0.6);
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
vec![(0, 0.8), (2, 2.0)],
vec![(1, 0.8), (3, 1.0)],
vec![(2, 0.6), (4, 0.4)],
vec![(2, 0.6)]],
edge_list(&builder));
builder.duplicate(0.4);
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
vec![(0, 0.8), (2, 2.0)],
vec![(1, 0.8), (3, 1.0)],
vec![(2, 0.6), (4, 0.4)],
vec![(2, 0.6), (2, 0.4)]],
edge_list(&builder));
builder.reverse();
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
vec![(0, 0.8), (2, 2.0)],
vec![(1, 0.8), (3, 1.0), (4, 0.4)],
vec![(2, 0.6), (4, 0.4)],
vec![(2, 0.6)]],
edge_list(&builder));
assert_eq!(4, builder.get_state().to_node);
assert_eq!(2, builder.get_state().from_node);
assert_eq!(1, builder.get_state().link_in_to_node);
builder.parent(NthEdgeI(1));
assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
vec![(0, 0.8), (2, 2.0)],
vec![(1, 0.8), (3, 1.0), (4, 0.4)],
vec![(2, 0.6), (4, 0.4)],
vec![(2, 0.6)]],
edge_list(&builder));
assert_eq!(4, builder.get_state().to_node);
assert_eq!(1, builder.get_state().from_node);
assert_eq!(1, builder.get_state().link_in_to_node);
builder.merge(NthEdgeI(1));
assert_eq!(vec![vec![(4, 0.25), (2, 3.0)],
vec![],
vec![(4, 0.8), (3, 1.0), (4, 0.4)],
vec![(2, 0.6), (4, 0.4)],
vec![(2, 0.6), (0, 0.8), (2, 2.0)]],
edge_list(&builder));
}
#[test]
fn test_save_restore() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.save();
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.split(0.5);
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
assert_eq!(true, builder.restore());
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
builder.update_edge_weight(0.7);
assert_eq!(vec![vec![(1, 0.0), (0, 0.7)], vec![(0, 0.5)]],
edge_list(&builder));
builder.split(0.6);
assert_eq!(vec![vec![(1, 0.0), (2, 0.7)], vec![(0, 0.5)], vec![(0, 0.6)]],
edge_list(&builder));
}
#[test]
fn test_save_restore2() {
let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
builder.update_edge_weight(0.0);
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.save();
assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
builder.split(0.5);
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
assert_eq!(true, builder.restore());
assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
builder.split(0.6);
assert_eq!(vec![vec![(1, 0.0), (2, 0.0)], vec![(0, 0.5)], vec![(0, 0.6)]],
edge_list(&builder));
}