def test_5_add_edge_missing_verts(self): new_vert_1 = Vertex(5, 0) new_vert_2 = Vertex(6, 0) with self.assertRaises(KeyError): self.g.add_edge(new_vert_1.id, new_vert_2.id) self.assertEqual(self.g.get_edge_count(), 4) self.assertFalse(self.g.has_edge(new_vert_1.id, new_vert_2.id))
def test_SaveGraph_0_normal_graph(self): saved_g = Graph() v1 = Vertex("1", "black") v2 = Vertex("2", "white") v3 = Vertex("3", "black") v4 = Vertex("4", "white") v5 = Vertex("5", "black") saved_g.add_vert(v1) saved_g.add_vert(v2) saved_g.add_vert(v3) saved_g.add_vert(v4) saved_g.add_vert(v5) saved_g.add_edge(v1.id, v2.id) saved_g.add_edge(v1.id, v3.id) saved_g.add_edge(v2.id, v3.id) saved_g.add_edge(v3.id, v4.id) saved_xml_str = save_graph(saved_g, "SaveGraph_0_saved_normal_graph.xml") # Note: testing the string against a model is tedious because the order # of edges varies. # Test loaded graph loaded_g = load_graph("SaveGraph_0_saved_normal_graph.xml") self.assertEqual(loaded_g.get_vert_count(), 5) self.assertEqual(loaded_g.get_edge_count(), 4) self.assertTrue(loaded_g.has_vert(v1.id)) self.assertTrue(loaded_g.has_vert(v2.id)) self.assertTrue(loaded_g.has_vert(v3.id)) self.assertTrue(loaded_g.has_vert(v4.id)) self.assertTrue(loaded_g.has_vert(v5.id)) self.assertTrue(loaded_g.has_edge(v1.id, v2.id)) self.assertTrue(loaded_g.has_edge(v1.id, v3.id)) self.assertTrue(loaded_g.has_edge(v2.id, v3.id)) self.assertTrue(loaded_g.has_edge(v3.id, v4.id)) self.assertFalse(loaded_g.has_edge(v2.id, v4.id)) self.assertEqual(loaded_g.get_vert(v1.id).color, "black") self.assertEqual(loaded_g.get_vert(v2.id).color, "white") self.assertEqual(loaded_g.get_vert(v3.id).color, "black") self.assertEqual(loaded_g.get_vert(v4.id).color, "white") self.assertEqual(loaded_g.get_vert(v5.id).color, "black") self.assertEqual(loaded_g.neighbors(v1.id), {v2, v3}) self.assertEqual(loaded_g.neighbors(v2.id), {v3, v1}) self.assertEqual(loaded_g.neighbors(v3.id), {v1, v2, v4}) self.assertEqual(loaded_g.neighbors(v4.id), {v3}) self.assertEqual(loaded_g.neighbors(v5.id), set())
def test_1_add_vert_already_in(self): v1_copy = Vertex(1, 0) with self.assertRaises(ValueError): self.g.add_vert(v1_copy) v1_copy = Vertex(1, 1) # Same id, different color with self.assertRaises(ValueError): # Should also err; Vertex equality and hashing is based only on id. self.g.add_vert(v1_copy) self.assertEqual(self.g.get_vert_count(), 4)
def test_16_neighbors(self): v5 = Vertex(5, 0) v6 = Vertex(6, 0) self.g.add_vert(v5) self.assertEqual(self.g.neighbors(v5.id), set()) self.g.add_vert(v6) self.g.add_edge(v5.id, v6.id) self.assertEqual(self.g.neighbors(v5.id), {v6}) self.assertEqual(self.g.neighbors(v6.id), {v5})
def test_2_add_edge(self): new_vert = Vertex(5, 0) self.g.add_vert(new_vert) self.g.add_edge(self.v4.id, new_vert.id) self.assertEqual(self.g.get_vert_count(), 5) self.assertEqual(self.g.get_edge_count(), 5) self.assertTrue(self.g.has_vert(new_vert.id)) self.assertTrue(self.g.has_edge(new_vert.id, self.v4.id)) self.assertEqual(self.g.neighbors(new_vert.id), {self.v4}) self.g.add_edge(self.v4.id, self.v1.id) self.assertEqual(self.g.get_edge_count(), 6) self.assertTrue(self.g.has_edge(self.v1.id, self.v4.id)) self.assertEqual(self.g.neighbors(self.v4.id), {new_vert, self.v1, self.v3}) # Edge to self self.g.add_edge(new_vert.id, new_vert.id) self.assertEqual(self.g.get_edge_count(), 7) self.assertTrue(self.g.has_edge(new_vert.id, new_vert.id)) self.assertEqual(self.g.neighbors(new_vert.id), {new_vert, self.v4})
def test_0_add_vert_normal(self): new_vert = Vertex(5, 0) self.g.add_vert(new_vert) self.assertEqual(self.g.get_vert_count(), 5) self.assertTrue(self.g.has_vert(new_vert.id)) self.assertEqual(self.g.neighbors(new_vert.id), set())
def test_7_del_vert_missing(self): new_vert = Vertex(5, 0) with self.assertRaises(KeyError): self.g.del_vert(new_vert.id) self.assertEqual(self.g.get_vert_count(), 4) self.assertEqual(self.g.get_edge_count(), 4)
def test_4_add_edge_missing_vert(self): new_vert = Vertex(5, 0) with self.assertRaises(KeyError): self.g.add_edge(self.v1.id, new_vert.id) self.assertEqual(self.g.get_edge_count(), 4) self.assertFalse(self.g.has_edge(self.v1.id, new_vert.id))
def setUp(self): self.g = Graph() self.v1 = Vertex(1, 0) self.v2 = Vertex(2, 0) self.v3 = Vertex(3, 0) self.v4 = Vertex(4, 0) self.g.add_vert(self.v1) self.g.add_vert(self.v2) self.g.add_vert(self.v3) self.g.add_vert(self.v4) self.g.add_edge(self.v1.id, self.v2.id) self.g.add_edge(self.v1.id, self.v3.id) self.g.add_edge(self.v2.id, self.v3.id) self.g.add_edge(self.v3.id, self.v4.id) # Sanity check self.assertEqual(self.g.get_vert_count(), 4) self.assertEqual(self.g.get_edge_count(), 4) self.assertTrue(self.g.has_vert(self.v1.id)) self.assertTrue(self.g.has_vert(self.v2.id)) self.assertTrue(self.g.has_vert(self.v3.id)) self.assertTrue(self.g.has_vert(self.v4.id)) self.assertTrue(self.g.has_edge(self.v1.id, self.v2.id)) self.assertTrue(self.g.has_edge(self.v1.id, self.v3.id)) self.assertTrue(self.g.has_edge(self.v2.id, self.v3.id)) self.assertTrue(self.g.has_edge(self.v3.id, self.v4.id)) self.assertFalse(self.g.has_edge(self.v2.id, self.v4.id)) self.assertEqual(self.g.get_vert(self.v1.id).color, 0) self.assertEqual(self.g.get_vert(self.v2.id).color, 0) self.assertEqual(self.g.get_vert(self.v3.id).color, 0) self.assertEqual(self.g.get_vert(self.v4.id).color, 0) self.assertEqual(self.g.neighbors(self.v1.id), {self.v2, self.v3}) self.assertEqual(self.g.neighbors(self.v2.id), {self.v3, self.v1}) self.assertEqual(self.g.neighbors(self.v3.id), {self.v1, self.v2, self.v4}) self.assertEqual(self.g.neighbors(self.v4.id), {self.v3})
def test_RecolorGraph_4_black_star(self): g = Graph() g.add_vert(Vertex("center", "white")) # Spokes: g.add_vert(Vertex("1", "black")) g.add_vert(Vertex("2", "black")) g.add_vert(Vertex("3", "black")) g.add_vert(Vertex("4", "black")) g.add_vert(Vertex("5", "black")) g.add_vert(Vertex("6", "black")) g.add_vert(Vertex("7", "black")) g.add_vert(Vertex("8", "black")) g.add_edge("center", "1") g.add_edge("center", "2") g.add_edge("center", "3") g.add_edge("center", "4") g.add_edge("center", "5") g.add_edge("center", "6") g.add_edge("center", "7") g.add_edge("center", "8") # The center and the spokes will alternate colors on each recoloring. for i in range(100): central_color = None spoke_color = None recolor(g) if i % 2 == 0: central_color = "black" spoke_color = "white" else: central_color = "white" spoke_color = "black" self.assertTrue(g.get_vert("center").color == central_color) self.assertTrue(g.get_vert("1").color == spoke_color) self.assertTrue(g.get_vert("2").color == spoke_color) self.assertTrue(g.get_vert("3").color == spoke_color) self.assertTrue(g.get_vert("4").color == spoke_color) self.assertTrue(g.get_vert("5").color == spoke_color) self.assertTrue(g.get_vert("6").color == spoke_color) self.assertTrue(g.get_vert("7").color == spoke_color) self.assertTrue(g.get_vert("8").color == spoke_color)
def test_SaveGraph_1_empty_graph(self): saved_g = Graph() saved_xml_str = save_graph(saved_g, "SaveGraph_1_empty_graph.xml") empty_graph_xml_str = '<?xml version="1.0" ?>\n<graph/>\n' self.assertEqual(saved_xml_str, empty_graph_xml_str) loaded_g = load_graph("SaveGraph_1_empty_graph.xml") self.assertEqual(loaded_g.get_vert_count(), 0) self.assertEqual(loaded_g.get_edge_count(), 0) # Add some stuff to the graph v1 = Vertex("1", "black") v2 = Vertex("2", "white") loaded_g.add_vert(v1) loaded_g.add_vert(v2) loaded_g.add_edge("1", "2") saved_xml_str = save_graph(loaded_g, "SaveGraph_1_empty_graph.xml") reloaded_g = load_graph("SaveGraph_1_empty_graph.xml") self.assertEqual(reloaded_g.get_vert_count(), 2) self.assertEqual(reloaded_g.get_edge_count(), 1) self.assertTrue(reloaded_g.has_vert("1")) self.assertTrue(reloaded_g.has_vert("2")) self.assertTrue(reloaded_g.has_edge("2", "1")) self.assertEqual(reloaded_g.get_vert("1").color, "black") self.assertEqual(reloaded_g.get_vert("2").color, "white") # Remove the stuff reloaded_g.del_vert("1") reloaded_g.del_vert("2") saved_xml_str = save_graph(reloaded_g, "SaveGraph_1_empty_graph.xml") self.assertEqual(saved_xml_str, empty_graph_xml_str)
def test_LoadGoodXML_1_good_colors(self): correct_g = Graph() v1 = Vertex("1", "white") v2 = Vertex("2", "black") v3 = Vertex("3", "white") v4 = Vertex("4", "white") v5 = Vertex("5", "white") v6 = Vertex("6", "white") v7 = Vertex("7", "white") v8 = Vertex("8", "black") v9 = Vertex("9", "black") correct_g.add_vert(v1) correct_g.add_vert(v2) correct_g.add_vert(v3) correct_g.add_vert(v4) correct_g.add_vert(v5) correct_g.add_vert(v6) correct_g.add_vert(v7) correct_g.add_vert(v8) correct_g.add_vert(v9) correct_g.add_edge(v1.id, v2.id) correct_g.add_edge(v1.id, v3.id) correct_g.add_edge(v2.id, v3.id) correct_g.add_edge(v3.id, v4.id) parsed_g = load_graph("LoadGoodXML_1_good_color.xml") self.assertTrue(parsed_g == correct_g) self.assertEqual(parsed_g.get_vert(v1.id).color, "white") self.assertEqual(parsed_g.get_vert(v2.id).color, "black") self.assertEqual(parsed_g.get_vert(v3.id).color, "white") self.assertEqual(parsed_g.get_vert(v4.id).color, "white") self.assertEqual(parsed_g.get_vert(v5.id).color, "white") self.assertEqual(parsed_g.get_vert(v6.id).color, "white") self.assertEqual(parsed_g.get_vert(v7.id).color, "white") self.assertEqual(parsed_g.get_vert(v8.id).color, "black") self.assertEqual(parsed_g.get_vert(v9.id).color, "black")
def test_3_add_edge_already_in(self): with self.assertRaises(ValueError): self.g.add_edge(self.v3.id, self.v2.id) self.assertEqual(self.g.get_edge_count(), 4) # Edge to self new_vert = Vertex(5, 0) self.g.add_vert(new_vert) self.g.add_edge(new_vert.id, new_vert.id) with self.assertRaises(ValueError): self.g.add_edge(new_vert.id, new_vert.id) self.assertEqual(self.g.get_edge_count(), 5) self.assertTrue(self.g.has_edge(new_vert.id, new_vert.id))
def test_6_del_vert(self): self.g.del_vert(self.v1.id) self.assertFalse(self.g.has_vert(self.v1.id)) self.assertTrue(self.g.has_vert(self.v2.id)) self.assertTrue(self.g.has_vert(self.v3.id)) self.assertTrue(self.g.has_vert(self.v4.id)) self.assertFalse(self.g.has_edge(self.v1.id, self.v2.id)) self.assertFalse(self.g.has_edge(self.v1.id, self.v3.id)) self.assertTrue(self.g.has_edge(self.v2.id, self.v3.id)) self.assertTrue(self.g.has_edge(self.v3.id, self.v4.id)) self.assertEqual(self.g.get_vert_count(), 3) self.assertEqual(self.g.get_edge_count(), 2) with self.assertRaises(KeyError): self.g.neighbors(self.v1.id) self.assertEqual(self.g.neighbors(self.v2.id), {self.v3}) self.assertEqual(self.g.neighbors(self.v3.id), {self.v2, self.v4}) self.assertEqual(self.g.neighbors(self.v4.id), {self.v3}) v2_copy = Vertex(2, 1) # Same id, different color self.g.del_vert(v2_copy.id) self.assertFalse(self.g.has_vert(self.v1.id)) self.assertFalse(self.g.has_vert(self.v2.id)) self.assertTrue(self.g.has_vert(self.v3.id)) self.assertTrue(self.g.has_vert(self.v4.id)) self.assertFalse(self.g.has_edge(self.v1.id, self.v2.id)) self.assertFalse(self.g.has_edge(self.v1.id, self.v3.id)) self.assertFalse(self.g.has_edge(self.v2.id, self.v3.id)) self.assertTrue(self.g.has_edge(self.v3.id, self.v4.id)) self.assertEqual(self.g.get_vert_count(), 2) self.assertEqual(self.g.get_edge_count(), 1) with self.assertRaises(KeyError): self.g.neighbors(self.v1.id) with self.assertRaises(KeyError): self.g.neighbors(self.v2.id) self.assertEqual(self.g.neighbors(self.v3.id), {self.v4}) self.assertEqual(self.g.neighbors(self.v4.id), {self.v3})
def test_RecolorGraph_3_all_white(self): g = Graph() g.add_vert(Vertex("1", "white")) g.add_vert(Vertex("2", "white")) g.add_vert(Vertex("3", "white")) g.add_vert(Vertex("4", "white")) g.add_vert(Vertex("5", "white")) g.add_vert(Vertex("6", "white")) g.add_vert(Vertex("7", "white")) g.add_edge("1", "2") g.add_edge("1", "3") g.add_edge("2", "3") g.add_edge("4", "3") g.add_edge("4", "5") g.add_edge("5", "6") g.add_edge("6", "7") self.assertTrue(g.get_vert("1").color == "white") self.assertTrue(g.get_vert("2").color == "white") self.assertTrue(g.get_vert("3").color == "white") self.assertTrue(g.get_vert("4").color == "white") self.assertTrue(g.get_vert("5").color == "white") self.assertTrue(g.get_vert("6").color == "white") self.assertTrue(g.get_vert("7").color == "white") recolor(g) self.assertTrue(g.get_vert("1").color == "white") self.assertTrue(g.get_vert("2").color == "white") self.assertTrue(g.get_vert("3").color == "white") self.assertTrue(g.get_vert("4").color == "white") self.assertTrue(g.get_vert("5").color == "white") self.assertTrue(g.get_vert("6").color == "white") self.assertTrue(g.get_vert("7").color == "white")
def test_RecolorGraph_0_normal(self): g = Graph() g.add_vert(Vertex("1", "white")) g.add_vert(Vertex("2", "white")) g.add_vert(Vertex("3", "black")) g.add_vert(Vertex("4", "white")) g.add_vert(Vertex("5", "white")) g.add_edge("1", "2") g.add_edge("1", "3") g.add_edge("3", "2") g.add_edge("4", "3") g.add_edge("5", "4") g.add_edge("5", "5") self.assertTrue(g.get_vert("1").color == "white") self.assertTrue(g.get_vert("2").color == "white") self.assertTrue(g.get_vert("3").color == "black") self.assertTrue(g.get_vert("4").color == "white") self.assertTrue(g.get_vert("5").color == "white") # print("Before recoloring:") # print_graph_colors(g) # After 4 recolorings, the entire graph should be black. recolor(g) # 1 # print("Recolor 1:") # print_graph_colors(g) self.assertTrue(g.get_vert("1").color == "black") self.assertTrue(g.get_vert("2").color == "black") self.assertTrue(g.get_vert("3").color == "white") self.assertTrue(g.get_vert("4").color == "black") self.assertTrue(g.get_vert("5").color == "white") recolor(g) # 2 # print("Recolor 2:") # print_graph_colors(g) self.assertTrue(g.get_vert("1").color == "black") self.assertTrue(g.get_vert("2").color == "black") self.assertTrue(g.get_vert("3").color == "black") self.assertTrue(g.get_vert("4").color == "white") self.assertTrue(g.get_vert("5").color == "black") # Neighbor of self! recolor(g) # 3 # print("Recolor 3:") # print_graph_colors(g) self.assertTrue(g.get_vert("1").color == "black") self.assertTrue(g.get_vert("2").color == "black") self.assertTrue(g.get_vert("3").color == "black") self.assertTrue(g.get_vert("4").color == "black") self.assertTrue(g.get_vert("5").color == "black") # So still black. recolor(g) # 4 # print("Recolor 4:") # print_graph_colors(g) self.assertTrue(g.get_vert("1").color == "black") self.assertTrue(g.get_vert("2").color == "black") self.assertTrue(g.get_vert("3").color == "black") self.assertTrue(g.get_vert("4").color == "black") self.assertTrue(g.get_vert("5").color == "black")
def load_graph(path): """Read an XML file at 'path' and return the graph it describes.""" g = Graph() # Remove surrounding "s if given "path" # (Common in Windows when using Shift + right-click > Copy as path) path_split = path.split("\"") if len(path_split) == 3: path = path_split[1] tree = ET.parse(path) root = tree.getroot() vertices = [] edges = [] if not root.tag.lower() == "graph": raise RuntimeError("load_graph(" + path + "): Root tag of a graph " +\ "file must be \"graph\"; instead, found: \"" +\ root.tag + "\"") # Collect vertices and edges for child in root: # Lowercase the keys of the child.attrib dict to tolerate # mixed case XML attributes child.attrib = dict((k.lower(), v) for k, v in child.attrib.items()) if ((child.tag.lower() == "vertex") or (child.tag.lower() == "v")): # Vertex element if not "id" in child.attrib: raise RuntimeError("load_graph(" + path + "): Vertex " +\ "element missing \"id\" attribute!") new_vert = Vertex(child.attrib["id"], "black") if "color" in child.attrib: if ((child.attrib["color"].strip().lower() == "white") or (child.attrib["color"].strip().lower() == "w")): new_vert.color = "white" elif not ((child.attrib["color"].strip().lower() == "black") or (child.attrib["color"].strip().lower() == "b")): raise RuntimeError("load_graph(" + path + "): " +\ "Unrecognized vertex color attribute: \"" +\ child.attrib["color"] + "\"") vertices.append(new_vert) elif ((child.tag.lower() == "edge") or (child.tag.lower() == "e")): # Edge element if not (("id1" in child.attrib) and ("id2" in child.attrib)): raise RuntimeError("load_graph(" + path + "): Edge element " +\ "missing \"id1\" and/or \"id2\" attributes!") edges.append((child.attrib["id1"], child.attrib["id2"])) else: # Unrecognized element raise RuntimeError("load_graph(" + path + "): Unrecognized " +\ "graph element: \"" + child.tag + "\"") # Add collected vertices... for v in vertices: g.add_vert(v) # ...then collected edges for e in edges: g.add_edge(e[0], e[1]) return g
def test_LoadGoodXML_0_normal(self): correct_g = Graph() v1 = Vertex("1", 0) v2 = Vertex("2", 0) v3 = Vertex("3", 0) v4 = Vertex("4", 0) v5 = Vertex("5", 0) correct_g.add_vert(v1) correct_g.add_vert(v2) correct_g.add_vert(v3) correct_g.add_vert(v4) correct_g.add_vert(v5) correct_g.add_edge(v1.id, v2.id) correct_g.add_edge(v1.id, v3.id) correct_g.add_edge(v2.id, v3.id) correct_g.add_edge(v3.id, v4.id) # Sanity check self.assertEqual(correct_g.get_vert_count(), 5) self.assertEqual(correct_g.get_edge_count(), 4) self.assertTrue(correct_g.has_vert(v1.id)) self.assertTrue(correct_g.has_vert(v2.id)) self.assertTrue(correct_g.has_vert(v3.id)) self.assertTrue(correct_g.has_vert(v4.id)) self.assertTrue(correct_g.has_vert(v5.id)) self.assertTrue(correct_g.has_edge(v1.id, v2.id)) self.assertTrue(correct_g.has_edge(v1.id, v3.id)) self.assertTrue(correct_g.has_edge(v2.id, v3.id)) self.assertTrue(correct_g.has_edge(v3.id, v4.id)) self.assertFalse(correct_g.has_edge(v2.id, v4.id)) self.assertEqual(correct_g.get_vert(v1.id).color, 0) self.assertEqual(correct_g.get_vert(v2.id).color, 0) self.assertEqual(correct_g.get_vert(v3.id).color, 0) self.assertEqual(correct_g.get_vert(v4.id).color, 0) self.assertEqual(correct_g.get_vert(v5.id).color, 0) self.assertEqual(correct_g.neighbors(v1.id), {v2, v3}) self.assertEqual(correct_g.neighbors(v2.id), {v3, v1}) self.assertEqual(correct_g.neighbors(v3.id), {v1, v2, v4}) self.assertEqual(correct_g.neighbors(v4.id), {v3}) self.assertEqual(correct_g.neighbors(v5.id), set()) # Parse XML file parsed_g = load_graph("LoadGoodXML_0_normal.xml") # g1 == g2 if they have same edges and same vertices by id # (even if vertices differ otherwise) self.assertTrue(parsed_g == correct_g) self.assertEqual(parsed_g.get_vert(v1.id).color, "black") self.assertEqual(parsed_g.get_vert(v2.id).color, "black") self.assertEqual(parsed_g.get_vert(v3.id).color, "black") self.assertEqual(parsed_g.get_vert(v4.id).color, "black") self.assertEqual(parsed_g.get_vert(v5.id).color, "black") # Modify edge or vert inventory to break equality correct_g.del_edge("1", "2") self.assertTrue(parsed_g != correct_g)