ExamplesBy LevelBy TopicLearning Paths
800 Fundamental

800-floyd-warshall — Floyd-Warshall Algorithm

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "800-floyd-warshall — Floyd-Warshall Algorithm" functional Rust example. Difficulty level: Fundamental. Key concepts covered: Functional Programming. Floyd-Warshall (1962) computes shortest paths between ALL pairs of vertices in a weighted graph in O(V³) time. Key difference from OCaml: 1. **All

Tutorial

The Problem

Floyd-Warshall (1962) computes shortest paths between ALL pairs of vertices in a weighted graph in O(V³) time. Unlike Dijkstra (single source) or Bellman-Ford (single source with negative weights), Floyd-Warshall solves the all-pairs problem directly. It is used in network distance matrices, routing table computation, social graph analysis (degree of separation), and computing transitive closures.

🎯 Learning Outcomes

  • • Initialize the distance matrix from edges and set dist[i][i] = 0
  • • Apply the DP recurrence: dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
  • • Understand why the order of loops (k outer, then i, j) is correct
  • • Detect negative cycles via dist[i][i] < 0 after the algorithm
  • • Use Floyd-Warshall as a transitive closure algorithm (boolean variant)
  • Code Example

    #![allow(clippy::all)]
    //! # Floyd-Warshall Algorithm
    
    pub fn floyd_warshall(n: usize, edges: &[(usize, usize, i32)]) -> Vec<Vec<i32>> {
        let mut dist = vec![vec![i32::MAX / 2; n]; n];
        for i in 0..n {
            dist[i][i] = 0;
        }
        for &(u, v, w) in edges {
            dist[u][v] = w;
        }
        for k in 0..n {
            for i in 0..n {
                for j in 0..n {
                    if dist[i][k] + dist[k][j] < dist[i][j] {
                        dist[i][j] = dist[i][k] + dist[k][j];
                    }
                }
            }
        }
        dist
    }
    
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_floyd() {
            let edges = [(0, 1, 3), (0, 2, 8), (1, 2, 2), (2, 0, 5)];
            let dist = floyd_warshall(3, &edges);
            assert_eq!(dist[0][2], 5);
        }
    }

    Key Differences

  • All-pairs vs single-source: Floyd-Warshall is the only practical all-pairs algorithm; Rust programs that need all-pairs often run Dijkstra V times instead for sparse graphs.
  • Overflow prevention: Both languages divide the infinity sentinel by 2; Rust's i32::MAX/2 and OCaml's max_int/2 serve the same purpose.
  • Negative cycles: dist[v][v] < 0 after the algorithm indicates a negative cycle; both languages detect this the same way.
  • Transitive closure: Boolean Floyd-Warshall (with || instead of min) computes reachability; OCaml's Ocamlgraph.Fixpoint does this automatically for labeled graphs.
  • OCaml Approach

    OCaml uses Array.make_matrix n n max_int with max_int/2 as the convention. The triple for-loop is identical. OCaml's min function and array mutation follow the same structure. For transitive closure, replace int with bool and min with ||. The Ocamlgraph library implements Floyd-Warshall as part of its path algorithms suite.

    Full Source

    #![allow(clippy::all)]
    //! # Floyd-Warshall Algorithm
    
    pub fn floyd_warshall(n: usize, edges: &[(usize, usize, i32)]) -> Vec<Vec<i32>> {
        let mut dist = vec![vec![i32::MAX / 2; n]; n];
        for i in 0..n {
            dist[i][i] = 0;
        }
        for &(u, v, w) in edges {
            dist[u][v] = w;
        }
        for k in 0..n {
            for i in 0..n {
                for j in 0..n {
                    if dist[i][k] + dist[k][j] < dist[i][j] {
                        dist[i][j] = dist[i][k] + dist[k][j];
                    }
                }
            }
        }
        dist
    }
    
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_floyd() {
            let edges = [(0, 1, 3), (0, 2, 8), (1, 2, 2), (2, 0, 5)];
            let dist = floyd_warshall(3, &edges);
            assert_eq!(dist[0][2], 5);
        }
    }
    ✓ Tests Rust test suite
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_floyd() {
            let edges = [(0, 1, 3), (0, 2, 8), (1, 2, 2), (2, 0, 5)];
            let dist = floyd_warshall(3, &edges);
            assert_eq!(dist[0][2], 5);
        }
    }

    Deep Comparison

    OCaml vs Rust: Floyd Warshall

    Overview

    See the example.rs and example.ml files for detailed implementations.

    Key Differences

    AspectOCamlRust
    Type systemHindley-MilnerOwnership + traits
    MemoryGCZero-cost abstractions
    MutabilityExplicit refmut keyword
    Error handlingOption/ResultResult<T, E>

    See README.md for detailed comparison.

    Exercises

  • Implement the boolean transitive closure variant: replace i32 with bool and use || and && instead of min/add.
  • Detect and report all negative cycles: after running Floyd-Warshall, find all vertices v where dist[v][v] < 0 and trace which cycle they belong to.
  • Use Floyd-Warshall to compute "six degrees of separation" in a social network: load a friend graph and find the average shortest path length between all pairs.
  • Open Source Repos