diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 87d08c3..d79d1cc 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -29,7 +29,7 @@ jobs: with: toolchain: stable override: true - + - name: Run cargo-tarpaulin uses: actions-rs/tarpaulin@v0.1 with: @@ -129,46 +129,4 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 - name: Check Clippy Linter - run: cargo clippy --all-features --all-targets -- -D warnings - -# TODO: move to scip-sys repo -# MacOS-test: -# runs-on: macos-latest -# steps: -# - uses: actions/checkout@v2 -# -# - name: Cache dependencies (SCIPOptSuite) -# id: cache-scip -# uses: actions/cache@v2 -# with: -# path: | -# ${{ runner.workspace }}/scipoptsuite -# ~/Library/Caches/Homebrew/tbb--* -# /usr/local/opt/tbb* -# ~/Library/Caches/Homebrew/downloads/*--tbb-* -# ~/Library/Caches/Homebrew/boost--* -# /usr/local/opt/boost* -# ~/Library/Caches/Homebrew/downloads/*--boost-* -# key: ${{ runner.os }}-scipopt-${{ env.version }}-${{ hashFiles('**/lockfiles') }} -# restore-keys: | -# ${{ runner.os }}-scipopt-${{ env.version }}- -# -# - name: Install dependencies (SCIPOptSuite) -# if: steps.cache-scip.outputs.cache-hit != 'true' -# run: | -# brew install tbb boost bison -# wget --quiet --no-check-certificate https://scipopt.org/download/release/scipoptsuite-${{ env.version }}.tgz -# tar xfz scipoptsuite-${{ env.version }}.tgz -# cd scipoptsuite-${{ env.version }} -# mkdir build -# cd build -# cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/scipoptsuite -DIPOPT=off -DSYM=none -DTPI=tny -DREADLINE=off -# make install -j -# -# - name: Build and test -# run: | -# brew install tbb boost bison -# export SCIPOPTDIR=${{ runner.workspace }}/scipoptsuite/ -# export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:${{ runner.workspace }}/scipoptsuite/lib -# cargo build -# cargo test + run: cargo clippy --all-features --all-targets -- -D warnings \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 0704413..b8a8cf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,10 @@ exclude = ["data/test/*"] [features] raw = [] +bundled = ["scip-sys/bundled"] [dependencies] -scip-sys = "0.1.5" -doc-comment = "0.3.3" +scip-sys = "0.1.8" [dev-dependencies] rayon = "1.5.1" diff --git a/README.md b/README.md index e89d3c4..8b0faac 100644 --- a/README.md +++ b/README.md @@ -14,66 +14,42 @@ [img_coverage]: https://img.shields.io/codecov/c/github/scipopt/russcip A safe Rust interface for [SCIP](https://www.scipopt.org/index.php#download). This crate also exposes access to the SCIP's C-API through the `ffi` module. -The project is currently actively developed, issues/pull-requests are very welcome. -## Dependencies -Make sure SCIP is installed, the easiest way to install it is to install a precompiled package from [here](https://scipopt.org/index.php#download) or through conda by running -```bash -conda install --channel conda-forge scip -``` -After which `russcip` would be able to find the installation in the current Conda environment. Alternatively, you can specify the installation directory through the `SCIPOPTDIR` environment variable. - -*russcip* is tested against SCIP 8.0.3 but it might work for other versions depending on which functionality you use. +The project is currently actively developed, issues/pull-requests are very welcome. ## Installation By running ```bash -cargo add russcip +cargo add russcip --features bundled ``` or to get the most recent version, add the following to your `Cargo.toml` ```toml [dependencies] -russcip = { git = "https://github.com/scipopt/russcip" } +russcip = { git = "https://github.com/scipopt/russcip", features = ["bundled"] } ``` -## Example -Model and solve an integer program. -```rust -use russcip::prelude::*; - -fn main() { - // Create model - let mut model = Model::new() - .hide_output() - .include_default_plugins() - .create_prob("test") - .set_obj_sense(ObjSense::Maximize); - - // Add variables - let x1 = model.add_var(0., f64::INFINITY, 3., "x1", VarType::Integer); - let x2 = model.add_var(0., f64::INFINITY, 4., "x2", VarType::Integer); - - // Add constraints - model.add_cons(vec![x1.clone(), x2.clone()], &[2., 1.], -f64::INFINITY, 100., "c1"); - model.add_cons(vec![x1.clone(), x2.clone()], &[1., 2.], -f64::INFINITY, 80., "c2"); +The `bundled` feature will download a precompiled SCIP as part of the build process. +This is the easiest to get started with russcip, if you want to use a custom SCIP installation check the [section](#custom-scip-installation) below. - let solved_model = model.solve(); - let status = solved_model.status(); - println!("Solved with status {:?}", status); - - let obj_val = solved_model.obj_val(); - println!("Objective value: {}", obj_val); +## Custom SCIP installation +If the `bundled` feature is not enabled, `russcip` will look for a scip installation in the current conda environment, +to install SCIP using conda run the following command +```bash +conda install --channel conda-forge scip +``` +Alternatively, you can specify the installation directory through the `SCIPOPTDIR` environment variable. - let sol = solved_model.best_sol().unwrap(); - let vars = solved_model.vars(); +*russcip* is tested against SCIP 9.0.0 but it might work for other versions depending on which functionality you use. - for var in vars { - println!("{} = {}", &var.name(), sol.val(var)); - } -} +### Examples +An [example](examples/create_and_solve.rs) on how to model and solve an integer program can be found in the [examples](examples) directory. +To run the example, you can use the following command +```bash +cargo run --example create_and_solve ``` + ## The `raw` feature You can enable this feature by specifying the feature in your `Cargo.toml` ```toml diff --git a/examples/create_and_solve.rs b/examples/create_and_solve.rs new file mode 100644 index 0000000..cbe1b98 --- /dev/null +++ b/examples/create_and_solve.rs @@ -0,0 +1,45 @@ +use russcip::prelude::*; + +fn main() { + // Create model + let mut model = Model::new() + .hide_output() + .include_default_plugins() + .create_prob("test") + .set_obj_sense(ObjSense::Maximize); + + // Add variables + let x1 = model.add_var(0., f64::INFINITY, 3., "x1", VarType::Integer); + let x2 = model.add_var(0., f64::INFINITY, 4., "x2", VarType::Integer); + + // Add constraints + model.add_cons( + vec![x1.clone(), x2.clone()], + &[2., 1.], + -f64::INFINITY, + 100., + "c1", + ); + model.add_cons( + vec![x1.clone(), x2.clone()], + &[1., 2.], + -f64::INFINITY, + 80., + "c2", + ); + + let solved_model = model.solve(); + + let status = solved_model.status(); + println!("Solved with status {:?}", status); + + let obj_val = solved_model.obj_val(); + println!("Objective value: {}", obj_val); + + let sol = solved_model.best_sol().unwrap(); + let vars = solved_model.vars(); + + for var in vars { + println!("{} = {}", &var.name(), sol.val(var)); + } +} diff --git a/src/lib.rs b/src/lib.rs index 5ce45c4..95a3c5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,47 +1,10 @@ //! # russcip -//! Safe Rust interface for SCIP. +//! Safe Rust interface for [SCIP](https://scipopt.org/) optimization suite. //! -//! # Example -//! Model and solve an integer program. -//! ```rust -//! use russcip::prelude::*; -//! -//! // Create model -//! let mut model = Model::new() -//! .hide_output() -//! .include_default_plugins() -//! .create_prob("test") -//! .set_obj_sense(ObjSense::Maximize); -//! -//! // Add variables -//! let x1 = model.add_var(0., f64::INFINITY, 3., "x1", VarType::Integer); -//! let x2 = model.add_var(0., f64::INFINITY, 4., "x2", VarType::Integer); -//! -//! // Add constraints -//! model.add_cons(vec![x1.clone(), x2.clone()], &[2., 1.], -f64::INFINITY, 100., "c1"); -//! model.add_cons(vec![x1.clone(), x2.clone()], &[1., 2.], -f64::INFINITY, 80., "c2"); -//! -//! let solved_model = model.solve(); -//! -//! let status = solved_model.status(); -//! println!("Solved with status {:?}", status); -//! -//! let obj_val = solved_model.obj_val(); -//! println!("Objective value: {}", obj_val); -//! -//! let sol = solved_model.best_sol().expect("No solution found"); -//! let vars = solved_model.vars(); -//! -//! for var in vars { -//! println!("{} = {}", &var.name(), sol.val(var)); -//! } +//! For examples and usage, please refer to the [repository](https://github.com/scipopt/russcip). #![deny(missing_docs)] -extern crate core; -extern crate doc_comment; -doc_comment::doctest!("../README.md"); - /// Re-exports the `scip_sys` crate, which provides low-level bindings to the SCIP library. pub use scip_sys as ffi;