use std::fs;
use std::io::{BufWriter, Write};
use std::path::Path;
struct DimacsGraph {
name: String,
n: usize,
source: usize,
sink: usize,
edges: Vec<(usize, usize, i64)>,
}
impl DimacsGraph {
fn write_to(&self, dir: &Path) {
let path = dir.join(format!("{}.max", self.name));
let file = fs::File::create(&path).unwrap();
let mut f = BufWriter::with_capacity(1 << 20, file); writeln!(f, "c {}", self.name).unwrap();
writeln!(f, "p max {} {}", self.n, self.edges.len()).unwrap();
writeln!(f, "n {} s", self.source).unwrap();
writeln!(f, "n {} t", self.sink).unwrap();
for &(u, v, cap) in &self.edges {
writeln!(f, "a {} {} {}", u, v, cap).unwrap();
}
f.flush().unwrap();
}
fn estimated_bytes(&self) -> usize {
60 + self.edges.len() * 20
}
}
fn layered(name: &str, layers: usize, width: usize) -> DimacsGraph {
let s = 1;
let t = layers * width + 2;
let n = t;
let vid = |l: usize, p: usize| l * width + p + 2;
let m_est = width + (layers - 1) * width * 3 + width;
let mut edges = Vec::with_capacity(m_est);
for p in 0..width {
edges.push((s, vid(0, p), (50 + p % 1000) as i64));
}
for l in 0..layers - 1 {
for p in 0..width {
for d in 0..=2usize {
edges.push((
vid(l, p),
vid(l + 1, (p + d) % width),
(10 + (p + d) % 1000) as i64,
));
}
}
}
for p in 0..width {
edges.push((vid(layers - 1, p), t, (50 + p % 1000) as i64));
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn grid(name: &str, rows: usize, cols: usize) -> DimacsGraph {
let s = 1;
let t = rows * cols + 2;
let n = t;
let vid = |r: usize, c: usize| r * cols + c + 2;
let m_est = cols + rows * (cols - 1) + (rows - 1) * cols + cols;
let mut edges = Vec::with_capacity(m_est);
for c in 0..cols {
edges.push((s, vid(0, c), (50 + c % 1000) 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) % 1000) 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) % 1000) as i64));
}
}
for c in 0..cols {
edges.push((vid(rows - 1, c), t, (50 + c % 1000) as i64));
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn bipartite(name: &str, left: usize, right: usize) -> DimacsGraph {
let s = 1;
let t = left + right + 2;
let n = t;
let m_est = left + left * right + right;
let mut edges = Vec::with_capacity(m_est);
for i in 0..left {
edges.push((s, 2 + i, (100 + (i * 7) % 50) as i64));
}
for i in 0..left {
for j in 0..right {
edges.push((2 + i, 2 + left + j, (10 + (i * 13 + j * 7) % 40) as i64));
}
}
for j in 0..right {
edges.push((2 + left + j, t, (100 + (j * 11) % 50) as i64));
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn random_er(name: &str, n_inner: usize, edge_prob_pct: usize, max_cap: i64) -> DimacsGraph {
let s = 1;
let t = n_inner + 2;
let n = t;
let m_est = n_inner + (n_inner * n_inner * edge_prob_pct / 100) + n_inner;
let mut edges = Vec::with_capacity(m_est);
let mut lcg: u64 = 12345;
for v in 2..=n_inner + 1 {
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % max_cap as u64) as i64 + 1;
edges.push((s, v, cap));
}
for u in 2..=n_inner + 1 {
for v in 2..=n_inner + 1 {
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));
}
}
}
}
for v in 2..=n_inner + 1 {
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % max_cap as u64) as i64 + 1;
edges.push((v, t, cap));
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn chains(name: &str, k: usize, len: usize) -> DimacsGraph {
let s = 1;
let t = k * len + 2;
let n = t;
let m_est = k * (1 + (len - 1) + 1);
let mut edges = Vec::with_capacity(m_est);
for chain in 0..k {
let first = 2 + chain * len;
let last = first + len - 1;
edges.push((s, first, (50 + (chain * 3) % 1000) as i64));
for i in 0..len - 1 {
edges.push((first + i, first + i + 1, (20 + (chain + i) % 1000) as i64));
}
edges.push((last, t, (50 + (chain * 3) % 1000) as i64));
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn washington(name: &str, k: usize, n_per_layer: usize, max_cap: i64) -> DimacsGraph {
let s = 1;
let t = k * n_per_layer + 2;
let n = t;
let vid = |layer: usize, idx: usize| 2 + layer * n_per_layer + idx;
let mut edges = Vec::new();
let mut lcg: u64 = 99991;
for i in 0..n_per_layer {
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % max_cap as u64) as i64 + 1;
edges.push((s, vid(0, i), cap));
}
for l in 0..k - 1 {
for i in 0..n_per_layer {
for j in 0..n_per_layer {
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % max_cap as u64) as i64 + 1;
edges.push((vid(l, i), vid(l + 1, j), cap));
}
}
}
for i in 0..n_per_layer {
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % max_cap as u64) as i64 + 1;
edges.push((vid(k - 1, i), t, cap));
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn vision_grid_2d(name: &str, rows: usize, cols: usize) -> DimacsGraph {
let s = 1;
let t = rows * cols + 2;
let n = t;
let vid = |r: usize, c: usize| r * cols + c + 2;
let n_tlinks = 2 * rows * cols;
let n_nlinks = 2 * (rows * (cols - 1) + (rows - 1) * cols);
let mut edges = Vec::with_capacity(n_tlinks + n_nlinks);
let mut lcg: u64 = 77777;
for r in 0..rows {
for c in 0..cols {
let v = vid(r, c);
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap_s = (lcg % 500) as i64 + 1;
edges.push((s, v, cap_s));
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap_t = (lcg % 500) as i64 + 1;
edges.push((v, t, cap_t));
}
}
for r in 0..rows {
for c in 0..cols {
let u = vid(r, c);
if c + 1 < cols {
let v = vid(r, c + 1);
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % 50) as i64 + 1;
edges.push((u, v, cap));
edges.push((v, u, cap));
}
if r + 1 < rows {
let v = vid(r + 1, c);
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % 50) as i64 + 1;
edges.push((u, v, cap));
edges.push((v, u, cap));
}
}
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn vision_grid_3d(name: &str, lx: usize, ly: usize, lz: usize) -> DimacsGraph {
let total_voxels = lx * ly * lz;
let s = 1;
let t = total_voxels + 2;
let n = t;
let vid = |x: usize, y: usize, z: usize| x * ly * lz + y * lz + z + 2;
let n_tlinks = 2 * total_voxels;
let n_nlinks_est = 2 * (lx * ly * (lz - 1) + lx * (ly - 1) * lz + (lx - 1) * ly * lz);
let mut edges = Vec::with_capacity(n_tlinks + n_nlinks_est);
let mut lcg: u64 = 88888;
for x in 0..lx {
for y in 0..ly {
for z in 0..lz {
let v = vid(x, y, z);
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap_s = (lcg % 500) as i64 + 1;
edges.push((s, v, cap_s));
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap_t = (lcg % 500) as i64 + 1;
edges.push((v, t, cap_t));
}
}
}
for x in 0..lx {
for y in 0..ly {
for z in 0..lz {
let u = vid(x, y, z);
if x + 1 < lx {
let v = vid(x + 1, y, z);
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % 50) as i64 + 1;
edges.push((u, v, cap));
edges.push((v, u, cap));
}
if y + 1 < ly {
let v = vid(x, y + 1, z);
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % 50) as i64 + 1;
edges.push((u, v, cap));
edges.push((v, u, cap));
}
if z + 1 < lz {
let v = vid(x, y, z + 1);
lcg = lcg.wrapping_mul(6364136223846793005).wrapping_add(1);
let cap = (lcg % 50) as i64 + 1;
edges.push((u, v, cap));
edges.push((v, u, cap));
}
}
}
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn rfim_2d(name: &str, l: usize, j_coupling: i64, sigma: f64) -> DimacsGraph {
let total = l * l;
let s = 1;
let t = total + 2;
let n = t;
let vid = |x: usize, y: usize| x * l + y + 2;
let mut edges = Vec::with_capacity(total + 4 * total);
let mut lcg: u64 = 31415;
let next_gaussian = |lcg_state: &mut u64| -> f64 {
*lcg_state = lcg_state.wrapping_mul(6364136223846793005).wrapping_add(1);
let u1 = (*lcg_state as f64) / (u64::MAX as f64);
let u1 = u1.max(1e-10); *lcg_state = lcg_state.wrapping_mul(6364136223846793005).wrapping_add(1);
let u2 = (*lcg_state as f64) / (u64::MAX as f64);
(-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos()
};
for x in 0..l {
for y in 0..l {
let v = vid(x, y);
let h = next_gaussian(&mut lcg) * sigma;
if h > 0.0 {
let cap = (h * 1000.0) as i64 + 1; edges.push((s, v, cap));
} else {
let cap = (-h * 1000.0) as i64 + 1;
edges.push((v, t, cap));
}
}
}
for x in 0..l {
for y in 0..l {
let u = vid(x, y);
let v = vid((x + 1) % l, y);
edges.push((u, v, j_coupling));
edges.push((v, u, j_coupling));
let v = vid(x, (y + 1) % l);
edges.push((u, v, j_coupling));
edges.push((v, u, j_coupling));
}
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn rfim_3d(name: &str, l: usize, j_coupling: i64, sigma: f64) -> DimacsGraph {
let total = l * l * l;
let s = 1;
let t = total + 2;
let n = t;
let vid = |x: usize, y: usize, z: usize| x * l * l + y * l + z + 2;
let mut edges = Vec::with_capacity(total + 6 * total);
let mut lcg: u64 = 27182;
let next_gaussian = |lcg_state: &mut u64| -> f64 {
*lcg_state = lcg_state.wrapping_mul(6364136223846793005).wrapping_add(1);
let u1 = (*lcg_state as f64) / (u64::MAX as f64);
let u1 = u1.max(1e-10);
*lcg_state = lcg_state.wrapping_mul(6364136223846793005).wrapping_add(1);
let u2 = (*lcg_state as f64) / (u64::MAX as f64);
(-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos()
};
for x in 0..l {
for y in 0..l {
for z in 0..l {
let v = vid(x, y, z);
let h = next_gaussian(&mut lcg) * sigma;
if h > 0.0 {
let cap = (h * 1000.0) as i64 + 1;
edges.push((s, v, cap));
} else {
let cap = (-h * 1000.0) as i64 + 1;
edges.push((v, t, cap));
}
}
}
}
for x in 0..l {
for y in 0..l {
for z in 0..l {
let u = vid(x, y, z);
let v = vid((x + 1) % l, y, z);
edges.push((u, v, j_coupling));
edges.push((v, u, j_coupling));
let v = vid(x, (y + 1) % l, z);
edges.push((u, v, j_coupling));
edges.push((v, u, j_coupling));
let v = vid(x, y, (z + 1) % l);
edges.push((u, v, j_coupling));
edges.push((v, u, j_coupling));
}
}
}
DimacsGraph {
name: name.to_string(),
n,
source: s,
sink: t,
edges,
}
}
fn main() {
let dir = Path::new("../graph-pool");
fs::create_dir_all(dir).unwrap();
let mut all_graphs: Vec<DimacsGraph> = Vec::new();
all_graphs.push(layered("layered_5x5", 5, 5));
all_graphs.push(layered("layered_10x10", 10, 10));
all_graphs.push(layered("layered_20x10", 20, 10));
all_graphs.push(layered("layered_50x50", 50, 50));
all_graphs.push(layered("layered_100x100", 100, 100));
all_graphs.push(grid("grid_5x5", 5, 5));
all_graphs.push(grid("grid_10x10", 10, 10));
all_graphs.push(grid("grid_20x20", 20, 20));
all_graphs.push(grid("grid_50x50", 50, 50));
all_graphs.push(grid("grid_100x100", 100, 100));
all_graphs.push(bipartite("bipartite_5x5", 5, 5));
all_graphs.push(bipartite("bipartite_10x10", 10, 10));
all_graphs.push(bipartite("bipartite_20x20", 20, 20));
all_graphs.push(bipartite("bipartite_50x50", 50, 50));
all_graphs.push(bipartite("bipartite_100x100", 100, 100));
all_graphs.push(random_er("random_20_10pct", 20, 10, 100));
all_graphs.push(random_er("random_20_30pct", 20, 30, 100));
all_graphs.push(random_er("random_50_10pct", 50, 10, 100));
all_graphs.push(random_er("random_50_30pct", 50, 30, 100));
all_graphs.push(random_er("random_200_10pct", 200, 10, 100));
all_graphs.push(chains("chains_5x10", 5, 10));
all_graphs.push(chains("chains_10x20", 10, 20));
all_graphs.push(chains("chains_20x10", 20, 10));
all_graphs.push(chains("chains_50x50", 50, 50));
all_graphs.push(DimacsGraph {
name: "clrs".to_string(),
n: 6,
source: 1,
sink: 6,
edges: vec![
(1, 2, 16),
(1, 3, 13),
(2, 3, 10),
(2, 4, 12),
(3, 2, 4),
(3, 5, 14),
(4, 3, 9),
(4, 6, 20),
(5, 4, 7),
(5, 6, 4),
],
});
all_graphs.push(layered("layered_200x50", 200, 50));
all_graphs.push(layered("layered_500x100", 500, 100));
all_graphs.push(grid("grid_200x200", 200, 200));
all_graphs.push(grid("grid_500x500", 500, 500));
all_graphs.push(bipartite("bipartite_200x200", 200, 200));
all_graphs.push(bipartite("bipartite_500x500", 500, 500));
all_graphs.push(random_er("random_500_5pct", 500, 5, 1000));
all_graphs.push(random_er("random_1000_5pct", 1000, 5, 1000));
all_graphs.push(random_er("random_1000_10pct", 1000, 10, 1000));
all_graphs.push(chains("chains_100x100", 100, 100));
all_graphs.push(chains("chains_500x100", 500, 100));
all_graphs.push(washington("washington_10x100", 10, 100, 1000));
all_graphs.push(washington("washington_5x200", 5, 200, 1000));
all_graphs.push(layered("layered_500x500", 500, 500)); all_graphs.push(layered("layered_1000x100", 1000, 100)); all_graphs.push(layered("layered_1000x1000", 1000, 1000)); all_graphs.push(grid("grid_1000x1000", 1000, 1000)); all_graphs.push(grid("grid_2000x2000", 2000, 2000)); all_graphs.push(bipartite("bipartite_1000x1000", 1000, 1000)); all_graphs.push(bipartite("bipartite_2000x2000", 2000, 2000)); all_graphs.push(random_er("random_2000_5pct", 2000, 5, 1000)); all_graphs.push(random_er("random_2000_10pct", 2000, 10, 1000)); all_graphs.push(random_er("random_5000_3pct", 5000, 3, 1000)); all_graphs.push(random_er("random_5000_5pct", 5000, 5, 1000)); all_graphs.push(random_er("random_5000_10pct", 5000, 10, 1000)); all_graphs.push(random_er("random_10000_3pct", 10000, 3, 1000)); all_graphs.push(random_er("random_10000_5pct", 10000, 5, 1000)); all_graphs.push(chains("chains_1000x1000", 1000, 1000)); all_graphs.push(washington("washington_10x500", 10, 500, 1000)); all_graphs.push(washington("washington_20x200", 20, 200, 1000));
all_graphs.push(layered("layered_2000x1000", 2000, 1000)); all_graphs.push(layered("layered_2000x2000", 2000, 2000)); all_graphs.push(layered("layered_5000x1000", 5000, 1000)); all_graphs.push(layered("layered_3000x3000", 3000, 3000)); all_graphs.push(layered("layered_10000x1000", 10000, 1000)); all_graphs.push(layered("layered_10000x2000", 10000, 2000));
all_graphs.push(grid("grid_3000x3000", 3000, 3000));
all_graphs.push(chains("chains_2000x2000", 2000, 2000)); all_graphs.push(chains("chains_5000x1000", 5000, 1000));
all_graphs.push(vision_grid_2d("vision2d_100x100", 100, 100)); all_graphs.push(vision_grid_2d("vision2d_500x500", 500, 500)); all_graphs.push(vision_grid_2d("vision2d_1000x1000", 1000, 1000)); all_graphs.push(vision_grid_2d("vision2d_2000x2000", 2000, 2000)); all_graphs.push(vision_grid_2d("vision2d_5000x5000", 5000, 5000));
all_graphs.push(vision_grid_3d("vision3d_50x50x50", 50, 50, 50)); all_graphs.push(vision_grid_3d("vision3d_100x100x100", 100, 100, 100)); all_graphs.push(vision_grid_3d("vision3d_200x200x200", 200, 200, 200)); all_graphs.push(vision_grid_3d("vision3d_300x300x300", 300, 300, 300));
all_graphs.push(rfim_2d("rfim2d_100", 100, 1000, 1.0)); all_graphs.push(rfim_2d("rfim2d_500", 500, 1000, 1.0)); all_graphs.push(rfim_2d("rfim2d_1000", 1000, 1000, 1.0)); all_graphs.push(rfim_2d("rfim2d_2000", 2000, 1000, 1.0));
all_graphs.push(rfim_3d("rfim3d_32", 32, 1000, 2.3)); all_graphs.push(rfim_3d("rfim3d_64", 64, 1000, 2.3)); all_graphs.push(rfim_3d("rfim3d_100", 100, 1000, 2.3)); all_graphs.push(rfim_3d("rfim3d_128", 128, 1000, 2.3)); all_graphs.push(rfim_3d("rfim3d_200", 200, 1000, 2.3)); all_graphs.push(rfim_3d("rfim3d_256", 256, 1000, 2.3));
let mut total_bytes: usize = 0;
for g in &all_graphs {
let est = g.estimated_bytes();
total_bytes += est;
print!(
"writing {}.max (V={}, E={}, ~{} MB)...",
g.name,
g.n,
g.edges.len(),
est / (1024 * 1024)
);
std::io::stdout().flush().unwrap();
g.write_to(dir);
println!(" done");
}
println!(
"\nTotal: {} graphs, estimated ~{:.1} GB",
all_graphs.len(),
total_bytes as f64 / (1024.0 * 1024.0 * 1024.0)
);
}