示例#1
0
def johnson(g: Graph):
    g.vertices["s"] = Vertex("s")
    g.neighbors["s"] = []
    for vertex in g.vertices:
        g.edges.append(Edge("s", vertex, 0))
        g.neighbors["s"] += [(vertex, 0)]
    bf = bellman_ford(g, "s")
    if not bf:
        print("Ujemny cykl")
        return
    distances_b_f, _ = bf
    for edge in g.edges:
        edge.weight = edge.weight + \
                      distances_b_f[edge.start] \
                      - distances_b_f[edge.end]
    s_edges = [edge for edge in g.edges
               if edge.start == "s"]
    for edge in s_edges:
        g.edges.remove(edge)
    g.vertices.pop("s")
    g.neighbors.pop("s")
    distances = {}
    path = {}
    for vertex in g.vertices:
        distances[vertex], path[vertex] = \
            dijkstra(g, vertex)
    for v_1 in g.vertices:
        for v_2 in g.vertices:
            distances[v_1][v_2] += \
                distances_b_f[v_2] - distances_b_f[v_1]
    for edge in g.edges:
        edge.weight = edge.weight + \
                      distances_b_f[edge.start] \
                      - distances_b_f[edge.end]
    return distances, path
示例#2
0
def generate(vertices_number, edges_number):
    vertices = []
    for i in range(vertices_number):
        name = ""
        first_letter = int(i / 26)
        second_letter = i % 26
        if first_letter != 0:
            first_letter = chr(97 + first_letter - 1)
            name += first_letter
        second_letter = chr(97 + second_letter)
        name += second_letter
        vertices.append(Vertex(name))
    edges = []
    graph_edges = []
    available_edges = []
    for v_start in vertices:
        for v_end in vertices:
            if v_start == v_end:
                continue
            available_edges.append((v_start, v_end))
    for i in range(edges_number):
        random_edge = random.choice(available_edges)
        edges.append(random_edge)
        available_edges.remove(random_edge)
    for edge in edges:
        start_vertex, end_vertex = edge
        weight = random.randint(0, 10)
        graph_edges.append(Edge(start_vertex.name, end_vertex.name, weight))
    graph_edges.sort(key=operator.attrgetter('start', 'end'))
    graph = Graph(vertices={vertex.name: vertex
                            for vertex in vertices},
                  edges=graph_edges)
    return graph
from described.bellman_ford import bellman_ford, \
    print_bellman_ford
from described.graph import Edge, Graph, Vertex

G = Graph(vertices={
    "a": Vertex("a"),
    "b": Vertex("b"),
    "c": Vertex("c"),
    "d": Vertex("d"),
    "e": Vertex("e")
},
          edges=[
              Edge("a", "b", 4),
              Edge("a", "c", 5),
              Edge("b", "a", -3),
              Edge("b", "c", -4),
              Edge("c", "d", 7),
              Edge("d", "b", 9),
              Edge("d", "e", 10),
              Edge("e", "b", 8)
          ])

print_bellman_ford(G, "e", bellman_ford(G, "e"))
from described.graph import Edge, Graph, Vertex
from described.johnson import johnson, print_johnson

G = Graph(vertices={
    "a": Vertex("a"),
    "b": Vertex("b"),
    "c": Vertex("c"),
    "d": Vertex("d"),
    "e": Vertex("e")
},
          edges=[
              Edge("a", "b", -1),
              Edge("a", "d", 8),
              Edge("a", "e", 1),
              Edge("b", "c", -3),
              Edge("b", "e", -4),
              Edge("c", "a", 9),
              Edge("c", "e", 2),
              Edge("d", "c", -6),
              Edge("e", "d", 7)
          ])

print_johnson(G, johnson(G))
示例#5
0
from described.floyd_warshall import floyd_warshall, \
    print_floyd_warshall
from described.graph import Edge, Graph, Vertex

G = Graph(vertices={
    "a": Vertex("a"),
    "b": Vertex("b"),
    "c": Vertex("c"),
    "d": Vertex("d"),
    "e": Vertex("e")
},
          edges=[
              Edge("a", "c", -3),
              Edge("a", "d", 2),
              Edge("b", "a", -5),
              Edge("b", "c", 4),
              Edge("c", "d", 6),
              Edge("d", "e", 1),
              Edge("e", "b", 9),
              Edge("e", "c", -4)
          ])

print_floyd_warshall(G, floyd_warshall(G))
示例#6
0
from described.dijkstra import dijkstra, print_dijkstra
from described.graph import Edge, Graph, Vertex

G = Graph(vertices={
    "a": Vertex("a"),
    "b": Vertex("b"),
    "c": Vertex("c"),
    "d": Vertex("d"),
    "e": Vertex("e"),
    "f": Vertex("f")
},
          edges=[
              Edge("a", "b", 7),
              Edge("a", "c", 9),
              Edge("a", "f", 14),
              Edge("b", "c", 10),
              Edge("b", "d", 15),
              Edge("c", "d", 11),
              Edge("c", "f", 2),
              Edge("d", "e", 6),
              Edge("e", "f", 9)
          ])

