gecode中自定义brancher

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gecode中自定义brancher相关的知识,希望对你有一定的参考价值。

实际应用中,往往要比官方的示例复杂很多,这里对变量的选择等往往需要以自定义的方式进行选择,这个时候就需要自定义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的主要内容,如果未能解决你的问题,请参考以下文章

活动中自定义对话框内的 ANDROID 片段

gecode FunctionBranch 源码分析

gecode中的idx recorder分析

在 Leanback 应用程序中自定义播放控件

Gecode branch()函数的z3替代方案?

gecode中的meritbase