minion_rs/lib.rs
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
//! This crate provides low level Rust bindings to the [Minion](https://github.com/minion/minion)
//! constraint solver.
//!
//! # Examples
//!
//! Consider the following Minion problem:
//!
//! ```plaintext
//! MINION 3
//! **VARIABLES**
//! DISCRETE x #
//! {1..3}
//! DISCRETE y #
//! {2..4}
//! DISCRETE z #
//! {1..5}
//! **SEARCH**
//! PRINT[[x],[y],[z]]
//! VARORDER STATIC [x, y, z]
//! **CONSTRAINTS**
//! sumleq([x,y,z],4)
//! ineq(x, y, -1)
//! **EOF**
//! ```
//!
//! This can be solved in Rust like so:
//!
//! ```
//! use minion_rs::ast::*;
//! use minion_rs::run_minion;
//! use std::collections::HashMap;
//! use std::sync::Mutex;
//!
//! // Get solutions out of Minion.
//! // See the documentation for Callback for details.
//!
//! static ALL_SOLUTIONS: Mutex<Vec<HashMap<VarName,Constant>>> = Mutex::new(vec![]);
//!
//! fn callback(solutions: HashMap<VarName,Constant>) -> bool {
//! let mut guard = ALL_SOLUTIONS.lock().unwrap();
//! guard.push(solutions);
//! true
//! }
//!
//! // Build and run the model.
//! let mut model = Model::new();
//! model
//! .named_variables
//! .add_var("x".to_owned(), VarDomain::Bound(1, 3));
//! model
//! .named_variables
//! .add_var("y".to_owned(), VarDomain::Bound(2, 4));
//! model
//! .named_variables
//! .add_var("z".to_owned(), VarDomain::Bound(1, 5));
//!
//! let leq = Constraint::SumLeq(
//! vec![
//! Var::NameRef("x".to_owned()),
//! Var::NameRef("y".to_owned()),
//! Var::NameRef("z".to_owned()),
//! ],
//! Var::ConstantAsVar(4),
//! );
//!
//! let geq = Constraint::SumGeq(
//! vec![
//! Var::NameRef("x".to_owned()),
//! Var::NameRef("y".to_owned()),
//! Var::NameRef("z".to_owned()),
//! ],
//! Var::ConstantAsVar(4),
//! );
//!
//! let ineq = Constraint::Ineq(
//! Var::NameRef("x".to_owned()),
//! Var::NameRef("y".to_owned()),
//! Constant::Integer(-1),
//! );
//!
//! model.constraints.push(leq);
//! model.constraints.push(geq);
//! model.constraints.push(ineq);
//!
//! let res = run_minion(model, callback);
//! res.expect("Error occurred");
//!
//! // Get solutions
//! let guard = ALL_SOLUTIONS.lock().unwrap();
//! let solution_set_1 = &(guard.get(0).unwrap());
//!
//! let x1 = solution_set_1.get("x").unwrap();
//! let y1 = solution_set_1.get("y").unwrap();
//! let z1 = solution_set_1.get("z").unwrap();
//!
//! assert_eq!(guard.len(),1);
//! assert_eq!(*x1,Constant::Integer(1));
//! assert_eq!(*y1,Constant::Integer(2));
//! assert_eq!(*z1,Constant::Integer(1));
//! ```
//!
//! ## `PRINT` and `VARORDER`
//!
//! These bindings have no replacement for Minion's `PRINT` and `VARORDER` statements - any
//! variable given to the model that does not have a constant value is considered a search
//! variable. Solutions are returned through the [callback function](Callback) as a `HashMap`.
pub use run::*;
pub mod error;
mod ffi;
pub mod ast;
mod run;
mod scoped_ptr;
mod wrappers;
pub use wrappers::*;