1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//! This crate provides Rust bindings for Gurobi Optimizer.  It currently requires Gurobi 9.0 or higher.
//!
//! ## Installing
//!
//! * Before using this crate, you should install Gurobi and obtain a [license](http://www.gurobi.com/downloads/licenses/license-center).
//!
//! * Make sure that the environment variable `GUROBI_HOME` is set to the installation path of Gurobi
//!   (like `C:\gurobi911\win64` or `/opt/gurobi911/linux64`).  If you are using the Conda package
//!   from the Gurobi channel, the build script will fall back to `GUROBI_HOME=${CONDA_PREFIX}`, so you
//!   should not set `GUROBI_HOME`.
//!
//! ## Quick Start
//! The example below sets up and solves a Mixed Integer Program (MIP).  Additional examples covering the more specific aspects of this crate's API can
//! be found [here](https://github.com/ykrist/rust-grb/tree/master/examples).
//!
//! The documention for [`Model`] contains most of the details for defining, solving and querying models.
//! ```
//! use grb::prelude::*;
//!
//! let mut model = Model::new("model1")?;
//!
//! // add decision variables with no bounds
//! let x1 = add_ctsvar!(model, name: "x1", bounds: ..)?;
//! let x2 = add_intvar!(model, name: "x2", bounds: ..)?;
//!
//! // add linear constraints
//! let c0 = model.add_constr("c0", c!(x1 + 2*x2 >= -14))?;
//! let c1 = model.add_constr("c1", c!(-4 * x1 - x2 <= -33))?;
//! let c2 = model.add_constr("c2", c!(2* x1 <= 20 - x2))?;
//!
//! // model is lazily updated by default
//! assert_eq!(model.get_obj_attr(attr::VarName, &x1).unwrap_err(), grb::Error::ModelObjectPending);
//! assert_eq!(model.get_attr(attr::IsMIP)?, 0);
//!
//! // set the objective function, which updates the model objects (variables and constraints).
//! // One could also call `model.update()`
//! model.set_objective(8*x1 + x2, Minimize)?;
//! assert_eq!(model.get_obj_attr(attr::VarName, &x1)?, "x1");
//! assert_eq!(model.get_attr(attr::IsMIP)?, 1);
//!
//! // write model to the file.
//! model.write("model.lp")?;
//!
//! // optimize the model
//! model.optimize()?;
//! assert_eq!(model.status()?, Status::Optimal);
//!
//! // Querying a model attribute
//! assert_eq!(model.get_attr(attr::ObjVal)? , 59.0);
//!
//! // Querying a model object attributes
//! assert_eq!(model.get_obj_attr(attr::Slack, &c0)?, -34.5);
//! let x1_name = model.get_obj_attr(attr::VarName, &x1)?;
//!
//! // Querying an attribute for multiple model objects
//! let val = model.get_obj_attr_batch(attr::X, vec![x1, x2])?;
//! assert_eq!(val, [6.5, 7.0]);
//!
//! // Querying variables by name
//! assert_eq!(model.get_var_by_name(&x1_name)?, Some(x1));
//!
//! # Ok::<(), grb::Error>(())
//! ```
//!
//! ## Errors
//! Due to the nature of C APIs, almost every Gurobi routine can return an error.  Unless otherwise stated,
//! if a method or function returns a [`Result`], the error will be [`Error::FromAPI`].
#![warn(missing_docs)]
#![warn(missing_crate_level_docs)]

use grb_sys2 as ffi;

/// Returns the version number of Gurobi
pub fn version() -> (i32, i32, i32) {
    let (mut major, mut minor, mut technical) = (-1, -1, -1);
    unsafe { ffi::GRBversion(&mut major, &mut minor, &mut technical) };
    (major, minor, technical)
}

/// Convienence wrapper around [`Model::add_var`]; adds a new variable to a `Model` object.  The macro keyword arguments are
/// optional.
///
/// # Syntax
/// The syntax of macro is two positional arguments followed by any number of named arguments:
/// ```text
/// add_var!(MODEL, VAR_TYPE, NAMED_ARG1: VAL1, NAMED_ARG2: VAL2, ...)
/// ```
/// `MODEL` should be an instance of a `Model`.
///
/// `VAR_TYPE` should be the variable type - a variant of [`VarType`].
///
/// The named arguments are described below.
///
/// | Name     | Type                                                      | `Model::add_var` argument |
/// | -------- | -------------------------------------------------------   | --------------------------- |
/// | `name`   | Anything that implements `AsRef<str>` (&str, String, etc) | `name`                      |
/// | `obj`    | Anything that can be cast to a `f64`                      | `obj`                       |
/// | `bounds` | A range expression, see below                             | `ub` & `lb`                 |
///
/// The `bounds` argument takes a value of the form `LB..UB` where `LB` and `UB` are the upper and lower bounds of the variable.
///  `LB` and `UB` can be   left off as well, so `..UB` (short for `-INFINITY..UB`), `LB..` (short for `LB..INFINITY`) and `..`
/// are also valid values.
///
///
///
/// [`Model::add_var`]: struct.Model.html#method.add_var
/// [`VarType`]: enum.VarType.html
/// ```
/// use grb::prelude::*;
/// let mut model = Model::new("Model").unwrap();
/// add_var!(model, Continuous, name: "name", obj: 0.0, bounds: -10..10)?;
/// add_var!(model, Integer, bounds: 0..)?;
/// add_var!(model, Continuous, name: &format!("X[{}]", 42))?;
/// # Ok::<(), grb::Error>(())
/// ```
///
#[doc(inline)]
pub use grb_macro::add_var;

