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::*;