"""Provides utility functions for unit testing.""" from ..pygraph import (DirectedGraph, UndirectedGraph, build_triangle_graph, build_k5_graph, build_k33_graph, build_5_cycle_graph, merge_graphs) def build_simple_test_graph(directed=False): """Builds a simple undirected graph that gets used for testing.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() # There are 7 vertices in the test graph for _ in range(7): graph.new_node() # There are 4 edges in the test graph # --Edge: a graph.new_edge(1, 2) # --Edge: b graph.new_edge(1, 4) # --Edge: c graph.new_edge(2, 5) # --Edge: d graph.new_edge(6, 7) return graph def build_single_node_graph(directed=False): """Builds a graph with a single node for testing.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() graph.new_node() return graph def build_2_node_graph(directed=False): """Builds a 2-node connected graph for testing.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() graph.new_node() graph.new_node() graph.new_edge(1, 2) return graph def build_3_node_line_graph(directed=False): """Builds a 3-node, 2-edge connected line graph for testing.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() graph.new_node() graph.new_node() graph.new_node() graph.new_edge(1, 2) graph.new_edge(2, 3) return graph def build_3_node_line_root_articulation_graph(directed=False): """Builds a 3-node, 2-edge connected line graph for testing, where the root node is the articulation vertex.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() graph.new_node() graph.new_node() graph.new_node() graph.new_edge(1, 2) graph.new_edge(1, 3) return graph def build_biconnected_test_graph(directed=False): """Builds a graph with multiple biconnected components that gets used for testing.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() # There are 12 vertices in the test graph for _ in range(12): graph.new_node() # Nodes 1,2,3 form the first component graph.new_edge(1, 2) graph.new_edge(1, 3) graph.new_edge(2, 3) # Nodes 4,5,6,7 form the second component graph.new_edge(4, 5) graph.new_edge(4, 6) graph.new_edge(5, 6) graph.new_edge(5, 7) graph.new_edge(6, 7) # Nodes 8,9,10,11,12 form the third component graph.new_edge(8, 9) graph.new_edge(8, 10) graph.new_edge(8, 11) graph.new_edge(8, 12) graph.new_edge(9, 10) graph.new_edge(10, 11) graph.new_edge(10, 12) graph.new_edge(11, 12) # Nodes 2 and 5 connect the first and second components graph.new_edge(2, 5) # Nodes 7 and 8 connect the second and third components graph.new_edge(7, 8) return graph def build_fully_biconnected_test_graph(): """Builds a graph with only one biconnected component that gets used for testing.""" graph = build_biconnected_test_graph() # Connect the first and third components to create a ring, converting everything into a single biconnected component graph.new_edge(1, 12) return graph def build_disconnected_test_graph(): """Builds a graph with three disconnected components that gets used for testing.""" graph = build_triangle_graph() g2 = build_triangle_graph() g3 = build_triangle_graph() merge_graphs(graph, g2) merge_graphs(graph, g3) return graph def build_triangle_graph_with_costs(directed=False): """Builds a triangle graph with costs for testing.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() graph.new_node() graph.new_node() graph.new_node() graph.new_edge(1, 2, 1) graph.new_edge(2, 3, 2) graph.new_edge(3, 1, 10) return graph def build_square_test_graph_with_costs(directed=False): """Builds a square graph with costs for testing.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() graph.new_node() graph.new_node() graph.new_node() graph.new_node() graph.new_edge(1, 2, 2) graph.new_edge(1, 4, 10) graph.new_edge(2, 3, 3) graph.new_edge(3, 4, 1) return graph def build_complicated_test_graph_with_one_mst(directed=False): """Builds a test graph that has a unique minimum spanning tree.""" if directed: graph = DirectedGraph() else: graph = UndirectedGraph() for _ in range(7): graph.new_node() graph.new_edge(1, 2, 2) # 1 graph.new_edge(1, 3, 4) # 2 graph.new_edge(1, 4, 1) # 3 graph.new_edge(2, 4, 3) # 4 graph.new_edge(2, 5, 10) # 5 graph.new_edge(3, 4, 2) # 6 graph.new_edge(3, 6, 5) # 7 graph.new_edge(4, 5, 7) # 8 graph.new_edge(4, 6, 8) # 9 graph.new_edge(4, 7, 4) # 10 graph.new_edge(5, 7, 6) # 11 graph.new_edge(6, 7, 1) # 12 return graph def build_non_planar_test_graph_with_k5_subgraph(): """Builds a test graph that contains K5 as a subgraph, and is thus non-planar.""" graph = build_triangle_graph() addition_graph = build_k5_graph() merge_graphs(graph, addition_graph) return graph def build_non_planar_test_graph_with_k33_subgraph(): """Builds a test graph that contains K3,3 as a subgraph, and is thus non-planar.""" graph = build_triangle_graph() addition_graph = build_k33_graph() merge_graphs(graph, addition_graph) return graph def build_non_planar_disconnected_test_graph_with_k5_subgraph(): """Builds a disconnected test graph that contains K5 as a subgraph, and is thus non-planar.""" graph = build_triangle_graph() addition_graph = build_k5_graph() addition_graph2 = build_k5_graph() merge_graphs(graph, addition_graph) merge_graphs(graph, addition_graph2) return graph def build_petersons_graph(): """Builds a non-planar test graph that does not contain K5 or K3,3 as a subgraph (Peterson's Graph). Ref: http://mathworld.wolfram.com/PetersenGraph.html""" graph = build_5_cycle_graph() # --Build a 5-pointed star for _ in range(5): graph.new_node() graph.new_edge(6, 8) graph.new_edge(6, 9) graph.new_edge(7, 9) graph.new_edge(7, 10) graph.new_edge(8, 10) # --Connect it to the outside 5-cycle graph graph.new_edge(1, 6) graph.new_edge(2, 7) graph.new_edge(3, 8) graph.new_edge(4, 9) graph.new_edge(5, 10) return graph