rugraph/
multidigraph.rs

1use std::cell::RefCell;
2use std::fs::File;
3use std::io::Write;
4use std::rc::Rc;
5use std::vec::Vec;
6
7use crate::rugraph::IGraph;
8use crate::rugraph::IMultiDiGraph;
9
10/// `MultiDiGraph` is actually a `generic` multi directed graph where each node of type `T`
11///  and edge of type `E`
12///  must implement: `T: Ord + Clone + std::fmt::Display + std::fmt::Debug` and
13///  `E: Ord + Clone + std::fmt::Display + std::fmt::Debug`
14pub struct MultiDiGraph<T, E>
15where
16    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
17    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
18{
19    /// Nodes are stored in the heap
20    nodes: RefCell<Vec<Rc<MultiNode<T, E>>>>,
21}
22
23/// A `Node` is represented as a generic `T` and a list of pointers to their neighbors (allocated in the heap)
24struct MultiNode<T, E>
25where
26    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
27    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
28{
29    elem: T,
30    neighbors: RefCell<Vec<Rc<Edge<T, E>>>>,
31}
32
33struct Edge<T, E>
34where
35    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
36    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
37{
38    node: Rc<MultiNode<T, E>>,
39    edge: E,
40}
41
42impl<T, E> MultiNode<T, E>
43where
44    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
45    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
46{
47    pub fn new(elem: T) -> Self {
48        MultiNode::<T, E> {
49            elem: elem,
50            neighbors: RefCell::new(Vec::new()),
51        }
52    }
53}
54
55impl<T, E> MultiDiGraph<T, E>
56where
57    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
58    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
59{
60    pub fn new() -> Self {
61        MultiDiGraph::<T, E> {
62            nodes: RefCell::new(vec![]),
63        }
64    }
65
66    fn get_index_by_node_id(&self, from: T) -> Result<usize, &'static str> {
67        let nodes = self.nodes.borrow();
68        let idx_from = nodes.iter().position(|r| r.elem == from);
69        match idx_from {
70            None => Err("Element not found"),
71            Some(value) => Ok(value),
72        }
73    }
74
75    fn dfs(
76        &self,
77        previous_from: T,
78        from: T,
79        to: T,
80        dst: T,
81        edge: E,
82        simple_path: &mut Vec<Vec<(T, T, E)>>,
83        current_path: &mut Vec<(T, T, E)>,
84        visited: &mut Vec<T>,
85    ) {
86        if visited.contains(&previous_from.clone()) {
87            return;
88        }
89        visited.push(previous_from.clone());
90        current_path.push((previous_from.clone(), dst.clone(), edge.clone()));
91        if from == to {
92            simple_path.push(current_path.clone());
93            if visited.contains(&previous_from.clone()) {
94                let index = visited
95                    .iter()
96                    .position(|x| x.clone() == previous_from.clone())
97                    .unwrap();
98                visited.remove(index);
99                current_path.pop();
100                return;
101            }
102        }
103
104        let neighbors = self.get_neighbors(dst.clone());
105        for n in neighbors.iter() {
106            self.dfs(
107                dst.clone(),
108                n.0.clone(),
109                to.clone(),
110                n.0.clone(),
111                n.1.clone(),
112                simple_path,
113                current_path,
114                visited,
115            );
116        }
117
118        current_path.pop();
119        if visited.contains(&previous_from.clone()) {
120            let index = visited
121                .iter()
122                .position(|x| x.clone() == previous_from.clone())
123                .unwrap();
124            visited.remove(index);
125        }
126    }
127}
128
129impl<T, E> Drop for MultiDiGraph<T, E>
130where
131    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
132    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
133{
134    fn drop(&mut self) {
135        self.nodes.borrow_mut().clear();
136    }
137}
138
139impl<T, E> IGraph<T> for MultiDiGraph<T, E>
140where
141    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
142    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
143{
144    /// Adds a new node `elem` to the graph
145    fn add_node(&mut self, elem: T) {
146        if self.node_exists(elem.clone()) {
147            return;
148        }
149
150        let mut nodes = self.nodes.borrow_mut();
151        let n = Rc::new(MultiNode::<T, E>::new(elem));
152
153        nodes.push(n);
154    }
155
156    fn node_exists(&self, from: T) -> bool {
157        let nodes = self.nodes.borrow();
158        let idx_from = nodes.iter().position(|r| r.elem == from);
159        match idx_from {
160            None => {
161                return false;
162            }
163            Some(_value) => {
164                return true;
165            }
166        }
167    }
168
169    /// Returns if node `to` is a neighbord of `from`
170    fn is_directly_connected(&self, from: T, to: T) -> bool {
171        let nodes = self.nodes.borrow();
172        let ret_idx_from = self.get_index_by_node_id(from.clone());
173        let idx_from;
174        match ret_idx_from {
175            Ok(v) => idx_from = v,
176            Err(e) => {
177                println!("Error {}", e);
178                return false;
179            }
180        };
181
182        let ret_idx_to = self.get_index_by_node_id(to.clone());
183        let idx_to;
184        match ret_idx_to {
185            Ok(v) => idx_to = v,
186            Err(e) => {
187                println!("Error {}", e);
188                return false;
189            }
190        };
191
192        let n = &nodes[idx_from];
193        let m = nodes[idx_to].clone();
194        for e in n.neighbors.borrow().iter() {
195            if Rc::ptr_eq(&e.node, &m) {
196                //println!("Node {} is connected to {}", from, to);
197                return true;
198            }
199        }
200        //println!("Node {} is NOT connected to {}", from, to);
201        return false;
202    }
203
204    /// Returns if a node `from` is connected to a node `to`
205    fn is_connected(&self, from: T, to: T) -> bool {
206        //println!("Checking from {} to {}", from, to);
207        let mut seen = Vec::<(T, E)>::new();
208        let mut to_process = Vec::<(T, E)>::new();
209
210        let neighbors = self.get_neighbors(from.clone());
211        for n in neighbors.iter() {
212            to_process.push(n.clone());
213        }
214        //println!(" |-> Neighbors of {} : {:?}",from,neighbors);
215
216        let mut end = false;
217        while !end {
218            let node = to_process.pop().unwrap().clone();
219            let node_id = node.0;
220
221            let neighbors = self.get_neighbors(node_id.clone());
222            //println!(" |-> Neighbors of {} : {:?}",node_id,neighbors);
223            let contains = neighbors.iter().any(|r| r.0 == to.clone());
224            //println!("    |-> Neighbors of {} contains {}? {}",node_id,from,contains);
225
226            if contains {
227                return true;
228            } else {
229                for n in neighbors.iter() {
230                    if !seen.contains(n) {
231                        to_process.push(n.clone());
232                        seen.push(n.clone());
233                    }
234                }
235            }
236
237            end = to_process.is_empty();
238        }
239
240        return false;
241    }
242
243    /// Exports the graph to a dot file. `file` must be a valid
244    /// file ready to be written.
245    /// `graph_name` is the name of the graph
246    fn to_dot_file(&self, file: &mut File, graph_name: &str) {
247        let s = self.to_dot_string(graph_name);
248        file.write_all(s.as_bytes()).expect("Error writing file!");
249    }
250
251    /// Returns an `String` with a dot file representation of the graph
252    fn to_dot_string(&self, graph_name: &str) -> String {
253        let mut s = String::from("digraph ") + graph_name + &String::from("{\n");
254        let nodes = self.nodes.borrow();
255        for n in nodes.iter() {
256            for m in n.neighbors.borrow().iter() {
257                s = s + &n.elem.to_string();
258                s = s
259                    + &String::from(" -> ")
260                    + &m.node.elem.to_string()
261                    + &String::from(" [label=\"")
262                    + &m.edge.to_string()
263                    + &String::from("\"];\n");
264            }
265        }
266        s = s + &String::from("}\n");
267        return s;
268    }
269
270    fn is_empty(&self) -> bool {
271        return self.nodes.borrow().is_empty();
272    }
273
274    fn count_nodes(&self) -> usize {
275        return self.nodes.borrow().len();
276    }
277    fn get_nodes(&self) -> Vec<T> {
278        let mut ret = Vec::<T>::new();
279        for n in self.nodes.borrow().iter() {
280            ret.push(n.elem.clone());
281        }
282        return ret;
283    }
284}
285
286/// Returns a multidirected string graph `MultiDiGraph<String, String>` from a dot file content
287pub fn multidigraph_from_dot_string(
288    content: &String,
289) -> Result<MultiDiGraph<String, String>, &'static str> {
290    let mut graph = MultiDiGraph::<String, String>::new();
291    let idx1: usize;
292    let idx2: usize;
293    match content.chars().position(|c| c == '{') {
294        None => {
295            return Err("Dot file not correct. { not found.");
296        }
297        Some(i) => {
298            idx1 = i + 1;
299        }
300    }
301
302    match content.chars().position(|c| c == '}') {
303        None => {
304            return Err("Dot file not correct. } not found.");
305        }
306        Some(i) => {
307            idx2 = i - 1;
308        }
309    }
310
311    if idx2 < idx1 {
312        return Err("Dot file not correct. } before {");
313    }
314
315    let c = &content[idx1..idx2];
316    //println!("Content {}",c);
317    let v_c: Vec<&str> = c.split(';').collect();
318
319    for line in v_c.iter() {
320        if line.is_empty() {
321            continue;
322        }
323        //println!("Line {}", line);
324        // [
325        let idx3 = match line.chars().position(|c| c == '[') {
326            None => {
327                return Err("Dot file not correct. [ not found.");
328            }
329            Some(i) => i - 1,
330        };
331
332        let l_nodes = line[0..idx3].trim();
333
334        let v_nodes: Vec<&str> = l_nodes.split("->").collect();
335
336        let n_from;
337        let n_to;
338        if v_nodes.len() == 2 {
339            n_from = v_nodes[0].trim().to_string();
340            n_to = v_nodes[1].trim().to_string();
341            graph.add_node(n_from.clone());
342            graph.add_node(n_to.clone());
343        } else {
344            return Err("Dot file not correct.");
345        }
346
347        let label = line[idx3..]
348            .replace("[label=\"", "")
349            .replace("\"]", "")
350            .trim()
351            .to_string();
352        //println!("LAbel {}",label.clone());
353        graph.add_edge(n_from, n_to, label.to_string())
354    }
355
356    Ok(graph)
357}
358
359impl<T, E> IMultiDiGraph<T, E> for MultiDiGraph<T, E>
360where
361    T: Ord + Clone + std::fmt::Display + std::fmt::Debug,
362    E: Ord + Clone + std::fmt::Display + std::fmt::Debug,
363{
364    ///Creates a new edge from node `from` to node `to`
365    ///nodes `from` and `to` must be previously added to the graph
366    fn add_edge(&mut self, from: T, to: T, edge: E) {
367        if !self.node_exists(from.clone())
368            || !self.node_exists(to.clone())
369            || self.is_directly_connected_by(from.clone(), to.clone(), edge.clone())
370        {
371            return;
372        }
373
374        let nodes = self.nodes.borrow_mut();
375
376        let idx_from = nodes.iter().position(|r| r.elem == from).unwrap();
377        let idx_to = nodes.iter().position(|r| r.elem == to).unwrap();
378
379        let n = &nodes[idx_from];
380        let m = nodes[idx_to].clone();
381
382        n.neighbors.borrow_mut().push(Rc::new(Edge {
383            node: m.clone(),
384            edge: edge,
385        }));
386    }
387
388    /// Returns if node `to` is a neighbord of `from` by edge `edge`
389    fn is_directly_connected_by(&self, from: T, to: T, edge: E) -> bool {
390        let nodes = self.nodes.borrow();
391        let ret_idx_from = self.get_index_by_node_id(from.clone());
392        let idx_from;
393        match ret_idx_from {
394            Ok(v) => idx_from = v,
395            Err(e) => {
396                println!("Error {}", e);
397                return false;
398            }
399        };
400
401        let ret_idx_to = self.get_index_by_node_id(to.clone());
402        let idx_to;
403        match ret_idx_to {
404            Ok(v) => idx_to = v,
405            Err(e) => {
406                println!("Error {}", e);
407                return false;
408            }
409        };
410
411        let n = &nodes[idx_from];
412        let m = nodes[idx_to].clone();
413        for e in n.neighbors.borrow().iter() {
414            if Rc::ptr_eq(&e.node, &m) && (e.edge == edge) {
415                //println!("Node {} is connected to {}", from, to);
416                return true;
417            }
418        }
419        //println!("Node {} is NOT connected to {}", from, to);
420        return false;
421    }
422
423    /// Returns a vector `Vec<Vec<(T, T, E)>>` containing all the simple paths
424    /// from node `from` to node `to` in a vector of tuples `(from,to,edge)`
425    fn all_simple_paths(&self, from: T, to: T) -> Vec<Vec<(T, T, E)>> {
426        let mut ret = Vec::<Vec<(T, T, E)>>::new();
427        let mut current_path = Vec::<(T, T, E)>::new();
428        let mut visited = Vec::<T>::new();
429        let neighbors = self.get_neighbors(from.clone());
430        if neighbors.len() == 0 {
431            return ret;
432        }
433        for n in neighbors.iter() {
434            self.dfs(
435                from.clone(),
436                n.0.clone(),
437                to.clone(),
438                n.0.clone(),
439                n.1.clone(),
440                &mut ret,
441                &mut current_path,
442                &mut visited,
443            );
444        }
445        return ret;
446    }
447
448    fn get_neighbors(&self, from: T) -> Vec<(T, E)> {
449        let mut neighbors = Vec::<(T, E)>::new();
450
451        if !self.node_exists(from.clone()) {
452            return neighbors;
453        }
454
455        let nodes = self.nodes.borrow();
456
457        let idx_from = nodes.iter().position(|r| r.elem == from).unwrap();
458
459        let n = &nodes[idx_from];
460
461        //n.neighbors
462        for e in n.neighbors.borrow().iter() {
463            neighbors.push((e.node.elem.clone(), e.edge.clone()));
464        }
465
466        return neighbors;
467    }
468}
469
470#[cfg(test)]
471mod tests {
472    use super::MultiDiGraph;
473    use crate::multidigraph::multidigraph_from_dot_string;
474    use crate::multidigraph::File;
475    use crate::rugraph::IGraph;
476    use crate::rugraph::IMultiDiGraph;
477
478    #[test]
479    fn multidigraph_test1() {
480        let mut graph = MultiDiGraph::<i32, i32>::new();
481        graph.add_node(1);
482
483        let exists = graph.node_exists(1);
484        assert_eq!(exists, true);
485        let exists = graph.node_exists(99);
486        assert_eq!(exists, false);
487
488        graph.add_node(2);
489        graph.add_node(3);
490        graph.add_node(4);
491        graph.add_node(5);
492        graph.add_node(6);
493        graph.add_node(7);
494        graph.add_edge(1, 2, 0);
495        graph.add_edge(1, 2, 1);
496        graph.add_edge(2, 3, 0);
497        graph.add_edge(2, 4, 0);
498        graph.add_edge(2, 5, 1);
499        graph.add_edge(5, 7, 0);
500
501        let ret = graph.is_directly_connected(1, 2);
502        assert_eq!(ret, true);
503
504        let ret = graph.is_directly_connected(1, 3);
505        assert_eq!(ret, false);
506
507        let s = graph.get_neighbors(2);
508        assert_eq!(s, [(3, 0), (4, 0), (5, 1)]);
509
510        let ret = graph.is_connected(1, 7);
511        assert_eq!(ret, true);
512
513        let ret = graph.is_connected(1, 6);
514        assert_eq!(ret, false);
515    }
516
517    #[test]
518    fn multidigraph_generics() {
519        let mut graph = MultiDiGraph::<String, String>::new();
520        graph.add_node("a".to_string());
521        graph.add_node("b".to_string());
522        graph.add_node("c".to_string());
523        graph.add_node("d".to_string());
524        graph.add_edge("a".to_string(), "b".to_string(), "ab".to_string());
525        graph.add_edge("b".to_string(), "c".to_string(), "bc".to_string());
526        graph.add_edge("c".to_string(), "d".to_string(), "cd".to_string());
527        graph.add_edge("a".to_string(), "d".to_string(), "ad".to_string());
528
529        println!("From a to d");
530        let paths = graph.all_simple_paths("a".to_string(), "d".to_string());
531        println!("{:?}", paths);
532        //
533        assert_eq!(
534            paths,
535            vec![
536                vec![
537                    ("a".to_string(), "b".to_string(), "ab".to_string()),
538                    ("b".to_string(), "c".to_string(), "bc".to_string()),
539                    ("c".to_string(), "d".to_string(), "cd".to_string())
540                ],
541                vec![("a".to_string(), "d".to_string(), "ad".to_string())]
542            ]
543        );
544
545        let s = graph.to_dot_string(&String::from("to_dot_multidigraph_test"));
546        println!("Dot:\n{}", s);
547        assert_eq!(s.is_empty(), false);
548    }
549
550    #[test]
551    fn multidigraph_from_dot_str() {
552        let content =
553            String::from("digraph multidigraph_from_dot_str{\na -> b [label=\"ab\"];\na -> d [label=\"ad\"];\nb -> c [label=\"bc\"];\nc -> d [label=\"cd\"];\n}");
554
555        let graph = match multidigraph_from_dot_string(&content) {
556            Ok(v) => v,
557            Err(e) => {
558                println!("Error {}", e);
559                MultiDiGraph::<String, String>::new()
560            }
561        };
562
563        assert_eq!(graph.count_nodes(), 4);
564        let s = graph.to_dot_string(&String::from("multidigraph_from_dot_str"));
565        println!("{}", s);
566        //assert_eq!(s,content);
567    }
568
569    #[test]
570    fn all_paths() {
571        let mut graph = MultiDiGraph::<String, String>::new();
572        graph.add_node("a".to_string());
573        graph.add_node("b".to_string());
574        graph.add_node("c".to_string());
575        graph.add_node("d".to_string());
576        graph.add_node("e".to_string());
577        graph.add_node("f".to_string());
578
579        graph.add_edge("a".to_string(), "b".to_string(), "ab0".to_string());
580        graph.add_edge("a".to_string(), "b".to_string(), "ab1".to_string());
581        graph.add_edge("b".to_string(), "c".to_string(), "bc0".to_string());
582        graph.add_edge("b".to_string(), "c".to_string(), "bc1".to_string());
583        graph.add_edge("c".to_string(), "d".to_string(), "cd".to_string());
584        graph.add_edge("d".to_string(), "e".to_string(), "de".to_string());
585        graph.add_edge("d".to_string(), "a".to_string(), "da".to_string());
586        graph.add_edge("c".to_string(), "e".to_string(), "ce".to_string());
587        graph.add_edge("e".to_string(), "f".to_string(), "ef".to_string());
588        graph.add_edge("a".to_string(), "d".to_string(), "ad".to_string());
589
590        println!("From a to d");
591        let paths = graph.all_simple_paths("a".to_string(), "f".to_string());
592        println!("Len {} {:?}", paths.len(), paths);
593
594        assert_eq!(
595            paths,
596            vec![
597                vec![
598                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
599                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
600                    ("c".to_string(), "d".to_string(), "cd".to_string()),
601                    ("d".to_string(), "e".to_string(), "de".to_string()),
602                    ("e".to_string(), "f".to_string(), "ef".to_string())
603                ],
604                vec![
605                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
606                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
607                    ("c".to_string(), "e".to_string(), "ce".to_string()),
608                    ("e".to_string(), "f".to_string(), "ef".to_string())
609                ],
610                vec![
611                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
612                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
613                    ("c".to_string(), "d".to_string(), "cd".to_string()),
614                    ("d".to_string(), "e".to_string(), "de".to_string()),
615                    ("e".to_string(), "f".to_string(), "ef".to_string())
616                ],
617                vec![
618                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
619                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
620                    ("c".to_string(), "e".to_string(), "ce".to_string()),
621                    ("e".to_string(), "f".to_string(), "ef".to_string())
622                ],
623                vec![
624                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
625                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
626                    ("c".to_string(), "d".to_string(), "cd".to_string()),
627                    ("d".to_string(), "e".to_string(), "de".to_string()),
628                    ("e".to_string(), "f".to_string(), "ef".to_string())
629                ],
630                vec![
631                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
632                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
633                    ("c".to_string(), "e".to_string(), "ce".to_string()),
634                    ("e".to_string(), "f".to_string(), "ef".to_string())
635                ],
636                vec![
637                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
638                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
639                    ("c".to_string(), "d".to_string(), "cd".to_string()),
640                    ("d".to_string(), "e".to_string(), "de".to_string()),
641                    ("e".to_string(), "f".to_string(), "ef".to_string())
642                ],
643                vec![
644                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
645                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
646                    ("c".to_string(), "e".to_string(), "ce".to_string()),
647                    ("e".to_string(), "f".to_string(), "ef".to_string())
648                ],
649                vec![
650                    ("a".to_string(), "d".to_string(), "ad".to_string()),
651                    ("d".to_string(), "e".to_string(), "de".to_string()),
652                    ("e".to_string(), "f".to_string(), "ef".to_string())
653                ]
654            ]
655        );
656
657        //
658        /*assert_eq!(
659            paths,
660            vec![
661                vec![
662                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
663                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
664                    ("c".to_string(), "d".to_string(), "cd".to_string()),
665                    ("d".to_string(), "e".to_string(), "de".to_string()),
666                    ("e".to_string(), "f".to_string(), "ef".to_string())
667                ],
668                vec![
669                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
670                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
671                    ("c".to_string(), "e".to_string(), "ce".to_string()),
672                    ("e".to_string(), "f".to_string(), "ef".to_string())
673                ],
674                vec![
675                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
676                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
677                    ("c".to_string(), "d".to_string(), "cd".to_string()),
678                    ("d".to_string(), "e".to_string(), "de".to_string()),
679                    ("e".to_string(), "f".to_string(), "ef".to_string())
680                ],
681                vec![
682                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
683                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
684                    ("c".to_string(), "e".to_string(), "ce".to_string()),
685                    ("e".to_string(), "f".to_string(), "ef".to_string())
686                ],
687                vec![
688                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
689                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
690                    ("c".to_string(), "d".to_string(), "cd".to_string()),
691                    ("d".to_string(), "e".to_string(), "de".to_string()),
692                    ("e".to_string(), "f".to_string(), "ef".to_string())
693                ],
694                vec![
695                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
696                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
697                    ("c".to_string(), "e".to_string(), "ce".to_string()),
698                    ("e".to_string(), "f".to_string(), "ef".to_string())
699                ],
700                vec![
701                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
702                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
703                    ("c".to_string(), "d".to_string(), "cd".to_string()),
704                    ("d".to_string(), "e".to_string(), "de".to_string()),
705                    ("e".to_string(), "f".to_string(), "ef".to_string())
706                ],
707                vec![
708                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
709                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
710                    ("c".to_string(), "e".to_string(), "ce".to_string()),
711                    ("e".to_string(), "f".to_string(), "ef".to_string())
712                ],
713                vec![
714                    ("a".to_string(), "d".to_string(), "ad".to_string()),
715                    ("d".to_string(), "e".to_string(), "de".to_string()),
716                    ("e".to_string(), "f".to_string(), "ef".to_string())
717                ],
718                vec![
719                    ("a".to_string(), "d".to_string(), "ad".to_string()),
720                    ("d".to_string(), "a".to_string(), "da".to_string()),
721                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
722                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
723                    ("c".to_string(), "e".to_string(), "ce".to_string()),
724                    ("e".to_string(), "f".to_string(), "ef".to_string())
725                ],
726                vec![
727                    ("a".to_string(), "d".to_string(), "ad".to_string()),
728                    ("d".to_string(), "a".to_string(), "da".to_string()),
729                    ("a".to_string(), "b".to_string(), "ab0".to_string()),
730                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
731                    ("c".to_string(), "e".to_string(), "ce".to_string()),
732                    ("e".to_string(), "f".to_string(), "ef".to_string())
733                ],
734                vec![
735                    ("a".to_string(), "d".to_string(), "ad".to_string()),
736                    ("d".to_string(), "a".to_string(), "da".to_string()),
737                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
738                    ("b".to_string(), "c".to_string(), "bc0".to_string()),
739                    ("c".to_string(), "e".to_string(), "ce".to_string()),
740                    ("e".to_string(), "f".to_string(), "ef".to_string())
741                ],
742                vec![
743                    ("a".to_string(), "d".to_string(), "ad".to_string()),
744                    ("d".to_string(), "a".to_string(), "da".to_string()),
745                    ("a".to_string(), "b".to_string(), "ab1".to_string()),
746                    ("b".to_string(), "c".to_string(), "bc1".to_string()),
747                    ("c".to_string(), "e".to_string(), "ce".to_string()),
748                    ("e".to_string(), "f".to_string(), "ef".to_string())
749                ]
750            ]
751        );*/
752
753        println!("-----");
754        for p in paths {
755            println!("{:?}", p)
756        }
757
758        let s = graph.to_dot_string(&String::from("to_dot_multidigraph_test"));
759        println!("Dot:\n{}", s);
760        assert_eq!(s.is_empty(), false);
761        let mut fd = File::create("test_multidirected.dot").expect("error creating file");
762        graph.to_dot_file(&mut fd, &String::from("paths_test"));
763    }
764}