java-如何将测试功能应用于遗传算法

我已经编写了以下用于种群进化的代码(遗传算法实现):

个人.java

import java.util.Random;

public class Individual {

    public static int SIZE = 500;
    private int[] genes = new int[SIZE];
    private double fitnessValue = 0.0;


    // Getters and Setters
    public void setGene(int index,int gene){
        this.genes[index] = gene;
    }

    public int getGene(int index){
        return this.genes[index];
    }

    public void setFitnessValue(double fitness){
        this.fitnessValue = fitness;
    }

    public double getFitnessValue(){
        return this.fitnessValue;
    }

    //Function to generate a new individual with random set of genes
    public void generateIndividual(){
        Random rand = new Random();
        for(int i=0;i<SIZE;i++){
            this.setGene(i, rand.nextInt(2));
        }
    }

    //Mutation Function
    public void mutate(){
        Random rand = new Random();
        int index = rand.nextInt(SIZE);
        this.setGene(index, 1-this.getGene(index)); // Flipping value of gene 
    }

    //Function to set Fitness value of an individual
    public int evaluate(){

        int fitness = 0;
        for(int i=0; i<SIZE; ++i) {
            fitness += this.getGene(i);
        }
        this.setFitnessValue(fitness);
        return fitness;
    }

}

人口.java

import java.util.Random;

public class Population {

    final static int ELITISM = 5;
    final static int POP_SIZE = 200+ELITISM; //Population size + Elitism (1)
    final static int MAX_ITER = 10000;
    final static double MUTATION_RATE = 0.05;
    final static double CROSSOVER_RATE = 0.7;
    public static int generation = 2;

    private static Random rand = new Random(); 
    private double totalFitness;
    private  Individual[] pop;

    //Constructor
    public Population(){
        pop = new Individual[POP_SIZE];
        //Initialising population
        for(int i=0;i<POP_SIZE;i++){
            pop[i] = new Individual();
            pop[i].generateIndividual();

        }
        //Evaluating current population
        this.evaluate();
    }

    //Storing new generation in population
    public void setPopulation(Individual[] newPop) {
        System.arraycopy(newPop, 0, this.pop, 0, POP_SIZE);
    }


    //Method to find total fitness of population
    public double evaluate(){
        this.totalFitness = 0.0;
        for (int i = 0; i < POP_SIZE; i++) {
            this.totalFitness +=  pop[i].evaluate();
        }


       return this.totalFitness;
    }


    //Getters
    public Individual getIndividual(int index) {
        return pop[index];
    }


    //Function to find fittest individual for elitism
    public Individual getFittest() {
        Individual fittest = pop[0];
        for (int i = 0; i < POP_SIZE; i++) {
            if (fittest.getFitnessValue() <= getIndividual(i).getFitnessValue()) {
                fittest = getIndividual(i);
            }
        }
        return fittest;
    }

    //CROSSOVER Function : Takes 2 individuals and returns 2 new individuals
    public static Individual[] crossover(Individual indiv1,Individual indiv2) {
        Individual[] newIndiv = new Individual[2];
        newIndiv[0] = new Individual();
        newIndiv[1] = new Individual();
        int randPoint = rand.nextInt(Individual.SIZE);
        int i;
        for (i=0; i<randPoint; ++i) {
            newIndiv[0].setGene(i, indiv1.getGene(i));
            newIndiv[1].setGene(i, indiv2.getGene(i));
        }
        for (; i<Individual.SIZE; ++i) {
            newIndiv[0].setGene(i, indiv2.getGene(i));
            newIndiv[1].setGene(i, indiv1.getGene(i));
        }

        return newIndiv;
    }

    //Roulette Wheel Selection Function
    public Individual rouletteWheelSelection() {

        double randNum = rand.nextDouble() * this.totalFitness;
        int idx;

        for (idx=0; idx<POP_SIZE && randNum>0; idx++) {
            randNum -= pop[idx].getFitnessValue();
        }
        return pop[idx-1];
    }

