我试图根据我从"用于游戏程序员的AI技术"一书中选择的技术编写遗传算法,该技术使用二进制编码和适应度比例选择(也称为轮盘赌选择)对人群的基因进行在程序中以二维数组随机生成.
我最近遇到了一个伪代码,并试图实现它,但是我遇到了一些问题,我需要做些什么.我检查过一些书籍和一些开源代码,但仍在努力取得进展.我明白我必须得到总人口的总体适应度的总和,在总和与零之间选择一个随机数,然后如果数字大于父母要覆盖它,但我正在努力实施这些想法.
由于我的Java生疏,因此非常感谢任何帮助实现这些想法.
以下是GA的完整概述.我确保非常详细,因此可以很容易地编码为C/Java/Python/..
/* 1. Init population */ POP_SIZE = number of individuals in the population pop = newPop = [] for i=1 to POP_SIZE { pop.add( getRandomIndividual() ) } /* 2. evaluate current population */ totalFitness = 0 for i=1 to POP_SIZE { fitness = pop[i].evaluate() totalFitness += fitness } while not end_condition (best fitness, #iterations, no improvement...) { // build new population // optional: Elitism: copy best K from current pop to newPop while newPop.size()0; idx++) { rnd -= pop[idx].fitness } indiv1 = pop[idx-1] // select 2nd individual rnd = getRandomDouble([0,1]) * totalFitness for(idx=0; idx 0; idx++) { rnd -= pop[idx].fitness } indiv2 = pop[idx-1] /* 4. crossover */ indiv1, indiv2 = crossover(indiv1, indiv2) /* 5. mutation */ indiv1.mutate() indiv2.mutate() // add to new population newPop.add(indiv1) newPop.add(indiv2) } pop = newPop newPop = [] /* re-evaluate current population */ totalFitness = 0 for i=1 to POP_SIZE { fitness = pop[i].evaluate() totalFitness += fitness } } // return best genome bestIndividual = pop.bestIndiv() // max/min fitness indiv
请注意,目前您缺少适应度函数(取决于域).交叉将是一个简单的单点交叉(因为您使用的是二进制表示).突变可以是随机的一点点简单的翻转.
编辑:我已经在Java中实现了上面的伪代码考虑到你当前的代码结构和符号(请记住,我比ac/c ++更多的是java).请注意,这绝不是最有效或最完整的实现,我承认我写得很快:
Individual.java
import java.util.Random; public class Individual { public static final int SIZE = 500; private int[] genes = new int[SIZE]; private int fitnessValue; public Individual() {} public int getFitnessValue() { return fitnessValue; } public void setFitnessValue(int fitnessValue) { this.fitnessValue = fitnessValue; } public int getGene(int index) { return genes[index]; } public void setGene(int index, int gene) { this.genes[index] = gene; } public void randGenes() { Random rand = new Random(); for(int i=0; iPopulation.java
import java.util.Random; public class Population { final static int ELITISM_K = 5; final static int POP_SIZE = 200 + ELITISM_K; // population size final static int MAX_ITER = 2000; // max number of iterations final static double MUTATION_RATE = 0.05; // probability of mutation final static double CROSSOVER_RATE = 0.7; // probability of crossover private static Random m_rand = new Random(); // random-number generator private Individual[] m_population; private double totalFitness; public Population() { m_population = new Individual[POP_SIZE]; // init population for (int i = 0; i < POP_SIZE; i++) { m_population[i] = new Individual(); m_population[i].randGenes(); } // evaluate current population this.evaluate(); } public void setPopulation(Individual[] newPop) { // this.m_population = newPop; System.arraycopy(newPop, 0, this.m_population, 0, POP_SIZE); } public Individual[] getPopulation() { return this.m_population; } public double evaluate() { this.totalFitness = 0.0; for (int i = 0; i < POP_SIZE; i++) { this.totalFitness += m_population[i].evaluate(); } return this.totalFitness; } public Individual rouletteWheelSelection() { double randNum = m_rand.nextDouble() * this.totalFitness; int idx; for (idx=0; idx0; ++idx) { randNum -= m_population[idx].getFitnessValue(); } return m_population[idx-1]; } public Individual findBestIndividual() { int idxMax = 0, idxMin = 0; double currentMax = 0.0; double currentMin = 1.0; double currentVal; for (int idx=0; idx currentMax) { currentMax = currentVal; idxMax = idx; } if (currentVal < currentMin) { currentMin = currentVal; idxMin = idx; } } //return m_population[idxMin]; // minimization return m_population[idxMax]; // maximization } public static Individual[] crossover(Individual indiv1,Individual indiv2) { Individual[] newIndiv = new Individual[2]; newIndiv[0] = new Individual(); newIndiv[1] = new Individual(); int randPoint = m_rand.nextInt(Individual.SIZE); int i; for (i=0; i