Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python Floyd-Warshall: all-pairs costs with negative-cycle rejection

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

Floyd-Warshall computes shortest-path costs between every pair by considering each vertex as an allowed intermediate.

Download Python source kit

Operation contract

The owned graph has a negative edge but no negative cycle. The algorithm starts from zero self-distances, keeps the cheapest parallel edge and relaxes through every intermediate vertex. The first source reaches the third vertex with cost seven via the second; an unreachable pair is represented as None in the display. A second graph with a negative cycle is rejected after the diagonal becomes negative.

Failure and ownership boundary

A path cost alone does not reconstruct the path; that needs a next-hop matrix. Never run this cubic algorithm on an unbounded graph. Python Bellman-Ford: negative edges and reachable negative cycles, Python Dijkstra: nonnegative weights and stale heap entries and Python topological sort: dependency order and cycle rejection have different cost and input contracts.

Working program

python
def all_pairs(vertex_count, edges):
    if type(vertex_count) is not int or not 1 <= vertex_count <= 12 or type(edges) is not list or len(edges) > 100:
        raise ValueError("graph bounds")
    infinity = float("inf")
    distance = [[0 if row == col else infinity for col in range(vertex_count)] for row in range(vertex_count)]
    for edge in edges:
        if type(edge) is not tuple or len(edge) != 3:
            raise ValueError("edge tuple")
        start, end, cost = edge
        if any(type(value) is not int for value in edge) or not 0 <= start < vertex_count or not 0 <= end < vertex_count or not -10 <= cost <= 10:
            raise ValueError("edge fields")
        distance[start][end] = min(distance[start][end], cost)
    for middle in range(vertex_count):
        for start in range(vertex_count):
            for end in range(vertex_count):
                distance[start][end] = min(distance[start][end], distance[start][middle] + distance[middle][end])
    if any(distance[index][index] < 0 for index in range(vertex_count)):
        raise ValueError("negative cycle")
    return [[None if value == infinity else value for value in row] for row in distance]

matrix = all_pairs(3, [(0, 1, 5), (1, 2, 2), (0, 2, 9)])
print(matrix[0], matrix[2][0])
try:
    all_pairs(2, [(0, 1, -2), (1, 0, 1)])
except ValueError:
    print("negative cycle rejected")

Output

Output
[0, 5, 7] None
negative cycle rejected

Costs and limits

O(V^3) relaxation time and O(V^2) matrix storage dominate this implementation. The twelve-vertex cap makes the teaching fixture bounded; it is not a large-network benchmark.

Common Mistakes

  • A negative edge is allowed; a negative cycle makes shortest cost undefined.
  • The distance matrix alone does not identify the route.

Connected lessons

Python Bellman-Ford: negative edges and reachable negative cycles, Python Dijkstra: nonnegative weights and stale heap entries, Python topological sort: dependency order and cycle rejection.

python
floyd-warshall-paths
Storage details