use good_lp::variable::ProblemVariables;
use good_lp::{default_solver, variable, variables, Expression, Solution, SolverModel, Variable};
struct Product {
needed_fuel: f64,
needed_time: f64,
value: f64, }
struct ResourceAllocationProblem {
vars: ProblemVariables,
total_value: Expression,
consumed_fuel: Expression,
consumed_time: Expression,
available_fuel: f64,
available_time: f64,
}
impl ResourceAllocationProblem {
fn new(available_fuel: f64, available_time: f64) -> ResourceAllocationProblem {
ResourceAllocationProblem {
vars: variables!(),
available_fuel,
available_time,
consumed_fuel: 0.into(),
consumed_time: 0.into(),
total_value: 0.into(),
}
}
fn add(&mut self, product: Product) -> Variable {
let amount_to_produce = self.vars.add(variable().min(0));
self.total_value += amount_to_produce * product.value;
self.consumed_fuel += amount_to_produce * product.needed_fuel;
self.consumed_time += amount_to_produce * product.needed_time;
amount_to_produce
}
fn best_product_quantities(self) -> impl Solution {
self.vars
.maximise(self.total_value)
.using(default_solver)
.with(self.consumed_fuel.leq(self.available_fuel))
.with(self.consumed_time.leq(self.available_time))
.solve()
.unwrap()
}
}
use float_eq::assert_float_eq;
#[test]
fn resource_allocation() {
let mut pb = ResourceAllocationProblem::new(5., 3.);
let steel = pb.add(Product {
needed_fuel: 1.,
needed_time: 1.,
value: 10.,
});
let stainless_steel = pb.add(Product {
needed_fuel: 2.,
needed_time: 1.,
value: 11.,
});
let solution = pb.best_product_quantities();
assert_float_eq!(1., solution.value(steel), abs <= 1e-10);
assert_float_eq!(2., solution.value(stainless_steel), abs <= 1e-10);
}
#[test]
fn using_a_vector() {
let products = vec![
Product {
needed_fuel: 1.,
needed_time: 1.,
value: 10.,
},
Product {
needed_fuel: 2.,
needed_time: 1.,
value: 11.,
},
];
let mut pb = ResourceAllocationProblem::new(5., 3.);
let variables: Vec<_> = products.into_iter().map(|p| pb.add(p)).collect();
let solution = pb.best_product_quantities();
let product_quantities: Vec<_> = variables.iter().map(|&v| solution.value(v)).collect();
assert_float_eq!(1., product_quantities[0], abs <= 1e-10);
assert_float_eq!(2., product_quantities[1], abs <= 1e-10);
}