Все объекты, сделанные через конструктор, имеют одинаковые векторы - PullRequest
1 голос
/ 13 февраля 2020

Я новичок в C ++ и пытаюсь создать базовый c geneti c алгоритм. Я создал класс хромосом и хочу создать класс общества, который генерирует вектор этих хромосом со случайно сгенерированными «генами». Гены - это вектор в хромосоме, который содержит значения 0 или 1. Я тестировал конструктор хромосом, и все объекты имеют одинаковые генные векторы. Как я могу заставить конструктор генерировать случайные значения? Я включил код ниже. Любая другая практика кодирования или советы по оптимизации также были бы очень благодарны.

Источник. cpp

#include "Chromosome.h"
#include "Society.h"

using namespace std;

int main()
{
    Chromosome demo = Chromosome::Chromosome();
    Chromosome demo2 = Chromosome::Chromosome();
    return 1;
}

Chromosome.h

#pragma once
#include <vector>
using namespace std;

class Chromosome
{
private:
    int fitness;
    vector<int> genes;

public:
    Chromosome();

    void generateGenes();

    int calculateFitness(),
        getFitness();

    vector<int> getGenes();
    void setGenes(vector<int> child);
};

Хромосома. cpp

#include "Chromosome.h"
#include <cstdlib>
#include <ctime> 
#include <numeric>
using namespace std;

Chromosome::Chromosome()
{
    generateGenes();
    Chromosome::fitness = calculateFitness();
}

void Chromosome::generateGenes()
{
    srand(time(NULL));
    for (unsigned i = 0; i < 10; i++)
    {
        unsigned chance = rand() % 5;
        Chromosome::genes.push_back((!chance)? 1 : 0);
    }
}

int Chromosome::calculateFitness()
{
    int sum = 0;
    for (unsigned i = 0; i < Chromosome::genes.size(); i++)
    {
        sum += Chromosome::genes[i];
    }
    return sum;
}

int Chromosome::getFitness()
{
    return Chromosome::fitness;
}

vector<int> Chromosome::getGenes()
{
    return Chromosome::genes;
}

void Chromosome::setGenes(vector<int> child)
{
    Chromosome::genes = child;
}

Ответы [ 2 ]

5 голосов
/ 13 февраля 2020

Вы заполняете генератор случайных чисел тем же значением time(NULL). Два вызова после друг друга вернут тот же time_t. Сначала вы сгенерируете один набор случайных чисел, затем сбросите генератор случайных чисел и сгенерируете их снова.

Только звоните srand() один раз в течение всего запуска программы.

Кроме того, вместо этого используйте <random>, чтобы получить лучшее / более быстрое случайное число генераторы.

Вместо rand() % 5;, используя <random>:

#include <random>

// A function to return a random number generator.
inline std::mt19937& generator() {
    // the generator will only be seeded once since it's static
    static std::mt19937 gen(std::random_device{}());
    return gen;
}

// A function to generate unsigned int:s in the range [min, max]
int my_rand(unsigned  min, unsigned  max) {
    std::uniform_int_distribution<unsigned > dist(min, max);
    return dist(generator());
}

Затем назовите его:

unsigned chance = my_rand(0, 4);
3 голосов
/ 13 февраля 2020

Ваша проблема заключается в использовании rand & srand в программе на C ++.

srand(time(NULL));
unsigned chance = rand() % 5;

в этой реализации rand может возвращать несколько чисел, которые дадут вам одинаковое окончательный результат. например: 19, 24, 190214, 49789, 1645879, 15623454, 4, 156489719, 1645234, 152349, ...

Существуют разные способы генерации случайных чисел в C ++, но этот не рекомендуется из-за плохих результатов.

Один (из многих) хороших способов генерации случайных чисел , используя «псевдослучайный» в C ++:

void Chromosome::generateGenes()
{
    // Initialize random
    std::random_device rd;  // Will be used to obtain a seed for the random number engine
    std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
    std::uniform_int_distribution<> dis(0, 5);

    for (unsigned i = 0; i < 10; i++)
    {
        // Use random: dis(gen);
        unsigned chance = dis(gen);
        Chromosome::genes.push_back((!chance)? 1 : 0);
    }
}

Включить:

#include <random>

Правильная нота @TedLyngmo: Каждый раз, когда будет вызываться эта функция (в вашем случае, в каждом создание объекта в вызове конструктора), этот код заставит вас сгенерировать новое случайное начальное число (в разделе «Инициализация случайного»). В большинстве случаев или по мере роста программы настоятельно рекомендуется извлечь эту инициализацию в другую функцию (и, возможно, в новый объект класса по причине модульного программирования). В этом ответе я продемонстрировал общий синтаксис использования этого типа случайных чисел в вашем случае.

Читайте о:

Генерация псевдослучайных чисел

Равномерное распределение

Благодаря @MM: Как кратко, портативно и тщательно посеять PRNG mt19937?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...