-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from niklasdewally/minion-bindings
Represent and run a minion model in Rust
- Loading branch information
Showing
17 changed files
with
533 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
debug/ | ||
target/ | ||
vendor/build | ||
*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,5 @@ | ||
This directory contains in progress bindings for the [Minion solver](https://github.com/minion/minion). | ||
|
||
Currently, this builds `minion`, but provides no functionality. | ||
|
||
# Installation / Usage | ||
|
||
TODO | ||
Note that minion is single threaded only so tests must be ran with | ||
cargo test -- --test-threads=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
//! The Model Syntax tree for the Minion bindings. | ||
|
||
use std::collections::HashMap; | ||
|
||
pub type VarName = String; | ||
|
||
pub struct Model { | ||
/// A lookup table of all named variables. | ||
pub named_variables: SymbolTable, | ||
pub constraints: Vec<Constraint>, | ||
} | ||
|
||
impl Model { | ||
pub fn new() -> Model { | ||
Model { | ||
named_variables: SymbolTable::new(), | ||
constraints: Vec::new(), | ||
} | ||
} | ||
} | ||
|
||
pub enum Constraint { | ||
SumLeq(Vec<Var>, Var), | ||
SumGeq(Vec<Var>, Var), | ||
Ineq(Var, Var, Constant), | ||
} | ||
|
||
/// A variable can either be a named variable, or an anomynous "constant as a variable". | ||
/// | ||
/// The latter is not stored in the symbol table, or counted in Minions internal list of all | ||
/// variables, but is used to allow the use of a constant in the place of a variable in a | ||
/// constraint. | ||
pub enum Var { | ||
NameRef(VarName), | ||
ConstantAsVar(i32), | ||
} | ||
|
||
pub enum Constant { | ||
Bool(bool), | ||
Integer(i32), | ||
} | ||
|
||
#[derive(Copy, Clone)] | ||
pub enum VarDomain { | ||
Bound(i32, i32), | ||
Discrete(i32, i32), | ||
SparseBound(i32, i32), | ||
Bool(bool), | ||
} | ||
|
||
pub struct SymbolTable { | ||
table: HashMap<VarName, VarDomain>, | ||
|
||
// for now doubles both as Minion's SearchOrder and print order | ||
var_order: Vec<VarName>, | ||
} | ||
|
||
impl SymbolTable { | ||
fn new() -> SymbolTable { | ||
SymbolTable { | ||
table: HashMap::new(), | ||
var_order: Vec::new(), | ||
} | ||
} | ||
|
||
/// Creates a new variable and adds it to the symbol table. | ||
/// If a variable already exists with the given name, an error is thrown. | ||
pub fn add_var(&mut self, name: VarName, vartype: VarDomain) -> Option<()> { | ||
if self.table.contains_key(&name) { | ||
return None; | ||
} | ||
|
||
self.table.insert(name.clone(), vartype); | ||
self.var_order.push(name); | ||
|
||
return Some(()); | ||
} | ||
|
||
pub fn get_vartype(&self, name: VarName) -> Option<VarDomain> { | ||
match self.table.get(&name) { | ||
Some(m) => Some(*m), | ||
None => None, | ||
} | ||
} | ||
|
||
pub fn get_variable_order(&self) -> Vec<VarName> { | ||
self.var_order.clone() | ||
} | ||
|
||
pub fn contains(&self, name: VarName) -> bool { | ||
self.table.contains_key(&name) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
pub mod bindings { | ||
include!(concat!(env!("OUT_DIR"), "/bindings.rs")); | ||
} | ||
mod raw_bindings; | ||
|
||
mod run; | ||
pub use run::*; | ||
|
||
pub mod ast; | ||
|
||
mod scoped_ptr; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#![allow(warnings)] | ||
include!(concat!(env!("OUT_DIR"), "/bindings.rs")); | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
|
||
use super::*; | ||
use std::ffi::CString; | ||
|
||
// solutions | ||
static mut X_VAL: i32 = 0; | ||
static mut Y_VAL: i32 = 0; | ||
static mut Z_VAL: i32 = 0; | ||
|
||
#[no_mangle] | ||
pub extern "C" fn hello_from_rust() -> bool { | ||
unsafe { | ||
X_VAL = printMatrix_getValue(0) as _; | ||
Y_VAL = printMatrix_getValue(1) as _; | ||
Z_VAL = printMatrix_getValue(2) as _; | ||
return true; | ||
} | ||
} | ||
|
||
#[test] | ||
fn xyz_raw() { | ||
// A simple constraints model, manually written using FFI functions. | ||
// Testing to see if it does not segfault. | ||
// Results can be manually inspected in the outputted minion logs. | ||
unsafe { | ||
// See https://rust-lang.github.io/rust-bindgen/cpp.html | ||
let options = newSearchOptions(); | ||
let args = newSearchMethod(); | ||
let instance = newInstance(); | ||
|
||
let x_str = CString::new("x").expect("bad x"); | ||
let y_str = CString::new("y").expect("bad y"); | ||
let z_str = CString::new("z").expect("bad z"); | ||
|
||
newVar_ffi(instance, x_str.as_ptr() as _, VariableType_VAR_BOUND, 1, 3); | ||
newVar_ffi(instance, y_str.as_ptr() as _, VariableType_VAR_BOUND, 2, 4); | ||
newVar_ffi(instance, z_str.as_ptr() as _, VariableType_VAR_BOUND, 1, 5); | ||
|
||
let x = getVarByName(instance, x_str.as_ptr() as _); | ||
let y = getVarByName(instance, y_str.as_ptr() as _); | ||
let z = getVarByName(instance, z_str.as_ptr() as _); | ||
|
||
printMatrix_addVar(instance, x); | ||
printMatrix_addVar(instance, y); | ||
printMatrix_addVar(instance, z); | ||
|
||
// VARORDER | ||
let search_vars = vec_var_new(); | ||
vec_var_push_back(search_vars as _, x); | ||
vec_var_push_back(search_vars as _, y); | ||
vec_var_push_back(search_vars as _, z); | ||
let search_order = newSearchOrder(search_vars as _, VarOrderEnum_ORDER_STATIC, false); | ||
instance_addSearchOrder(instance, search_order); | ||
|
||
// CONSTRAINTS | ||
let leq = newConstraintBlob(ConstraintType_CT_LEQSUM); | ||
let geq = newConstraintBlob(ConstraintType_CT_GEQSUM); | ||
let ineq = newConstraintBlob(ConstraintType_CT_INEQ); | ||
|
||
let rhs_vars = vec_var_new(); | ||
vec_var_push_back(rhs_vars, constantAsVar(4)); | ||
|
||
// leq / geq : [var] [var] | ||
constraint_addVarList(leq, search_vars as _); | ||
constraint_addVarList(leq, rhs_vars as _); | ||
|
||
constraint_addVarList(geq, search_vars as _); | ||
constraint_addVarList(geq, rhs_vars as _); | ||
|
||
// ineq: [var] [var] [const] | ||
let x_vec = vec_var_new(); | ||
vec_var_push_back(x_vec, x); | ||
|
||
let y_vec = vec_var_new(); | ||
vec_var_push_back(y_vec, y); | ||
|
||
let const_vec = vec_int_new(); | ||
vec_int_push_back(const_vec, -1); | ||
|
||
constraint_addVarList(ineq, x_vec as _); | ||
constraint_addVarList(ineq, y_vec as _); | ||
constraint_addConstantList(ineq, const_vec as _); | ||
|
||
instance_addConstraint(instance, leq); | ||
instance_addConstraint(instance, geq); | ||
instance_addConstraint(instance, ineq); | ||
|
||
let res = runMinion(options, args, instance, Some(hello_from_rust)); | ||
|
||
// does it get this far? | ||
assert_eq!(res, 0); | ||
|
||
// test if solutions are correct | ||
assert_eq!(X_VAL, 1); | ||
assert_eq!(Y_VAL, 2); | ||
assert_eq!(Z_VAL, 1); | ||
} | ||
} | ||
} |
Oops, something went wrong.