graphalgos/
graphs.rs

1// Contains definition of graph structures.
2use std::cmp::Ordering;
3use std::collections::HashMap;
4use std::fmt;
5use std::fmt::Debug;
6use std::fs::File;
7use std::io::Write;
8use std::io::{BufRead, BufReader, Error};
9
10/// vertex_label_type
11type VLT = String;
12
13/// Edge Type - Directed and Undirected Edge
14#[derive(Debug, Copy, Clone, PartialEq)]
15pub enum EdgeType {
16    Directed,
17    Undirected,
18}
19
20/// Edge Weight Type constraint enum
21///
22/// Weight can only be a numeric type
23///
24/// eg: GNumber::I32(10)
25#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
26pub enum GNumber {
27    U16(u16),
28    U32(u32),
29    U64(u64),
30    I16(i16),
31    I32(i32),
32    I64(i64),
33    F32(f32),
34    F64(f64),
35}
36
37impl fmt::Display for GNumber {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            GNumber::U16(x) => write!(f, "{}", x),
41            GNumber::U32(x) => write!(f, "{}", x),
42            GNumber::U64(x) => write!(f, "{}", x),
43            GNumber::I16(x) => write!(f, "{}", x),
44            GNumber::I32(x) => write!(f, "{}", x),
45            GNumber::I64(x) => write!(f, "{}", x),
46            GNumber::F32(x) => write!(f, "{}", x),
47            GNumber::F64(x) => write!(f, "{}", x),
48        }
49    }
50}
51
52/// This is the basic graph structure. Graph consists of vertices, edges and edge_type
53///
54/// # Vertices:
55///
56/// Vertices - Hashmap of type String, Vertex. Vertex has a label and a value
57///
58/// Example: A vertex with label A and value 10 will look like this
59/// ```
60///  self.vertices.insert(
61///     String::from("A");
62///     Vertex {
63///         label: String::from("A"),
64///         value: 10,
65///     },
66/// );
67/// ```
68///
69/// The structure of the vertex
70///
71/// ```
72/// pub struct Vertex<T> {
73///     pub label: VLT,
74///     pub value: T,
75/// }
76/// ```
77///
78/// # Edges:
79///
80/// Edges - Hashmap of type (VLT, VLT), Edge.
81///
82/// (VLT, VLT) are two end points of the edge.
83///
84/// Edge has weight and edge type
85///
86/// Example:
87///
88/// ```
89/// HashMap - Key: (String::from("A"), String::from("B")) | Value: Edge
90/// ```
91///
92/// Edge Looks like this:
93///
94/// ```
95/// pub struct Edge {
96///     pub endpoints: (VLT, VLT),
97///     pub weight: GNumber,
98///     pub edge_type: EdgeType,
99///}
100/// ```
101///
102/// # Edge Type
103///
104/// edge_type: EdgeType - Directed or Undirected
105#[derive(Clone)]
106pub struct Graph {
107    pub vertices: HashMap<VLT, Vertex>,
108    pub edges: HashMap<(VLT, VLT), Edge>,
109    pub edge_type: EdgeType,
110}
111
112impl Graph {
113    /// Creates a new Graph
114    ///
115    /// # Parameters:
116    ///
117    /// directed - type boolean
118    ///
119    /// directed = true if we want a directed graph
120    ///
121    /// directed = false if we want an undirected graph
122    ///
123    /// # Return value
124    ///
125    /// This function returns Graph - directed or undirected based on the parameter passed (Graph)
126    ///
127    /// # Example
128    ///
129    /// Basic Usage:
130    ///
131    /// 1. Undirected graph:
132    /// ```
133    /// let mut g: graphs::Graph = graphs::Graph::new(false);
134    /// ```
135    /// 2. Directed graph:
136    /// ```
137    /// let mut g: graphs::Graph = graphs::Graph::new(true);
138    /// ```
139    pub fn new(directed: bool) -> Graph {
140        //Create an empty graph.
141        let v: HashMap<VLT, Vertex> = HashMap::new();
142        let e: HashMap<(VLT, VLT), Edge> = HashMap::new();
143        let edge_type = if directed {
144            EdgeType::Directed
145        } else {
146            EdgeType::Undirected
147        };
148        Graph {
149            vertices: v,
150            edges: e,
151            edge_type: edge_type,
152        }
153    }
154
155    /// Prints the graph
156    ///
157    /// # usage:
158    /// ```
159    /// let mut g: graphs::Graph = graphs::Graph::new(false); // creates undirected graph
160    /// g.print() // prints the graph
161    /// ```
162    pub fn print(&self) {
163        println!("Vertices:");
164        for (id, vertex) in &self.vertices {
165            println!("{:?}: {:?}", id, vertex);
166        }
167
168        println!("Edges:");
169        for ((src, dst), edge) in &self.edges {
170            println!("({:?}, {:?}) -> {:?}", src, dst, edge);
171        }
172    }
173
174    /// Returns topological sorted order of the vertice of the graph
175    ///
176    pub fn get_topological_order(&mut self) -> Vec<VLT> {
177        //FIXME: Function not finished.
178        //TODO: Consider moving to utils.
179        let mut g: Graph = Graph::new(true);
180        let nodes = g.get_vertices().keys();
181        // let nodes =  g.edges;
182        let mut order: Vec<VLT> = vec![];
183        let visited_vertex: HashMap<VLT, bool> = HashMap::new();
184
185        for node in nodes {
186            if visited_vertex.get(node) == None {
187                self.get_order(node, &mut order);
188            }
189        }
190        order.reverse();
191        println!("{:?}", order);
192        return order;
193    }
194
195    pub fn get_order(&mut self, node: &VLT, order: &mut Vec<VLT>) {
196        //TODO: Consider moving to utils.
197        let mut g: Graph = Graph::new(true);
198        //let coming_nodes = self.get_vertices().get(node);
199        let coming_nodes = g.get_vertices().keys();
200
201        for _value in coming_nodes {
202            self.get_order(node, order)
203        }
204        // if new_graph.get(node) == None {
205        // if coming_nodes != None {
206        //     for value in coming_nodes. {
207        //         self.get_order(value, order);
208        //     }
209        // }
210        if !order.contains(node) {
211            order.push(node.to_string()); //FIXME: Is .to_string needed here?
212        }
213    }
214
215    pub fn get_vertices(&mut self) -> &mut HashMap<VLT, Vertex> {
216        &mut self.vertices
217    }
218
219    pub fn get_edges(&mut self) -> &mut HashMap<(VLT, VLT), Edge> {
220        &mut self.edges
221    }
222
223    /// Add vertex to the graph
224    ///
225    /// # Parameters:
226    ///
227    /// 1. label - the label of the vertex which should be of type String
228    ///
229    /// 2. value - value of the vertex, any generic
230    ///
231    /// # Example
232    ///
233    /// ```
234    /// let mut G: graphs::Graph = graphs::Graph::new(false); // create undirected graph
235    /// g.add_vertex(String::from("A")); // add vertex to the graph with label A and value 0
236    /// ```
237    pub fn add_vertex(&mut self, label: VLT) {
238        //Add vertex to graph.
239        if self.contains_vertex(&label) {
240            // self.vertices.iter().any(|vert| vert.label.eq(&label)){
241            //TODO: Create more sophosticated handling.
242            //println!("Vertex '{}' already in graph", label);
243        } else {
244            self.vertices.insert(
245                label.clone(),
246                Vertex {
247                    label: label,
248                    value: 0f64,
249                },
250            );
251        }
252    }
253
254    /// Remove vertex and all of its adjacent edges.
255    ///
256    /// # Parameters
257    ///
258    /// 1. label: The label of the vertex
259    ///
260    /// # Example
261    ///
262    /// ```
263    /// g.remove_vertex(String::from("A")); // Remove vertex A from the graph G
264    /// ```
265    ///  
266    pub fn remove_vertex(&mut self, label: VLT) {
267        // Find all neighbors.
268        let neighbors = self.get_neighbors(&label);
269
270        // Remove all edges, regardless of direction.
271        // TODO: Decide on handling of directed vs undirected graphs.
272        for vert_label in neighbors.into_iter() {
273            //FIXME: Keep an eye on these '.to_string' uses.
274            self.remove_edge((label.clone(), vert_label.to_string()));
275            self.remove_edge((vert_label.to_string(), label.clone()));
276        }
277
278        //Remove central vertex.
279        self.vertices.remove(&label);
280    }
281
282    /// Adds an edge to the graph (Endpoint vertices must be present in graph)
283    ///
284    /// # Parameters
285    ///
286    /// 1. (endpoint1, endpoint2) - the two endpoints of the edge each will be of type String
287    ///
288    /// 2. weight - The weight of the edge
289    ///
290    /// # Example
291    ///
292    /// ```
293    /// // Edge with I32 weights having endpoints "A" and "B"
294    ///  g.add_edge(
295    ///     (String::from("A"), String::from('B')),
296    ///     graphs::GNumber::I32(4),
297    /// );
298    ///
299    /// // Edge with F32 weights having endpoints "A" and "B"
300    /// g2.add_edge(
301    ///     (String::from("A"), String::from('B')),
302    ///     graphs::GNumber::F32(4.),
303    /// );
304    ///
305    /// // Edge with U32 weights having endpoints "A" and "B"
306    /// g3.add_edge(
307    ///     (String::from("A"), String::from('B')),
308    ///     graphs::GNumber::U32(2),
309    /// );
310    /// ```
311    pub fn add_edge(&mut self, e: (VLT, VLT), weight: GNumber) {
312        let edge_type = self.edge_type;
313
314        let is_undirected = match edge_type {
315            EdgeType::Directed => false,
316            EdgeType::Undirected => true,
317        };
318
319        if self.contains_edge(&e) {
320            //println!("Edge '{}'-'{}' already in graph", e.0, e.1);
321            return;
322        }
323
324        if is_undirected {
325            let rev = (e.1.clone(), e.0.clone());
326            if self.contains_edge(&rev) {
327                //println!("Edge '{}'-'{}' already in graph", e.1, e.0);
328                return;
329            }
330        }
331
332        if self.contains_vertex(&e.0) && self.contains_vertex(&e.1) {
333            self.edges.entry(e.clone()).or_insert(Edge {
334                endpoints: e,
335                weight: weight,
336                edge_type,
337            });
338        }
339    }
340
341    /// Update the weight of an edge to the graph (Edge must be present in graph)
342    ///
343    /// # Parameters
344    ///
345    /// 1. (endpoint1, endpoint2) - the two endpoints of the edge each will be of type String
346    ///
347    /// 2. weight - The weight of the edge
348    ///
349    /// # Example
350    ///
351    /// ```
352    /// // This will update the value of the edge with endpoint (A, B) to 10 (I32 value)
353    ///  g.update_edge(
354    ///     (String::from("A"), String::from('B')),
355    ///     graphs::GNumber::I32(10),
356    /// );
357    /// ```
358    pub fn update_edge(&mut self, e: (VLT, VLT), weight: GNumber) {
359        if self.contains_edge(&e) {
360            self.edges.insert(
361                e.clone(),
362                Edge {
363                    endpoints: e,
364                    weight: weight,
365                    edge_type: EdgeType::Undirected,
366                },
367            );
368        }
369    }
370
371    /// Removes an edge from a graph (Endpoint vertices are not affected)
372    ///
373    /// # Parameters
374    ///
375    /// 1. (endpoint1, endpoint2) - the two endpoints of the edge (type String)
376    ///
377    /// # Example
378    ///
379    /// ```
380    /// // This will remove edge with endpoints A and B
381    ///  g.remove_edge(
382    ///     (String::from("A"), String::from('B')),
383    /// );
384    /// ```
385    pub fn remove_edge(&mut self, e: (VLT, VLT)) {
386        let target_edge = self.edges.get(&e);
387        match target_edge {
388            Some(te) => match te.edge_type {
389                EdgeType::Directed => {
390                    if self.edges.contains_key(&e) {
391                        self.edges.remove(&e);
392                    }
393                }
394                EdgeType::Undirected => {
395                    let re = (e.1.clone(), e.0.clone()); //reverse_edge
396                    if self.edges.contains_key(&e) || self.edges.contains_key(&re) {
397                        self.edges.remove(&e);
398                        self.edges.remove(&re);
399                    }
400                }
401            },
402            None => println!("Edge '{}'-'{}' not in graph", e.0, e.1),
403        }
404    }
405
406    /// Input a vertex label (Returns a vector of vertex labels which correspond to the neighbors of the input vertex)
407    ///
408    /// # Parameter:
409    ///
410    /// 1. label - Label of type String
411    ///
412    /// # Return Value:
413    ///
414    /// Returns a vector of labels of all the vertices that are neighbors of this vertex
415    ///
416    /// # Example
417    ///
418    /// ```
419    /// G.get_neighbors(String::from("A")) // returns all the neighbors of A
420    ///
421    /// // example return: ["B", "C", "D"]. If B, C and D are neighbors of A
422    /// ```
423    pub fn get_neighbors(&self, label: &VLT) -> Vec<VLT> {
424        let mut neighbors: Vec<VLT> = Vec::<VLT>::new();
425        for (edge_labels, _edge) in self.edges.iter() {
426            if (label).eq(&edge_labels.0) {
427                neighbors.push(edge_labels.1.clone())
428            } else if (label).eq(&edge_labels.1) {
429                neighbors.push(edge_labels.0.clone())
430            }
431        }
432        neighbors
433    }
434
435    /// Input a vertex label. Returns a vector of vertex labels which correspond to the outgoing neighbors of the input vertex.
436    ///
437    /// # Parameter:
438    ///
439    /// 1. label - Label of type String
440    ///
441    /// # Return Value:
442    ///
443    /// Returns a vector of labels of all the vertices that are outgoing neighbors of this vertex.
444    /// This is for a directed graph
445    ///
446    /// # Example
447    ///
448    /// ```
449    /// g.get_out_neighbors(String::from("A")) // returns all the  outgoing neighbors of A
450    ///
451    /// // example return: ["B", "C", "D"].
452    /// // A -> B, A -> C, A -> D
453    pub fn get_out_neighbors(&self, label: &VLT) -> Vec<VLT> {
454        let mut neighbors: Vec<VLT> = Vec::<VLT>::new();
455        for (edge_labels, _edge) in self.edges.iter() {
456            if (label).eq(&edge_labels.0) {
457                neighbors.push(edge_labels.1.clone())
458            }
459        }
460        neighbors
461    }
462
463    /// Input a vertex label. Returns a vector of vertex labels which correspond to the incoming neighbors of the input vertex.
464    ///
465    /// # Parameter:
466    ///
467    /// 1. label - Label of type String
468    ///
469    /// # Return Value:
470    ///
471    /// Returns a vector of labels of all the vertices that are incoming neighbors of this vertex.
472    /// This is for a directed graph
473    ///
474    /// # Example
475    ///
476    /// ```
477    /// G.get_in_neighbors(String::from("A")) // returns all the incoming neighbors of A
478    ///
479    /// // example return: ["B", "C", "D"].
480    /// // B -> A, C -> A, D -> A
481    pub fn get_in_neighbors(&self, label: &VLT) -> Vec<VLT> {
482        let mut neighbors: Vec<VLT> = Vec::<VLT>::new();
483        for (edge_labels, _edge) in self.edges.iter() {
484            if (label).eq(&edge_labels.1) {
485                neighbors.push(edge_labels.0.clone())
486            }
487        }
488        neighbors
489    }
490
491    // TODO: Documentation
492    /// Reads an adjacency matrix from a file and returns it as a `Vec<Vec<u32>>`
493    pub fn read_adjacency_matrix(filename: &str) -> Result<Vec<Vec<u32>>, Error> {
494        // Open the file for reading.
495        let file = File::open(filename)?;
496        // Create a buffered reader to read the file line by line.
497        let reader = BufReader::new(file);
498        // Initialize an empty vector to hold the matrix.
499        let mut matrix: Vec<Vec<u32>> = Vec::new();
500        // Iterate over each line in the file.
501        for line in reader.lines() {
502            // Parse each line as a vector of u32 values.
503            let row: Vec<u32> = line?
504                .split_whitespace() // Split the line by space.
505                .map(|s| s.parse().unwrap()) // Parse each value as u32
506                .collect(); // Collect the values into a vector.
507                            // Add the row to the matrix.
508            matrix.push(row);
509        }
510
511        // Return the completed matrix.
512        Ok(matrix)
513    }
514
515    // TODO: Documentation
516    /// Writes an adjacency matrix to a file.
517    pub fn write_adjacency_matrix(matrix: &[Vec<u32>], filename: &str) -> Result<(), Error> {
518        // Open the file for writing.
519        let mut file = File::create(filename)?;
520
521        // Iterate over each row in the matrix.
522        for row in matrix.iter() {
523            // Convert the row to a string, separating each value with a space.
524            let row_str = row
525                .iter()
526                .map(|x| x.to_string())
527                .collect::<Vec<String>>()
528                .join(" ");
529
530            // Write the row string to the file, followed by a newline character.
531            writeln!(file, "{}", row_str)?;
532        }
533
534        // Return success.
535        Ok(())
536    }
537
538    /// Function to get the vertex given the label
539    ///
540    /// # Parameters:
541    ///
542    /// 1. label - Label of the vertex - type String
543    ///
544    /// # Return Type:
545    ///
546    /// Returns an Option of type mutable `Vertex`. If there are no vertex with the provided label - None will be returned
547    ///
548    /// # Example
549    ///
550    /// ```
551    /// let vertex_A = g.get_vertex(String::from("A")); // this wil return the vertex A which is mutable (We can change the value of the vertex)
552    /// ```
553    pub fn get_vertex(&mut self, label: &VLT) -> Option<&mut Vertex> {
554        self.vertices.get_mut(label)
555    }
556
557    /// Function to check if the given vertex is present in the graph
558    ///
559    /// # Parameters
560    ///
561    /// 1. label - Label of the vertex - type String
562    ///
563    /// # Return Type
564    ///
565    /// Returns a boolean value.
566    ///
567    /// true - if the vertex is present in the graph
568    ///
569    /// false - if the vertex is not present in the graph
570    ///
571    /// # Example
572    ///
573    /// ```
574    /// if g.contains_vertex(String::from("A")){
575    ///     // Do something
576    /// }
577    /// ```
578    fn contains_vertex(&self, label: &VLT) -> bool {
579        //Check if graph contain vertex with label.
580        self.vertices.contains_key(label)
581    }
582
583    /// Function to check if the given edge is present in the graph
584    ///
585    /// # Parameters
586    ///
587    /// 1. (endpoint1, endpoint2) - endpoints of the edge (String, String)
588    ///
589    /// # Return Type
590    ///
591    /// Returns a boolean value.
592    ///
593    /// true - if the edge is present in the graph
594    ///
595    /// false - if the edge is not present in the graph
596    ///
597    /// # Example
598    ///
599    /// ```
600    /// // Check if the edge A-B is present in the graph
601    /// // Note if the graph is directed, it will return true only if the edge A -> B is present. B -> A will not be counted
602    /// if g.contains_edge((String::from("A"), String::from("B"))){
603    ///     // Do something
604    /// }
605    /// ```
606    fn contains_edge(&self, e: &(VLT, VLT)) -> bool {
607        //Check if graph contain an edge.
608        self.edges.contains_key(e)
609    }
610}
611
612//Internal macro that matches the pattern of a single expession (indicating the user would like to add a vertex,
613//or a tuple-like pattern (str, i32, str), indicating the user would like an edge.
614#[allow(unused_macros)]
615#[macro_export]
616#[doc(hidden)]
617macro_rules! edg_or_vert {
618    ( $G:expr, ($a:literal, $b:literal, $c:literal) ) => {
619        {
620            $G.add_vertex(String::from($a));
621            $G.add_vertex(String::from($c));
622            $G.add_edge((String::from($a), String::from($c)), GNumber::I32($b));
623        }
624    };
625
626    ( $G:expr, $($x:expr ),* ) => {
627        {
628            {
629                $(
630                    $G.add_vertex(String::from($x));
631                )*
632            }
633        }
634    };
635}
636
637/// Function to check if the given vertex is present in the graph
638///
639/// # Parameters
640///
641/// 1. label - Label of the vertex - type String
642///
643/// # Return Type
644///
645/// Returns a boolean value.
646///
647/// true - if the vertex is present in the graph
648///
649/// false - if the vertex is not present in the graph
650///
651/// # Example
652///
653/// ```
654/// if g.contains_vertex(String::from("A")){
655///     // Do something
656/// }
657/// ```
658
659///Build an undirected graph
660///
661///Requires importing at least graphalgos::graphs::{Graph, GNumber} and graphalgos::gph.
662///This macro can make both vertices and edges.
663///For a vertex, simple pass a string literal to be that vertex's label.
664///For an edge, write a pattern of the form (str, i32, str) where the first and last element represent the label of a vertex, and the middle value is the edges weight.
665///
666///# Example
667/// ```
668/// let G = gph!("A", "B", "C", ("A", 3, "C"), ("B", 7, "D"))
669/// ```
670///Notice that we do not need to list all vertices before adding edges for them, as shown in the last edge pattern.
671#[macro_export]
672macro_rules! gph {
673    ( $($sub:tt),* ) => { //iterate over every token. Could be a single string or an edge tuple.
674        {
675            let mut g: Graph = Graph::new(false);
676            $(
677                $crate::edg_or_vert!(&mut g, $sub);
678            )*
679            g
680        }
681    };
682}
683
684/// Vertex Structure
685///
686/// The structure of the vertex
687///
688/// A vertex has a label and a value
689///
690/// Label is a string and value is f64
691#[derive(Debug, Clone)]
692pub struct Vertex {
693    pub label: VLT,
694    pub value: f64,
695}
696
697impl Vertex {
698    pub fn get_value(&self) -> f64 {
699        self.value.clone()
700    }
701}
702
703impl Vertex {
704    pub fn set_value(&mut self, new_value: f64) {
705        self.value = new_value;
706    }
707}
708
709impl PartialEq for Vertex {
710    //Two vertices are equal if they have the same label.
711    fn eq(&self, other: &Self) -> bool {
712        self.label == other.label
713    }
714}
715
716impl Eq for Edge {}
717
718impl Ord for Edge {
719    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
720        self.weight.partial_cmp(&other.weight).unwrap()
721    }
722}
723
724impl PartialOrd for Edge {
725    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
726        self.weight.partial_cmp(&other.weight)
727    }
728}
729
730/// Edge Structure
731///
732/// Edges have three fields
733///
734/// 1. endpoints (a,b) - this contains the info of the two vertices of the edge (A -- B)
735/// 2. weight - the weight of the edge. It's of type GNumber
736/// 3. edge_type - the type of the edge (Directed / Undirected)
737#[derive(Debug, Clone)]
738pub struct Edge {
739    pub endpoints: (VLT, VLT),
740    pub weight: GNumber,
741    pub edge_type: EdgeType,
742}
743
744impl PartialEq for Edge {
745    fn eq(&self, e: &Edge) -> bool {
746        let ends1 = &self.endpoints;
747        let ends2 = &e.endpoints;
748        match self.edge_type {
749            EdgeType::Directed => (ends1.0).eq(&ends2.0) && (ends1.1).eq(&ends2.1),
750            EdgeType::Undirected => {
751                (ends1.0).eq(&ends2.0) && (ends1.1).eq(&ends2.1)
752                    || (ends1.1).eq(&ends2.1) && (ends1.0).eq(&ends2.0)
753            }
754        }
755    }
756}
757
758/// Test cases
759#[cfg(test)]
760mod graph_tests {
761    //extern crate graphs;
762    //use graphs::Graph;
763    use super::*;
764
765    fn get_test_graph_1() -> Graph {
766        let mut g: Graph = Graph::new(false);
767        g.add_vertex(String::from("A"));
768        g.add_vertex(String::from("B"));
769        g.add_vertex(String::from("C"));
770        g.add_vertex(String::from("D"));
771        g.add_vertex(String::from("E"));
772        g.add_vertex(String::from("F"));
773        g.add_vertex(String::from("G"));
774        g.add_vertex(String::from("H"));
775        g.add_vertex(String::from("I"));
776        g
777    }
778
779    #[test]
780    fn add_one_vertex() {
781        let mut g: Graph = Graph::new(false);
782        g.add_vertex(String::from("A"));
783        assert_eq!(g.get_vertices().len(), 1);
784        assert_eq!(g.get_vertex(&String::from("A")).unwrap().label, "A");
785    }
786
787    #[test]
788    fn add_multiple_vertices() {
789        let mut g = get_test_graph_1();
790        assert_eq!(g.get_vertices().len(), 9);
791        assert_eq!(g.get_vertex(&String::from("A")).unwrap().label, "A");
792        assert_eq!(g.get_vertex(&String::from("C")).unwrap().label, "C");
793        assert_eq!(g.get_vertex(&String::from("H")).unwrap().label, "H");
794        assert_eq!(g.get_vertex(&String::from("H")).unwrap().label, "H");
795        assert_eq!(g.get_vertex(&String::from("I")).unwrap().label, "I");
796    }
797
798    #[test]
799    fn remove_one_vertex() {
800        let mut g = get_test_graph_1();
801        g.remove_vertex(String::from("F"));
802        assert_eq!(g.get_vertices().len(), 8);
803        assert_eq!(g.get_vertices().get("F").is_none(), true);
804    }
805
806    #[test]
807    fn remove_multiple_vertices() {
808        let mut g = get_test_graph_1();
809        g.remove_vertex(String::from("I"));
810        g.remove_vertex(String::from("H"));
811        assert_eq!(g.get_vertices().len(), 7);
812        g.remove_vertex(String::from("E"));
813        assert_eq!(g.get_vertices().len(), 6);
814        g.remove_vertex(String::from("A"));
815        g.remove_vertex(String::from("B"));
816        assert_eq!(g.get_vertices().len(), 4);
817        g.remove_vertex(String::from("I"));
818        assert_eq!(g.get_vertices().len(), 4);
819        g.remove_vertex(String::from("G"));
820        g.remove_vertex(String::from("F"));
821        g.remove_vertex(String::from("D"));
822        g.remove_vertex(String::from("C"));
823        assert_eq!(g.get_vertices().len(), 0);
824    }
825
826    #[test]
827    fn add_one_undirected_edge() {
828        let mut g = get_test_graph_1();
829        g.add_edge((String::from("A"), String::from('B')), GNumber::F64(4.));
830        assert_eq!(g.get_edges().len(), 1);
831    }
832
833    #[test]
834    fn make_from_macro() {
835        let mut g = gph!("A", "B");
836        assert_eq!(g.get_vertices().len(), 2);
837        let mut g = gph!("C", ("A", 5, "B"));
838        assert_eq!(g.get_vertices().len(), 3);
839        assert_eq!(g.get_edges().len(), 1);
840    }
841}