Open heartsh opened 3 years ago
Hello heartsh,
It should work if you transform u8 to str when you give a unique identifier for the variables : LpBinary::new(&format!("{}_{}", m,w));
Can you provide a minimalist snippet we can test ?
The code below (which slightly modifies your assignment problem example) gives the error "thread 'main' panicked at 'Cannot open file', examples/assignment.rs:64:5" when I execute "cargo run --example assignment":
extern crate lp_modeler;
use std::collections::HashMap;
use lp_modeler::dsl::*;
use lp_modeler::solvers::{SolverTrait, CbcSolver};
fn main() {
// Problem Data
let men = vec![1, 2, 3];
let women = vec![4, 5, 6];
let compatibility_score: HashMap<(u8, u8),f32> = vec![
((1, 4), 50.0),
((1, 5), 75.0),
((1, 6), 75.0),
((2, 4), 60.0),
((2, 5), 95.0),
((2, 6), 80.0),
((3, 4), 60.0),
((3, 5), 70.0),
((3, 6), 80.0),
].into_iter().collect();
// Define Problem
let mut problem = LpProblem::new("Matchmaking", LpObjective::Maximize);
// Define Variables
let vars: HashMap<(u8,u8), LpBinary> =
men.iter()
.flat_map(|&m| women.iter()
.map(move |&w| {
let key = (m,w);
let value = LpBinary::new(&format!("{}_{}", m,w));
(key, value)
}))
.collect();
// Define Objective Function
let obj_vec: Vec<LpExpression> = {
vars.iter().map( |(&(m,w), bin)| {
let &coef = compatibility_score.get(&(m, w)).unwrap();
coef * bin
} )
}.collect();
problem += obj_vec.sum();
// Define Constraints
// - constraint 1: Each man must be assigned to exactly one woman
for &m in &men{
problem += sum(&women, |&w| vars.get(&(m,w)).unwrap() ).equal(1);
}
// - constraint 2: Each woman must be assigned to exactly one man
for &w in &women{
problem += sum(&men, |&m| vars.get(&(m,w)).unwrap() ).equal(1);
}
// Run Solver
let solver = CbcSolver::new();
let result = solver.run(&problem);
// Compute final objective function value
// (terminate if error, or assign status & variable values)
assert!(result.is_ok(), result.unwrap_err());
let solution = result.unwrap();
let mut obj_value = 0f32;
for (&(m, w), var) in &vars{
let obj_coef = compatibility_score.get(&(m, w)).unwrap();
let var_value = solution.results.get(&var.name).unwrap();
obj_value += obj_coef * var_value;
}
// Print output
println!("Status: {:?}", solution.status);
println!("Objective Value: {}", obj_value);
for (var_name, var_value) in &solution.results{
let int_var_value = *var_value as u32;
if int_var_value == 1{
println!("{} = {}", var_name, int_var_value);
}
}
}
However, it works when I replaced
let value = LpBinary::new(&format!("{}_{}", m,w));
with
let value = LpBinary::new(&format!("A{}_B{}", m,w));
resulting
Status: Optimal
Objective Value: 230
A3_B4 = 1
A2_B5 = 1
A1_B6 = 1
My CBC MILP solver is version 2.10.5.
I got it. It's to the underlying file format. The variable name should start by a letter and must respect some rules (typically +-^/ ). Mhmmm. I will mention rules for naming convention and try to find a way to crash with a better indication.
Hi Developer,
I am writing the software that solves mixture integer programming. In this software, an objective function maximizes the sum of the scores of possible certain index pairs(, as you show as an example of an assignment problem). I noticed that your assignment problem example shows the error "Cannot open file" when I replace the type of men and women (&str) with u8. (e.g., men: "A", "B", "C" -> 1, 2, 3, women: "D", "E", "F" -> 4, 5, 6.) Am I forced to use type "&str"?
Thank you in advance.