def load_from_json(self, file_name: str) -> bool: """ Loads a graph from a json file. @param file_name: The path to the json file @returns True if the loading was successful, False o.w. """ graph = DiGraph() dict_graph = list() try: with open(file_name, "r") as file: dict_graph = json.load(file) for i in dict_graph['Nodes']: if i.__contains__("pos"): s = i["pos"].split(",") x = float(s[0]) y = float(s[1]) graph.add_node(i["id"], (x, y)) else: graph.add_node(i["id"]) for i in dict_graph["Edges"]: graph.add_edge(i["src"], i["dest"], i["w"]) except IOError as e: print(e) return False self.__grp = graph return True
def test_all_out_edges_of_node(self): graph = DiGraph() for i in range(10): graph.add_node(i) for i in range(9): graph.add_edge(i, i + 1, i * 2 + 1) self.assertTrue(graph.all_out_edges_of_node(0).__contains__(1)) graph.remove_edge(0, 1) self.assertFalse(graph.all_in_edges_of_node(0).__contains__(1)) graph.add_node(12) graph.add_edge(12, 4, 19) self.assertIn(4, graph.all_out_edges_of_node(12))
def test_get_all_v(self): graph = DiGraph() for i in range(10): graph.add_node(i) for i in range(9): graph.add_edge(i, i + 1, i * 2 + 1) l = [] for vertex in graph.Nodes.values(): l.append(vertex) for vertex in l: self.assertIn(vertex, graph.get_all_v()) graph.remove_node(3) self.assertNotIn(3, graph.get_all_v())
def test_remove_edge(self): graph = DiGraph() for i in range(10): graph.add_node(i) for i in range(9): graph.add_edge(i, i + 1, i * 2 + 1) graph.remove_edge(2, 3) self.assertEqual(graph.v_size(), 10) self.assertEqual(graph.e_size(), 8) self.assertFalse(graph.all_out_edges_of_node(2).__contains__(3)) self.assertFalse(graph.all_in_edges_of_node(3).__contains__(2)) self.assertFalse(graph.remove_edge(6, 0)) self.assertFalse(graph.remove_edge(5, 100))
def test_remove_node(self): graph = DiGraph() for i in range(10): graph.add_node(i) for i in range(9): graph.add_edge(i, i + 1, i * 2 + 1) self.assertTrue(graph.remove_node(0)) self.assertEqual(graph.e_size(), 8) self.assertEqual(graph.v_size(), 9) self.assertFalse(0 in graph.Nodes.keys()) self.assertTrue(8 in graph.Nodes.keys()) self.assertFalse(graph.remove_node(0)) self.assertFalse(graph.remove_node(20)) self.assertEqual(graph.v_size(), 9)
def test_graphMillion(self): """ Build a graph with a million vertices each vertex has 3 edges """ st = time.time() g = DiGraph() for i in range(1000): g.add_node(i) for i in range(1000): for j in range(3): g.add_edge(i, i + j, 1) print("Graph construction 10,000 nodes run time: ", round(time.time() - st, 3), " sec") for i in range(10000, 100000): g.add_node(i) for i in range(10000, 100000): for j in range(3): g.add_edge(i, i + j, 1) print("Graph construction 100,000 nodes run time: ", round(time.time() - st, 3), " sec") for i in range(100000, 1000000): g.add_node(i) for i in range(100000, 1000000): for j in range(3): g.add_edge(i, i + j, 1) print("Graph construction 1,000,000 nodes run time: ", round(time.time() - st, 3), " sec")
def check0(): """ This function tests the naming (main methods of the DiGraph class, as defined in GraphInterface. :return: """ g = DiGraph() # creates an empty directed graph for n in range(4): g.add_node(n) g.add_edge(0, 1, 1) g.add_edge(1, 0, 1.1) g.add_edge(1, 2, 1.3) g.add_edge(2, 3, 1.1) g.add_edge(1, 3, 1.9) g.remove_edge(1, 3) g.add_edge(1, 3, 10) print(g.v_size()) # prints the __repr__ (func output) print(g.e_size()) # prints the __repr__ (func output) print(g.get_all_v()) # prints a dict with all the graph's vertices. print(g.all_in_edges_of_node(1)) print(g.all_out_edges_of_node(1)) g_algo = GraphAlgo(g) print(g_algo.shortest_path(0, 3)) g_algo.plot_graph()
def test_get_mc(self): graph = DiGraph() for i in range(10): graph.add_node(i) for i in range(9): graph.add_edge(i, i + 1, i * 2 + 1) self.assertEqual(graph.get_mc(), 19) graph.remove_edge(0, 1) self.assertEqual(graph.get_mc(), 20) graph.add_edge(0, 1, 1) self.assertEqual(graph.get_mc(), 21) graph.add_edge(0, 1, 1) self.assertEqual(graph.get_mc(), 21) graph.remove_node(0) self.assertEqual(graph.get_mc(), 22) graph.remove_node(0) self.assertEqual(graph.get_mc(), 22) graph.add_node(0) self.assertEqual(graph.get_mc(), 23) graph.add_node(0) self.assertEqual(graph.get_mc(), 23)
def test_add_edge(self): graph = DiGraph() for i in range(10): graph.add_node(i) for i in range(9): graph.add_edge(i, i + 1, i * 2 + 1) self.assertEqual(graph.e_size(), 9) graph.add_edge(9, 0, 5.5) self.assertEqual(graph.e_size(), 10) graph.add_edge(1, 3, 2.7) graph.add_edge(9, 4, 3) self.assertEqual(graph.e_size(), 12) graph.add_edge(9, 4, 3) self.assertEqual(graph.e_size(), 12) graph.add_edge(2, 2, 100) self.assertEqual(graph.e_size(), 12) graph.add_edge(6, 7, -3) self.assertEqual(graph.e_size(), 12) graph.add_edge(15, 8, 100) self.assertEqual(graph.e_size(), 12) graph.add_edge(0, 1, 10) self.assertEqual(graph.e_size(), 12)
class GraphAlgo(GraphAlgoInterface): def __init__(self, graph: DiGraph = DiGraph()): self.graph = graph self.string = "Graph" def get_graph(self) -> GraphInterface: return self.graph def load_from_json(self, file_name: str) -> bool: self.string = file_name vertex = {} edges = {} try: with open(file_name, "r") as file: new_graph_dict = json.load(file) vertex = new_graph_dict["Nodes"] edges = new_graph_dict["Edges"] self.graph = DiGraph() for i in vertex: if "pos" not in i: i["pos"] = None self.graph.add_node(i["id"], i["pos"]) for e in edges: self.graph.add_edge(e["src"], e["dest"], e["w"]) except IOError as e: print(e) return False return True def save_to_json(self, file_name: str) -> bool: vertex = [] edges = [] graph = {} for i in self.graph.get_all_v(): n = {"pos": i.pos, "id": i.key} vertex.append(n) for j in self.graph.all_out_edges_of_node(i.key).values(): e = {"src": i.key, "w": j.weight, "dest": j.dst} edges.append(e) graph["Edges"] = edges graph["Nodes"] = vertex try: with open(file_name, "w") as file: json.dump(graph, indent=4, fp=file) except IOError as e: print(e) return False return True def shortest_path(self, id1: int, id2: int) -> (float, list): if id1 not in self.graph.Nodes.keys( ) or id2 not in self.graph.Nodes.keys(): return float('infinity'), [] self.Dijkstra(id1) ls = [] if self.graph.Nodes.get(id2).tag == float('infinity'): return float('infinity'), ls form = id2 ls.append(form) while id1 not in ls: ls.append(self.graph.Nodes.get(form).r_from.key) form = self.graph.Nodes.get(form).r_from.key ls.reverse() return self.graph.Nodes.get(id2).tag, ls def connected_component(self, id1: int): if id1 not in self.graph.Nodes.keys() or self.graph is None: return [] l_ist = self.Kosaraju(id1) return l_ist def connected_components(self) -> List[list]: if self.graph is None: return [] l_ist = [] al_inScc = [] for i in self.graph.Nodes.values(): if i.key not in al_inScc: l = self.Kosaraju(i.key) for k in l: al_inScc.append(k) l_ist.append(l) return l_ist def plot_graph(self) -> None: plt.title(self.string) x_vals = [] y_vals = [] for xy in self.graph.Nodes.values(): if xy.pos is None: xy.pos = (random.randrange(0, 100), random.randrange(0, 100), 0) x_vals.append(xy.pos[0]) y_vals.append(xy.pos[1]) else: string = xy.pos.split(',') xy.pos = tuple(string) x_vals.append(float(string[0])) y_vals.append(float(string[1])) plt.plot(x_vals, y_vals, 'o') for v in self.graph.Nodes.values(): v_x = float(v.pos[0]) v_y = float(v.pos[1]) plt.annotate(v.key, (v_x - 0.00015, v_y + 0.00015), color='red') for e in self.graph.EdgesSrc[v.key].values(): x_e = float(self.graph.Nodes[e.dst].pos[0]) y_e = float(self.graph.Nodes[e.dst].pos[1]) plt.arrow(v_x, v_y, x_e - v_x, y_e - v_y, length_includes_head=True, head_width=0.0001991599, width=0.0000005, color='blue') plt.show() def Dijkstra(self, src): """ Dijkstra Algorithm : Traverse the Graph from Source Node and tag each reachable Node with the MinSum Weight Use's for Shortest_Path """ for vertex in self.graph.Nodes.values(): vertex.tag = float('infinity') self.graph.Nodes.get(src).tag = 0 pq = [self.graph.Nodes.get(src)] visited = [src] while len(pq) > 0: node = pq.pop(0) for neighbor in self.graph.EdgesSrc[node.key].values(): weight = node.tag + neighbor.weight if weight < self.graph.Nodes.get(neighbor.dst).tag: self.graph.Nodes.get(neighbor.dst).tag = weight self.graph.Nodes.get(neighbor.dst).r_from = node if neighbor.dst not in visited: pq.append(self.graph.Nodes.get(neighbor.dst)) visited.append(neighbor.dst) return def Kosaraju(self, src): """ This Algorithm is for finding all SCC in the graph -> Use on all Vertices Work this way -> DFS on the Graph - Contain a list of all reachable Vertices from Source Node Graph^T = Transpose Original Graph DFS on the Graph^T - Contain a list of all reachable Vertices from Source Node (On Graph^T) :return An Intersection between both lists - > The Source Node SCC """ s = [src] visited = {} while len(s) > 0: # DFS Graph v = s.pop() if v not in visited.keys(): visited[v] = self.graph.Nodes[v] for edge in self.graph.EdgesSrc[v].values(): s.append(edge.dst) visited_2 = {} s_2 = [src] while len(s_2) > 0: v = s_2.pop() if v not in visited_2.keys(): visited_2[v] = self.graph.Nodes[v] for edge in self.graph.EdgesDst[v].values(): s_2.append(edge.dst) x = set(visited).intersection(visited_2) return list(x)
def create_graph(self): g = DiGraph() g.add_node(0) g.add_node(1) g.add_node(2) g.add_node(3) g.add_node(4) g.add_node(5) g.add_node(6) g.add_node(7) g.add_node(8) g.add_node(9) g.add_edge(0, 1, 1) g.add_edge(1, 2, 2.1) g.add_edge(2, 0, 3) g.add_edge(2, 3, 5.5) g.add_edge(3, 2, 5.5) g.add_edge(3, 4, 4) g.add_edge(4, 5, 2) g.add_edge(5, 3, 3.4) g.add_edge(5, 6, 1) g.add_edge(6, 7, 5) g.add_edge(7, 8, 4.8) # 4.8 fails exp 37.4 g.add_edge(8, 6, 1.9) g.add_edge(8, 9, 12) return g