grb 1.3.0

A Rust API for Gurobi optimizer
Documentation
use grb::*;

mod example_utils;
use example_utils::*;

fn main() {
    let env = Env::new("").unwrap();

    let mut model = load_model_file_from_clarg(&env);
    assert!(
        model.get_attr(attr::IsMIP).unwrap() != 0,
        "Model is not a MIP"
    );

    model.optimize().unwrap();

    let status = model.status().unwrap();
    assert!(
        status == Status::Optimal,
        "Optimization ended with status {:?}",
        status
    );

    // store the optimal solution.
    let orig_obj = model.get_attr(attr::ObjVal).unwrap();
    let orig_sol: Vec<_> = model
        .get_vars()
        .unwrap()
        .iter()
        .map(|v| model.get_obj_attr(attr::X, v).unwrap())
        .collect();

    // disable solver output for subsequent solvers.
    model.get_env_mut().set(param::OutputFlag, 0).unwrap();

    // iterate through unfixed, binary variables in model
    let vars = model.get_vars().unwrap().to_vec();
    for (v, &orig_x) in vars.iter().zip(orig_sol.iter()) {
        let vtype: VarType = model.get_obj_attr(attr::VType, v).unwrap().into();
        if !(vtype == VarType::Binary || vtype == VarType::Integer) {
            continue;
        }

        let mut lb = model.get_obj_attr(attr::LB, v).unwrap();
        let mut ub = model.get_obj_attr(attr::UB, v).unwrap();

        if (lb - 0.0).abs() < 1e-6 && (ub - 1.0).abs() < 1e-6 {
            let vname = model.get_obj_attr(attr::VarName, v).unwrap();

            // set variable to 1 - x, where x is its value in optimal solution
            // (it means that `negate` value of the binary variable)
            let start;
            if orig_x < 0.5 {
                lb = 1.0;
                ub = 1.0;
                start = 1.0;
            } else {
                lb = 0.0;
                ub = 0.0;
                start = 0.0;
            }

            model.set_obj_attr(attr::LB, v, lb).unwrap();
            model.set_obj_attr(attr::UB, v, ub).unwrap();
            model.set_obj_attr(attr::Start, v, start).unwrap();

            // update MIP start for the other variables.
            for (vv, &orig_xx) in vars.iter().zip(orig_sol.iter()) {
                if v != vv {
                    model.set_obj_attr(attr::Start, v, orig_xx).unwrap();
                }
            }

            // solve for new value and capture sensitivity information.
            model.optimize().unwrap();
            match model.status().unwrap() {
                Status::Optimal => {
                    let objval = model.get_attr(attr::ObjVal).unwrap();
                    println!(
                        "Objective sensitivity for variable {} is {}",
                        vname,
                        objval - orig_obj
                    );
                }
                _ => {
                    println!("Objective sensitivity for variable {} is infinite", vname);
                }
            }

            // restore the original variable bounds
            model.set_obj_attr(attr::LB, v, 0.0).unwrap();
            model.set_obj_attr(attr::UB, v, 1.0).unwrap();
        }
    }
}