C++ кроссовер генетический алгоритм вектор push_back перезаписывает старый
У меня проблема с моим кодом. Я пытаюсь сделать кроссовер из 4 родителей. Проблема в том, что вектор push_back продолжает перезаписывать верхний, если в векторе есть одно и то же значение.
Например,
parent 1 = 101
parent 2 = 200
parent 3 = 101
parent 4 = 302
допустим, точка пересечения равна 1,
1|01
2|00
1|01
3|02
ребенок будет
1|00
2|01
1|02
3|01
вместо того, чтобы получить дочерний элемент выше, я получаю другой вывод, который перезаписывается вектором push_back.
ребенок, который я получаю
1|02
2|01
1|02
3|01
Как вы можете видеть, значение кроссовера от родителя 3 перезаписывается на родительский 1 после завершения кроссовера. Любая помощь очень ценится. Извините, если я нарушаю какие-либо правила, я новичок в этом форуме.
Код ниже:
void GA::Crossover()
{
int i=0;
int po=0;
int po1=1;
do
{
int point1 = 0;
while (point1==0)
point1=rand() % 3;
std::ofstream log("log.txt", std::ios_base::app);
log<<"---------------------------------"<<"\n";
log<<"cross point: "<<point1<<std::endl;
log.close();
Chromosome* child1=parent.at(po);
Chromosome* child2=parent.at(po1);
for(int c1=0;c1<point1;c1++)
{
int one=parent.at(po1)->GetGene(c1);
int two=parent.at(po)->GetGene(c1);
child1->SetGene(c1,one);
child2->SetAnonGene(c1,two);
}
/*for(int c1=2;c1>=point1;c1--)
{
int one=parent.at(po1)->GetGene(c1);
int two=parent.at(po)->GetGene(c1);
child1->SetGene(c1,one);
child2->SetGene(c1,two);
}*/
Evaluate(child1);
child.push_back(child1);
Evaluate(child2);
child.push_back(child2);
po=2;
po1=3;
i++;
}while(i<2);
std::cout<<"child size:"<<child.size()<<std::endl;
std::ofstream log("log.txt", std::ios_base::app);
log<<"---------------------------------"<<"\n";
log<<"Child:"<<std::endl;
log.close();
for(int p=0;p<(int)child.size();p++)
{
child.at(p)->Print();
}
log.open("log.txt", std::ios_base::app);
log<<"---------------------------------"<<"\n";
log.close();
parent.clear();
parent.shrink_to_fit();
}
2 ответа
В вашем коде childs являются указателями:
Chromosome* child1=parent.at(po);
Это не копии хромосомы, которые вы можете потом свободно модифицировать, но они указывают на оригинального родителя. Итак, когда вы мутируете ген:
child1->SetGene(c1,one);
Вы мутируете родителей! Второй do-while
Итерация тогда работает на мутировавших родителей. Вот почему вы не получаете то, что ожидаете.
Решение состоит в том, чтобы скопировать детей. Есть несколько возможностей. У меня нет определений ваших классов, но, например, если Chromosome
имел конструктор копирования, который вы могли бы сделать:
Chromosome* child1=new Chromosome(*parent.at(po));
У вас есть вектор указателей на объекты. Из приведенного вами кода непонятно, но может случиться так, что у вас есть несколько указателей на один и тот же объект (выполненный с использованием поверхностной копии), и, обновляя значение объекта, на который указывает один указатель, вы в конечном итоге обновляете значение указывает на другое.
Предложение было бы использовать vector<Chromosome>
скорее, чем vector<Chromosome*>
но это изменило бы то, как ваш код работает и в других местах.
С другой стороны: можно оптимизировать следующие строки:
while (point1==0)
point1=rand() % 3;
написав
point1=1+(rand()%2);