def test_is_connected_graph(self):
        g = DirectedGraph(3)
        g.connect(1, 2)
        g.connect(1, 3)
        g.connect(2, 3)
        assert not g.is_connected_graph()

        g.connect(3, 1)
        assert g.is_connected_graph()
    def test_incidence_matrix_file(self):
        g = DirectedGraph(8)
        g.add_random_edges(15)

        before = g.to_adjacency_matrix()
        g.save("test", "im")
        g.load("test.im")
        after = g.to_adjacency_matrix()

        assert before == after
Exemple #3
0
def example04():
    g = DirectedGraph().from_adjacency_list(adjacency_list_2)
    print(g)
    rank = page_rank(g, algorithm="matrix")
    display_pagerank(rank)
    g.save("pr_matrix_2",
           "png",
           engine="dot",
           color_components=True,
           alphabetical=True)
    def test_incidence_matrix(self):
        g = DirectedGraph(8)
        g.add_random_edges(15)
        before = g.to_adjacency_list()
        g.from_incidence_matrix(g.to_incidence_matrix())
        after = g.to_adjacency_list()

        assert before == after
Exemple #5
0
def example01():
    g = DirectedGraph().from_adjacency_list(adjacency_list_1)
    print(g)
    rank = page_rank(g, algorithm="random_walk")
    display_pagerank(rank)
    g.save(
        "pr_random_walk_1",
        "png",
        engine="dot",
        color_components=True,
        alphabetical=True,
    )
    def test_ford_fulkerson(self, graph, f_max):
        g = DirectedGraph().from_adjacency_matrix(graph)
        f = ford_fulkerson(g)

        gf_max = sum(weight for ((begin, end), weight) in f.items()
                     if begin == 1)
        assert gf_max == f_max
    def test_adjacency_matrix(self):
        g = DirectedGraph(8)
        g.add_random_edges(15)

        before = g.to_adjacency_matrix()
        g.from_adjacency_matrix(before)
        after = g.to_adjacency_matrix()

        assert before == after
def _page_rank_matrix(g: DirectedGraph, d) -> Dict[int, float]:
    n = len(g.nodes)
    P = np.zeros((n, n))
    A = np.array(g.to_adjacency_matrix())
    for i in range(n):
        for j in range(n):
            P[i][j] = (1.0 - d) * A[i][j] / g.node_degree(i + 1) + d / float(n)

    p0 = np.full(n, 1 / n)
    p1 = np.zeros(n)
    i = 0
    err = float("inf")
    while err > 1e-11:
        p1 = p0.dot(P)
        diff = p1 - p0
        err = sum(x**2 for x in diff)
        p0 = p1
        i += 1

    print(f"Zbieżność uzyskano po {i} iteracjach.")
    return {k: p1[k - 1] for k in range(1, n + 1)}
def find_shortest_path_bellman_ford(
        g: DirectedGraph,
        source: Node) -> Tuple[Dict[Node, int], Dict[Node, Node]]:
    """ Przyjmuje graf i zrodlo (wierzcholek).
        Zwraca:
        - slownik odleglosci od zrodla
        - slownik poprzednikow
    """
    predecessors = {}
    distance = {}

    for node in g.nodes:
        distance[node] = float("inf")
        predecessors[node] = None
    distance[source] = 0

    for _ in range(1, len(g)):
        for edge in g.edges:
            u = edge.begin
            v = edge.end
            new_distance = distance[u] + g.edge_to_node(u, v).weight
            old_distance = distance[v]
            if new_distance < old_distance:
                distance[v] = new_distance
                predecessors[v] = u

    # sprawdz, czy nie ma cykli o ujemnych wagach:
    for edge in g.edges:
        u = edge.begin
        v = edge.end
        if distance[v] > distance[u] + g.edge_to_node(u, v).weight:
            print("Wystepuje cykl o ujemnych wagach.")
            import sys

            sys.exit(-1)

    d = {node: int(distance[node]) for node in g.nodes}
    p = {node: predecessors[node] for node in g.nodes}

    return d, p
    def test_components(self):
        g = DirectedGraph(3)
        g.connect(2, 1)
        g.connect(1, 3)
        g.connect(3, 1)

        comps = g.components()

        assert comps[1] == comps[3]
        assert comps[2] != comps[1]
        assert comps[2] != comps[3]
    def test_component_list(self):
        g = DirectedGraph(3)
        g.connect(2, 1)
        g.connect(1, 3)
        g.connect(3, 1)

        comps = g.component_list()

        assert [1, 3] in comps.values()
        assert [2] in comps.values()
        assert [2, 1] not in comps.values()
