rs-graph 0.20.0

A library for graph algorithms and combinatorial optimization
Documentation
/*
 * Copyright (c) 2021 Frank Fischer <frank-fischer@shadow-soft.de>
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see  <http://www.gnu.org/licenses/>
 */

use rs_graph::dimacs;
use rs_graph::mcf::{MinCostFlow, NetworkSimplex};
use rs_graph::traits::*;
use rs_graph::vec::{EdgeVec, NodeVec};
use rs_graph::Net;
use std::error::Error;
use std::io::Write;
use std::path::PathBuf;
use std::result::Result;

use rustop::opts;
use time::OffsetDateTime;

fn main() -> Result<(), Box<dyn Error>> {
    let (args, _) = opts! {
        synopsis "Solve min-cost-flow problem with a network simplex algorithm.";
        param file:String, desc:"Instance file name";
    }
    .parse_or_exit();

    let tstart = OffsetDateTime::now_utc();
    let instance = dimacs::min::read_from_file(&args.file).unwrap();

    let g: Net = instance.graph;
    let balances = NodeVec::new_from_vec(&g, instance.balances);
    let lower = EdgeVec::new_from_vec(&g, instance.lower);
    let upper = EdgeVec::new_from_vec(&g, instance.upper);
    let costs = EdgeVec::new_from_vec(&g, instance.costs);

    let tend = OffsetDateTime::now_utc();
    println!("Instance            : {}", args.file);
    println!("Read Time (seconds) : {}", (tend - tstart).as_seconds_f64());
    println!("Graph type          : {}", std::any::type_name::<Net>());
    println!("Number of nodes     : {}", g.num_nodes());
    println!("Number of edges     : {}", g.num_edges());

    let mut spx = NetworkSimplex::new(&g);
    spx.set_balances(|u| balances[u]);
    spx.set_lowers(|e| lower[e]);
    spx.set_uppers(|e| upper[e]);
    spx.set_costs(|e| costs[e]);

    let tstart = OffsetDateTime::now_utc();
    let state = spx.solve();
    let tend = OffsetDateTime::now_utc();
    let soltime = (tend - tstart).as_seconds_f64();

    println!();
    println!("Solution state      : {:?}", state);
    println!("Value               : {:.2}", spx.value());
    println!("Time (seconds)      : {:.2}", soltime);
    println!("Iterations (total)  : {}", spx.num_iterations());
    println!();
    println!("Write solution to   : {}.sol", args.file);

    let solfile = PathBuf::from(args.file + ".sol");
    let f = &mut std::fs::File::create(&solfile)?;
    let fname = solfile
        .file_name()
        .map(|s| s.to_string_lossy())
        .unwrap_or_else(|| "".into());
    writeln!(f, "c Solved with a primal network simplex")?;
    writeln!(f, "c instance            : {}", fname)?;
    writeln!(f, "c solution time       : {:.2} seconds", soltime)?;
    writeln!(f, "c number of iterations: {}", spx.num_iterations())?;
    dimacs::min::write_solution(f, &g, |e| spx.flow(e) as isize, spx.value() as isize)?;

    Ok(())
}