我在这里发帖询问是否有办法交替不同的分支策略。让我解释一下,我有一个有效的分支策略,我们称之为策略A。最大的问题是策略A不能经常使用。所以当我不能使用策略A时,我会使用另一种策略,我将其称为策略B,它的效率较低。
文档说:
分支订单。创建分支器会将其注册到其主空间。空间维护其分支器的队列,因为首先注册的分支器也首先用于分支。分支队列中的第一个分支称为当前分支。
所以,我想如果我发布分支 A 然后分支B,分支Astatus
将具有优先级,并且每次A说没有分支要做,分支B将被使用。似乎我错了,因为当status
分支返回false
时,它再也不会被调用。这是一个“最小示例”:
#include <gecode/minimodel.hh>
#include <iostream>
using namespace Gecode;
using namespace std;
class MyChoice : public Choice {
public:
int pos; // Position of the variable
int val; // Value of to assign
MyChoice(const Brancher& b, int pos0, int val0)
: Choice(b,2), pos(pos0), val(val0) {}
// Report size occupied
virtual size_t size(void) const {
return sizeof(*this);
}
// Archive into e
virtual void archive(Archive& e) const {
Choice::archive(e);
e << pos << val;
}
};
class BranchA : public Brancher {
protected:
ViewArray<Int::IntView> x;
public:
BranchA(Home home, ViewArray<Int::IntView>& x0)
: Brancher(home), x(x0) {}
static void post(Home home, ViewArray<Int::IntView>& x) {
(void) new (home) BranchA(home,x);
}
virtual size_t dispose(Space& home) {
(void) Brancher::dispose(home);
return sizeof(*this);
}
BranchA(Space& home, bool share, BranchA& b)
: Brancher(home,share,b) {
x.update(home,share,b.x);
}
virtual Brancher* copy(Space& home, bool share) {
return new (home) BranchA(home,share,*this);
}
// status
virtual bool status(const Space& home) const {
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
return !i%2 && x[i].in(1);
return false;
}
// choice
virtual Choice* choice(Space& home) {
for (int i=0; true; i++)
if (!x[i].assigned())
return new MyChoice(*this,i,1);
GECODE_NEVER;
return NULL;
}
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new MyChoice(*this, pos, val);
}
// commit
virtual ExecStatus commit(Space& home,
const Choice& c,
unsigned int a) {
const MyChoice& pv = static_cast<const MyChoice&>(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;
}
};
void branchA(Home home, const IntVarArgs& x) {
if (home.failed()) return;
ViewArray<Int::IntView> y(home,x);
BranchA::post(home,y);
}
// BranchB //////////////////////////////////////////////////////
class BranchB : public Brancher {
protected:
ViewArray<Int::IntView> x;
public:
BranchB(Home home, ViewArray<Int::IntView>& x0)
: Brancher(home), x(x0) {}
static void post(Home home, ViewArray<Int::IntView>& x) {
(void) new (home) BranchB(home,x);
}
virtual size_t dispose(Space& home) {
(void) Brancher::dispose(home);
return sizeof(*this);
}
BranchB(Space& home, bool share, BranchB& b)
: Brancher(home,share,b) {
x.update(home,share,b.x);
}
virtual Brancher* copy(Space& home, bool share) {
return new (home) BranchB(home,share,*this);
}
// status
virtual bool status(const Space& home) const {
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
return i%2 && x[i].in(2);
return false;
}
// choice
virtual Choice* choice(Space& home) {
for (int i=0; true; i++)
if (!x[i].assigned())
return new MyChoice(*this,i,2);
GECODE_NEVER;
return NULL;
}
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new MyChoice(*this, pos, val);
}
// commit
virtual ExecStatus commit(Space& home,
const Choice& c,
unsigned int a) {
const MyChoice& pv = static_cast<const MyChoice&>(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;
}
};
void branchB(Home home, const IntVarArgs& x) {
if (home.failed()) return;
ViewArray<Int::IntView> y(home,x);
BranchB::post(home,y);
}
// Minimal Space ///////////////////////////////////////
class TestSpace : public Space {
protected:
IntVarArray x;
public:
TestSpace(int size)
: x(*this, size, 0, 10) {
branchA(*this, x);
branchB(*this, x);
}
TestSpace (bool share, TestSpace& s)
: Space(share, s) {
x.update(*this, share, s.x);
}
virtual Space* copy (bool share) {
return new TestSpace(share, *this);
}
void print(std::ostream& os) {
os << "x= " << x << endl;
}
};
// Minimal Main //////////////////////:
int main (int, char**) {
// create model and search engine
TestSpace* m = new TestSpace(10);
DFS<TestSpace> e(m);
delete m;
// search and print all solutions
while (TestSpace* s = e.next()) {
s->print(cout); delete s;
}
return 0;
}
在此示例中,如果要分配的下一个变量位于偶数索引上并且该变量可以采用( else )的值,status
则分支器A的 如果下一个要分配的变量位于奇数索引上并且该变量可以取( else)的值,则分支器B返回。使用该代码,我希望获得解决方案和(以及其他组合,例如),但是由于分支在返回时被处理,因此只分配了前两个变量。true
1
false
status
true
2
false
[1, 2, 1, 2, ...]
[!1, !2, !1, !2, ...]
[!1, 2, 1, !2, ...]
status
false
有没有一种好方法可以使分支器在status
返回后不被处理false
(或交替使用两种不同的分支策略),还是应该将两个分支器合并为一个?