예제 #1
0
    def test_prim(self):
        g = graph.Graph()
        for i in range(0, 6):
            v = vertex.Vertex(i)
            g.add_vertex(v)
        e1 = edge.Edge(0, 1, {"WEIGHT": 4})
        g.add_edge(e1)
        e2 = edge.Edge(0, 2, {"WEIGHT": 1})
        g.add_edge(e2)
        e3 = edge.Edge(0, 3, {"WEIGHT": 5})
        g.add_edge(e3)
        e4 = edge.Edge(1, 3, {"WEIGHT": 2})
        g.add_edge(e4)
        e5 = edge.Edge(1, 4, {"WEIGHT": 3})
        g.add_edge(e5)
        e6 = edge.Edge(1, 5, {"WEIGHT": 3})
        g.add_edge(e6)
        e7 = edge.Edge(2, 3, {"WEIGHT": 2})
        g.add_edge(e7)
        e8 = edge.Edge(2, 4, {"WEIGHT": 8})
        g.add_edge(e8)
        e9 = edge.Edge(3, 4, {"WEIGHT": 1})
        g.add_edge(e9)
        e10 = edge.Edge(4, 5, {"WEIGHT": 3})
        g.add_edge(e10)
        primg = g.Prim()
        amount = 0
        for k in primg.edges:
            amount = amount + primg.edges[k].attr["WEIGHT"]

        self.assertEqual(amount, 9)
예제 #2
0
파일: models.py 프로젝트: ablarry/pygraph
def dorogovtsev_mendes(n, directed=False):
    """
    Create a Dorogovtsev-Mendes graph
    :param n: number of nodes
    :param directed: enable graph directed
    :return: graph created
    """
    # Parameter's validation
    if n < 3:
        raise ValueError("n parameter must to be >= 3 ")

    g = graph.Graph()
    # Add attribute DIRECTED in graph
    g.attr[graph.DIRECTED] = directed

    # Create 3 vertex and 3 edges to form triangle
    for i in range(3):
        g.add_vertex(vertex.Vertex(i))
    for i in range(3):
        j = i + 1 if i < 2 else 0
        g.add_edge(edge.Edge(i, j), directed)

    # To add next vertices one by one, choosing randomly one edge of the grap
    # and create edges between new vertice and origin and source of edge selected
    for i in range(3, n):
        g.add_vertex(vertex.Vertex(i))
        # Select random edge of the graph
        id_edge = randint(0, len(g.get_edges()) - 1)
        edge_selected = g.get_edges()[id_edge]
        (source, target) = edge_selected
        # Create edges between new vertice and origin and source of edge selected
        g.add_edge(edge.Edge(i, source), directed)
        g.add_edge(edge.Edge(i, target), directed)

    return g
예제 #3
0
파일: models.py 프로젝트: ablarry/pygraph
def mesh(m, n, directed=False):
    """
    Creates a graph of m*n nodes
    :param m: number of columns (>1)
    :param n: number of rows (>1)
    :param directed: enable graph directed
    :return: Graph created
    """
    # Parameter's validation
    if m <= 1 or n <= 1:
        raise ValueError("m,n parameters must to be > 1")

    g = graph.Graph()
    # Add attribute DIRECTED in graph
    g.attr[graph.DIRECTED] = directed

    for i in range(m * n):
        v = vertex.Vertex(i)
        g.add_vertex(v)
    index = 0
    for i in range(m):
        for j in range(n):
            if i != (m - 1):
                g.add_edge(edge.Edge(index, (index + n)), directed)
            if j != (n - 1):
                g.add_edge(edge.Edge(index, (index + 1)), directed)
            index = index + 1
    return g
