diff --git a/solvers/chuffed/build.rs b/solvers/chuffed/build.rs index 38f82ea62d..280dbd7d90 100644 --- a/solvers/chuffed/build.rs +++ b/solvers/chuffed/build.rs @@ -16,6 +16,8 @@ fn main() { println!("cargo:rustc-link-search=all=./solvers/chuffed/vendor/build/"); println!("cargo:rustc-link-lib=static=chuffed"); println!("cargo:rustc-link-lib=static=chuffed_fzn"); + println!("cargo:rustc-link-search=all=./solvers/chuffed/"); + println!("cargo:rustc-link-lib=static=wrapper"); // also need to (dynamically) link to c++ stdlib // https://flames-of-code.netlify.app/blog/rust-and-cmake-cplusplus/ @@ -64,6 +66,17 @@ fn bind() { // in C++ stdlib that will make it crash. .allowlist_function("createVars") .allowlist_function("createVar") + .allowlist_function("all_different") + .allowlist_function("branch") + .allowlist_function("output_vars") + .allowlist_function("var_sym_break") + .allowlist_function("new_dummy_problem") + .allowlist_function("get_idx") + .allowlist_function("make_vec_intvar") + .allowlist_function("destroy_vec_intvar") + .allowlist_function("p_addVars") + .allowlist_function("p_setcallback") + .allowlist_function("branch_IntVar") .clang_arg("-Ivendor/build") // generated from configure.py .clang_arg("-Ivendor") .clang_arg(r"--std=gnu++11") diff --git a/solvers/chuffed/build.sh b/solvers/chuffed/build.sh index 373916388e..6615852803 100644 --- a/solvers/chuffed/build.sh +++ b/solvers/chuffed/build.sh @@ -4,9 +4,14 @@ SCRIPT_DIR=$(dirname "$0") git submodule init git submodule update -cd "$SCRIPT_DIR" +cd "$SCRIPT_DIR" || exit echo "------ BUILDING ------" cd vendor || exit cmake -B build -S . cmake --build build +cd .. + +# Build wrapper.cpp as static library +c++ -c wrapper.cpp -Ivendor --std=c++11 +ar rvs libwrapper.a wrapper.o diff --git a/solvers/chuffed/clean.sh b/solvers/chuffed/clean.sh index e3a7382500..2873cb0737 100755 --- a/solvers/chuffed/clean.sh +++ b/solvers/chuffed/clean.sh @@ -2,3 +2,5 @@ cargo clean rm -rf vendor/build +rm libwrapper.a +rm wrapper.o diff --git a/solvers/chuffed/compile_flags.txt b/solvers/chuffed/compile_flags.txt new file mode 100644 index 0000000000..fd91cc6aea --- /dev/null +++ b/solvers/chuffed/compile_flags.txt @@ -0,0 +1,3 @@ +-I./vendor +-xc++ +--std=c++11 diff --git a/solvers/chuffed/src/lib.rs b/solvers/chuffed/src/lib.rs index 6a7b2eab1e..f935887260 100644 --- a/solvers/chuffed/src/lib.rs +++ b/solvers/chuffed/src/lib.rs @@ -4,3 +4,50 @@ pub mod bindings { #![allow(non_snake_case)] include!(concat!(env!("OUT_DIR"), "/chuffed_bindings.rs")); } + +pub mod wrappers { + use crate::bindings::{ + all_different, branch_IntVar, createVar, createVars, make_vec_intvar, vec, ConLevel, + IntVar, ValBranch, VarBranch, + }; + use core::ptr; + + // The signature of createVar is below for reference. + // createVar(x: *mut *mut IntVar, min: ::std::os::raw::c_int, max: ::std::os::raw::c_int, el: bool) + pub fn create_var(min: i32, max: i32, el: bool) -> *mut IntVar { + let mut ptr: *mut IntVar = ptr::null_mut(); + + unsafe { + createVar(&mut ptr, min, max, el); + ptr + } + } + + // createVars void createVars(vec& x, int n, int min, int max, bool el) + pub fn create_vars(n: i32, min: i32, max: i32, el: bool) -> *mut vec<*mut IntVar> { + let ptr: *mut vec<*mut IntVar> = unsafe { make_vec_intvar() }; + + unsafe { + createVars(ptr, n, min, max, el); + ptr + } + } + + // void all_different(vec& x, ConLevel cl) + pub unsafe fn all_different_wrapper(x: *mut vec<*mut IntVar>, cl: ConLevel) { + unsafe { + all_different(x, cl); + } + } + + // void branch(vec x, VarBranch var_branch, ValBranch val_branch); + pub unsafe fn branch_wrapper( + x: *mut vec<*mut IntVar>, + var_branch: VarBranch, + val_branch: ValBranch, + ) { + unsafe { + branch_IntVar(x, var_branch, val_branch); + } + } +} diff --git a/solvers/chuffed/src/main.rs b/solvers/chuffed/src/main.rs index 9504a44a4d..c97ff07353 100644 --- a/solvers/chuffed/src/main.rs +++ b/solvers/chuffed/src/main.rs @@ -1,8 +1,47 @@ -use chuffed_rs::bindings::createVar; -use chuffed_rs::bindings::IntVar; -pub fn main() { - let mut var = std::mem::MaybeUninit::::uninit(); +use chuffed_rs::bindings::{ + get_idx, new_dummy_problem, p_addVars, p_setcallback, vec, ConLevel_CL_DEF, IntVar, + VarBranch_VAR_INORDER, VarBranch_VAR_MIN_MIN, +}; +use chuffed_rs::wrappers::{all_different_wrapper, branch_wrapper, create_vars}; + +unsafe fn post_constraints(_n: i32) -> *mut vec<*mut IntVar> { + // Create constant + let n: i32 = _n; + // Create some variables + let x: *mut vec<*mut IntVar> = create_vars(n, 0, n, false); + + // Post some constraints + all_different_wrapper(x, ConLevel_CL_DEF); + + // Post some branchings + branch_wrapper(x as _, VarBranch_VAR_INORDER, VarBranch_VAR_MIN_MIN); + + x +} + +// Custom printing function for this problem +#[no_mangle] +pub unsafe extern "C" fn callback(x: *mut vec<*mut IntVar>) { + print!("First output is: {:?}", get_idx(x, 0)); +} + +fn main() { + let args: Vec = std::env::args().collect(); + + if args.len() != 2 { + println!("Invalid number of arguments"); + return; + } + + let n: i32 = args[1].parse().expect("Invalid input"); + unsafe { - createVar(&mut var.as_mut_ptr(), 0, 5, false); + let x = post_constraints(n); + // make new dummy problem + let p = new_dummy_problem(); + // Call problem.addvars() + p_addVars(p, x); + // Call problem.setcallback() + p_setcallback(p, Some(callback)); } } diff --git a/solvers/chuffed/wrapper.cpp b/solvers/chuffed/wrapper.cpp new file mode 100644 index 0000000000..94d90aed20 --- /dev/null +++ b/solvers/chuffed/wrapper.cpp @@ -0,0 +1,23 @@ +#include "./wrapper.h" + +DummyProblem *new_dummy_problem() { return new DummyProblem(); } +void p_addVars(DummyProblem *p, vec *_searchVars) { + p->addVars(_searchVars); +} +void p_setcallback(DummyProblem *p, void (*_callback)(vec *)) { + p->setcallback(_callback); +} +IntVar* get_idx(vec *x, int i) { return *x[i]; } + +vec* make_vec_intvar() { + return new vec(); +} + +void destroy_vec_intvar(vec* v) { + delete v; +} + +void branch_IntVar(vec *x, VarBranch var_branch, + ValBranch val_branch) { + branch(*x, var_branch, val_branch); +} diff --git a/solvers/chuffed/wrapper.h b/solvers/chuffed/wrapper.h index 9b073dbb12..6a0773539a 100644 --- a/solvers/chuffed/wrapper.h +++ b/solvers/chuffed/wrapper.h @@ -1 +1,26 @@ +#include "chuffed/branching/branching.h" +#include "chuffed/core/engine.h" +#include "chuffed/core/propagator.h" #include "chuffed/vars/modelling.h" + +class DummyProblem { +public: + vec *searchVars; + // callback + void (*callback)(vec *); + + void print() { callback(searchVars); } + void setcallback(void (*_callback)(vec *)) { callback = _callback; } + void addVars(vec *_searchVars) { searchVars = _searchVars; } +}; + +DummyProblem *new_dummy_problem(); +void p_addVars(DummyProblem *p, vec *_searchVars); +void p_setcallback(DummyProblem *p, void (*_callback)(vec *)); +IntVar* get_idx(vec *x, int i); + +vec* make_vec_intvar(); +void destroy_vec_intvar(vec* v); + +void branch_IntVar(vec *x, VarBranch var_branch, + ValBranch val_branch);