// -*- c++ -*- //============================================================================= // Copyright (C) 2011 by Denys Duchier // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published by the // Free Software Foundation, either version 3 of the License, or (at your // option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . //============================================================================= #ifndef GECODE_COMMON #define GECODE_COMMON #if defined(_MSC_VER) || defined(__MINGW32__) #define __i386__ 1 #if __x86_64__ #define _WIN64 1 #define _AMD64_ 1 #endif #include #endif #include "gecode/driver.hh" #include "gecode/int.hh" #include "gecode/set.hh" #include "gecode/search.hh" #include namespace generic_gecode { using namespace std; using namespace Gecode; // description of the optimization criterion struct Optimizing { enum What { OPT_NONE, OPT_INT, OPT_RATIO }; enum How { OPT_MIN, OPT_MAX }; int num; int den; What what; How how; Optimizing(): num(-1), den(-1), what(OPT_NONE), how(OPT_MAX) {} Optimizing(Optimizing& o) : num(o.num), den(o.den), what(o.what), how(o.how) {} void check_ok() const { if (what!=OPT_NONE) throw Exception("gecode-python","too many optimization criteria"); } void maximize(int i) { check_ok(); what = OPT_INT; how = OPT_MAX; num = i; }; void maximize(int i,int j) { check_ok(); what = OPT_RATIO; how = OPT_MAX; num = i; den = j; }; void minimize(int i) { check_ok(); what = OPT_INT; how = OPT_MIN; num = i; }; void minimize(int i,int j) { check_ok(); what = OPT_RATIO; how = OPT_MIN; num = i; den = j; }; }; struct GenericSpace; struct GenericEngine { virtual GenericSpace* next(void)=0; virtual ~GenericEngine() {}; }; struct GenericDFS: GenericEngine { DFS engine; GenericDFS(GenericSpace* s,Search::Options& opt) : engine(s,opt) {} virtual GenericSpace* next(void) { return engine.next(); } }; struct GenericRestartDFS: GenericEngine { RBS engine; GenericRestartDFS(GenericSpace* s,Search::Options& opt) : engine(s,opt) {} virtual GenericSpace* next(void) { return engine.next(); } }; struct GenericBAB: GenericEngine { BAB engine; GenericBAB(GenericSpace* s,Search::Options& opt) : engine(s,opt) {} virtual GenericSpace* next(void) { return engine.next(); } }; struct GenericRestartBAB: GenericEngine { RBS engine; GenericRestartBAB(GenericSpace* s,Search::Options& opt) : engine(s,opt) {} virtual GenericSpace* next(void) { return engine.next(); } }; #ifdef OLD struct GenericRestart: GenericEngine { Restart engine; GenericRestart(GenericSpace* s,Search::Options& opt): engine(s,opt) {} virtual GenericSpace* next(void) { return engine.next(); } }; #endif struct LoadingDock { vector ivars; vector bvars; vector fvars; vector svars; vector ikeep; vector bkeep; vector fkeep; vector skeep; bool keeping_some() const { return (ikeep.size() != 0) || (bkeep.size() != 0) || (fkeep.size() != 0) || (skeep.size() != 0); } IntVar get_ivar(int i) const { return ivars[i]; } BoolVar get_bvar(int i) const { return bvars[i]; } FloatVar get_fvar(int i) const { return fvars[i]; } SetVar get_svar(int i) const { return svars[i]; } int enter_ivar(const IntVar& v) { ivars.push_back(v); return static_cast(ivars.size()-1); } int enter_bvar(const BoolVar& v) { bvars.push_back(v); return static_cast(bvars.size()-1); } int enter_fvar(const FloatVar& v) { fvars.push_back(v); return static_cast(fvars.size()-1); } int enter_svar(const SetVar& v) { svars.push_back(v); return static_cast(svars.size()-1); } int keep_ivar(int i) { ikeep.push_back(i); return static_cast(ikeep.size()-1); } int keep_bvar(int i) { bkeep.push_back(i); return static_cast(bkeep.size()-1); } int keep_fvar(int i) { fkeep.push_back(i); return static_cast(fkeep.size()-1); } int keep_svar(int i) { skeep.push_back(i); return static_cast(skeep.size()-1); } void freeze(Space& home, IntVarArray& iarr, BoolVarArray& barr, SetVarArray& sarr, FloatVarArray& farr, int& num, int& den) { if (keeping_some()) { // make sure that optimization vars (if any) are kept if (num != -1) { const int _num(num); const int _den(den); int n = static_cast(ikeep.size()); bool num_found(false); bool den_found(false); for (;n--;) { const int idx(ikeep[n]); if (idx==_num) { num_found=true; if (den_found) break; } if (idx==_den) { den_found=true; if (num_found) break; } } if (!num_found) { ikeep.push_back(_num); num=static_cast(ikeep.size()-1); } if (_den != -1 && !den_found) { ikeep.push_back(_den); den=static_cast(ikeep.size()-1); } } { int n = static_cast(ikeep.size()); iarr = IntVarArray(home, n); for (;n--;) iarr[n]=ivars[ikeep[n]]; } { int n = static_cast(bkeep.size()); barr = BoolVarArray(home, n); for (;n--;) barr[n]=bvars[bkeep[n]]; } { int n = static_cast(skeep.size()); sarr = SetVarArray(home, n); for (;n--;) sarr[n]=svars[skeep[n]]; } { int n = static_cast(fkeep.size()); farr = FloatVarArray(home, n); for (;n--;) farr[n]=fvars[skeep[n]]; } } else { { int n = static_cast(ivars.size()); iarr = IntVarArray(home, n); for (;n--;) iarr[n]=ivars[n]; } { int n = static_cast(bvars.size()); barr = BoolVarArray(home, n); for (;n--;) barr[n]=bvars[n]; } { int n = static_cast(svars.size()); sarr = SetVarArray(home, n); for (;n--;) sarr[n]=svars[n]; } { int n = static_cast(fvars.size()); farr = FloatVarArray(home, n); for (;n--;) farr[n]=fvars[n]; } } } }; struct GenericSpace: Space { Optimizing optim; IntVarArray ivars; BoolVarArray bvars; FloatVarArray fvars; SetVarArray svars; LoadingDock* dock; bool keeping_some; // iff only SOME of the vars are kept Space* space() { return this; } GenericSpace(bool share, GenericSpace& s) : Space(share, s), optim(s.optim), dock(NULL), keeping_some(s.keeping_some) { ivars.update(*this, share, s.ivars); bvars.update(*this, share, s.bvars); svars.update(*this, share, s.svars); fvars.update(*this, share, s.fvars); } Space* copy(bool share) { freeze(); return new GenericSpace(share, *this); } GenericSpace() : dock(new LoadingDock()), keeping_some(false) {} ~GenericSpace() { delete dock; } // throw some C++ exception on behalf of glue code void kaboom(const char* s) { throw Exception("gecode-python", s); } int ikaboom(const char* s) { kaboom(s); return 0; } // freeze the space before handing it off to a search engine void freeze() { if (dock) { keeping_some = dock->keeping_some(); dock->freeze(*this, ivars, bvars, svars, fvars, optim.num, optim.den); delete dock; dock = NULL; } } IntVar get_ivar(int i) const { return (dock)?dock->get_ivar(i):ivars[i]; } BoolVar get_bvar(int i) const { return (dock)?dock->get_bvar(i):bvars[i]; } SetVar get_svar(int i) const { return (dock)?dock->get_svar(i):svars[i]; } FloatVar get_fvar(int i) const { return (dock)?dock->get_fvar(i):fvars[i]; } int keep_ivar(int i) { if (dock) return dock->keep_ivar(i); else return ikaboom("too late to keep"); } int keep_bvar(int i) { if (dock) return dock->keep_bvar(i); else return ikaboom("too late to keep"); } int keep_svar(int i) { if (dock) return dock->keep_svar(i); else return ikaboom("too late to keep"); } int keep_fvar(int i) { if (dock) return dock->keep_fvar(i); else return ikaboom("too late to keep"); } bool frozen() const { return dock==NULL; } bool has_keepers() const { return keeping_some; } // when frozen and has_keepers: which is just has_keepers actually bool use_keep_index() const { return has_keepers(); } GenericEngine* new_engine(bool restart, Search::Options& opt) { freeze(); return (optim.what == Optimizing::OPT_NONE) ? ( restart ? static_cast(new GenericRestartDFS(this,opt)) : static_cast(new GenericDFS(this,opt)) ) : (restart ? static_cast(new GenericRestartBAB(this,opt)) : static_cast(new GenericBAB(this,opt)) ); } int _new_ivar(IntVar& v) { if (dock) return dock->enter_ivar(v); else return ikaboom("too late to create vars"); } int new_ivar(int lo, int hi) { IntVar v(*this, lo, hi); return _new_ivar(v); } int new_ivar(IntSet& s) { IntVar v(*this, s); return _new_ivar(v); } int _new_fvar(FloatVar& v) { if (dock) return dock->enter_fvar(v); else return ikaboom("too late to create vars"); } int new_fvar(double lo, double hi) { FloatVar v(*this, lo, hi); return _new_fvar(v); } int _new_bvar(BoolVar& v) { if (dock) return dock->enter_bvar(v); else return ikaboom("too late to create vars"); } int new_bvar() { BoolVar v(*this, 0, 1); return _new_bvar(v); } int _new_svar(SetVar& v) { if (dock) return dock->enter_svar(v); else return ikaboom("too late to create vars"); } int new_svar(int glbMin, int glbMax, int lubMin, int lubMax, unsigned int cardMin=0, unsigned int cardMax=Set::Limits::card) { SetVar v(*this, glbMin, glbMax, lubMin, lubMax, cardMin, cardMax); return _new_svar(v); } int new_svar(IntSet glb, int lubMin, int lubMax, unsigned int cardMin=0, unsigned int cardMax=Set::Limits::card) { SetVar v(*this, glb, lubMin, lubMax, cardMin, cardMax); return _new_svar(v); } int new_svar(int glbMin, int glbMax, IntSet lub, unsigned int cardMin=0, unsigned int cardMax=Set::Limits::card) { SetVar v(*this, glbMin, glbMax, lub, cardMin, cardMax); return _new_svar(v); } int new_svar(IntSet glb, IntSet lub, unsigned int cardMin=0, unsigned int cardMax=Set::Limits::card) { SetVar v(*this, glb, lub, cardMin, cardMax); return _new_svar(v); } void minimize(int i) { optim.minimize(i); } void minimize(int i, int j) { optim.minimize(i,j); } void maximize(int i) { optim.maximize(i); } void maximize(int i, int j) { optim.maximize(i,j); } virtual void constrain(const Space& s) { const GenericSpace& sol = static_cast(s); switch (optim.what) { case Optimizing::OPT_NONE: break; case Optimizing::OPT_INT: rel(*this, ivars[optim.num], ((optim.how==Optimizing::OPT_MIN) ? IRT_LE : IRT_GR), sol.ivars[optim.num].val()); break; case Optimizing::OPT_RATIO: { IntArgs c(2, sol.ivars[optim.den].val(), - sol.ivars[optim.num].val()); IntVarArgs v(2); v[0] = ivars[optim.num]; v[1] = ivars[optim.den]; linear(*this, c, v, ((optim.how==Optimizing::OPT_MIN) ? IRT_LE : IRT_GR), 0); break; } } } }; } #ifdef DISJUNCTOR #include "disjunctor.icc" #endif #endif