예제 #4
0
    def dijkstra_tree(self, s):
        """
        dijkstra_tree is an algorithm for finding tree of cost for each node according Dijkstra's algorithm.
        :param s: node source
        :param t: node target
        :return g graph generated with the shortest path from source to target 
        """
        l = []
        dist = {}
        prev = {}
        discovered = {}
        g = Graph(attr={DIRECTED: True})
        g.add_vertex(vertex.Vertex(s, {"WEIGHT": 0}))
        for v in self.get_vertices():
            dist[v] = float('inf')
            prev[v] = None
            discovered[v] = False
        dist[s] = 0
        l.append((s, dist[s]))
        while len(l) != 0:
            u = min(l, key=lambda x: x[1])
            l.remove(u)
            u = u[0]
            discovered[u] = True
            for v in self.get_adjacent_vertices_by_vertex(u):
                if not discovered[v]:
                    alt = dist[u] + self.get_edge((u, v)).attr["WEIGHT"]
                    if alt < dist[v]:
                        dist[v] = alt
                        prev[v] = u
                        l.append((v, dist[v]))
                        g.add_vertex(vertex.Vertex(v, {"WEIGHT": dist[v]}))
                        g.add_edge(edge.Edge(u, v, {"WEIGHT": dist[v]}))

        return g
예제 #5
0
파일: models.py 프로젝트: ablarry/pygraph
def erdos_rengy(n, m, directed=False, auto=False):
    """
    Creates a graph of n nodes with model Erdos-Renyi
    :param n: number of nodes ( > 0)
    :param m: number of edges ( >= n-1)
    :param directed: enable graph directed
    :param auto: allow auto-cycle (loops)
    :return: Graph created
    """
    # Parameter's validation
    if n <= 0:
        raise ValueError("n parameter must to be > 0 ")
    if m < n - 1:
        raise ValueError("m parameter must to be >= n-1 ")

    g = graph.Graph()
    # Add attribute DIRECTED in graph
    g.attr[graph.DIRECTED] = directed

    for i in range(n):
        g.add_vertex(vertex.Vertex(i))
    edges = {}
    while len(g.edges) != m:
        # Create random m different edges
        source = randint(0, m - 1)
        target = randint(0, m - 1)
        e = (source, target)
        if e not in edges:
            edges[e] = e
            g.add_edge(edge.Edge(source, target), directed, auto)
    return g
예제 #6
0
파일: models.py 프로젝트: ablarry/pygraph
def gilbert(n, p, directed=False, auto=False):
    """
    Creates a graph of n nodes with model Gilbert 
    :param n: number of nodes ( > 0)
    :param p: probability to create an edge (0,1)
    :param directed: enable graph directed
    :param auto: allow auto-cycle (loops)
    :return: Graph created
    """
    # Parameter's validation
    if n <= 0:
        raise ValueError("n parameter must to be > 0 ")
    if p <= 0 or p >= 1:
        raise ValueError("p parameter must to be in range (0,1)")

    g = graph.Graph()
    # Add attribute DIRECTED in graph
    g.attr[graph.DIRECTED] = directed

    for i in range(n):
        g.add_vertex(vertex.Vertex(i))
    for i in range(n):
        for j in range(n):
            # Create edge with probability => random number (0,1)
            if random() <= p:
                g.add_edge(edge.Edge(i, j), directed, auto)

    return g
예제 #7
0
    def dfs(self, s):
        """
        dfs Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data structures. 
        The algorithm starts at the root node and explores as far as possible along each branch before backtracking.
        :param s: root node for traversing
        :return g graph generated according DFS 
        """
        g = Graph(attr={DIRECTED: True})
        adjacent_type = '+' if DIRECTED in self.attr and self.attr[
            DIRECTED] else None
        # Insert s root node in stack 
        stack = collections.deque()
        # Initial node does not have origin, it is represented by # 
        stack.append(('#', s))

        while (len(stack) > 0):
            (source, target) = stack.pop()
            w = self.get_vertex(target)
            if DISCOVERED not in w.attributes or w.attributes[
                DISCOVERED] is False:
                w.attributes[DISCOVERED] = True
                g.add_vertex(w)
                if (source != '#'):
                    g.add_edge(edge.Edge(source, w.id), True)
                for e in self.get_adjacent_vertices_by_vertex(w.id,
                                                              adjacent_type):
                    stack.append((w.id, e))
        return g