/// Equivalent to calling [`add_var!`]`(model, Continuous, ...)`
#[doc(inline)]
pub use grb_macro::add_ctsvar;

/// Equivalent to calling [`add_var!`]`(model, Binary, ...)`
#[doc(inline)]
pub use grb_macro::add_binvar;

/// Equivalent to calling [`add_var!`]`(model, Integer, ...)`
#[doc(inline)]
pub use grb_macro::add_intvar;

/// A proc-macro for creating constraint objects.
///
/// # Syntax
/// ## Inequality constraints
/// To create an `IneqExpr` object for a linear or quadratic constraint, the syntax is
/// ```text
/// c!( LHS CMP RHS )
/// ```
/// `LHS` and `RHS` should be valid algebraic expressions involving `Var` objects and numeric constants.
/// For example, if `x`, `y` and `z` are `Var` objects and `vars` is an `Vec<Var>` objects, these are valid:
/// ```
/// # use grb::prelude::*;
/// # fn f(x: Var, y: Var, z: Var, vars: Vec<Var>){
///   c!(vars.iter().grb_sum() == x );
///   c!( x + 1/2 == 1.4*y - 2*z );
///   c!( 2*x >= z*y );
///   c!( 2*x >= 7*(z*y) ); // note the brackets on the non-linear term when a coefficient is present
/// # }
/// ```
/// but the following are not:
/// ```compile_fail
/// # use grb::*;
/// # fn f(x: Var, y: Var, z: Var){
///   c!(vars.iter().sum() == x ); // cannot infer type on sum() call
///   c!( 2*x >= z >= y ); // chained comparison
///   c!( 2*x >= 7*z*y ); // no brackets around var*var when a coefficient is present
/// # }
/// ```
/// The macro expands `c!( LHS == RHS )` to:
/// ```
/// # let LHS = 0;
/// # let RHS = 0;
/// grb::constr::IneqExpr {
///   lhs: grb::Expr::from(LHS),
///   sense: grb::ConstrSense::Equal,
///   rhs: grb::Expr::from(RHS),
/// };
/// ```
///
/// ## Range constraints
/// To create a `RangeExpr` object for a range constraint, use the syntax
/// ```text
/// c!( EXPR in LB..UB )
/// c!( EXPR in LB.. )
/// c!( EXPR in ..UB )
/// c!( EXPR in .. )
/// ```
/// where `EXPR` is a valid expression, like `LHS` and `RHS` above.  Additionally, `EXPR` must be linear,
/// although this is not checked at compile-time.
///
/// `LB` and `UB` can be any expression that evaluates to type that can be cast to a `f64` using
/// the `as` operator. For example, the following are valid (variables have the meaning as above):
/// ```
/// # use grb::prelude::*;
/// # fn f(x: Var, y: Var, z: Var, vars: Vec<Var>){
///   c!( x - y + 2*z in 0..200 );
///   c!( x - y + 2*z in 1.. );
///   c!( x - y in (1.0/3.0)..(1<<4));
/// # }
/// ```
///
#[doc(inline)]
pub use grb_macro::c;


// public modules
pub mod attribute;
pub mod callback;
pub mod constr;
pub mod expr;
pub mod parameter;
pub mod prelude;

// Public re-exports
#[doc(no_inline)]
pub use attribute::attr;
pub use expr::Expr;
#[doc(no_inline)]
pub use parameter::param;

// private modules and their re-exports
mod constants;
pub use constants::{
    ConstrSense, ModelSense, RelaxType, SOSType, Status, VarType, GRB_INFINITY as INFINITY,
};

mod env;
pub use env::{EmptyEnv, Env};

mod error;
pub use error::{Error, Result};

mod model;
pub use model::{AsyncHandle, AsyncModel, Model};

mod model_object;
pub use model_object::{Constr, ModelObject, QConstr, Var, SOS};

mod util;