C++ 为什么可以';在解决原始问题之前,不能在Gecode中克隆一个空格吗?

C++ 为什么可以';在解决原始问题之前,不能在Gecode中克隆一个空格吗?,c++,segmentation-fault,gecode,C++,Segmentation Fault,Gecode,我正在寻找一种方法来复制Gecode中的Space实例,然后在以后分析空格之间的差异 然而,在第一份拷贝之后,它就已经出错了。当复制Gecode中建模和编程一书中的代码时,如下所示,并简单地修改它,使其首先复制(SendMoreMoney*smm=m->copy(true);),无论shared选项是true还是false,都会出现分段错误 #include <gecode/int.hh> #include <gecode/search.hh> using namesp

我正在寻找一种方法来复制Gecode中的
Space
实例,然后在以后分析空格之间的差异

然而,在第一份拷贝之后,它就已经出错了。当复制Gecode中建模和编程一书中的代码时,如下所示,并简单地修改它,使其首先复制(
SendMoreMoney*smm=m->copy(true);
),无论
shared
选项是
true
还是
false
,都会出现分段错误

#include <gecode/int.hh>
#include <gecode/search.hh>

using namespace Gecode;

class SendMoreMoney : public Space {
protected:
  IntVarArray l;
public:
  SendMoreMoney(void) : l(*this, 8, 0, 9) {
    IntVar s(l[0]), e(l[1]), n(l[2]), d(l[3]),
           m(l[4]), o(l[5]), r(l[6]), y(l[7]);
    // no leading zeros
    rel(*this, s, IRT_NQ, 0);
    rel(*this, m, IRT_NQ, 0);
    // all letters distinct
    distinct(*this, l);
    // linear equation
    IntArgs c(4+4+5); IntVarArgs x(4+4+5);
    c[0]=1000; c[1]=100; c[2]=10; c[3]=1;
    x[0]=s;    x[1]=e;   x[2]=n;  x[3]=d;
    c[4]=1000; c[5]=100; c[6]=10; c[7]=1;
    x[4]=m;    x[5]=o;   x[6]=r;  x[7]=e;
    c[8]=-10000; c[9]=-1000; c[10]=-100; c[11]=-10; c[12]=-1;
    x[8]=m;      x[9]=o;     x[10]=n;    x[11]=e;   x[12]=y;
    linear(*this, c, x, IRT_EQ, 0);
    // post branching
    branch(*this, l, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
  }
  // search support
  SendMoreMoney(bool share, SendMoreMoney& s) : Space(share, s) {
    l.update(*this, share, s.l);
  }
  virtual SendMoreMoney* copy(bool share) {
    return new SendMoreMoney(share,*this);
  }
  // print solution
  void print(void) const {
    std::cout << l << std::endl;
  }
};

// main function
int main(int argc, char* argv[]) {
  // create model and search engine
  SendMoreMoney* m = new SendMoreMoney;
  SendMoreMoney* mc = m->copy(true);
  DFS<SendMoreMoney> e(m);
  delete m;
  // search and print all solutions
  while (SendMoreMoney* s = e.next()) {
    s->print(); delete s;
  }
  return 0;
}
#包括
#包括
使用名称空间代码;
类别:公共空间{
受保护的:
INTVARL阵列;
公众:
SendMoreMoney(无效):l(*此,8,0,9){
IntVar s(l[0])、e(l[1])、n(l[2])、d(l[3]),
m(l[4])、o(l[5])、r(l[6])、y(l[7]);
//没有前导零
相关(*本,s,IRT_NQ,0);
rel(*此,m,IRT_NQ,0);
//所有字母都不同
独特(*本,l);
//线性方程
IntArgs c(4+4+5);IntVarArgs x(4+4+5);
c[0]=1000;c[1]=100;c[2]=10;c[3]=1;
x[0]=s;x[1]=e;x[2]=n;x[3]=d;
c[4]=1000;c[5]=100;c[6]=10;c[7]=1;
x[4]=m;x[5]=o;x[6]=r;x[7]=e;
c[8]=-10000;c[9]=-1000;c[10]=-100;c[11]=-10;c[12]=-1;
x[8]=m;x[9]=o;x[10]=n;x[11]=e;x[12]=y;
线性(*此,c,x,IRT_等式,0);
//分支后
分支(*this,l,INT_VAR_SIZE_MIN(),INT_VAL_MIN());
}
//搜索支持
SendMoreMoney(bool share,SendMoreMoney&s):空间(share,s){
l、 更新(*此,共享,s.l.);
}
虚拟SendMoreMoney*拷贝(bool共享){
返还新的SendmareMoney(股份,*本);
}
//打印溶液
无效打印(无效)常量{
std::cout print();删除s;
}
返回0;
}

如何制作真实副本?

作为一种解决方法,可以创建一个完全独立的空间,然后使用相等约束 在变量级别上减少这些变量的域

示例:

void cloneHalfValues(SendMoreMoney* origin) {
    int n = l.size();
    for(int i = 0x00; i < n/2; i++) {
        if(origin->l[i].assigned()) {
            rel(*this, l[i], IRT_EQ, origin->l[i].val());
        }
    }
}
void cloneHalfValues(SendMoreMoney*origin){
int n=l.size();
对于(int i=0x00;il[i].assigned()){
rel(*this,l[i],IRT_EQ,origin->l[i].val());
}
}
}

但是,无法克隆
空间的原因仍然是个谜。

您必须首先在
空间中调用
状态()

我在Gecode邮件列表档案中发现了此交换:

在内部,Gecode似乎使用copy函数和构造函数来实现其自身的内部目的,因此要创建空间的“按值复制”副本,您需要使用space接口中定义的clone()函数。但是,如@Anonymous answer中所述,在调用clone之前需要调用status(),否则它将抛出类型为
SpaceNotStable

我使用下面的函数扩展了我的空间,以自动调用status、创建克隆并返回派生类型的指针:

struct示例:公共空间{
...
示例*cast_clone(){
状态();
返回静态_cast(此->克隆());
}
...
}

您可以将
copy
的返回类型从
Space
更改为
SendMoreMoney
,并且它仍然计为覆盖。这是派生类型的一个特例。@NeilKirk:是的,我先这么做了,但没有成功。因此,我复制了原始代码,以确保在执行过程中不会出现任何问题。在原始代码中,没有出现Liskov替换。[修改]。