使用遗传算法找到与其他人不重叠的最大圆圈

时间:2014-11-29 15:43:38

标签: genetic-algorithm

我正在使用GA,所以我从这个页面(http://www.ai-junkie.com/ga/intro/gat3.html)中取了示例,并尝试自己做。 问题是,它不起作用。例如,最大适应度并不总是在下一代增长,而是变得最小。此外,经过几代人的努力,它才会越来越好。例如,在前100代中,它找到了半径为104的最大圆。在接下来的900最大半径为107.在绘制之后,我发现它可以长得更多。

这是我与GA相关的代码。我遗漏了生成随机圆圈,解码和绘图。

private Genome ChooseParent(Genome[] population, Random r)
    {
        double sumFitness = 0;
        double maxFitness = 0;
        for (int i = 0; i < population.Length; i++)
        {
            sumFitness += population[i].fitness;
            if (i == 0 || maxFitness < population[i].fitness)
            {
                maxFitness = population[i].fitness;
            }
        }
        sumFitness = population.Length * maxFitness - sumFitness; 

        double randNum = r.NextDouble() *sumFitness;
        double acumulatedSum = 0;
        for(int i=0;i<population.Length;i++)
        {
            acumulatedSum += population[i].fitness;
            if(randNum<acumulatedSum)
            {
                return population[i];
            }
        }
        return population[0];
    }


   private void Crossover(Genome parent1, Genome parent2, Genome child1, Genome child2, Random r)
    {
        double d=r.NextDouble();
        if(d>this.crossoverRate || child1.Equals(child2))
        {
             for (int i = 0; i < parent1.bitNum; i++)
             {
                 child1.bit[i] = parent1.bit[i];
                 child2.bit[i] = parent2.bit[i];
             }
        }
        else
        {
            int cp = r.Next(parent1.bitNum - 1);
            for (int i = 0; i < cp; i++)
            {
                child1.bit[i] = parent1.bit[i];
                child2.bit[i] = parent2.bit[i];
            }
            for (int i = cp; i < parent1.bitNum; i++)
            {
                child1.bit[i] = parent2.bit[i];
                child2.bit[i] = parent1.bit[i];
            }
        }
    }

  private void Mutation(Genome child, Random r)
    {
        for(int i=0;i<child.bitNum;i++)
        {
            if(r.NextDouble()<=this.mutationRate)
            {
                child.bit[i] = (byte)(1 - child.bit[i]);
            }
        }
    }


 public void Run()
    {

       for(int generation=0;generation<1000;generation++)
        {
            CalculateFitness(population);
            System.Diagnostics.Debug.WriteLine(maxFitness);
            population = population.OrderByDescending(x => x).ToArray();

            //ELITIZM
            Copy(population[0], newpopulation[0]);
            Copy(population[1], newpopulation[1]);


            for(int i=1;i<this.populationSize/2;i++)
            {
                Genome parent1 = ChooseParent(population, r);
                Genome parent2 = ChooseParent(population, r);
                Genome child1 = newpopulation[2 * i];
                Genome child2 = newpopulation[2 * i + 1];
                Crossover(parent1, parent2, child1, child2, r);
                Mutation(child1, r);
                Mutation(child2, r);
            }

            Genome[] tmp = population;
            population = newpopulation;
            newpopulation = tmp;

            DekodePopulation(population); //decoding and fitness calculation for each member of population
        }
    }

如果有人可以指出导致此类行为的潜在问题以及修复方法,我将不胜感激。

2 个答案:

答案 0 :(得分:0)

欢迎来到遗传算法的世界!

我会解决您的问题并提出潜在问题。我们走了:

  1. 最大适应度并不总是在下一代增长,但变得最小 - 你可能意味着更小。这很奇怪,因为你使用精英主义,因此每一代人的最佳个体应该至少与前一个一样好。我建议你检查代码是否存在错误,因为这确实不应该发生。但是,健身不需要始终成长。在GA中实现这一点是不可能的 - 它是随机算法,随机性 - 假设偶然发生一代中没有突变或交叉 - 那么由于没有变化,适应性无法改善到下一代
  2. 经过几代人的努力,它才会越来越好。例如,在前100代中,它找到了半径为104的最大圆。在接下来的900最大半径为107.在绘制之后,我看到它可以增长得更多。 - 这可能是(可能)一种称为早熟收敛的现象的迹象,不幸的是,它是正常的&#34;遗传算法中的东西。早期收敛是当整个群体收敛到单个解决方案或一组彼此接近并且是次优的解决方案(即,它不是最好的解决方案)时的情况。当发生这种情况时,GA很难逃避这种局部最优。您可以尝试调整参数,尤其是变异概率,以强制进行更多探索。
  3. 此外,另一个可能导致问题的非常重要的事情是编码,即位串如何映射到圆圈。如果编码过于间接,则可能导致GA的性能不佳。当基因型中存在可以在群体之间交换的构建块时,GAs起作用。如果没有这样的区块,GA的表现通常会很差。

答案 1 :(得分:0)

我已经执行了此练习,并取得了良好的效果。链接在这里: https://github.com/ManhTruongDang/ai-junkie

希望这对您有用。