algods 0.1.0

A collection of data structures and algorithms
Documentation
#[cfg(test)]
mod tests {
    use super::super::{DirectedGraph, EdgeWeightedDigraph};
    use crate::graph::processing::{
        BreadthFirstSearch, DepthFirstSearch, StrongConnectedComponent, TopologicalSort,
    };

    #[test]
    fn test_directed_graph() {
        let n: usize = 10;
        let mut graph = DirectedGraph::init(n);
        assert_eq!(graph.nb_vertices(), n);
        graph.add_edge(0, 5);
        graph.add_edge(4, 8);
        graph.add_edge(7, 4);
        assert_eq!(graph.nb_edges(), 3);
        assert_eq!(graph.out_degree(&2), 0);
        assert_eq!(graph.out_degree(&4), 1);
        assert_eq!(graph.in_degree(&0), 0);
        assert_eq!(graph.in_degree(&8), 1);
        assert_eq!(graph.self_loop_number(), 0);
        graph.add_edge(0, 0);
        assert_eq!(graph.self_loop_number(), 1);
    }

    #[test]
    fn test_edge_weighted_directed_graph() {
        let n: usize = 10;
        let mut graph = EdgeWeightedDigraph::<i8>::init(n);
        assert_eq!(graph.nb_vertices(), n);
        graph.add_edge(0, 5, 1);
        graph.add_edge(4, 8, 1);
        graph.add_edge(7, 4, 1);
        assert_eq!(graph.nb_edges(), 3);
        assert_eq!(graph.out_degree(&2), 0);
        assert_eq!(graph.out_degree(&4), 1);
        assert_eq!(graph.in_degree(&0), 0);
        assert_eq!(graph.in_degree(&4), 1);
        assert_eq!(graph.self_loop_number(), 0);
        graph.add_edge(0, 0, 1);
        assert_eq!(graph.self_loop_number(), 1);
    }

    #[test]
    #[should_panic]
    fn test_directed_graph_panic1() {
        let n: usize = 2;
        let mut graph = DirectedGraph::init(n);
        graph.add_edge(4, 1);
    }

    #[test]
    #[should_panic]
    fn test_directed_graph_panic2() {
        let graph = DirectedGraph::new();
        graph.average_degree();
    }

    #[test]
    fn test_dfs() {
        let mut graph = DirectedGraph::init(9);
        graph.add_edge(0, 1);
        graph.add_edge(0, 2);
        graph.add_edge(0, 6);
        graph.add_edge(0, 5);
        graph.add_edge(6, 4);
        graph.add_edge(4, 3);
        graph.add_edge(5, 4);
        graph.add_edge(5, 3);

        let mut dfs = DepthFirstSearch::init(graph.nb_vertices, 0);
        dfs.find_paths(&graph);
        assert_eq!(dfs.path_to(2), Some(vec![2, 0]));
        assert!(
            dfs.path_to(4) == Some(vec![4, 6, 0])
                || dfs.path_to(4) == Some(vec![4, 5, 0])
                || dfs.path_to(4) == Some(vec![4, 3, 5, 0])
        );
    }

    #[test]
    fn test_bfs() {
        let mut graph = DirectedGraph::init(9);
        graph.add_edge(0, 1);
        graph.add_edge(0, 2);
        graph.add_edge(0, 6);
        graph.add_edge(0, 5);
        graph.add_edge(6, 4);
        graph.add_edge(4, 3);
        graph.add_edge(5, 4);
        graph.add_edge(5, 3);

        let mut bfs = BreadthFirstSearch::init(graph.nb_vertices, 0);
        bfs.find_paths(&graph);
        assert_eq!(bfs.path_to(2), Some(vec![2, 0]));
        assert!(bfs.path_to(4) == Some(vec![4, 6, 0]) || bfs.path_to(4) == Some(vec![4, 5, 0]));
        assert_eq!(bfs.path_to(5), Some(vec![5, 0]));
    }

    #[test]
    fn test_topological_sort() {
        let mut graph = DirectedGraph::init(7);
        graph.add_edge(0, 1);
        graph.add_edge(0, 2);
        graph.add_edge(0, 5);
        graph.add_edge(1, 4);
        graph.add_edge(3, 2);
        graph.add_edge(3, 4);
        graph.add_edge(3, 5);
        graph.add_edge(3, 6);
        graph.add_edge(5, 2);
        graph.add_edge(6, 4);
        graph.add_edge(6, 0);

        let mut topo = TopologicalSort::init(graph.nb_vertices);
        topo.depth_first_order(&graph);
        assert!(
            topo.reverse_postorder() == &vec![4, 1, 2, 5, 0, 6, 3]
                || topo.reverse_postorder() == &vec![2, 5, 4, 1, 0, 6, 3]
                || topo.reverse_postorder() == &vec![2, 4, 1, 5, 0, 6, 3]
        );
        for (pos, a) in topo.order().enumerate() {
            if pos == 0 {
                assert_eq!(a, &3);
            }
            if pos == 1 {
                assert_eq!(a, &6);
            }
            if pos == 2 {
                assert_eq!(a, &0);
            }
            if pos == 3 {
                assert!(a == &5 || a == &1);
            }
            if pos == 4 {
                assert!(a == &1 || a == &2 || a == &4);
            }
            if pos == 5 {
                assert!(a == &1 || a == &5 || a == &4);
            }
            if pos == 6 {
                assert!(a == &2 || a == &4);
            }
        }
    }

    #[test]
    fn test_strong_connected_components() {
        let mut graph = DirectedGraph::init(13);
        graph.add_edge(0, 1);
        graph.add_edge(0, 5);
        graph.add_edge(2, 0);
        graph.add_edge(2, 3);
        graph.add_edge(3, 2);
        graph.add_edge(3, 5);
        graph.add_edge(4, 2);
        graph.add_edge(4, 3);
        graph.add_edge(5, 4);
        graph.add_edge(6, 0);
        graph.add_edge(6, 4);
        graph.add_edge(6, 8);
        graph.add_edge(6, 9);
        graph.add_edge(7, 6);
        graph.add_edge(7, 9);
        graph.add_edge(8, 6);
        graph.add_edge(9, 10);
        graph.add_edge(9, 11);
        graph.add_edge(10, 12);
        graph.add_edge(11, 4);
        graph.add_edge(11, 12);
        graph.add_edge(12, 9);

        let mut scc = StrongConnectedComponent::init(graph.nb_vertices);
        scc.find_scc(&graph);
        assert!(scc.connected(0, 3).unwrap());
        assert!(scc.connected(0, 2).unwrap());
        assert!(scc.connected(0, 4).unwrap());
        assert!(scc.connected(0, 5).unwrap());
        assert!(!scc.connected(0, 1).unwrap());
        assert!(scc.connected(9, 10).unwrap());
        assert!(scc.connected(9, 11).unwrap());
        assert!(scc.connected(11, 10).unwrap());
        assert!(!scc.connected(9, 8).unwrap());
    }
}