1. 程式人生 > >gecode中自定義brancher

gecode中自定義brancher

size 方式 val mit share pro clu assign rtu

實際應用中,往往要比官方的示例復雜很多,這裏對變量的選擇等往往需要以自定義的方式進行選擇,這個時候就需要自定義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");
    }
  }

  

gecode中自定義brancher