def _page_rank_random_walk(g: DirectedGraph, d) -> Dict[int, float]:
    adj_l = g.to_adjacency_list()
    visited = {n: 0 for n in g.nodes}
    current_node = random.choice(list(g.nodes))
    N = 0
    while N < 100000:
        if random.random() > d and len(adj_l[current_node]) != 0:
            current_node = random.choice(list(adj_l[current_node]))
        else:
            current_node = random.choice(list(g.nodes))

        visited[current_node] += 1
        N += 1
    return {n: v / sum(visited.values()) for n, v in visited.items()}
def ford_fulkerson(g: DirectedGraph,
                   verbose: bool = False) -> Dict[Tuple[int, int], int]:
    """Edmonds–Karp implementation"""
    # sieć rezydualna
    gf = copy.deepcopy(g)
    # źródło
    s: Node = 1
    # ujście
    t: Node = len(g)
    # przepływ krawędzi
    f = {(e.begin, e.end): 0 for e in g.edges}

    step = 0

    while True:
        p = get_trail_to_node(breadth_first_search(gf, s, t), t)
        if p == [t]:
            if verbose:
                print("nie istnieje kolejna ścieżka rozszerzająca")
            break
        if verbose:
            print(f"ścieżka rozszerzająca: {p}")
        p_edges = [gf.edge_to_node(p[i - 1], p[i]) for i in range(1, len(p))]
        cf_p = min(e.weight for e in p_edges)
        if verbose:
            print(f"przepustowość rezydualna ścieżki: {cf_p}")
        for edge in p_edges:
            u = edge.begin
            v = edge.end
            if g.is_connected(u, v):
                f[(u, v)] = f[(u, v)] + cf_p
            else:
                f[(v, u)] = f[(v, u)] - cf_p
                if verbose:
                    print(f"kasowanie przepływu, krawędź: ({u}, {v})")
        # update residual network weights
        gf.edges = set()
        for u, v, c in {(e.begin, e.end, e.weight) for e in g.edges}:
            w1 = c - f[(u, v)]
            w2 = f[(u, v)]
            if w1 != 0:
                gf.connect(u, v, w1)
            if w2 != 0:
                gf.connect(v, u, w2)
        step += 1
    return f
Exemple #14
0
def main():
    print("Wywołanie:\n./lab05.py gen save_dir N\n./lab05.py ff save_dir")
    print("Sieć przykładowa: ./lab05.py gen example\n")

    if len(sys.argv) < 2:
        return

    if sys.argv[1] == "gen":
        save_dir = sys.argv[2]

        if save_dir == "example":
            print(f"Używanie sieci przykładowej (z input_5.pdf)")
            g = get_example()
        else:
            N = int(sys.argv[3])
            print(f"Generowanie sieci przepływowej, N={N}")
            g = generate_network(N=N)
        prep_dir(save_dir)
        g.save(save_dir + "/G", file_format="am")
        g.save(save_dir + "/G", file_format="png", engine="dot")
        print(f"Zapisano do katalogu {save_dir}")

    elif sys.argv[1] == "ff":
        save_dir = sys.argv[2]

        g = DirectedGraph()
        g.load(save_dir + "/G.am")
        # odświeżenie diagramu w razie ręcznej edycji macierzy sąsiedztwa
        g.save(save_dir + "/G", file_format="png", engine="dot")
        print(f"Odczytano sieć przepływową z katalogu {save_dir}")

        f = ford_fulkerson(g, verbose=True)

        f_max = sum(weight for ((begin, end), weight) in f.items()
                    if begin == 1)
        print(f"maksymalny przepływ: {f_max}")

        labels = {(e.begin, e.end): f"{f[(e.begin, e.end)]}/{e.weight}"
                  for e in g.edges}
        g.save(save_dir + "/G-ff",
               file_format="png",
               engine="dot",
               edge_labels=labels)
