graph_edge_evolution/
lib.rs

1#![feature(augmented_assignments)]
2#![feature(op_assign_traits)]
3
4use std::fmt::Debug;
5use std::collections::BTreeMap;
6use std::ops::AddAssign;
7use std::ops::Neg;
8
9pub trait NthEdge: Clone {
10    fn edge_index(&self, num_edges: usize, offset: usize) -> Option<usize>;
11}
12
13#[derive(Debug, Clone, Copy)]
14pub struct NthEdgeI(pub u32);
15#[derive(Debug, Clone, Copy)]
16pub struct NthEdgeF(pub f32);
17
18impl NthEdge for NthEdgeI {
19    fn edge_index(&self, num_edges: usize, offset: usize) -> Option<usize> {
20        if num_edges > 0 {
21            Some((self.0 as usize + offset) % num_edges)
22        } else {
23            None
24        }
25    }
26}
27
28impl NthEdge for NthEdgeF {
29    fn edge_index(&self, num_edges: usize, offset: usize) -> Option<usize> {
30        debug_assert!(self.0 >= 0.0 && self.0 < 1.0);
31        if num_edges > 0 {
32            let edge = (self.0 * num_edges as f32) as usize;
33            debug_assert!(edge < num_edges);
34            Some((edge + offset) % num_edges)
35        } else {
36            None
37        }
38    }
39}
40
41#[test]
42fn test_nthedge() {
43    let n = NthEdgeI(3);
44    assert_eq!(Some(3), n.edge_index(4, 0));
45    assert_eq!(Some(0), n.edge_index(3, 0));
46    assert_eq!(None, n.edge_index(0, 0));
47
48    assert_eq!(Some(0), NthEdgeF(0.0).edge_index(10, 0));
49    assert_eq!(Some(0), NthEdgeF(0.09).edge_index(10, 0));
50    assert_eq!(Some(1), NthEdgeF(0.1).edge_index(10, 0));
51    assert_eq!(Some(2), NthEdgeF(0.2).edge_index(10, 0));
52    assert_eq!(Some(3), NthEdgeF(0.3).edge_index(10, 0));
53    assert_eq!(Some(9), NthEdgeF(0.9).edge_index(10, 0));
54    assert_eq!(Some(9), NthEdgeF(0.999).edge_index(10, 0));
55    assert_eq!(Some(9), NthEdgeF(0.999).edge_index(10, 10));
56}
57
58#[derive(Debug, Clone)]
59pub enum EdgeOperation<W: Clone, N: Clone, NT: Clone> {
60    IncreaseWeight {
61        weight: W,
62    },
63    DecreaseWeight {
64        weight: W,
65    },
66    Duplicate {
67        weight: W,
68    },
69    Split {
70        weight: W,
71    },
72    Loop {
73        weight: W,
74    },
75    Output {
76        weight: W,
77    },
78    Merge {
79        n: NT,
80    },
81    Next {
82        n: NT,
83    },
84    Parent {
85        n: NT,
86    },
87    SetNodeFunction {
88        function: N,
89    },
90    Reverse,
91
92    // Saves the state
93    Save,
94
95    // Restores a previously saved state
96    Restore,
97}
98
99#[derive(Debug, Clone)]
100struct Edge<W: Debug + Clone> {
101    src: usize,
102    dst: usize,
103    weight: W,
104}
105
106impl<W: Debug + Clone + Default> Edge<W> {
107    fn new(src: usize, dst: usize, weight: W) -> Edge<W> {
108        Edge {
109            src: src,
110            dst: dst,
111            weight: weight,
112        }
113    }
114}
115
116#[derive(Debug, Clone)]
117struct Node<N: Clone + Default + Debug> {
118    in_edges: Vec<usize>,
119    out_edges: Vec<usize>,
120    node_fn: N,
121}
122
123impl<N: Default + Clone + Debug> Node<N> {
124    fn new() -> Node<N> {
125        Node {
126            in_edges: Vec::new(),
127            out_edges: Vec::new(),
128            node_fn: N::default(),
129        }
130    }
131
132    fn is_empty(&self) -> bool {
133        self.in_edges.is_empty() && self.out_edges.is_empty()
134    }
135}
136
137#[derive(Debug, Clone)]
138struct State {
139    from_node: usize,
140    to_node: usize,
141    link_in_to_node: usize,
142}
143
144#[derive(Debug)]
145pub struct GraphBuilder<W: Debug + Default + Clone, N: Debug + Default + Clone> {
146    edges: BTreeMap<usize, Edge<W>>,
147    nodes: Vec<Node<N>>,
148    next_edge_id: usize,
149    current_state: State,
150    states: Vec<State>,
151}
152
153impl<W: Debug + Default + Clone + AddAssign<W>, N: Debug + Default + Clone> GraphBuilder<W, N> {
154    pub fn new() -> GraphBuilder<W, N> {
155        // we begin with an empty node and a virtual edge.
156
157        GraphBuilder {
158            edges: BTreeMap::new(),
159            nodes: vec![Node::new()],
160            next_edge_id: 0,
161
162            // link_in_to_node: 0 points to a non-existing "virtual" edge
163            current_state: State {
164                from_node: 0,
165                to_node: 0,
166                link_in_to_node: 0,
167            },
168            states: Vec::new(),
169        }
170    }
171
172    /// Saves the current state to the internal state stack.
173    pub fn save(&mut self) {
174        let state = self.get_state();
175        self.states.push(state);
176    }
177
178    /// Restore a previously saved state. Returns false, if
179    /// no saved state exists on the stack.
180    pub fn restore(&mut self) -> bool {
181        if let Some(state) = self.states.pop() {
182            self.set_state(state);
183            true
184        } else {
185            false
186        }
187    }
188
189    fn get_state(&self) -> State {
190        self.current_state.clone()
191    }
192
193    fn set_state(&mut self, state: State) {
194        self.current_state = state;
195    }
196
197    pub fn count_nodes(&self) -> usize {
198        let mut count = 0;
199        self.visit_nodes(|_, _| count += 1);
200        count
201    }
202
203    // iterate over all non-empty nodes.
204    #[inline]
205    pub fn visit_nodes<F: FnMut(usize, &N)>(&self, mut callback: F) {
206        for (i, node) in self.nodes.iter().enumerate() {
207            if !node.is_empty() {
208                callback(i, &node.node_fn);
209            }
210        }
211    }
212
213    #[inline]
214    pub fn visit_edges<F: FnMut((usize, usize), &W)>(&self, mut callback: F) {
215        for (i, node) in self.nodes.iter().enumerate() {
216            if !node.is_empty() {
217                for out_edge in node.out_edges.iter() {
218                    let edge = &self.edges[out_edge];
219                    debug_assert!(edge.src == i);
220                    callback((edge.src, edge.dst), &edge.weight);
221                }
222            }
223        }
224    }
225
226    pub fn to_edge_list(&self) -> Vec<Option<(N, Vec<(usize, W)>)>> {
227        self.nodes
228            .iter()
229            .map(|n| {
230                if n.is_empty() {
231                    None
232                } else {
233                    Some((n.node_fn.clone(),
234                          n.out_edges
235                           .iter()
236                           .map(|oe| {
237                               let edge = &self.edges[oe];
238                               (edge.dst, edge.weight.clone())
239                           })
240                           .collect()))
241                }
242            })
243            .collect()
244    }
245
246    pub fn apply_operation<NT: NthEdge>(&mut self, op: EdgeOperation<W, N, NT>)
247        where W: Neg<Output = W>
248    {
249        match op {
250            EdgeOperation::IncreaseWeight  {weight: w} => self.update_edge_weight(w),
251            EdgeOperation::DecreaseWeight  {weight: w} => self.update_edge_weight(-w),
252            EdgeOperation::Duplicate       {weight: w} => self.duplicate(w),
253            EdgeOperation::Split           {weight: w} => self.split(w),
254            EdgeOperation::Loop            {weight: w} => self.add_self_loop(w),
255            EdgeOperation::Output          {weight: w} => self.output(w),
256            EdgeOperation::Merge           {n} => self.merge(n),
257            EdgeOperation::Next            {n} => self.next(n),
258            EdgeOperation::Parent          {n} => self.parent(n),
259            EdgeOperation::SetNodeFunction {function: f} => self.set_node_function(f),
260            EdgeOperation::Reverse => self.reverse(),
261            EdgeOperation::Save => self.save(),
262            EdgeOperation::Restore => {
263                let _ = self.restore();
264            }
265        }
266    }
267
268    /// creates an output node and connects it to the from neuron.
269    /// does not change the link
270    fn output(&mut self, weight: W) {
271        let from = self.current_state.from_node;
272        let output_node = self.new_node();
273        let edge_idx = self.create_new_edge_with_weight(from, output_node, weight);
274        self.insert_edge(edge_idx);
275    }
276
277    /// changes the node function of the current to-node.
278    fn set_node_function(&mut self, node_fn: N) {
279        self.nodes[self.current_state.to_node].node_fn = node_fn;
280    }
281
282    fn get_current_edge(&self) -> Option<usize> {
283        let to_node = &self.nodes[self.current_state.to_node];
284        if let Some(&edge_idx) = to_node.in_edges.get(self.current_state.link_in_to_node) {
285            let edge = &self.edges[&edge_idx];
286            if edge.src == self.current_state.from_node && edge.dst == self.current_state.to_node {
287                Some(edge_idx)
288            } else {
289                None
290            }
291        } else {
292            None
293        }
294    }
295
296    /// decrease-weight or increase-weight, depending on the sign of the weight.
297    /// Updates the weight of the current edge, or in case of a virtual edge,
298    /// creates a new edge with that weight.
299    pub fn update_edge_weight(&mut self, weight: W) {
300        let (from, to) = (self.current_state.from_node, self.current_state.to_node);
301        let cur_edge = self.get_current_edge();
302
303        if let Some(edge_idx) = cur_edge {
304            let e = self.get_mut_edge(edge_idx);
305            assert!(e.src == from);
306            assert!(e.dst == to);
307            e.weight += weight;
308        } else {
309            // Virtual edge. Create!
310            let edge_idx = self.create_new_edge_with_weight(from, to, weight);
311            self.current_state.link_in_to_node = self.nodes[to].in_edges.len();
312            self.insert_edge(edge_idx);
313        }
314    }
315
316    /// Adds a loop to the current edge's target neuron.
317    pub fn add_self_loop(&mut self, weight: W) {
318        let to = self.current_state.to_node;
319        let edge_idx = self.create_new_edge_with_weight(to, to, weight);
320        self.current_state.link_in_to_node = self.nodes[to].in_edges.len();
321        self.current_state.from_node = to;
322        self.insert_edge(edge_idx);
323    }
324
325    fn get_mut_edge(&mut self, edge_idx: usize) -> &mut Edge<W> {
326        self.edges.get_mut(&edge_idx).unwrap()
327    }
328
329    /// Change from-node of current link to it's n-th sibling.
330    /// The n-th sibling is the current+n-th incoming node into the to-node.
331    pub fn next<NT: NthEdge>(&mut self, n: NT) {
332        let to_node = &self.nodes[self.current_state.to_node];
333        if let Some(new_n) = n.edge_index(to_node.in_edges.len(),
334                                          self.current_state.link_in_to_node) {
335            let sibling_edge = to_node.in_edges[new_n];
336            let new_from = self.edges[&sibling_edge].src;
337            self.current_state.from_node = new_from;
338            self.current_state.link_in_to_node = new_n;
339        }
340    }
341
342    /// Change from-node of current link to n-th input edge of current from node.
343    /// If no input edge exists, the edge is left as is. TODO: Test case
344    /// The n-th input node is not deleted.
345    /// NOTE: Does not modify the graph itself, only changes the current link.
346    pub fn parent<NT: NthEdge>(&mut self, n: NT) {
347        let from = self.current_state.from_node;
348        let edge_idx = n.edge_index(self.nodes[from].in_edges.len(), 0);
349        if let Some(idx) = edge_idx {
350            let new_from = self.edges[&self.nodes[from].in_edges[idx]].src;
351            self.current_state.from_node = new_from;
352            self.current_state.link_in_to_node = idx;
353        } else {
354            // XXX
355            // self.current_state.link_in_to_node = 0;
356            return;
357        }
358    }
359
360    /// Copy all incoming edges of from-node into to-node, then replace from-node with to-node.
361    /// The current link is removed.
362    /// Do not create a self-loop for links between A and B.
363    fn merge<NT: NthEdge>(&mut self, n: NT) {
364        // 1. delete current edge.
365        // 2. modify all outgoing edges of A. replace the .src to B.
366        // 3. copy all incoming edges of A to B.
367        // 4. set the n-th incoming edge into A as new current edge.
368
369        let (from, to) = (self.current_state.from_node, self.current_state.to_node);
370
371        // 1. delete current edge (if exists)
372        if let Some(edge_idx) = self.get_current_edge() {
373            let edge = self.edges.remove(&edge_idx).unwrap();
374            debug_assert!(edge.src == from);
375            debug_assert!(edge.dst == to);
376            self.nodes[from].out_edges.retain(|&i| i != edge_idx);
377            self.nodes[to].in_edges.retain(|&i| i != edge_idx);
378        }
379
380        if from == to {
381            return;
382        }
383
384        // 2. modify all outgoing edges of A.
385        let mut new_out_edges = Vec::new();
386        for &out_edge in self.nodes[from].out_edges.iter() {
387            let edge = self.edges.get_mut(&out_edge).unwrap();
388            debug_assert!(edge.src == from);
389            edge.src = to;
390            new_out_edges.push(out_edge);
391        }
392        self.nodes[to].out_edges.extend(new_out_edges);
393
394        // 3. copy all incoming edges of A to B. Modify them.
395        let mut new_in_edges = Vec::new();
396        for &in_edge in self.nodes[from].in_edges.iter() {
397            let edge = self.edges.get_mut(&in_edge).unwrap();
398            debug_assert!(edge.dst == from);
399            edge.dst = to;
400            new_in_edges.push(in_edge);
401        }
402        self.nodes[to].in_edges.extend(new_in_edges);
403
404        // remove from node (TODO: improve)
405        self.nodes[from].out_edges.clear();
406        self.nodes[from].in_edges.clear();
407
408        // 4.
409        let edges = &self.nodes[to].in_edges;
410        if let Some(idx) = n.edge_index(edges.len(), 0) {
411            // we use the n-th in edge as new current edge
412            self.current_state.link_in_to_node = edges[idx];
413            self.current_state.from_node = self.edges[&self.current_state.link_in_to_node].src;
414            debug_assert!(self.edges[&self.current_state.link_in_to_node].dst == to);
415        } else {
416            self.current_state.link_in_to_node = 0;
417            self.current_state.from_node = to;
418        }
419    }
420
421    /// Split the current edge in two, and insert a node in the middle of it.
422    /// If ```A -> B``` is the current edge, this will result into ```A -> N -> B```
423    /// with ```N -> B``` being the next current edge.
424    /// There is no A -> B link after this operation, that's why we delete the edge,
425    /// so that backtracking cannot later make use of it.
426    fn split(&mut self, weight: W) {
427        let (from, to) = (self.current_state.from_node, self.current_state.to_node);
428
429        // create intermediate node
430        let middle_node = self.new_node();
431
432        // Move current link from (A,B) to (A,C) (or create a new with weight 0.0).
433        let cur_edge = self.get_current_edge();
434        if let Some(edge_idx) = cur_edge {
435            // new to_node is middle_node.
436            self.get_mut_edge(edge_idx).dst = middle_node;
437
438            // remove from incoming edges.
439            self.nodes[to].in_edges.retain(|&i| i != edge_idx);
440            // add to incoming edges of new to_node
441            self.nodes[middle_node].in_edges.push(edge_idx);
442        } else {
443            // current edge is virtual. Create a edge with weight 0.0.
444            let edge_idx = self.create_new_edge_with_weight(from, middle_node, W::default());
445            self.insert_edge(edge_idx);
446        }
447
448        // Add new link from middle_node to `B` with `weight`
449        let edge_idx = self.create_new_edge_with_weight(middle_node, to, weight);
450        self.current_state.link_in_to_node = self.insert_edge(edge_idx);
451        self.current_state.from_node = middle_node;
452    }
453
454    /// Duplicates the current edge. The new edge becomes the new current edge.
455    fn duplicate(&mut self, weight: W) {
456        let (from, to) = (self.current_state.from_node, self.current_state.to_node);
457        let edge_idx = self.create_new_edge_with_weight(from, to, weight);
458        self.current_state.link_in_to_node = self.insert_edge(edge_idx);
459    }
460
461    /// Reverse the current edge.
462    fn reverse(&mut self) {
463        let (from, to) = (self.current_state.from_node, self.current_state.to_node);
464
465        // Delete current link
466        let cur_edge = self.get_current_edge();
467        let orig_weight = if let Some(edge_idx) = cur_edge {
468            // delete edge
469            let edge = self.edges.remove(&edge_idx).unwrap();
470            self.nodes[from].out_edges.retain(|&i| i != edge_idx);
471            self.nodes[to].in_edges.retain(|&i| i != edge_idx);
472            edge.weight
473        } else {
474            // If current edge does not exist, just change the state.
475            W::default()
476        };
477
478        // Add new reversed link
479        let edge_idx = self.create_new_edge_with_weight(to, from, orig_weight);
480        let new_state = State {
481            link_in_to_node: self.insert_edge(edge_idx),
482            to_node: from,
483            from_node: to,
484        };
485        self.current_state = new_state;
486    }
487
488    /// Returns the incoming edge index of the target node.
489    fn insert_edge(&mut self, edge_idx: usize) -> usize {
490        let edge = self.edges.get(&edge_idx).unwrap().clone(); // XXX
491        self.nodes[edge.src].out_edges.push(edge_idx);
492        let idx = self.nodes[edge.dst].in_edges.len();
493        self.nodes[edge.dst].in_edges.push(edge_idx);
494        idx
495    }
496
497    /// Allocates a new Edge and returns new edge index.
498    fn create_new_edge_with_weight(&mut self, from: usize, to: usize, weight: W) -> usize {
499        let edge_id = self.next_edge_id;
500        let edge = Edge::new(from, to, weight);
501        self.next_edge_id += 1;
502        self.edges.insert(edge_id, edge);
503        return edge_id;
504    }
505
506    fn new_node(&mut self) -> usize {
507        let node_id = self.nodes.len();
508        let node = Node::new();
509        self.nodes.push(node);
510        return node_id;
511    }
512}
513
514#[cfg(test)]
515fn edge_list<W: Debug + Default + Clone + AddAssign<W>, N: Debug + Default + Clone>
516    (builder: &GraphBuilder<W, N>)
517     -> Vec<Vec<(usize, W)>> {
518    builder.to_edge_list()
519           .into_iter()
520           .map(|n| {
521               match n {
522                   Some((_, b)) => b,
523                   None => vec![],
524               }
525           })
526           .collect()
527}
528
529#[test]
530fn test_empty() {
531    let builder: GraphBuilder<f32, usize> = GraphBuilder::new();
532    let v: Vec<Vec<(usize, f32)>> = vec![vec![]];
533    assert_eq!(v, edge_list(&builder));
534}
535
536#[test]
537fn test_split() {
538    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
539    builder.update_edge_weight(0.0);
540
541    // start with a single node, self-connected with zero weight
542    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
543
544    builder.split(1.0);
545    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
546
547    builder.split(2.0);
548    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(0, 2.0)]],
549               edge_list(&builder));
550
551    builder.split(3.0);
552    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0)]],
553               edge_list(&builder));
554}
555
556#[test]
557fn test_duplicate() {
558    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
559    builder.update_edge_weight(0.0);
560
561    // start with a single node, self-connected with zero weight
562    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
563
564    builder.duplicate(1.0);
565    assert_eq!(vec![vec![(0, 0.0), (0, 1.0)]], edge_list(&builder));
566
567    builder.split(0.25);
568    assert_eq!(vec![vec![(0, 0.0), (1, 1.0)], vec![(0, 0.25)]],
569               edge_list(&builder));
570
571    builder.duplicate(2.0);
572    assert_eq!(vec![vec![(0, 0.0), (1, 1.0)], vec![(0, 0.25), (0, 2.0)]],
573               edge_list(&builder));
574}
575
576#[test]
577fn test_reverse() {
578    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
579    builder.update_edge_weight(0.0);
580
581    // start with a single node, self-connected with zero weight
582    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
583
584    builder.split(1.0);
585    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
586
587    builder.reverse();
588    assert_eq!(vec![vec![(1, 0.0), (1, 1.0)], vec![]], edge_list(&builder));
589}
590
591#[test]
592fn test_update_edge_weight() {
593    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
594    builder.update_edge_weight(0.0);
595
596    // start with a single node, self-connected with zero weight
597    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
598
599    builder.update_edge_weight(4.0);
600    assert_eq!(vec![vec![(0, 4.0)]], edge_list(&builder));
601
602    builder.update_edge_weight(-4.0);
603    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
604}
605
606#[test]
607fn test_add_self_loop() {
608    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
609    builder.update_edge_weight(0.0);
610
611    // start with a single node, self-connected with zero weight
612    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
613
614    builder.add_self_loop(1.0);
615    assert_eq!(vec![vec![(0, 0.0), (0, 1.0)]], edge_list(&builder));
616}
617
618#[test]
619fn test_next() {
620    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
621    builder.update_edge_weight(0.0);
622
623    // start with a single node, self-connected with zero weight
624    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
625
626    builder.split(1.0);
627    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
628
629    builder.split(2.0);
630    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(0, 2.0)]],
631               edge_list(&builder));
632
633    builder.split(3.0);
634    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0)]],
635               edge_list(&builder));
636
637    // does not change anything, because there is only one edge (no sibling).
638    builder.next(NthEdgeI(1));
639    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0)]],
640               edge_list(&builder));
641
642    builder.duplicate(5.0);
643    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0), (0, 5.0)]],
644               edge_list(&builder));
645
646    builder.update_edge_weight(1.0);
647    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0), (0, 6.0)]],
648               edge_list(&builder));
649
650    builder.next(NthEdgeI(0));
651    builder.update_edge_weight(1.0);
652    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 3.0), (0, 7.0)]],
653               edge_list(&builder));
654
655
656    builder.next(NthEdgeI(1));
657    builder.update_edge_weight(1.0);
658    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 4.0), (0, 7.0)]],
659               edge_list(&builder));
660
661    builder.next(NthEdgeI(2));
662    builder.update_edge_weight(1.0);
663    assert_eq!(vec![vec![(1, 0.0)], vec![(2, 1.0)], vec![(3, 2.0)], vec![(0, 5.0), (0, 7.0)]],
664               edge_list(&builder));
665}
666
667#[test]
668fn test_parent() {
669    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
670    builder.update_edge_weight(0.0);
671
672    // start with a single node, self-connected with zero weight
673    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
674
675    builder.parent(NthEdgeI(0));
676    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
677    builder.parent(NthEdgeI(3));
678    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
679
680    builder.split(1.0);
681    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
682
683    builder.parent(NthEdgeI(0));
684    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 1.0)]], edge_list(&builder));
685
686    // XXX: add more tests
687}
688
689#[test]
690fn test_merge_self_loop() {
691    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
692    builder.update_edge_weight(0.0);
693
694    // start with a single node, self-connected with zero weight
695    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
696
697    builder.merge(NthEdgeI(1));
698    let v: Vec<Vec<(usize, f32)>> = vec![vec![]];
699    assert_eq!(v, edge_list(&builder));
700
701    let mut nodes = vec![];
702    builder.visit_nodes(|i, _| nodes.push(i));
703    assert!(nodes.is_empty());
704    assert_eq!(0, builder.count_nodes());
705
706    let mut edges = vec![];
707    builder.visit_edges(|(i, j), _w| edges.push((i, j)));
708    let res: Vec<(usize, usize)> = vec![];
709    assert_eq!(res, edges);
710}
711
712#[test]
713fn test_merge_self_loop2() {
714    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
715    builder.update_edge_weight(0.0);
716
717    // start with a single node, self-connected with zero weight
718    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
719
720    builder.add_self_loop(1.0);
721
722    assert_eq!(vec![vec![(0, 0.0), (0, 1.0)]], edge_list(&builder));
723
724    builder.merge(NthEdgeI(1));
725    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
726}
727
728#[test]
729fn test_graph_paper() {
730    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
731
732    // figure 2.a
733    builder.update_edge_weight(0.25);
734    assert_eq!(vec![vec![(0, 0.25)]], edge_list(&builder));
735
736    // figure 2.b
737    builder.split(0.8);
738    assert_eq!(vec![vec![(1, 0.25)], vec![(0, 0.8)]], edge_list(&builder));
739
740    // figure 2.c
741    builder.duplicate(3.0);
742    assert_eq!(vec![vec![(1, 0.25)], vec![(0, 0.8), (0, 3.0)]],
743               edge_list(&builder));
744
745    // figure 2.d
746    builder.reverse();
747    assert_eq!(vec![vec![(1, 0.25), (1, 3.0)], vec![(0, 0.8)]],
748               edge_list(&builder));
749
750    // figure 2.e
751    builder.split(0.8);
752    builder.duplicate(2.0);
753    builder.reverse();
754    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)], vec![(0, 0.8), (2, 2.0)], vec![(1, 0.8)]],
755               edge_list(&builder));
756
757    // figure 2.f
758    builder.add_self_loop(1.0);
759    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)], vec![(0, 0.8), (2, 2.0)], vec![(1, 0.8), (2, 1.0)]],
760               edge_list(&builder));
761
762    // figure 2.g1
763    builder.split(0.6);
764    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
765                    vec![(0, 0.8), (2, 2.0)],
766                    vec![(1, 0.8), (3, 1.0)],
767                    vec![(2, 0.6)]],
768               edge_list(&builder));
769
770    // figure 2.g2
771    builder.duplicate(0.4);
772    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
773                    vec![(0, 0.8), (2, 2.0)],
774                    vec![(1, 0.8), (3, 1.0)],
775                    vec![(2, 0.6), (2, 0.4)]],
776               edge_list(&builder));
777
778    // figure 2.g3
779    builder.split(0.6);
780    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
781                    vec![(0, 0.8), (2, 2.0)],
782                    vec![(1, 0.8), (3, 1.0)],
783                    vec![(2, 0.6), (4, 0.4)],
784                    vec![(2, 0.6)]],
785               edge_list(&builder));
786
787    // figure 2.g4
788    builder.duplicate(0.4);
789    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
790                    vec![(0, 0.8), (2, 2.0)],
791                    vec![(1, 0.8), (3, 1.0)],
792                    vec![(2, 0.6), (4, 0.4)],
793                    vec![(2, 0.6), (2, 0.4)]],
794               edge_list(&builder));
795
796    // figure 2.g5
797    builder.reverse();
798    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
799                    vec![(0, 0.8), (2, 2.0)],
800                    vec![(1, 0.8), (3, 1.0), (4, 0.4)],
801                    vec![(2, 0.6), (4, 0.4)],
802                    vec![(2, 0.6)]],
803               edge_list(&builder));
804
805    assert_eq!(4, builder.get_state().to_node);
806    assert_eq!(2, builder.get_state().from_node);
807    assert_eq!(1, builder.get_state().link_in_to_node);
808
809    // figure 2.g
810    builder.parent(NthEdgeI(1));
811    assert_eq!(vec![vec![(1, 0.25), (2, 3.0)],
812                    vec![(0, 0.8), (2, 2.0)],
813                    vec![(1, 0.8), (3, 1.0), (4, 0.4)],
814                    vec![(2, 0.6), (4, 0.4)],
815                    vec![(2, 0.6)]],
816               edge_list(&builder));
817
818    assert_eq!(4, builder.get_state().to_node);
819    assert_eq!(1, builder.get_state().from_node);
820    assert_eq!(1, builder.get_state().link_in_to_node);
821
822    // figure 2.h
823    builder.merge(NthEdgeI(1));
824    assert_eq!(vec![vec![(4, 0.25), (2, 3.0)],
825                    vec![],
826                    vec![(4, 0.8), (3, 1.0), (4, 0.4)],
827                    vec![(2, 0.6), (4, 0.4)],
828                    vec![(2, 0.6), (0, 0.8), (2, 2.0)]],
829               edge_list(&builder));
830
831}
832
833#[test]
834fn test_save_restore() {
835    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
836    builder.update_edge_weight(0.0);
837
838    // start with a single node, self-connected with zero weight
839    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
840
841    builder.save();
842    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
843
844    builder.split(0.5);
845    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
846
847    assert_eq!(true, builder.restore());
848    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
849
850    // there is now a virtual edge between 0 -> 0.
851    builder.update_edge_weight(0.7); // this will create a real edge.
852
853    assert_eq!(vec![vec![(1, 0.0), (0, 0.7)], vec![(0, 0.5)]],
854               edge_list(&builder));
855
856    builder.split(0.6);
857    assert_eq!(vec![vec![(1, 0.0), (2, 0.7)], vec![(0, 0.5)], vec![(0, 0.6)]],
858               edge_list(&builder));
859}
860
861#[test]
862fn test_save_restore2() {
863    let mut builder: GraphBuilder<f32, usize> = GraphBuilder::new();
864    builder.update_edge_weight(0.0);
865
866    // start with a single node, self-connected with zero weight
867    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
868
869    builder.save();
870    assert_eq!(vec![vec![(0, 0.0)]], edge_list(&builder));
871
872    builder.split(0.5);
873    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
874
875    assert_eq!(true, builder.restore());
876    assert_eq!(vec![vec![(1, 0.0)], vec![(0, 0.5)]], edge_list(&builder));
877
878    // there is now a virtual edge between 0 -> 0 with weight 0.0.
879    builder.split(0.6);
880    assert_eq!(vec![vec![(1, 0.0), (2, 0.0)], vec![(0, 0.5)], vec![(0, 0.6)]],
881               edge_list(&builder));
882}