예제 #8
0
    def bfs(self, s):
        """
        bfs Breadth-first search (BFS) is an algorithm
        for traversing or searching graph data structures.
        It starts at the s node
        and explores all of the neighbor nodes at the present
        depth prior to moving on to the nodes at the next depth level.
        :param s: root node for traversing
        :return g graph generated according BFS
        """
        g = Graph(attr={DIRECTED: True})
        root = self.get_vertex(s)
        root.attributes[DISCOVERED] = True
        q = collections.deque()
        adjacent_type = '+' if DIRECTED in self.attr and self.attr[
            DIRECTED] else None
        # Insert root node in graph and queue
        g.add_vertex(root)
        q.append(s)

        while (len(q) > 0):
            v = q.popleft()
            for e in self.get_adjacent_vertices_by_vertex(v, adjacent_type):
                w = self.get_vertex(e)
                if DISCOVERED not in w.attributes or w.attributes[
                    DISCOVERED] is False:
                    w.attributes[DISCOVERED] = True
                    q.append(w.id)
                    g.add_vertex(w)
                    g.add_edge(edge.Edge(v, e), True)
        return g
예제 #9
0
    def KruskalD(self):
        """
        KruskalD is a function based on Krustal's algorithm to find a minimum spanning forest of an undirected edge-weighted graph. 
        :return g graph representing minimum spannng forest 
        """
        g = Graph(attr={DIRECTED: False})
        # Create set for each v of V[G]
        parent = []
        rank = []
        for v in self.get_vertices():
            parent.append(v)
            rank.append(0)

        # Sort edges by weight
        q = sorted(self.edges.items(), key=lambda e: e[1].attr["WEIGHT"])
        for e in q:
            (u, v) = e[0]
            v1 = self.find(parent, u)
            v2 = self.find(parent, v)
            if v1 != v2:
                g.add_vertex(vertex.Vertex(u))
                g.add_vertex(vertex.Vertex(v))
                g.add_edge(edge.Edge(u, v, {"WEIGHT": e[1].attr["WEIGHT"]}))
                if rank[v1] < rank[v2]:
                    parent[v1] = v2
                    rank[v2] += 1
                else:
                    parent[v2] = v1
                    rank[v1] += 1
        return g
예제 #10
0
 def test_add_edge(self):
     g = graph.Graph()
     v1 = vertex.Vertex(1)
     v2 = vertex.Vertex(2)
     g.add_vertex(v1)
     g.add_vertex(v2)
     e = edge.Edge(1, 2)
     g.add_edge(e)
     self.assertEqual(1, len(g.get_edges()))
예제 #11
0
 def test_edges(self):
     g = graph.Graph()
     v = vertex.Vertex(1)
     g.add_vertex(v)
     v = vertex.Vertex(2)
     g.add_vertex(v)
     e = edge.Edge(1, 2)
     g.add_edge(e)
     self.assertEqual([(1, 2)], g.get_edges())
예제 #12
0
 def test_get_by_vertex(self):
     g = graph.Graph()
     v = vertex.Vertex(1)
     g.add_vertex(v)
     v = vertex.Vertex(2)
     g.add_vertex(v)
     v = vertex.Vertex(3)
     g.add_vertex(v)
     e = edge.Edge(1, 2)
     g.add_edge(e)
     self.assertEqual([(1, 2)], g.get_edges_by_vertex(1))
     e = edge.Edge(1, 3)
     g.add_edge(e)
     self.assertEqual(2, len(g.get_edges_by_vertex(1)))
     e = edge.Edge(2, 1)
     g.add_edge(e, True)
     self.assertEqual(3, len(g.get_edges_by_vertex(1, 0)))
     self.assertEqual(2, len(g.get_edges_by_vertex(1, 1)))
     self.assertEqual(1, len(g.get_edges_by_vertex(1, 2)))
