2016-12-29 9 views
3

Я написал следующий код для эволюции популяции (генетический алгоритм реализации):Как применять тест-функции генетического алгоритма

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

} 

Population.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 Контрольные функции для оптимизации отдельных объектов

Может кто-нибудь объяснить, как это сделать? Объяснение для любой функции из списка было бы полезно.

+0

Как это отличается от вопроса, который вы опубликовали несколько часов назад? http://stackoverflow.com/questions/41374297/genetic-algorithm-implementation Вместо того, чтобы создавать новый вопрос, вы могли бы отредактировать свой предыдущий вопрос и добавить этот код. – rafid059

+0

Это было характерно для функции Easom, но теперь я думаю, что если я получу объяснение какой-либо функции, я могу сделать все остальное самостоятельно. Итак, теперь вопрос не зависит от конкретной функции. – Aman

+0

Я не понимаю, что этот код пытается выполнить. Генетический алгоритм мутирует людей, чтобы попытаться улучшить их пригодность. Прямо сейчас ваша пригодность определяется как сумма генов, см. 'Оценка()' (ужасное именование BTW). Не будут ли люди просто иметь более высокие и более высокие гены? Функции на странице Википедии, которые вы связали, - это все функции с двумя входами x и y. Я бы предложил дать вашим людям 2 гена, и я бы определил фитнес как результат функции, которую вы тестируете. Не могли бы вы сказать, правильно ли мои предположения, чтобы я мог написать ответ? –

ответ

3

Что гены должны представлять

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

Сейчас ваша функция пригодности определяется как сумма всех генов:

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

Это странно, что нужно сделать: давайте думать об индивидуальной ведьме будет иметь высокую физическую форму. Надеюсь, вы видите, что нет реального оптимума, индивидуумы просто будут увеличивать каждый из своих генов, потому что это заархивирует более высокий фитнес.

Вторая проблема заключается в том, что гены должны представлять что-то: что на самом деле означают двойники в геном-массиве? Почему нас это волнует? Возможным примером могло бы быть то, чтобы они представляли поведение индивидов в симуляции. Это, конечно, целая другая тема, поэтому нам нужно, чтобы они имели в виду что-то простое, поэтому легко вычислить их пригодность.

Давайте дадим массиву размер 1 и скажем x = genes[0]. У индивидуумов будет только один ген: x-координата. Теперь нам нужно определить нашу фитнес-функцию, мы будем выбирать Easom с y = 0. Это, как я хотел бы определить новую функцию приспособленности:

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.

Почему массив генов?

I думаю, ваше задание хочет, чтобы вы использовали массив double в качестве генов, чтобы в итоге вы получили программу, которая может оптимизировать любую функцию с любым количеством переменных. В программировании всегда полезно писать код, который можно использовать повторно для нескольких разных вещей.

Не стесняйтесь задавать любые вопросы!

Я попытался объяснить все как можно яснее, но если вы не понимаете, что-то не стесняйтесь спрашивать!

+0

Спасибо за ответ. Мой запрос состоит в том, что если мы возьмем генный массив только с одним элементом, тогда не будет никакого значения кроссовера (что означает, что некоторые гены происходят от одного родителя и отдыхают от другого). Люди нового поколения должны иметь качества (гены) своих родителей, кроме тех, которые мутируют (очень низкие шансы 0.001-0.05). – Aman

+0

Хорошо, если вы проверили, что он работает с одной переменной, вы можете попробовать ее с большим количеством, вы можете, например, сказать, что 'y = genes [1]'. –

+0

Да, это именно то, что я хочу спросить. Должен ли я выполнять свою функцию (скажем, например, суммировать все гены индивида и принять mod 5 и сделать его равным x) и найти пригодность индивида в соответствии с ним, или я должен принять x как случайное число в своей области и вычислить пригодность, используя это? – Aman