def page_rank(g: DirectedGraph,
              d=0.15,
              algorithm="matrix") -> Dict[int, float]:
    """
    Zwraca ranking węzłów w grafie skierowanym
    d - prawdopodobieństwo teleportacji
    """
    if d < 0 or d > 1:
        raise ValueError("Nieprawidłowa wartość dla prawdopodobieństwa")

    if g.has_dangling_nodes():
        raise ValueError(
            "Nieprawidłowy graf: posiada wierzchołki bez krawędzi wyjściowych."
        )

    if algorithm == "random_walk":
        return _page_rank_random_walk(g, d=d)
    elif algorithm == "matrix":
        return _page_rank_matrix(g, d=d)
    else:
        raise ValueError("Nieprawidłowy wybór algorytmu.")
    def get_random_flow_network(N: int) -> DirectedGraph:
        """
        Losowa sieć przepływu
        N - liczba warstw sieci
        źródło - Node #1
        ujście - Node #len(graph)
        """
        assert N >= 2

        print(f"liczba warstw: {N}")

        # krok 1: tworzenie warstw
        node_count_in_layer = [1] + [random.randint(2, N) for _ in range(N)] + [1]

        node_layer = [None]
        layer_nodes = []

        total = 1
        for i, count in enumerate(node_count_in_layer):
            node_layer.extend([i] * count)
            layer_nodes.append(list(range(total, total + count)))
            total += count

        print(f"liczba wierzchołków w warstwie: {node_count_in_layer}")
        print(f"wierzchołki w warstwie: {layer_nodes}")

        # krok 2: losowanie krawędzi między warstwami
        g = DirectedGraph(size=sum(node_count_in_layer))

        for i in range(1, N + 1):
            for node in layer_nodes[i]:
                # losowa krawędź wchodząca
                g.connect(random.choice(layer_nodes[i - 1]), node)
                # losowa krawędź wychodząca
                g.connect(node, random.choice(layer_nodes[i + 1]))

        # krok 3: odajemy 2N losowych łuków

        edges_added = 0
        while edges_added < 2 * N:
            # brak krawędzi wychodzącej z ujścia
            n1 = random.randint(1, len(g) - 1)
            # brak krawędzi wchodzącej do źródła
            n2 = random.randint(2, len(g))
            if n1 == n2 or g.is_connected(n1, n2) or g.is_connected(n2, n1):
                continue
            g.connect(n1, n2)
            edges_added += 1
        # krok 4: przypisanie każdej krawędzi losowej przepustowości
        g.assign_random_weights()

        return g
 def get_random_digraph(max_size=20) -> DirectedGraph:
     size = random.randint(2, max_size)
     g = DirectedGraph(size)
     g.connect_random(random.random())
     return g
    def test_connect(self):
        g = DirectedGraph(8)
        n1 = 1
        n2 = 2

        g.connect(n1, n2)
        assert g.is_connected(n1, n2)
        assert not g.is_connected(n2, n1)

        g.disconnect(n1, n2)
        assert not g.is_connected(n1, n2)

        g.connect(n1, n2)
        g.connect(n2, n1)
        assert g.is_connected(n1, n2)
        assert g.is_connected(n2, n1)
Exemple #19
0
def get_example():
    exg = DirectedGraph(11)

    s = 1
    a = 2
    b = 3
    c = 4
    d = 5
    e = 6
    f = 7
    g = 8
    h = 9
    i = 10
    t = 11

    exg.connect(s, a, 10)
    exg.connect(s, b, 3)
    exg.connect(s, c, 6)

    exg.connect(a, b, 8)
    exg.connect(a, d, 8)
    exg.connect(a, e, 6)

    exg.connect(b, e, 2)
    exg.connect(b, f, 10)

    exg.connect(c, d, 9)
    exg.connect(c, f, 1)

    exg.connect(d, h, 5)

    exg.connect(e, d, 1)
    exg.connect(e, i, 7)

    exg.connect(f, g, 9)

    exg.connect(g, t, 7)

    exg.connect(h, t, 5)

    exg.connect(i, t, 7)

    return exg
Exemple #20
0
def load_graph_to_work_on(args):
    g = DirectedGraph()

    if args.load:
        g.load(args.load)

    elif args.n:
        g.add_nodes(int(args.n))
        if args.l:
            g.add_random_edges(int(args.l))
        elif args.p:
            g.connect_random(float(args.p))

    if args.w is not None:
        if args.w[0]:
            g.assign_random_weights(int(args.w[0][0]), int(args.w[0][1]))
        else:
            g.assign_random_weights()
    return g