예제 #13
0
파일: test_dfs.py 프로젝트: ablarry/pygraph
    def test_dfs_r_simple_8(self):
        g = graph.Graph(attr={graph.DIRECTED: True})
        for i in range(1, 9):
            v = vertex.Vertex(i)
            g.add_vertex(v)
        e = edge.Edge(1, 2)
        g.add_edge(e)
        e = edge.Edge(1, 3)
        g.add_edge(e)
        e = edge.Edge(1, 4)
        g.add_edge(e)
        e = edge.Edge(2, 5)
        g.add_edge(e)
        e = edge.Edge(5, 7)
        g.add_edge(e)
        e = edge.Edge(7, 8)
        g.add_edge(e)
        e = edge.Edge(3, 6)
        g.add_edge(e)
        e = edge.Edge(6, 8)
        g.add_edge(e)
        e = edge.Edge(6, 7)
        g.add_edge(e)
        g2 = g.dfs_r(1)
        dot = g2.create_graphviz('dfs')
        print(dot)
        gbase = '''digraph {
    1 [label=1]
    2 [label=2]
    5 [label=5]
    7 [label=7]
    8 [label=8]
    3 [label=3]
    6 [label=6]
    4 [label=4]
    1 -> 2
    2 -> 5
    5 -> 7
    7 -> 8
    1 -> 3
    3 -> 6
    1 -> 4
}'''

        # dot.render('dfs_r',view=True)
        self.assertEqual(gbase, str(dot))
예제 #14
0
 def test_dijkstra_simple_3(self):
     g = graph.Graph()
     for i in range(1, 6):
         v = vertex.Vertex(i)
         g.add_vertex(v)
     e = edge.Edge(1, 2, {"WEIGHT": 1})
     g.add_edge(e)
     e = edge.Edge(2, 4, {"WEIGHT": 1})
     g.add_edge(e)
     e = edge.Edge(4, 5, {"WEIGHT": 1})
     g.add_edge(e)
     e = edge.Edge(1, 3, {"WEIGHT": 5})
     g.add_edge(e)
     e = edge.Edge(3, 4, {"WEIGHT": 3})
     g.add_edge(e)
     dot = g.create_graphviz('dijkstra_original_3',
                             attr_label_edge="WEIGHT")
     dot.render('dijkstra_3_original', view=True)
     result = g.dijkstra(1, 5)
     print(result)
     dot = result.create_graphviz('dijkstra_calculado_3', "WEIGHT", 1)
예제 #15
0
 def dfs_rec(self, g, s):
     adjacent_type = '+' if DIRECTED in self.attr and self.attr[
         DIRECTED] else None
     (source, target) = s
     w = self.get_vertex(target)
     if DISCOVERED not in w.attributes or w.attributes[DISCOVERED] is False:
         w.attributes[DISCOVERED] = True
         g.add_vertex(w)
         if (source != '#'):
             g.add_edge(edge.Edge(source, w.id), True)
         for e in self.get_adjacent_vertices_by_vertex(w.id, adjacent_type):
             self.dfs_rec(g, (w.id, e))
     return g
예제 #16
0
파일: models.py 프로젝트: ablarry/pygraph
def barabasi(n, d, directed=False, auto=False):
    """
    Create Barabasi-Albert (BA) graph
    :param n: number of nodes ( > 0)
    :param d: max number of edges of vertex ( > 1)
    :param directed: enable graph directed
    :param auto: allow auto-cycle (loops)
    return: graph created
    """
    # Parameter's validation
    if n <= 0:
        raise ValueError("n parameter must to be > 0 ")
    if d <= 1:
        raise ValueError("d parameter must to be > 1")

    g = graph.Graph()
    # Add attribute DIRECTED in graph
    g.attr[graph.DIRECTED] = directed

    # The first d vertices are created with edges to relate each one with the others
    for i in range(d):
        g.add_vertex(vertex.Vertex(i))
    for i in range(d):
        for j in range(d):
            if len(g.get_edges_by_vertex(i)) < d and len(
                    g.get_edges_by_vertex(j)) < d:
                g.add_edge(edge.Edge(i, j), directed, auto)

    for i in range(d, n):
        g.add_vertex(vertex.Vertex(i))
        for j in range(i):
            # The probability p that the new node i is connected to node j
            # is the grade of vertex j divided by the number of edges of graph
            p = len(g.get_edges_by_vertex(j)) / len(g.get_edges())
            if len(g.get_edges_by_vertex(i)) < d and len(
                    g.get_edges_by_vertex(j)) < d and p >= random():
                g.add_edge(edge.Edge(i, j), directed, auto)
    return g
