我有一个名为GeneticOperator的类,该类负责遗传程序中的突变和交叉算子。对于不同的突变,我有不同的功能,对于突变,我有一个公共功能,其中我有关于type的switch语句。在功能random()中,我指定了突变类型和染色体中要突变的基因数量。

class GeneticOperator
{
public:
    enum MutationType
    {
        FUNCTION_MUTATION,
        ARGUMENTS_MUTATION,
        WORSTGENES_MUTATION //not implemented yet
    };
    enum CrossoverType //not implemented yet
    {
        ONEPOINT_CROSSOVER,
        TWOPOINT_CROSSOVER,
        UNIFORM_CROSSOVER,
        BESTGENE_CROSSOVER
    };
public:
    GeneticOperator();
    //GeneticOperator(const GeneGenerator* geneGenerator,
    //                int maxNGene);


    ChromosomePtr mutation(const Chromosome& parent) const;

private:
    void random();

    ChromosomePtr functionMutation(const Chromosome& parent) const;
    ChromosomePtr argumentsMutation(const Chromosome& parent) const;
private:
    const GeneGenerator* geneGenerator_;
    MutationType mutationType_;
    CrossoverType crossoverType_;
    int nMutatedGene_;
    int maxNMutatedGene_;
};


功能:

ChromosomePtr GeneticOperator::mutation(const Chromosome &parent) const
{
    if (parent.getSize() < maxNMutatedGene_)
    {
        throw "Za malo genow w chromosomie";
    }
    this->random();
    switch(mutationType_)
    {
    case FUNCTION_MUTATION:
        return functionMutation(parent);

    case ARGUMENTS_MUTATION:
        return argumentsMutation(parent);

    case WORSTGENES_MUTATION:
        //not implemented yet
        break;

    default:
        throw "Bad enum type";
        break;
    }
    return nullptr;
}

ChromosomePtr GeneticOperator::functionMutation(const Chromosome &parent) const
{
    ChromosomePtr child = parent.copy();

    for(int i = 0; i < nMutatedGene_; i++)
    {
        GenePtr newGene = nullptr;
        int geneNumber = rand() % (parent.getSize() - 1);

        switch(parent.getGene(geneNumber)->getType())
        {
        case Gene::TERMINAL_GENE:
            i--;
            break;

        case Gene::FUNCTION_GENE:
            int nArguments = parent.getGene(geneNumber)->getNArguments();
            GenePtr randomGene = move(geneGenerator_->getRandomFunctionGene(nArguments));
            for(int k = 0; k < nArguments; k++)
            {
                randomGene->addChild(parent.getGene(geneNumber)->getChild(k));
            }
            break;
        }
    }

    return child;
}

ChromosomePtr GeneticOperator::argumentsMutation(const Chromosome& parent) const
{
    ChromosomePtr child = parent.copy();

    for(int i = 0; i < nMutatedGene_; i++)
    {
        GenePtr newGene = nullptr;
        int geneNumber = rand() % (parent.getSize() - 1);

        switch(parent.getGene(geneNumber)->getType())
        {
        case Gene::TERMINAL_GENE:
            i--;
            break;

        case Gene::FUNCTION_GENE:
            GenePtr randomGene = move(parent.getGene(geneNumber)->clone());
            int nArguments = parent.getGene(geneNumber)->getNArguments();
            for(int k = 0; k < nArguments; k++)
            {
                int childGeneNumber = rand() % geneNumber;
                randomGene->setChild(childGeneNumber, k);
            }
            break;
        }
    }

    return child;
}


functionMutation()argumentsMutation()看起来像复制粘贴编程。

我该如何避免呢?我试图在此函数中仅返回GenePtr,但是方法mutation()不清楚。

您有什么建议?

最佳答案

复制粘贴的方法实际上只是杂乱无章的代码。我消除重复的解决方案是添加一个功能,以便从亲本基因中获得随机功能基因。这也将阐明职能的目的。

GenePtr GeneticOperator::getRandomFuncGene(const Chromosome &parent) const
{
    while(true)
    {
        int geneNumber = rand() % (parent.getSize() - 1);
        if (parent.getGene(geneNumber)->getType())
        {
            return parent.getGene(geneNumber);
        }
    }
}


使用新方法并消除混乱之后,旧函数如下所示:

ChromosomePtr GeneticOperator::functionMutation(const Chromosome &parent) const
{
    for(int i = 0; i < nMutatedGene_; i++)
    {
        GenePtr funcGene = getRandomFuncGene(parent);

        int nArguments = funcGene->getNArguments();
        GenePtr randomGene = move(geneGenerator_->getRandomFunctionGene(nArguments));
        for(int k = 0; k < nArguments; k++)
        {
            randomGene->addChild(funcGene->getChild(k));
        }
    }

    return parent.copy();
}

ChromosomePtr GeneticOperator::argumentsMutation(const Chromosome& parent) const
{
    for(int i = 0; i < nMutatedGene_; i++)
    {
        GenePtr funcGene = getRandomFuncGene(parent);

        GenePtr randomGene = move(funcGene->clone());
        int nArguments = funcGene->getNArguments();
        for(int k = 0; k < nArguments; k++)
        {
            int childGeneNumber = rand() % geneNumber;
            randomGene->setChild(childGeneNumber, k);
        }
    }

    return parent.copy();
}


我希望我不会误解代码,但是很难猜测有时会发生什么。

这些功能还存在其他一些问题。据我了解,返回值与该函数的实际用途不符。

08-26 23:52