Я ищу способ копирования экземпляров Space
в Gecode, а затем проанализировать разницу между пробелами позже.
Однако после первой копии это уже не так. Когда вы копируете код в книге "Моделирование и программирование в 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;
}
Как можно сделать реальную копию?
Сначала вы должны вызвать status()
в Space
.
Я нашел этот обмен в архивах списка рассылки Gecode: https://www.gecode.org/users-archive/2006-March/000439.html
Казалось бы, внутренне Gecode использует функцию копирования и конструктор для своих собственных внутренних целей, поэтому, чтобы сделать копию пространства "копировать по значению", вам нужно использовать функцию clone(), определенную в интерфейсе Space. Однако, как отмечено в ответе @Anonymous, вам нужно вызвать status() перед вызовом клона, иначе он выдаст исключение типа SpaceNotStable
Я увеличил свое пространство с помощью функции ниже, чтобы автоматически вызывать статус, делать клон и возвращать указатель моего производного типа:
struct Example : public Space {
...
Example * cast_clone() {
status();
return static_cast<Example *>(this->clone());
}
...
}
В качестве обходного пути можно создать абсолютно независимое пространство, а затем использовать ограничения равенства на уровне переменных, чтобы уменьшить домены этих переменных.
Пример:
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());
}
}
}
Однако причина, по которой человек не может клонировать Space
остается загадкой.
copy
изSpace
вSendMoreMoney
и он по- прежнему считается переопределение. Это особый случай для производных типов.