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
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