use time::OffsetDateTime;
use rustop::opts;
use rs_graph::dimacs;
use rs_graph::maxflow::PushRelabel;
use rs_graph::traits::*;
use rs_graph::Net;
use std::fmt::{Debug, Display};
use num_traits::{FromPrimitive, NumAssign};
use ordered_float::NotNan;
use std::iter::Sum;
fn run<'a, G, F, Us>(g: &mut PushRelabel<'a, G, F>, src: G::Node<'a>, snk: G::Node<'a>, upper: Us, niter: usize)
where
G: IndexDigraph,
F: Display + num_traits::NumAssign + Ord + Copy,
Us: Fn(G::Edge<'a>) -> F + Copy,
{
{
let tstart = OffsetDateTime::now_utc();
for _ in 0..niter {
g.solve(src, snk, upper);
}
let tend = OffsetDateTime::now_utc();
println!("Time: {}", (tend - tstart).as_seconds_f64());
println!("Flow: {}", g.value());
}
}
fn read_and_run<F>(filename: &str, num: usize, global_relabelling: bool, typ: &str)
where
F: Debug + Display + NumAssign + FromPrimitive + Copy + Ord + Sum,
{
let tstart = OffsetDateTime::now_utc();
let instance = dimacs::max::read_from_file(filename).unwrap();
let g: Net = instance.graph;
let s = g.id2node(instance.src);
let t = g.id2node(instance.snk);
let upper: Vec<_> = instance.upper.into_iter().map(|u| F::from_usize(u).unwrap()).collect();
let tend = OffsetDateTime::now_utc();
println!("Time: {}", (tend - tstart).as_seconds_f64());
println!(" graph: {}", std::any::type_name::<Net>());
println!(" number type: {}", typ);
println!(
" global-relabelling heuristic: {}",
if global_relabelling { "YES" } else { "NO" }
);
println!(" number of nodes: {}", g.num_nodes());
println!(" number of arcs: {}", g.num_edges());
let mut d = PushRelabel::new(&g);
d.use_global_relabelling = global_relabelling;
run(&mut d, s, t, |e| upper[g.edge_id(e)], num);
println!(" number of relabels: {}", d.cnt_relabel);
assert!(g
.edges()
.all(|e| d.flow(e) >= F::zero() && d.flow(e) <= upper[g.edge_id(e)]));
assert!(g.nodes().filter(|&u| u != s && u != t).all(|u| {
let f_out = g.outedges(u).map(|(e, _)| d.flow(e)).sum::<F>();
let f_in = g.inedges(u).map(|(e, _)| d.flow(e)).sum::<F>();
f_out == f_in
}));
assert_eq!(
{
let f_out = g.outedges(s).map(|(e, _)| d.flow(e)).sum::<F>();
let f_in = g.inedges(s).map(|(e, _)| d.flow(e)).sum::<F>();
f_out - f_in
},
d.value()
);
}
fn main() {
let (args, _) = opts! {
synopsis "Solve max-flow problem with a push-relabel algorithm.";
opt global_relabelling:bool, desc:"Use global-relabel heuristic.";
opt num:usize=1, desc:"Number of times the algorithm is repeated.";
opt real:bool, desc:"Use real valued flows.";
param file:String, desc:"Instance file name";
}
.parse_or_exit();
if !args.real {
read_and_run::<i32>(&args.file, args.num, args.global_relabelling, "i32");
} else {
read_and_run::<NotNan<f64>>(&args.file, args.num, args.global_relabelling, "f64");
}
}