示例#1
0
def bellman_ford(G, s):
    """
    Bellman-Ford single-source shortest-paths solution in the general case.

    Algorithm relaxes edges, making `|V|-1` passes over the edges of the graph,
     decreasing an estimate on the path from starting vertex `s`, gradually spreading
     the frontier of relaxed edges beyond those already estimated. In that sense,
     Bellman-Ford is also commonly regarded as a dynamic programming algorithm.

    After `|V|-1` passes of every edge in a graph, it will deterministically
     completely relax all of its edges, unless there's a negative-weight cycle.
     Second loop checks for cycles by verifying that none of the edges can be
     further relaxed otherwise reporting that negative-weight cycle exists.

    Complexity: O(VE) for main loop. Initialization O(V) + O(E) for cycle check.
    :param Graph G: Adjacency list weighted directed graph representation
    :param Vertex s: Starting vertex
    :return bool: Returns True iff the graph contains no negative-weight cycles
     that are reachable from the starting vertex, False otherwise. Graph vertices
     are updated.
    """
    n = len(G.V)  # Total number of vertices in a graph
    initialize_single_source(G, s)
    for i in range(0, n - 1):
        # Relax every edge `|V|-1` times
        for u, v in G.E():
            relax(u, v)
    for u, v in G.E():
        # Check if edge cannot be further relaxed
        if v.d > u.d + weight(u, v):
            return False
    return True
示例#2
0
def relax(u, v):
    """
    Relaxes edge (u, v).

    Term "relaxation" actually means tightening an upper bound. The process
     consists of testing whether we can improve the shortest path to `v` found
     so far by going through `u` and if so, updating both the estimate and
     parent relation.

    Once upper bound property (∂) is achieved, it never changes. Relaxed edges
     also follow triangle inequality: `∂(s, v) ≤ ∂(s, u) + w(u, v)`.

    Longest path can be calculated using negated weights.

    Complexity: O(1)
    :param Vertex u: Source vertex
    :param Vertex v: Target vertex
    :return None: Vertex `v` is updated
    """
    w = weight(u, v)
    if v.d > u.d + w:
        v.d = u.d + w
        v.p = u