通过构造函数创建的所有对象都具有相同的向量

All objects made through constructor have the same vectors

我是 C++ 的新手,我正在尝试创建一个基本的遗传算法。我创建了一个染色体 class 并想创建一个社会 class 来生成这些染色体的向量,这些染色体具有随机生成的 "genes"。基因是染色体中包含 0 或 1 值的向量。我正在测试染色体构造函数,所有对象都具有相同的基因向量。如何让构造函数生成随机值?我在下面包含了代码。任何其他编码实践或优化技巧也将不胜感激。

Source.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);
};

Chromosome.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;
}

您使用相同的值 time(NULL) 为随机数生成器设置种子。 彼此之后的两次调用将 return 相同 time_t。您将首先生成一组随机数,然后重置随机数生成器并再次生成它们。

整个程序只调用srand()一次运行.

此外,使用 <random> 来获取 better/faster 个随机数生成器。

而不是 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);

您的问题是在 C++ 程序中使用 rand & srand

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

在这个实现中,rand 可能 return 多个数字会给你相同的 final 结果。例如: 19, 24, 190214, 49789, 1645879, 15623454, 4, 156489719, 1645234, 152349, ...

在 C++ 中有多种生成随机数的方法,由于结果不好,不推荐使用这种方法。

在 C++ 中使用 "pseudo-random" 生成随机数的(许多)好方法之一:

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 的右注:每次调用该函数时(在您的情况下,在构造函数调用中的每个对象创建中),这段代码都会让您生成一个新的随机种子(在 'Initialize random'部分)。在更多进展情况下,或者随着程序的增长,强烈建议将此初始化提取到另一个函数(出于模块化编程的原因,可能提取到新的 class 对象)。在此回复中,我演示了在您的案例中使用这种类型的随机数的一般语法。

了解:

Pseudo-random number generation

Uniform Distribution

感谢@M.M:How to succinctly, portably, and thoroughly seed the mt19937 PRNG?