GA是用Java编写的

GA是用Java编写的,java,genetic-algorithm,evolutionary-algorithm,roulette-wheel-selection,Java,Genetic Algorithm,Evolutionary Algorithm,Roulette Wheel Selection,我正试图根据我从《游戏程序员的人工智能技术》一书中学到的技术编写一种遗传算法,该算法使用二进制编码和适应度比例选择(也称为轮盘赌轮选择),对在程序中以二维数组随机生成的群体基因进行选择 我最近遇到并尝试实施它,但在我需要做的具体工作中遇到了一些问题。我查阅了很多书和一些开源代码,但仍在努力取得进展。 我知道我必须得到总体适应度的总和,在总和和零之间选择一个随机数,然后如果这个数大于父母覆盖它,但我正在努力实现这些想法 由于我的Java已经过时,如果您能帮助我实现这些想法,我们将不胜感激。您正在寻

我正试图根据我从《游戏程序员的人工智能技术》一书中学到的技术编写一种遗传算法,该算法使用二进制编码和适应度比例选择(也称为轮盘赌轮选择),对在程序中以二维数组随机生成的群体基因进行选择

我最近遇到并尝试实施它,但在我需要做的具体工作中遇到了一些问题。我查阅了很多书和一些开源代码,但仍在努力取得进展。 我知道我必须得到总体适应度的总和,在总和和零之间选择一个随机数,然后如果这个数大于父母覆盖它,但我正在努力实现这些想法


由于我的Java已经过时,如果您能帮助我实现这些想法,我们将不胜感激。

