tide-maxflow 0.1.0

Tide max flow algorithm — a push-pull-relabel variant with O(1) array-based data structures
Documentation
//! Cross-validation binary: generate the same deterministic graphs as
//! the Haskell Validate.hs and output (graph_id, name, n, m, max_flow, steps).

use tide_maxflow::max_flow;

fn layered_graph(layers: usize, width: usize) -> (usize, usize, usize, Vec<(usize, usize, i64)>) {
    let s = 0;
    let t = layers * width + 1;
    let n = t + 1;
    let vid = |l: usize, p: usize| l * width + p + 1;
    let mut edges = Vec::new();
    for p in 0..width {
        edges.push((s, vid(0, p), (50 + p) as i64));
    }
    for l in 0..layers - 1 {
        for p in 0..width {
            for d in 0..=2 {
                edges.push((vid(l, p), vid(l + 1, (p + d) % width), (10 + p + d) as i64));
            }
        }
    }
    for p in 0..width {
        edges.push((vid(layers - 1, p), t, (50 + p) as i64));
    }
    (n, s, t, edges)
}

fn grid_graph(rows: usize, cols: usize) -> (usize, usize, usize, Vec<(usize, usize, i64)>) {
    let s = 0;
    let t = rows * cols + 1;
    let n = t + 1;
    let vid = |r: usize, c: usize| r * cols + c + 1;
    let mut edges = Vec::new();
    for c in 0..cols {
        edges.push((s, vid(0, c), (50 + c) as i64));
    }
    for r in 0..rows {
        for c in 0..cols - 1 {
            edges.push((vid(r, c), vid(r, c + 1), (5 + r + c) as i64));
        }
    }
    for r in 0..rows - 1 {
        for c in 0..cols {
            edges.push((vid(r, c), vid(r + 1, c), (5 + r + c) as i64));
        }
    }
    for c in 0..cols {
        edges.push((vid(rows - 1, c), t, (50 + c) as i64));
    }
    (n, s, t, edges)
}

fn bipartite_graph(left: usize, right: usize) -> (usize, usize, usize, Vec<(usize, usize, i64)>) {
    let s = 0;
    let t = left + right + 1;
    let n = t + 1;
    let mut edges = Vec::new();
    for i in 0..left {
        edges.push((s, 1 + i, (100 + (i * 7) % 50) as i64));
    }
    for i in 0..left {
        for j in 0..right {
            edges.push((1 + i, 1 + left + j, (10 + (i * 13 + j * 7) % 40) as i64));
        }
    }
    for j in 0..right {
        edges.push((1 + left + j, t, (100 + (j * 11) % 50) as i64));
    }
    (n, s, t, edges)
}

fn random_graph(
    n_inner: usize,
    edge_prob_pct: usize,
    max_cap: i64,
) -> (usize, usize, usize, Vec<(usize, usize, i64)>) {
    let s = 0;
    let t = n_inner + 1;
    let n = t + 1;
    let mut edges = Vec::new();
    let mut lcg: u64 = 12345;

    // Source edges
    for v in 1..=n_inner {
        lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
        let cap = (lcg % max_cap as u64) as i64 + 1;
        edges.push((s, v, cap));
    }
    // Inner edges
    for u in 1..=n_inner {
        for v in 1..=n_inner {
            if u != v {
                lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
                if (lcg % 100) < edge_prob_pct as u64 {
                    lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
                    let cap = (lcg % max_cap as u64) as i64 + 1;
                    edges.push((u, v, cap));
                }
            }
        }
    }
    // Sink edges
    for v in 1..=n_inner {
        lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
        let cap = (lcg % max_cap as u64) as i64 + 1;
        edges.push((v, t, cap));
    }
    (n, s, t, edges)
}

fn parallel_chains(k: usize, len: usize) -> (usize, usize, usize, Vec<(usize, usize, i64)>) {
    let s = 0;
    let t = k * len + 1;
    let n = t + 1;
    let mut edges = Vec::new();
    for chain in 0..k {
        let first = 1 + chain * len;
        let last = first + len - 1;
        edges.push((s, first, (50 + chain * 3) as i64));
        for i in 0..len - 1 {
            edges.push((first + i, first + i + 1, (20 + chain + i) as i64));
        }
        edges.push((last, t, (50 + chain * 3) as i64));
    }
    (n, s, t, edges)
}

fn main() {
    println!("graph_id,name,n,m,max_flow,steps");

    let graphs: Vec<(&str, (usize, usize, usize, Vec<(usize, usize, i64)>))> = vec![
        ("layered_5x5", layered_graph(5, 5)),
        ("layered_10x10", layered_graph(10, 10)),
        ("layered_20x10", layered_graph(20, 10)),
        ("layered_50x50", layered_graph(50, 50)),
        ("grid_5x5", grid_graph(5, 5)),
        ("grid_10x10", grid_graph(10, 10)),
        ("grid_20x20", grid_graph(20, 20)),
        ("grid_50x50", grid_graph(50, 50)),
        ("bipartite_5x5", bipartite_graph(5, 5)),
        ("bipartite_10x10", bipartite_graph(10, 10)),
        ("bipartite_20x20", bipartite_graph(20, 20)),
        ("bipartite_50x50", bipartite_graph(50, 50)),
        ("random_20_10pct", random_graph(20, 10, 100)),
        ("random_20_30pct", random_graph(20, 30, 100)),
        ("random_50_10pct", random_graph(50, 10, 100)),
        ("random_50_30pct", random_graph(50, 30, 100)),
        ("chains_5x10", parallel_chains(5, 10)),
        ("chains_10x20", parallel_chains(10, 20)),
        ("chains_20x10", parallel_chains(20, 10)),
        (
            "clrs",
            (
                6,
                0,
                5,
                vec![
                    (0, 1, 16),
                    (0, 2, 13),
                    (1, 2, 10),
                    (1, 3, 12),
                    (2, 1, 4),
                    (2, 4, 14),
                    (3, 2, 9),
                    (3, 5, 20),
                    (4, 3, 7),
                    (4, 5, 4),
                ],
            ),
        ),
    ];

    for (gid, (name, (n, s, t, edges))) in graphs.iter().enumerate() {
        let result = max_flow(*n, *s, *t, edges);
        println!(
            "{},{},{},{},{},{}",
            gid,
            name,
            n,
            edges.len(),
            result.flow,
            result.steps
        );
    }
}