예제 #1
0
 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
예제 #2
0
 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))
예제 #3
0
 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())
예제 #4
0
 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))
예제 #5
0
 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)
예제 #6
0
 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")
예제 #7
0
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()
예제 #8
0
 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)
예제 #9
0
 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)
예제 #10
0
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)
예제 #11
0
    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