您正在寻找的概念被称为“轮盘赌轮选择”。您还没有一个确定的适应度函数(您可能暗示每个个体的适应度是其染色体的积分值),但当你做一个总体计划时:

  • 将整个人群的适应度相加
  • 获取一个介于0和总适应度之间的随机数(称为x)
  • 在人群中迭代。对于每个成员:
  • 从x中减去成员的适合度
  • 如果x现在小于或等于零,请选择当前成员
  • 还有其他等效的实现,但一般的想法是选择与适合度成比例的成员

    编辑:
    关于适应度函数的几点注记。染色体的表示(在您的例子中是32位整数)与用于计算它的适应度函数无关。例如,二进制编码通常将染色体视为一组压缩成适当大小的整数值的位字段。然后可以通过适当的位掩蔽操作来完成交叉和变异。如果您感兴趣,我可以发布一些简单的GA代码(在C和Python中),它使用按位操作来实现这些函数。我不确定您对这些语言是否满意。

    我通过创建“累积适应度数组”和二进制搜索来实现此算法,从而减少了在选择过程中迭代数组中每个元素的需要:

  • 对于种群大小N,创建累积适应度数组:arr[N]
  • 设置arr[0]:=computeFitness(单个[0])
  • 然后,对于每个后续元素:X,arr[X]=arr[X-1]+计算性(单个[X])
  • 生成一个介于0和arr[N]之间的随机数(即总适应度)
  • 使用二进制搜索(例如Collections.binarySearch)在累积适应度数组中找到适当的索引,并使用此索引选择个人
  • 请注意,您只需要在复制阶段开始时创建适应度数组,然后可以多次重复使用该数组,以便在O(logn)时间内执行选择


    另外,请注意,锦标赛选择更容易实现

    关于轮盘赌轮盘选择的其他问题应该有帮助:


    在第一个例子中,轮盘赌是如何工作的。在第二种情况下。与之结合,这些应该足以让某些东西工作。

    以下是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()<POP_SIZE
        {
            /* 3. roulette wheel selection */
            // select 1st individual
            rnd = getRandomDouble([0,1]) * totalFitness
            for(idx=0; idx<POP_SIZE && rnd>0; idx++) {
                rnd -= pop[idx].fitness
            }
            indiv1 = pop[idx-1]
            // select 2nd individual
            rnd = getRandomDouble([0,1]) * totalFitness
            for(idx=0; idx<POP_SIZE && rnd>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
    
    /*1。初始总体*/
    POP_SIZE=群体中的个体数量
    pop=newPop=[]
    对于i=1的弹出式尺寸{
    添加(getRandomIndividual())
    }
    /* 2. 评估当前人口*/
    totalFitness=0
    对于i=1的弹出式尺寸{
    fitness=pop[i].evaluate()
    总适应度+=适应度
    }
    而不是结束条件(最佳适应度,#迭代,无改善…)
    {
    //建立新的人口
    //可选:精英主义:将最佳K从当前流行音乐复制到新流行音乐
    
    而newPop.size()只是值得一提的一点。轮盘赌轮选择(如伪代码所示)对最小化问题不起作用-但是,它对最大化问题有效


    由于选择最合适的个体的方式,最小化的情况将不成立。详细信息见:

    为什么不使用像JGAP这样的开源框架:

    我用java做了一个可扩展的实现,在这个实现中,操作符和个体结构由协同工作的接口很好地定义。Github repo

    它为每个操作员提供了一个标准实施方案,以及一个具有特定个人/群体结构和健身仪的示例问题实施方案。示例问题实施方案是在20支球队中找到一支有球员的优秀足球队,并且有预算限制

    要使其适应当前的问题,您需要提供以下接口的实现:

    juanmf.ga.structure.Gen;
    juanmf.ga.structure.Individual;
    juanmf.ga.structure.IndividualFactory; 
    juanmf.ga.structure.Population;  // Has a basic implementation already
    juanmf.ga.structure.PopulationFactory;
    
    pkg juanmf.grandt
    中,您有一个示例问题实现类,以及如何发布它们,如下面的代码片段所示

    要发布您的实现,您只需从SpringBeans返回适当的类:

    /**
     * Make sure @ComponentScan("pkg") in juanmf.ga.App.java includes this class' pkg 
     * so that these beans get registered.
     */
    @Configuration
    public class Config {
    
        @Bean(name="individualFactory")
        public IndividualFactory getIndividualFactory() {
            return new Team.TeamFactory();
        }
    
        @Bean(name="populationFactory")
        public PopulationFactory getPopulationFactory() {
            return new Team.TeamPopulationFactory();
        }
    
        @Bean(name="fitnessMeter")
        public FitnessMeter getFitnessMeter() {
            return new TeamAptitudeMeter();
        }
    } 
    
    Crosser运算符有两种相同技术的实现,一种是顺序实现,另一种是并发实现,其性能远远优于顺序实现

    可以指定停止条件。如果未给出任何条件,则默认停止条件在100代之后停止,没有任何改进(这里您必须小心使用Elite,不要失去每代中最好的部分,以便有效触发此停止条件)

    所以如果有人愿意尝试一下,我很乐意帮忙。
    欢迎任何人提供建议,以及更好的操作员实现:D或任何改进的pull请求。

    确切地说,您需要帮助吗?尝试用伪代码编写int,我们会的
    juanmf.ga.structure.Gen;
    juanmf.ga.structure.Individual;
    juanmf.ga.structure.IndividualFactory; 
    juanmf.ga.structure.Population;  // Has a basic implementation already
    juanmf.ga.structure.PopulationFactory;
    
    /**
     * Make sure @ComponentScan("pkg") in juanmf.ga.App.java includes this class' pkg 
     * so that these beans get registered.
     */
    @Configuration
    public class Config {
    
        @Bean(name="individualFactory")
        public IndividualFactory getIndividualFactory() {
            return new Team.TeamFactory();
        }
    
        @Bean(name="populationFactory")
        public PopulationFactory getPopulationFactory() {
            return new Team.TeamPopulationFactory();
        }
    
        @Bean(name="fitnessMeter")
        public FitnessMeter getFitnessMeter() {
            return new TeamAptitudeMeter();
        }
    }