Coder Social home page Coder Social logo

rust-or / good_lp Goto Github PK

View Code? Open in Web Editor NEW
204.0 10.0 31.0 286 KB

Linear Programming for Rust, with a user-friendly API. This crate allows modeling LP problems, and lets you solve them with various solvers.

Home Page: https://crates.io/crates/good_lp

License: MIT License

Rust 100.00%
linear-programs solvers lp-modeler cbc lpsolve linear-programming optimization

good_lp's People

Contributors

0xalpharush avatar carrascomj avatar jacobsvante avatar lovasoa avatar lucidfrontier45 avatar mfuhr avatar mmghannam avatar rayrrr avatar robbiemu avatar tiborschneider avatar yonch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

good_lp's Issues

Add support for Windows

I couldn't use this library on Windows, so it would be very helpful if it becomes usable.

Making CoinCbcProblem cloneable...

I was wondering if you'd be willing to have CoinCbcProblem use the Clone attribute.

image

The model is cloneable in coin_cbc and allows for the usage of an unsolved model to be used within a loop...

    let mut ref_model = SubsetModel::new(items, item_reqs, weights, state_1_values, state_2_values);
    ref_model.problem.set_parameter("log", "0");

    for storage in 0..state_1_sum_lb {
        for lodging in 0..state_2_sum_lb {
            let model = ref_model.clone();
            // The state sum LB constraints.
            let state_1_sum_lb_expr: Expression = (storage as f64).into();
            let state_2_sum_lb_expr: Expression = (lodging as f64).into();
            let state_1_sum_lb_constraint =
                constraint!(state_1_sum_lb_expr <= model.state_1_sum_expr);
            let state_2_sum_lb_constraint =
                constraint!(state_2_sum_lb_expr <= model.state_2_sum_expr);

            let subset_solution = model
                .problem
                .with(state_1_sum_lb_constraint)
                .with(state_2_sum_lb_constraint)
                .solve()
                .unwrap();
...

The performance is pretty much identical on my small test sets.

all-in-loop: TotalSeconds      : 70.7896676
  ref_model: TotalSeconds      : 70.5151181

but I imagine that on models with many more variables might benefit performance wise.

Perhaps there is already a better way to handle this kind of situation and I just missed it?

`From<Expression> not implemented for f64`

Given this code, where batt_var.b_energy: Vec<Vec<Variable>>:

        for (bat, b_energy_row) in batt_var.b_energy.iter().enumerate() {
            for (t, b_energy) in b_energy_row.iter().enumerate() {
                let mut energy_init: Expression = match bat {
                    0 => b_energy.clone(),
                    1 => Expression::from_other_affine(st_soc * e_max / 100.0),
                    _ => Expression::from_other_affine(b_energy_row[t-1]),
                };
                let bat_pc = Expression::from_other_affine(batt_var.bat_pc[bat][t]);
                energy_init.mul(bat_pc);
            }
        }

I get the following error output:

error[E0277]: the trait bound `f64: From<Expression>` is not satisfied
   --> src/model/constr.rs:449:51
    |
449 |                 energy_init.mul(bat_pc);
    |                                         --- ^^^^^^ the trait `From<Expression>` is not implemented for `f64`
    |                                         |
    |                                         required by a bound introduced by this call
    |

Update:

I have fixed my issue, but I am keeping this because it seems strange.

Suppressing Cbc command line output

When running the solver, I get the following output to my command line:

Welcome to the CBC MILP Solver
Version: 2.10.10
Build Date: Apr 20 2023

command line - Cbc_C_Interface -solve -quit (default strategy 1)
Continuous objective value is 12.5141 - 0.00 seconds
Cgl0004I processed model has 3 rows, 5 columns (5 integer (1 of which binary)) and 15 elements
Cutoff increment increased from 1e-05 to 0.0999
Cbc0012I Integer solution of 12.6 found by DiveCoefficient after 0 iterations and 0 nodes (0.00 seconds)
Cbc0001I Search completed - best objective 12.6, took 1 iterations and 0 nodes (0.00 seconds)
Cbc0035I Maximum depth 0, 1 variables fixed on reduced cost
Cuts at root node changed objective from 12.5221 to 12.6
Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)

Result - Optimal solution found

Objective value:                12.60000000
Enumerated nodes:               0
Total iterations:               1
Time (CPU seconds):             0.00
Time (Wallclock seconds):       0.00

Total time (CPU seconds):       0.00   (Wallclock seconds):       0.00

However, I am also using the command line to output results of my program. Would it be possible to suppress this output to not show?

External solver failing due to LP file format

Using an external solver fails on some problems, e.g., the first example on the main good_lp documentation page. When replacing default_solver with LpSolver(GlpkSolver::new()) the code panics with glpsol exited with status exit status: 1.

Running glpsol from the shell on a copy of the LP file shows more detail:

GLPSOL--GLPK LP/MIP Solver 5.0
Parameter(s) specified in the command line:
 --lp example.lp
Reading problem data from 'example.lp'...
example.lp:8: missing variable name
CPLEX LP file processing error

The file is:

 1  \ good_lp_problem
 2
 3  Maximize
 4    obj: -3 b + 10 a
 5
 6  Subject To
 7    c0: -1 b + 1 a <= -2
 8    c1: -1 b + -1 a <= -3
 9
10  Bounds
11    a <= 1
12    2 <= b <= 4
13
14  End

The problem appears to be the + -1 a on line 8. Cplex (at least version 20.1.0.0 at NEOS) also fails with the error CPLEX Error 1434: Line 8: Couldn't convert '+-1' to a number but Gurobi accepts the file.

I think the formatting is done by linear_coefficients_str() in solvers/lp_solvers.rs:

fn linear_coefficients_str(
    expr: &Expression,
    variables: &[lp_solvers::problem::Variable],
) -> StrExpression {
    StrExpression(
        expr.linear_coefficients()
            .map(|(var, coeff)| format!("{} {}", coeff, variables[var.index()].name))
            .collect::<Vec<String>>()
            .join(" + "),
    )
}

I don't know if this is the correct fix or not, but changing the format string to "{:+} {}" and the join string to " " generates a file that's acceptable to Glpk, Cplex, and Gurobi, even for other problems where the first coefficient has a leading +.

Thanks!

Add SCIP support

SCIP is one of the commonly-used MI(N)LP solvers and could be of interest to the rust-or communities (free and source available for academic use).

I'd be willing to help add it to lp-solvers if this is the appropriate repository

Compilation failing

I've tried using this crate today, and for the most part it has gone very well. Thank you very much for the effort!

I have a simple problem that I've built from one of the examples, which runs fine with cargo run and gives the correct answer for x=0, y=6, and z=0.5. So that tells me that linkers and libraries are set-up properly

use good_lp::{
    coin_cbc, variable, Expression, ProblemVariables, ResolutionError, Solution, SolverModel,
};

fn main() -> Result<(), ResolutionError> {
    let mut problem = ProblemVariables::new();

    let x = problem.add(variable().bounds(0..).name("x"));
    let y = problem.add(variable().bounds(0..).name("y"));
    let z = problem.add(variable().bounds(0..).name("z"));

    let objective = x + (2 * y) + z;

    let c1 = ((3 * x) + y).leq(6);
    let c2 = (y + (2 * z)).leq(7);

    let model = problem
        .maximise(objective)
        .using(coin_cbc)
        .with(c1)
        .with(c2);

    let result = model.solve()?;

    let r_x = result.value(x);
    let r_y = result.value(y);
    let r_z = result.value(z);

    println!("x={} y={} z={}", r_x, r_y, r_z);

    Ok(())
}

I then wanted to do a portability test, i.e. compile a binary on one machine and run it on another (assuming the CBC libraries are present, of course). However when trying to build this with cargo build --release I encountered the following error, which I'm unsure of what to do with:

error: linking with `cc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH=... VSLANG="1033" "cc" "-m64" "/tmp/rustcg8Thj6/symbols.o" "[PROJECT]/target/release/deps/tut_goodlp-92e8b26fa0c440e6.tut_goodlp.5c9cd6f5f2b2df3d-cgu.0.rcgu.o" "[PROJECT]/target/release/deps/tut_goodlp-92e8b26fa0c440e6.tut_goodlp.5c9cd6f5f2b2df3d-cgu.1.rcgu.o" "[PROJECT]/target/release/deps/tut_goodlp-92e8b26fa0c440e6.tut_goodlp.5c9cd6f5f2b2df3d-cgu.2.rcgu.o" "[PROJECT]/target/release/deps/tut_goodlp-92e8b26fa0c440e6.tut_goodlp.5c9cd6f5f2b2df3d-cgu.3.rcgu.o" "[PROJECT]/target/release/deps/tut_goodlp-92e8b26fa0c440e6.tut_goodlp.5c9cd6f5f2b2df3d-cgu.4.rcgu.o" "[PROJECT]/target/release/deps/tut_goodlp-92e8b26fa0c440e6.1tlwplqw1rp6pnvd.rcgu.o" "-Wl,--as-needed" "-L" "[PROJECT]/target/release/deps" "-L" "/usr/lib/x86_64-linux-gnu" "-L" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "[PROJECT]/target/release/deps/libgood_lp-05f2cd015599861a.rlib" "[PROJECT]/target/release/deps/libcoin_cbc-31d39607b8b834b9.rlib" "[PROJECT]/target/release/deps/liblazy_static-df89fd9b4b197d62.rlib" "[PROJECT]/target/release/deps/libcoin_cbc_sys-6b6210d15e0954f9.rlib" "[PROJECT]/target/release/deps/libfnv-4e5ea88ba9d01e53.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-66d8041607d2929b.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-a57e2388c0aea9b1.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-dcd9be90ae2cb505.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libmemchr-516789932d161b4e.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-1ff34b0cf871cb60.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-0c110dd0650d6cb7.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-a6e97aae2681ad8f.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-b93dac2525ec4d1e.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-ce1d65fb391ae98b.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-8933a2fb54d88492.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-306712ebb1ee1a3f.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-349c574f342b0d30.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-65c422a3ad95273d.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-7e6330a6c0cb9441.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-39c59240bfdfab27.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-e9d126c51bb8b2bb.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-5af394d9b1f07bdc.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-693a8f23970c5917.rlib" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-13fc9d1ed9c7a2bc.rlib" "-Wl,-Bdynamic" "-lCbcSolver" "-lCbc" "-lpthread" "-lrt" "-lCgl" "-lOsiClp" "-lClpSolver" "-lClp" "-lOsi" "-lCoinUtils" "-lbz2" "-lz" "-llapack" "-lblas" "-lm" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "[HOME]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "[PROJECT]/target/release/deps/tut_goodlp-92e8b26fa0c440e6" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-nodefaultlibs"
  = note: /usr/bin/ld: cannot find -lz: No such file or directory
          collect2: error: ld returned 1 exit status

I had actually originally intended to do my portability test with Highs (which also worked with cargo run, since AFAIK that should get packaged into the release, however I encountered the same error above. This is what leads me to believe that something is not configured right (I'm sure on my end) at the good_lp-level, rather than related to one particular solver. Nevertheless, I'm not sure how to proceed..

If you could please help me understand what this error means, and how (or if?) I can get a good_lp model compiled, then I would be very grateful

In case it's helpful, I'm running this in a WSL2-Unbuntu environment, and I had to manually install the CBC libraries, build-essential, and clang (which seemed necessary to use Highs, rather than CBC)

Add support for RELP

I am using good_lp (at the moment with minilp). I am interested in exact solutions for rational numbers, and therefore I would like to experiment with relp. This is a request to add relp, or guide me doing so.

If I understand correctly, a new "type" of good_lp::variable::VariableDefinition (other than the existing types "continuous" and "integer") would be required. Generally, I am not sure how to deal with the discrepancy of f64 vs. the number types in relp_num which relp uses.

Set coin_cbc verbosity

Hi,

I was wondering how I can set the verbosity level of coin_cbc through this crate. I found KardinalAI/coin_cbc#3 which looks to be what I want. I also saw that I can get an &Model from CoinCbcProblem::as_inner(). The problem is that Model::set_parameter() requires an &mut reference while I can only obtain an immutable one.

Is there a different solution which I missed? If not, maybe a second method could be added to CoinCbcProblem for getting a mutable reference? If this could prove hazardous for upkeeping internal invariants, making this method unsafe would seem like a good compromise to me.

Does good_lp work on Windows with CBC? [It does]

As the title states...

I didn't spot anything in the README or docs so I tried with the latest https://github.com/coin-or/Cbc/releases/tag/releases%2F2.10.8 msvc17 build and ensured the bin, lib and include are in the PATH but no love. I guessed it was because it is called libCBCSolver.lib and not CBCSolver.lib. So, I renamed it and still no love. So I moved it into my project root and at least it found it but then could resolve any of the exports. I also tried using the CBCSolver.lib from the OR-Tools distribution and the same thing.

`mul` with a float doesn't seem to to the right thing for binary variables

I'm trying to build a sum based on binary variables and coefficients, but the resulting expression doesn't seem to be correct.

let weights = vec![1.1, 1.2, 1.0, 0.9];
let mut vars = variables!();

let xs = vars.add_vector(variable().binary(), weights.len());

let objective = Expression::sum((0..weights.len()).iter().map(|i| xs[i].mul(weights[i])));

I would expect the xs variables to interpreted as ones or zeroes in the sum, i.e., the objective being the sum of the weights of the variables set to 1. However, it appears that the objective is capped at a value smaller than the sum of the weights.

Input linear program using matrix format

Hi,

I was trying to input a linear program using matrix format, i.e., with constraints in the form of Ax = b. I constructed a COO matrix A but cannot multiply it with the variable x.
I get the following error "cannot multiply numopt::matrix::coo::CooMat<f64> by good_lp::Variable".
Do you have any more complicated examples where the input is a matrix?
Below is my code.

fn main() -> Result<(), Box<dyn Error>> {
        let x = arr1(&[1.0]);
        let c = arr1(&[1.0]); 
        let b = arr1(&[10.0]);
        let u = arr1(&[15.0]);
        let l = arr1(&[-15.0]);
        let p = vec![false ];
        let A: CooMat<f64> = CooMat::<f64>::new(
            (1 , 1 ),
            vec![0],
            vec![0],
            vec![1.0]
        );
        variables! {
            vars:
                   a <= x;
        } // variables can also be added dynamically
        let solution = vars.maximise(  &a  )
            .using(default_solver) // multiple solvers available
            .with(constraint!( A * a == 5))
            .solve()?;
        println!("a={}   b={}", solution.value(a), solution.value(b));
        println!("a + b = {}", solution.eval(a + b));
        Ok(())
    }
}

Thank you for your help!

troubles adding a constraint with a count of bool variables

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!

HiGHS does depend on additional libs

Readme mentions that HiGHS solver does not depend on additional libs at runtime, which is not wholly true. The highs-sys crate mentions that the library depends on libstdc++ and libgomp at runtime. While most Linux distros include these libraries by default, mac needs to install libomp and lightweight container oriented Linux distros like alpine do not include the gcc tooling by default.

Creating a variable bounded by real numbers

Quick side note: this crate is awesome!

One problem I am running into is that I want to create an f64 variable that lies within the domain of all real numbers. How can I achieve this?

This is what I am currently trying to do, but it does not compile due to From<bool> is not implemented for f64.

use std::error::Error;

use good_lp::{constraint, coin_cbc, SolverModel, variables};

fn main() -> Result<(), Box<dyn Error>> {
    let INF: f32 = f32::INFINITY;
    let NEG_INF: f32 = f32::NEG_INFINITY; 

    variables! {
        vars:
            NEG_INF <= x1 <= INF;
            NEG_INF <= x2 <= INF;
    }
    let _solution = vars.minimise(2 * x1 + 3 * x2)
        .using(coin_cbc)
        .with(constraint!((3 * x1) + (4 * x2) >= 1))
        .solve()?;

    Ok(())
}

Edit: I can specify either a lower or upper bound but not both; I am wondering if this is suitable for this situation.

How can I set model/solver options, especially for HiGHS ?

I tried to set time limit option but I found there is no way to call highs::Model::set_option .

With good_lp API the only chance I can get an instance of highs::Model is to call good_lp::solvers::highs::HighsProblem::into_inner as solve does internally.

pub fn into_inner(self) -> highs::Model {

Then I can have several set_option calls and at the end solve method call. Even though I still cannot have HighsSolution instance as solution: highs::Solution field is private and HighsSolution does not have any explicit constructor like new method.

pub struct HighsSolution {

Can you give me any suggestion to simultaneously use good_lp API as well as set Highs options?

Thank you.

[Q/A] using HiGHs LP solver

There is no discussion section for this repo to post a general Q/A, but I was wondering: can this crate allows me to use just the HiGHs LP solver? I want to write my own basic Branch and Bound implementation. Will highs.rs provide that level of control?

Thanks!
Dave

cannot multiply `usize` by `good_lp::Variable` in constraint on integer variable

Im trying to add a constraint to integer variables:

  let mut problem = variables!();
  let ore = problem.add_vector(variable().integer().min(0), system.time_steps);
  let clay = problem.add_vector(variable().integer().min(0), system.time_steps);
  let obsidian =
    problem.add_vector(variable().integer().min(0), system.time_steps);
  let geode =
    problem.add_vector(variable().integer().min(0), system.time_steps);
...
  for i in 2..=system.time_steps {
  ...
    /* The amount of robots of each type on each minute is limited by the materials available to build them until that minute. the total amount of materials collected until that point minus the materials used to build other types of robots, divided by the cost. */
    model.add_constraint(constraint!(
      ore[i]
        >= (system.ore_robot.requirements.ore.unwrap_or(0) * (ore[I - 1] - 1))
          + (system.clay_robot.requirements.ore.unwrap_or(0) * clay[I - 1])
          + (system.obsidian_robot.requirements.ore.unwrap_or(0) * obsidian[I - 1])
          + (system.geode_robot.requirements.ore.unwrap_or(0) * geode[I - 1])
    ));

but I get errors like:

error[E0277]: cannot multiply `usize` by `good_lp::Variable`
  --> src/part1_solver.rs:98:63
   |
98 |           + (system.geode_robot.requirements.ore.unwrap_or(0) * geode[i])
   |                                                               ^ no implementation for `usize * good_lp::Variable`
   |
   = help: the trait `std::ops::Mul<good_lp::Variable>` is not implemented for `usize`
   = help: the following other types implement trait `std::ops::Mul<Rhs>`:
             <&'a usize as std::ops::Mul<usize>>
             <&usize as std::ops::Mul<&usize>>
             <usize as std::ops::Mul<&usize>>
             <usize as std::ops::Mul>

a hint in the error that we need to cast to f64 even for integer problems would be handy.

Typos in repo description

Current description of the repo:

Linear Programming for Rust, with an user-friendly API. This crate allows modeling LP problems, and let's you solve them with various solvers.

Fixed typos (an โ†’ a, let's โ†’ lets):

Linear Programming for Rust, with a user-friendly API. This crate allows modeling LP problems, and lets you solve them with various solvers.

Please update the description on GitHub :)

Add const to determine at compile-time what default_solver resolves to

Motivation: my application uses good_lp, and mirrors the structure you have here of using features to enable/disable various solver backends. I would like to be able to print out which solver is being used.

There's some reasonably complex logic in

good_lp/src/lib.rs

Lines 73 to 110 in f7483e2

#[cfg(feature = "coin_cbc")]
/// When the "coin_cbc" cargo feature is present, it is used as the default solver
pub use solvers::coin_cbc::coin_cbc as default_solver;
#[cfg(feature = "highs")]
#[cfg_attr(docsrs, doc(cfg(feature = "highs")))]
pub use solvers::highs::highs;
#[cfg(not(any(feature = "coin_cbc", feature = "minilp", feature = "lpsolve")))]
#[cfg(feature = "highs")]
/// When the "highs" cargo feature is present, highs is used as the default solver
pub use solvers::highs::highs as default_solver;
#[cfg(feature = "lp-solvers")]
#[cfg_attr(docsrs, doc(cfg(feature = "lp-solvers")))]
pub use solvers::lp_solvers::LpSolver;
#[cfg(feature = "lpsolve")]
#[cfg_attr(docsrs, doc(cfg(feature = "lpsolve")))]
pub use solvers::lpsolve::lp_solve;
#[cfg(not(any(feature = "coin_cbc", feature = "minilp")))]
#[cfg(feature = "lpsolve")]
/// When the "lpsolve" cargo feature is present, lpsolve is used as the default solver
pub use solvers::lpsolve::lp_solve as default_solver;
#[cfg(feature = "minilp")]
#[cfg_attr(docsrs, doc(cfg(feature = "minilp")))]
pub use solvers::minilp::minilp;
#[cfg(not(feature = "coin_cbc"))]
#[cfg(feature = "minilp")]
/// When the "coin_cbc" cargo feature is absent, minilp is used as the default solver
pub use solvers::minilp::minilp as default_solver;
#[cfg(feature = "scip")]
#[cfg_attr(docsrs, doc(cfg(feature = "highs")))]
pub use solvers::scip::scip;
#[cfg(not(any(
feature = "coin_cbc",
feature = "minilp",
feature = "lpsolve",
feature = "highs"
)))]
#[cfg(feature = "scip")]
pub use solvers::scip::scip as default_solver;
to determine which solver is the default which I'd rather not copy. I think the cleanest solution would be to add something like pub const SOLVER_NAME: &str = "cbc" in src/solvers/coin_cbc.rs etc. and reexport it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.