monadiccp-0.6: lib/gecodeglue.cpp
#define _interface_cpp_
#include <vector>
#include <iostream>
#include "gecode/kernel.hh"
#include "gecode/support.hh"
#include "gecode/int.hh"
#include "gecode/search.hh"
#include "gecodeglue.h"
using namespace std;
using namespace Gecode;
int static nModels=0;
int static nOrigModels=0;
class HaskellModel : public Space {
protected:
vector<BoolVar> boolVars;
vector<IntVar> intVars;
IntConLevel icl;
#ifndef NDEBUG
int level;
int origNum,num;
#endif
private:
static IntRelType mapGoperator(goperator_t op, bool revert=false) {
switch(op) {
case GOPERATOR_OEQUAL: return IRT_EQ;
case GOPERATOR_ODIFF: return IRT_NQ;
case GOPERATOR_OLESS: return revert ? IRT_GR : IRT_LE;
}
#ifndef NDEBUG
cerr << "(unknown goperator " << op << "\n";
#endif
assert(0);
}
public:
HaskellModel() : boolVars(), intVars(), icl(ICL_DEF)
#ifndef NDEBUG
, level(0), origNum(++nOrigModels), num(++nModels)
#endif
{
#ifndef NDEBUG
identify(); cerr << "newmodel\n";
#endif
}
~HaskellModel() {
#ifndef NDEBUG
identify(); cerr << "delmodel\n";
#endif
}
HaskellModel(bool share, HaskellModel &model) : Space(share,model), boolVars(model.boolVars.size()), intVars(model.intVars.size()), icl(model.icl)
#ifndef NDEBUG
, level(model.level+1), origNum(model.origNum), num(++nModels)
#endif
{
#ifndef NDEBUG
identify(); cerr << "newmodel from [" << model.origNum << ":" << model.num << "]\n";
#endif
for (int i=0; i<model.boolVars.size(); i++) {
boolVars.at(i).update(*this, share, model.boolVars.at(i));
}
for (int i=0; i<model.intVars.size(); i++) {
intVars.at(i).update(*this, share, model.intVars.at(i));
}
}
virtual Space *copy(bool share) {
return new HaskellModel(share, *this);
}
#ifndef NDEBUG
void identify() {
for (int i=0; i<level; i++) {
cerr << " ";
}
cerr << "[" << origNum << ":" << num << "] ";
}
#endif
int addIntVar(int low, int high) {
int ret = intVars.size();
IntVar b(*this,low,high);
intVars.push_back(b);
#ifndef NDEBUG
identify(); cerr << "addintvar v" << ret << "\n";
#endif
return ret;
}
int addBoolVar(int low, int high) {
int ret = boolVars.size();
BoolVar b(*this,low,high);
boolVars.push_back(b);
#ifndef NDEBUG
identify(); cerr << "addboolvar v" << ret << "\n";
#endif
return ret;
}
void getIntInfo(int var, int *min, int *max, int *med, int *size, int *val) {
assert(var>=0 && var<intVars.size());
IntVar &v = intVars.at(var);
SpaceStatus state=status();
if (state==SS_FAILED) {
if (min) *min=0;
if (max) *max=0;
if (med) *med=0;
if (size) *size=0;
#ifndef NDEBUG
identify(); cerr << "getintinfo failed)\n";
#endif
return;
}
if (min) *min=v.min();
if (max) *max=v.max();
if (med) *med=v.med();
int ss=v.size();
if (ss==1) {
if (size) *size=1;
if (val) *val=v.val();
} else {
if (size) *size=ss;
}
#ifndef NDEBUG
identify(); cerr << "getintinfo v" << var << ": min=" << v.min() << ", max=" << v.max() << ", med=" << v.med() << ", size=" << v.size() << ", val=" << ((v.size()<2) ? v.val() : -666) << "\n";
#endif
}
int testIntDomain(int var, int val) {
assert(var>=0 && var<intVars.size());
return intVars.at(var).in(val);
}
void getBoolInfo(int var, int *bound, int *val) {
assert(var>=0 && var<boolVars.size());
BoolVar &v = boolVars.at(var);
if (v.assigned()) {
if (bound) *bound=1;
if (val) *val=v.val();
} else {
if (bound) *bound=0;
}
}
void postIntValue(int var, int val) {
assert(var>=0 && var<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intvalue v" << var << " = " << val << "\n";
#endif
IntVar &v = intVars.at(var);
rel(*this,v,IRT_EQ,val,icl);
}
void postIntSame(int var1, int var2) {
assert(var1>=0 && var1<intVars.size());
assert(var2>=0 && var2<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intsame v" << var1 << " = v" << var2 << "\n";
#endif
IntVar &v1 = intVars.at(var1);
IntVar &v2 = intVars.at(var2);
rel(*this,v1,IRT_EQ,v2,icl);
}
void postIntDiff(int var1, int var2) {
assert(var1>=0 && var1<intVars.size());
assert(var2>=0 && var2<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intdiff v" << var1 << " != v" << var2 << "\n";
#endif
IntVar &v1 = intVars.at(var1);
IntVar &v2 = intVars.at(var2);
rel(*this,v1,IRT_NQ,v2,icl);
}
void postIntRel(int var1, goperator_t op, int var2) {
assert(var1>=0 && var1<intVars.size());
assert(var2>=0 && var2<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intrel v" << var1 << " " << (op==GOPERATOR_OEQUAL ? "==" : (op==GOPERATOR_OLESS ? "<" : "!=")) << " v" << var2 << "\n";
#endif
IntVar &v1 = intVars.at(var1);
IntVar &v2 = intVars.at(var2);
rel(*this,v1,mapGoperator(op),v2,icl);
}
void postIntRelCf(int v1, goperator_t op, int var2) {
assert(var2>=0 && var2<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intrelcf " << v1 << " " << (op==GOPERATOR_OEQUAL ? "==" : (op==GOPERATOR_OLESS ? "<" : "!=")) << " v" << var2 << "\n";
#endif
IntVar &v2 = intVars.at(var2);
rel(*this,v2,mapGoperator(op,true),v1,icl);
}
void postIntRelCs(int var1, goperator_t op, int v2) {
assert(var1>=0 && var1<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intrelcs v" << var1 << " " << (op==GOPERATOR_OEQUAL ? "==" : (op==GOPERATOR_OLESS ? "<" : "!=")) << " " << v2 << "\n";
#endif
IntVar &v1 = intVars.at(var1);
rel(*this,v1,mapGoperator(op),v2,icl);
}
void postIntMult(int var1, int var2, int varr) {
assert(var1>=0 && var1<intVars.size());
assert(var2>=0 && var2<intVars.size());
assert(varr>=0 && varr<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intmult v" << var1 << " * v" << var2 << " = v" << varr << "\n";
#endif
IntVar &v1 = intVars.at(var1);
IntVar &v2 = intVars.at(var2);
IntVar &vr = intVars.at(varr);
mult(*this,v1,v2,vr,icl);
}
void postIntDiv(int var1, int var2, int varr) {
assert(var1>=0 && var1<intVars.size());
assert(var2>=0 && var2<intVars.size());
assert(varr>=0 && varr<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intdiv v" << var1 << " / v" << var2 << " = v" << varr << "\n";
#endif
IntVar &v1 = intVars.at(var1);
IntVar &v2 = intVars.at(var2);
IntVar &vr = intVars.at(varr);
div(*this,v1,v2,vr,icl);
}
void postIntMod(int var1, int var2, int varr) {
assert(var1>=0 && var1<intVars.size());
assert(var2>=0 && var2<intVars.size());
assert(varr>=0 && varr<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intmod v" << var1 << " mod v" << var2 << " = v" << varr << "\n";
#endif
IntVar &v1 = intVars.at(var1);
IntVar &v2 = intVars.at(var2);
IntVar &vr = intVars.at(varr);
mod(*this,v1,v2,vr,icl);
}
void postIntAbs(int var, int varr) {
assert(var>=0 && var<intVars.size());
assert(varr>=0 && varr<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intabs abs(v" << var << ") = v" << varr << "\n";
#endif
IntVar &v = intVars.at(var);
IntVar &vr = intVars.at(varr);
abs(*this,v,vr,icl);
}
void postIntDom(int var, int low, int high) {
assert(var>=0 && var<intVars.size());
#ifndef NDEBUG
identify(); cerr << "intdom v" << var << " = [" << low << "," << high << "]\n";
#endif
IntVar &v = intVars.at(var);
dom(*this,v,low,high,icl);
}
void postIntLinear(int num, int *vars, int *coef, goperator_t op, int val) {
IntVarArgs vrs(num);
IntArgs vls(num,coef);
for (int i=0; i<num; i++) {
int id=vars[i];
assert(id>=0 && id<intVars.size());
vrs[i]=intVars.at(id);
}
#ifndef NDEBUG
identify(); cerr << "intlinear num=" << num << "\n";
#endif
linear(*this,vls,vrs,mapGoperator(op),val,icl);
}
void postIntAlldiff(int num, int *vars) {
IntVarArgs vrs(num);
for (int i=0; i<num; i++) {
int id=vars[i];
assert(id>=0 && id<intVars.size());
vrs[i]=intVars.at(id);
}
#ifndef NDEBUG
identify(); cerr << "intalldiff num=" << num << "\n";
#endif
distinct(*this,vrs,icl);
}
void postIntSorted(int num, int *vars, int strict) {
IntVarArgs vrs(num);
for (int i=0; i<num; i++) {
int id=vars[i];
assert(id>=0 && id<intVars.size());
vrs[i]=intVars.at(id);
}
#ifndef NDEBUG
identify(); cerr << "intsorted num=" << num << "\n";
#endif
rel(*this,vrs,strict ? IRT_LE : IRT_LQ,icl);
}
void postIntBranching(int num, int *vars) {
IntVarArgs vrs(num);
for (int i=0; i<num; i++) {
int id=vars[i];
assert(id>=0 && id<intVars.size());
vrs[i]=intVars.at(id);
}
#ifndef NDEBUG
identify(); cerr << "intbranch num=" << num << "\n";
#endif
branch(*this,vrs, INT_VAR_SIZE_MIN, INT_VAL_SPLIT_MIN);
}
void postBoolBranching(int num, int *vars) {
IntVarArgs vrs(num);
for (int i=0; i<num; i++) {
int id=vars[i];
assert(id>=0 && id<intVars.size());
vrs[i]=intVars.at(id);
}
#ifndef NDEBUG
identify(); cerr << "boolbranch num=" << num << "\n";
#endif
branch(*this,vrs, INT_VAR_SIZE_MIN, INT_VAL_SPLIT_MIN);
}
};
extern "C" HaskellModel *gecode_model_create(void) { return new HaskellModel(); }
extern "C" HaskellModel *gecode_model_copy(HaskellModel *model) { return (HaskellModel*)(model->clone(true)); }
extern "C" HaskellModel *gecode_model_copy_reentrant(HaskellModel *model) { return (HaskellModel*)(model->clone(false)); }
extern "C" void gecode_model_fail(HaskellModel *model) { model->fail(); }
extern "C" void gecode_model_destroy(HaskellModel *model) { delete model; }
extern "C" int gecode_int_rel(HaskellModel *model, int v1, goperator_t op, int v2) { model->postIntRel(v1,op,v2); return !model->failed(); }
extern "C" int gecode_int_rel_cf(HaskellModel *model, int v1, goperator_t op, int v2) { model->postIntRelCf(v1,op,v2); return !model->failed(); }
extern "C" int gecode_int_rel_cs(HaskellModel *model, int v1, goperator_t op, int v2) { model->postIntRelCs(v1,op,v2); return !model->failed(); }
extern "C" int gecode_int_newvar(HaskellModel *model) { return model->addIntVar(-1000000000,1000000000); }
extern "C" int gecode_int_value(HaskellModel *model, int v, int val) { model->postIntValue(v,val); return !model->failed(); }
extern "C" int gecode_int_mult(HaskellModel *model, int v1, int v2, int vr) { model->postIntMult(v1,v2,vr); return !model->failed(); }
extern "C" int gecode_int_div(HaskellModel *model, int v1, int v2, int vr) { model->postIntDiv(v1,v2,vr); return !model->failed(); }
extern "C" int gecode_int_mod(HaskellModel *model, int v1, int v2, int vr) { model->postIntMod(v1,v2,vr); return !model->failed(); }
extern "C" int gecode_int_abs(HaskellModel *model, int v, int vr) { model->postIntAbs(v,vr); return !model->failed(); }
extern "C" int gecode_int_dom(HaskellModel *model, int v, int low, int high) { model->postIntDom(v,low,high); return !model->failed(); }
extern "C" int gecode_int_linear(HaskellModel *model, int num, int *vars, int *coef, goperator_t op, int val) { model->postIntLinear(num,vars,coef,op,val); return !model->failed(); }
extern "C" int gecode_int_alldiff(HaskellModel *model, int num, int *vars) { model->postIntAlldiff(num,vars); return !model->failed(); }
extern "C" int gecode_int_sorted(HaskellModel *model, int num, int *vars, int strict) { model->postIntSorted(num,vars,strict); return !model->failed(); }
extern "C" void gecode_int_branch(HaskellModel *model, int num, int *vars) { model->postIntBranching(num,vars); }
extern "C" void gecode_int_info(HaskellModel *model, int var, int *min, int *max, int *med, int *size, int *val) { model->getIntInfo(var,min,max,med,size,val); }
extern "C" int gecode_bool_newvar(HaskellModel *model) { return model->addBoolVar(0,1); }
extern "C" void gecode_bool_branch(HaskellModel *model, int num, int *vars) { model->postBoolBranching(num,vars); }
extern "C" DFS<HaskellModel> *gecode_search_create(HaskellModel *model) {
DFS<HaskellModel> *srch=new DFS<HaskellModel>(model);
#ifndef NDEBUG
model->identify(); cerr << "search " << srch << " created\n";
#endif
return srch;
}
extern "C" void gecode_search_destroy(DFS<HaskellModel> *search) {
#ifndef NDEBUG
cerr << "[search " << search << "] destroyed\n";
#endif
delete search;
}
extern "C" HaskellModel *gecode_search_next(DFS<HaskellModel> *search) {
#ifndef NDEBUG
cerr << "[search " << search << "] requesting next\n";
#endif
HaskellModel *res=search->next();
#ifndef NDEBUG
cerr << "[search " << search << "] requested next (" << res << ")\n";
#endif
return res;
}