    //Main method

    public static void main(String[] args) {
        Population pop = new Population();
        Individual[] newPop = new Individual[POP_SIZE];
        Individual[] indiv = new Individual[2];
        //Current Population Stats
        System.out.print("Generation #1");
        System.out.println("Total Fitness = "+pop.totalFitness);
        System.out.println("Best  Fitness = "+pop.getFittest().getFitnessValue());

        int count;
        for(int iter=0;iter<MAX_ITER;iter++){
            count =0;

                //Elitism
                newPop[count] = pop.getFittest();
                count++;

           //Creating new population
            while(count < POP_SIZE){
                //Selecting parents
                indiv[0] = pop.rouletteWheelSelection();
                indiv[1] = pop.rouletteWheelSelection();

                // Crossover
                if (rand.nextDouble() < CROSSOVER_RATE ) {
                    indiv = crossover(indiv[0], indiv[1]);
                }

                // Mutation
                if ( rand.nextDouble() < MUTATION_RATE ) {
                    indiv[0].mutate();
                }
                if ( rand.nextDouble() < MUTATION_RATE ) {
                    indiv[1].mutate();
                }

                // add to new population
                newPop[count] = indiv[0];
                newPop[count+1] = indiv[1];
                count += 2;
            }
            // Saving new population in pop
            pop.setPopulation(newPop);
            //Evaluating new population
            pop.evaluate();
            System.out.println("Generation #"+ generation++);
            System.out.print("Total Fitness = " + pop.totalFitness);
            System.out.println(" ; Best Fitness = " +pop.getFittest().getFitnessValue()); 

            }


        Individual bestIndiv = pop.getFittest();
    }

}

我被要求使用以下功能测试我的算法:
https://en.wikipedia.org/wiki/Test_functions_for_optimization
用于单目标优化的测试功能

谁能解释这是怎么做的?列表中任何一项功能的说明都将有所帮助.

解决方法:

基因应该代表什么

我将假设您的遗传算法的实现是正确的,因为这超出了此问题的范围.

现在,您的适应度函数定义为所有基因的总和:

double fitness = 0;
for(int i=0; i<SIZE; ++i) {
  fitness += this.getGene(i);
}
this.setFitnessValue(fitness);

这是一件奇怪的事情:让我们考虑一下单个巫婆的身体健康.我希望您看到没有真正的最佳选择,因为个体将倾向于增加其每个基因,因为这将归档更高的适应性.

第二个问题是基因应该代表某种东西:基因阵列中的两倍实际上意味着什么?我们为什么在乎?一个可能的例子是让它们代表模拟中个人的行为.当然,这是另一个主题,因此我们需要它们表示简单的内容,以便轻松计算其适应性.

让我们让数组的大小为1,假设x = genes [0].个体将只有一个基因:x坐标.现在我们需要定义适应度函数,我们将选择y = 0的Easom.这就是我定义新适应度函数的方式:

double fitness = -cos(x)*cos(0)*exp(-(pow(x-PI,2)+pow(0-PI,2)));

当然,最合适的输入是类别的顶部:

import static java.lang.Math.*;

如果您的程序确实确实针对适应性进行了优化,则应收敛到x = PI.我很快写了我自己的(非常难看)implementation,它确实可以正确收敛.

还有一件事:基因应该是double []而不是int [],因为当x只能是int时,递增优化函数实际上并不起作用.

为什么需要基因阵列?

我认为您的作业希望您使用双精度数组作为基因,因此您最终得到了一个程序,该程序可以使用任何数量的变量来优化任何功能.在编程中,编写可重复用于多种不同事物的代码始终是一个好主意.

随意问任何问题!

我试图尽一切可能解释清楚,但是如果您不明白,请随时提出!

上一篇:遗传算法初始种子多样性使用值编码C#


下一篇:SQL优化入门(视频笔记20210720)