rust-or / good_lp

Linear Programming for Rust, with a user-friendly API. This crate allows modeling LP problems, and lets you solve them with various solvers.
https://crates.io/crates/good_lp
MIT License
216 stars 35 forks source link

troubles adding a constraint with a count of bool variables #8

Closed Crypto-Spartan closed 3 years ago

Crypto-Spartan commented 3 years ago

Thanks for this great library! I have my use-case almost perfect except for one spot.

I have created two vectors of bool variables like so:

let team1_bools = vars.add_vector(variable().binary(), num_players);
let team2_bools = vars.add_vector(variable().binary(), num_players);

later on in my program, I try to count the number of bool values used, and add it in as a constraint:

model = model.with(constraint!(team2_bools.iter().sum() == 5))

when that didn't work, I tried to use this instead:

model = model.with(constraint!(team2_bools.iter().filter(|x| x == 1).count() == 5))

no matter what I try, I always end up with my errors looking like this:

error[E0277]: can't compare `&&good_lp::variable::Variable` with `{integer}`
   --> src/main.rs:147:31
    |
147 |                 .filter(|x| x == 1)
    |                               ^^ no implementation for `&&good_lp::variable::Variable == {integer}`
    |
    = help: the trait `std::cmp::PartialEq<{integer}>` is not implemented for `&&good_lp::variable::Variable`

error[E0271]: type mismatch resolving `<usize as std::ops::Sub>::Output == good_lp::expression::Expression`
   --> src/main.rs:144:24
    |
144 |       model = model.with(constraint!(
    |  ________________________^
145 | |                 team2_bools
146 | |                 .iter()
147 | |                 .filter(|x| x == 1)
148 | |                 .count() == 5));
    | |______________________________^ expected struct `good_lp::expression::Expression`, found `usize`
    | 
   ::: /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/good_lp-1.1.3/src/constraint.rs:42:24
    |
42  |   pub fn eq<B, A: Sub<B, Output = Expression>>(a: A, b: B) -> Constraint {
    |                          ------------------- required by this bound in `good_lp::constraint::eq`

I currently have my algorithm working using another library in Python here. I just really want to use rust for the increased speed.

Is there any possible way I would be able to do something like this? Thanks!

lovasoa commented 3 years ago

Hello and thanks for getting in touch !

The first syntax you mentioned should work already

model = model.with(constraint!(team2_bools.iter().sum() == 5))

You may just need to help rust a little by adding a type annotation

model = model.with(constraint!(team2_bools.iter().sum::<Expression>() == 5))

or to make things clearer

let team1_score : Expression = team1_bools.iter().sum(); 
model = model.with(constraint!(team1_score == 5))
lovasoa commented 3 years ago

As an aside, what do you mean exactly by

I just really want to use rust for the increased speed.

?

Whether you define your model in python or in rust, the optimizer itself is a compiled library (written in C++ most of the time). So rewriting your code from python to rust will increase speed only if your model is tiny, or if startup time is important.

Crypto-Spartan commented 3 years ago

I'm not sure exactly how the MIP solver library was implemented, I just imported and used it within my python code. I would assume it was written in C or C++, but I never actually looked into it.

However, the rust code runs substantially faster than the python code ran. The fastest iteration of the python code was around 4-5 seconds, the rust code runs in about 0.3-0.5 seconds.

Thanks for the library, and thanks for your help!