use rand::{Rng, SeedableRng};
use russcip::{prelude::*, ParamSetting};
use russcip::{HeurResult, HeurTiming, Heuristic, Model, Solving, VarType};
struct RandomRoundingHeur;
impl Heuristic for RandomRoundingHeur {
fn execute(
&mut self,
model: Model<Solving>,
_timing: HeurTiming,
node_inf: bool,
) -> HeurResult {
if node_inf {
return HeurResult::DidNotRun;
}
let mut rng = rand::rngs::StdRng::seed_from_u64(1);
let sol = model.create_sol();
let vars = model.vars();
let mut has_fractional = false;
for var in &vars {
let lp_val = model.current_val(var);
if var.var_type() == VarType::Integer || var.var_type() == VarType::Binary {
let frac_part = lp_val.fract();
if frac_part > 1e-6 && frac_part < 1.0 - 1e-6 {
has_fractional = true;
let rounded = if rng.gen::<f64>() < frac_part {
lp_val.ceil()
} else {
lp_val.floor()
};
sol.set_val(var, rounded);
} else {
sol.set_val(var, lp_val.round());
}
} else {
sol.set_val(var, lp_val);
}
}
if !has_fractional {
return HeurResult::DidNotRun;
}
print!("-- RandomRoundingHeur: found a solution: ");
for var in &vars {
print!("{} = {}, ", var.name(), sol.val(var));
}
println!();
let sol_val = sol.obj_val();
match model.add_sol(sol) {
Ok(_) => {
println!(
"-- RandomRoundingHeur: Added solution to the model with val {}.",
sol_val
);
HeurResult::FoundSol
}
Err(_) => {
println!("-- RandomRoundingHeur: Failed to add solution to the model.");
HeurResult::NoSolFound
}
}
}
}
fn main() {
let mut model = Model::new()
.include_default_plugins()
.read_prob("data/test/simple.mps")
.unwrap()
.set_presolving(ParamSetting::Off)
.set_heuristics(ParamSetting::Off)
.set_separating(ParamSetting::Off);
model.add(
heur(RandomRoundingHeur)
.name("random_round")
.desc("Random rounding at LP solutions")
.priority(1000)
.freq(1)
.timing(HeurTiming::DURING_LP_LOOP),
);
let solved_model = model.solve();
assert!(
solved_model.n_sols() >= 2,
"Expected at least 2 solutions, the primal heuristic solution and the optimal solution."
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_random_rounding() {
main();
}
}