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);
Другие вопросы по тегам