예제 #17
0
 def dijkstra(self, s, t):
     """
     dijkstra is an algorithm for finding the shortest paths between nodes in a graph.
     :param s: node source
     :param t: node target
     :return g graph generated with the shortest path from source to target 
     """
     l = []
     dist = {}
     prev = {}
     discovered = {}
     for v in self.get_vertices():
         dist[v] = float('inf')
         prev[v] = None
         discovered[v] = False
     dist[s] = 0
     l.append((s, dist[s]))
     while len(l) != 0:
         u = min(l, key=lambda x: x[1])
         l.remove(u)
         u = u[0]
         discovered[u] = True
         if u == t:
             break
         for v in self.get_adjacent_vertices_by_vertex(u):
             if not discovered[v]:
                 alt = dist[u] + self.get_edge((u, v)).attr["WEIGHT"]
                 if alt < dist[v]:
                     dist[v] = alt
                     prev[v] = u
                     l.append((v, dist[v]))
     # Create a graph according to visited nodes store in prev array
     u = t
     g = Graph(attr={DIRECTED: True})
     while u is not None:
         g.add_vertex(vertex.Vertex(u, {"WEIGHT": dist[u]}))
         if prev[u] is not None:
             g.add_vertex(vertex.Vertex(prev[u], {"WEIGHT": dist[prev[u]]}))
             g.add_edge(edge.Edge(prev[u], u))
             u = prev[u]
         else:
             break
     return g
예제 #18
0
    def Prim(self):
        """
        Prim is a function based on  Prim's algorithm to find a minimum spanning forest of an undirected edge-weighted graph. 
        :return g graph representing minimum spannng forest 
        """
        g = Graph(attr={DIRECTED: False})
        distance = [sys.maxsize] * len(self.vertices)
        parent = [None] * len(self.vertices)
        set = [False] * len(self.vertices)

        distance[0] = 0
        parent[0] = -1

        for i in self.vertices:
            # Search vertex with minimum distance
            min_index = 0
            min = sys.maxsize
            for v in self.vertices:
                if distance[v] < min and set[v] is False:
                    min = distance[v]
                    min_index = v
            u = min_index

            # Add u vertex in set to not use it in other iteration 
            set[u] = True
            g.add_vertex(vertex.Vertex(u))

            # Iterate all adjacent vertices of u vertex and update distance 
            for v in self.get_adjacent_vertices_by_vertex(u):
                if set[v] is False and distance[v] > \
                        self.get_edge((u, v)).attr["WEIGHT"]:
                    distance[v] = self.get_edge((u, v)).attr["WEIGHT"]
                    parent[v] = u

        for i in self.vertices:
            if i == 0:
                continue
            if parent[i] is not None:
                g.add_edge(edge.Edge(parent[i], i, {"WEIGHT": self.get_edge((parent[i], i)).attr["WEIGHT"]}))

        return g
예제 #19
0
파일: models.py 프로젝트: ablarry/pygraph
def geo_simple(n, r, directed=False, auto=False):
    """
    Create a random graph with simple method geographic
    :param n: number of vertices ( > 0)
    :param r: max distance to generate edge between nodes (0,1)
    :param directed: enable graph directed
    :param auto: allow auto-cycle (loops)
    :return: graph created
    """
    # Parameter's validation
    if n <= 0:
        raise ValueError("n parameter must to be > 0 ")
    if r <= 0 or r >= 1:
        raise ValueError("r parameter must to be in range (0,1)")

    g = graph.Graph()
    # Add attribute DIRECTED in graph
    g.attr[graph.DIRECTED] = directed

    # Create n nodes with uniform coordinates
    for i in range(n):
        g.add_vertex(
            vertex.Vertex(i, {
                COORDINATE_X: random(),
                COORDINATE_Y: random()
            }))

    # Create edge between two vertex if there is a distance <= r
    for i in range(n):
        for j in range(n):
            # Calculate distance between two points
            p1 = (g.get_vertex(i).attributes[COORDINATE_X],
                  g.get_vertex(i).attributes[COORDINATE_Y])
            p2 = (g.get_vertex(j).attributes[COORDINATE_X],
                  g.get_vertex(j).attributes[COORDINATE_Y])
            d = calculate_distance(p1, p2)
            if d <= r:
                g.add_edge(edge.Edge(i, j), directed, auto)
    return g