dijkstra(G, "a")
print_dijkstra(G, "a")
from described.bellman_ford import bellman_ford, print_bellman_ford
from described.graph import Edge, Graph, Vertex

G = Graph(vertices={
    "a": Vertex("a"),
    "b": Vertex("b"),
    "c": Vertex("c"),
    "d": Vertex("d"),
    "e": Vertex("e")
},
          edges=[
              Edge("a", "c", 10),
              Edge("a", "b", 3),
              Edge("b", "a", 2),
              Edge("c", "d", -9),
              Edge("d", "e", 7),
              Edge("e", "a", 1),
              Edge("e", "c", -5)
          ])

print_bellman_ford(G, "a", bellman_ford(G, "a"))
def johnson(g: Graph):
    """
    Funkcja algorytmu Johnsona

        :param g: Obiekt klasy Graph, graf na którym wykonujemy algorytm
        :type g: Graph
        :return: Najkrótsze ścieżki między wszystkimi wierzchołkami oraz listę poprzedników

    Zwracana jest krotka:
        (distances, path)
    zawierająca odległości między wszystkimi wierzchołkami oraz macierz poprzedników
    oprócz zwracania wyników, algorytm przypisuje wyniki do obiektów wierzchołków grafu (klasa Vertex)
    """

    # sprawdzanie na wstępie czy graf zawiera ujemny cykl, nadmiarowe - usunięcie przyśpieszy w pewnym stopniu algorytm
    # przechodzimy przez wszystkie wierzchołki dlatego, że dla wierzchołka izolowanego lub takiego, który nie ma
    # krawędzi wychodzących algorytm bellmana_forda nie zwróci False, tylko dla każdego wierzchołka odległość będzie inf
    for vertex in g.vertices:
        # code może być wartością kodu błędu (-1 lub -2) lub też poprawnym wynikiem algorytmu
        code = bellman_ford(g, vertex)
        # -1 oznacza ujemny cykl wtedy wychodzimy z funkcji
        if code == -1:
            print("Ujemny cykl")
            return False
        # -2 oznacza że wierzchołek nie zawiera krawędzi wychodzących więc nie można stwierdzić czy występuje
        # ujemny cykl, więc przechodzimy do następnego
        elif code == -2:
            continue
        # jeśli nie nastąpił żaden błąd to graf nie zawiera ujemnych cykli - można przejść do algorytmu
        else:
            break

    # tworzymy pomocniczy wierzchołek "-s" oraz krawędzie z wierzchołka "-s" do każdego innego w grafie
    g.vertices["-s"] = Vertex("-s")
    g.neighbors["-s"] = []
    for vertex in g.vertices:
        g.edges.append(Edge("-s", vertex, 0))
        g.neighbors["-s"] += [(vertex, 0)]

    # po utworzeniu wierzchołka "-s" obliczamy odległości z wierzchołka "-s" do pozostałych wierzchołków
    # dodatkowo sprawdzamy czy graf nie zawiera ujemnych cykli, jeśli tak to wychodzimy z funkcji
    result = bellman_ford(g, "-s")
    # jeśli algorytm Bellmana-Forda zwróci False, również algorytm Johnsona zwraca False - ujemny cykl
    if not result:
        return False
    distances_b_f, _ = result
    # zmieniamy wagi dla każdej krawędzi uwzględniając odległości wyliczone przez algorytm Bellmana-Forda
    # przez co likwidujemy ujemne wagi i umożliwiamy użycie algorytmu Dijkstry
    for edge in g.edges:
        edge.weight = edge.weight + distances_b_f[edge.start] - distances_b_f[edge.end]
    # usuwamy wierzchołek "-s" oraz wszystkie krawędzie wyprowadzone z tego wierzchołka
    s_edges = [edge for edge in g.edges if edge.start == "-s"]
    for edge in s_edges:
        g.edges.remove(edge)
    g.vertices.pop("-s")
    g.neighbors.pop("-s")
    # wyliczamy algorytmem Dijkstry odległości i poprzedniki dla każdego wierzchołka
    distances = {}
    path = {}
    for vertex in g.vertices:
        distances[vertex], path[vertex] = dijkstra(g, vertex)
    # ponownie zmieniamy wagi dla każdej krawędzi oraz poprawiamy odległości uwzględniając poprzednio zmienione
    # ujemne wagi
    for v_1 in g.vertices:
        for v_2 in g.vertices:
            distances[v_1][v_2] += distances_b_f[v_2] - distances_b_f[v_1]
    for edge in g.edges:
        edge.weight = edge.weight + distances_b_f[edge.start] - distances_b_f[edge.end]

    # zwracamy krotkę zawierającą odległości oraz macierz poprzedników
    return distances, path