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
#![deny(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
//!  A Linear Programming modeler that is easy to use, performant with large problems, and well-typed.
//!
//!  ```rust
//!  use good_lp::{variables, variable, default_solver, SolverModel, Solution};
//!
//!  let mut vars = variables!();
//!  let a = vars.add(variable().max(1));
//!  let b = vars.add(variable().min(2).max(4));
//!  let solution = vars.maximise(10 * (a - b / 5) - b)
//!      .using(default_solver)
//!      .with(a + 2. << b) // or (a + 2).leq(b)
//!      .with(1 + a >> 4. - b)
//!      .solve()?;
//!
//!  assert_eq!(solution.value(a), 1.);
//!  assert_eq!(solution.value(b), 3.);
//!  Ok::<_, good_lp::ResolutionError>(())
//!  ```
//!
//! ## Solvers
//!
//! This crate supports multiple solvers,
//! that can be activated using [feature flags](https://docs.rs/crate/good_lp/latest/features).
//!
//! ## Usage
//!
//! You initially create your variables using [variables] and [ProblemVariables::add].
//!
//! Then you create your objective function.If it's large, you can write rust functions
//! to split complex expressions into components.
//!
//! ```
//! use good_lp::{Expression, Variable};
//!
//! fn total_cost<V>(energy: Variable<V>, time: Variable<V>) -> Expression<V> {
//! #   let dollars_per_hour = 0;
//!     energy_cost(energy) + dollars_per_hour * time
//! }
//!
//! fn energy_cost<V>(energy: Variable<V>) -> Expression<V> {
//! #   let fetch_energy_price = |_| 0.;
//!     let price = fetch_energy_price(energy);
//!     energy * price
//! }
//! ```
//!
//! Then you create a [solver](solvers) problem model instance
//! ```
//! # let my_variables = good_lp::variables!();
//! # let my_objective = good_lp::Expression::from(0);
//! # let my_solver = |_|();
//! let mut model = my_variables.minimise(my_objective).using(my_solver);
//! ```
//!
//! Then you add constraints and solve your problem using the methods in [SolverModel].
//!

pub use constraint::Constraint;
pub use expression::Expression;
pub use solvers::{ResolutionError, Solution, SolverModel};
pub use variable::{variable, ProblemVariables, Variable, VariableDefinition};

#[cfg_attr(docsrs, doc(cfg(feature = "minilp")))]
#[cfg(feature = "coin_cbc")]
pub use solvers::coin_cbc::coin_cbc;

#[cfg(feature = "minilp")]
#[cfg_attr(docsrs, doc(cfg(feature = "minilp")))]
pub use solvers::minilp::minilp;

#[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(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(not(any(feature = "coin_cbc", feature = "minilp")))]
compile_error!(
    "No solver available. \
You need to activate at least one solver feature flag in good_lp. \
You can do by adding the following to your Cargo.toml :
[dependencies]
good_lp = { version = \"*\", features = [\"minilp\"] }
"
);

mod expression;
#[macro_use]
pub mod variable;
pub mod constraint;
pub mod solvers;
mod variables_macro;