예제 #20
0
 def test_initialize_edge(self):
     e = edge.Edge(1, 2)
     self.assertEqual((1, 2), e.get_id())
예제 #21
0
파일: test_bfs.py 프로젝트: ablarry/pygraph
    def test_bfs_simple_10(self):
        g = graph.Graph()
        for i in range(1, 11):
            v = vertex.Vertex(i)
            g.add_vertex(v)
        e = edge.Edge(1, 2)
        g.add_edge(e)
        e = edge.Edge(1, 3)
        g.add_edge(e)
        e = edge.Edge(1, 4)
        g.add_edge(e)
        e = edge.Edge(1, 5)
        g.add_edge(e)
        e = edge.Edge(2, 6)
        g.add_edge(e)
        e = edge.Edge(2, 7)
        g.add_edge(e)
        e = edge.Edge(6, 9)
        g.add_edge(e)
        e = edge.Edge(9, 10)
        g.add_edge(e)
        e = edge.Edge(3, 7)
        g.add_edge(e)
        e = edge.Edge(3, 8)
        g.add_edge(e)
        e = edge.Edge(4, 8)
        g.add_edge(e)
        e = edge.Edge(5, 10)
        g.add_edge(e)
        g2 = g.bfs(1)
        dot = g2.create_graphviz('bfs')
        gbase = '''digraph {
    1 [label=1]
    2 [label=2]
    3 [label=3]
    4 [label=4]
    5 [label=5]
    6 [label=6]
    7 [label=7]
    8 [label=8]
    10 [label=10]
    9 [label=9]
    1 -> 2
    1 -> 3
    1 -> 4
    1 -> 5
    2 -> 6
    2 -> 7
    3 -> 8
    5 -> 10
    6 -> 9
}'''
        # dot.render('bfs',view=True)
        self.assertEqual(gbase, str(dot))
예제 #22
0
파일: test_dfs.py 프로젝트: ablarry/pygraph
    def test_dfs_simple_10(self):
        g = graph.Graph(attr={graph.DIRECTED: True})
        for i in range(1, 11):
            v = vertex.Vertex(i)
            g.add_vertex(v)
        e = edge.Edge(1, 2)
        g.add_edge(e)
        e = edge.Edge(1, 3)
        g.add_edge(e)
        e = edge.Edge(1, 4)
        g.add_edge(e)
        e = edge.Edge(1, 5)
        g.add_edge(e)
        e = edge.Edge(2, 6)
        g.add_edge(e)
        e = edge.Edge(2, 7)
        g.add_edge(e)
        e = edge.Edge(6, 9)
        g.add_edge(e)
        e = edge.Edge(9, 10)
        g.add_edge(e)
        e = edge.Edge(3, 7)
        g.add_edge(e)
        e = edge.Edge(3, 8)
        g.add_edge(e)
        e = edge.Edge(4, 8)
        g.add_edge(e)
        e = edge.Edge(5, 10)
        g.add_edge(e)
        g2 = g.dfs(1)
        dot = g2.create_graphviz('dfs')
        gbase = '''digraph {
    1 [label=1]
    5 [label=5]
    10 [label=10]
    4 [label=4]
    8 [label=8]
    3 [label=3]
    7 [label=7]
    2 [label=2]
    6 [label=6]
    9 [label=9]
    1 -> 5
    5 -> 10
    1 -> 4
    4 -> 8
    1 -> 3
    3 -> 7
    1 -> 2
    2 -> 6
    6 -> 9
}'''
        # dot.render('dfs',view=True)
        self.assertEqual(gbase, str(dot))