实际应用中,往往要比官方的示例复杂很多,这里对变量的选择等往往需要以自定义的方式进行选择,这个时候就需要自定义brancher,相关注释在代码中
#include <gecode/int.hh> using namespace Gecode; class NoneMin : public Brancher { protected: ViewArray<Int::IntView> x; // choice definition class PosVal : public Choice { public: int pos; int val; PosVal(const NoneMin& b, int p, int v) : Choice(b,2), pos(p), val(v) {} virtual size_t size(void) const { return sizeof(*this); } virtual void archive(Archive& e) const { Choice::archive(e); e << pos << val; } }; public: NoneMin(Home home, ViewArray<Int::IntView>& x0) : Brancher(home), x(x0) {} static void post(Home home, ViewArray<Int::IntView>& x) { (void) new (home) NoneMin(home,x); } virtual size_t dispose(Space& home) { (void) Brancher::dispose(home); return sizeof(*this); } NoneMin(Space& home, bool share, NoneMin& b) : Brancher(home,share,b) { x.update(home,share,b.x); } virtual Brancher* copy(Space& home, bool share) { return new (home) NoneMin(home,share,*this); } // status 选择某个变量,有时有些变量需要有优处理,这时可以在这个地方选择 virtual bool status(const Space& home) const { for (int i=0; i<x.size(); i++) if (!x[i].assigned()) return true; return false; } // choice 通过这个函数取得choice virtual Choice* choice(Space& home) { for (int i=0; true; i++) if (!x[i].assigned()) return new PosVal(*this,i,x[i].min()); GECODE_NEVER; return NULL; } virtual Choice* choice(const Space&, Archive& e) { int pos, val; e >> pos >> val; return new PosVal(*this, pos, val); } // commit virtual ExecStatus commit(Space& home, const Choice& c, unsigned int a) { const PosVal& pv = static_cast<const PosVal&>(c); int pos=pv.pos, val=pv.val; if (a == 0) //这里对应的一个节点的两个分支,左边的节点为付值,右边的节点为排除。 return me_failed(x[pos].eq(home,val)) ? ES_FAILED : ES_OK; else return me_failed(x[pos].nq(home,val)) ? ES_FAILED : ES_OK; } // print virtual void print(const Space& home, const Choice& c, unsigned int a, std::ostream& o) const { const PosVal& pv = static_cast<const PosVal&>(c); int pos=pv.pos, val=pv.val; if (a == 0) o << "x[" << pos << "] = " << val; else o << "x[" << pos << "] != " << val; } }; void nonemin(Home home, const IntVarArgs& x) { if (home.failed()) return; ViewArray<Int::IntView> y(home,x); NoneMin::post(home,y); }
commit函数在worker中被调用
void Space::_commit(const Choice& c, unsigned int a) { if (a >= c.alternatives()) throw SpaceIllegalAlternative("Space::commit"); if (failed()) return; if (Brancher* b = brancher(c.bid)) { // There is a matching brancher pc.p.ei.brancher(*b); ExecStatus es = b->commit(*this,c,a); pc.p.ei.other(); if (es == ES_FAILED) fail(); } else { // There is no matching brancher! throw SpaceNoBrancher("Space::commit"); } }
时间: 2024-10-10 06:40:20