Java和提高遗传算法效率

4
我想知道如何提高实现遗传算法的程序的整体效率,希望得到一些建议。是的,这是一个作业问题,但我已经独立完成了任务,只是想找到一种使其性能更好的方法。 问题描述 目前我的程序读取给定链,由“h”或“p”构成。(例如:hphpphhphpphphhpphph)对于每个H和P,它生成一个随机移动(上、下、左、右),并将该移动添加到包含在“染色体”对象中的ArrayList中。初始时,程序为10,000个染色体生成19个移动。
   SecureRandom sec = new SecureRandom();
    byte[] sbuf = sec.generateSeed(8);
    ByteBuffer bb = ByteBuffer.wrap(sbuf);
    Random numberGen = new Random(bb.getLong());
    int numberMoves = chromosoneData.length();
    moveList = new ArrayList(numberMoves);
    for (int a = 0; a < numberMoves; a++) {
        int randomMove = numberGen.nextInt(4);
        char typeChro = chromosoneData.charAt(a);
        if (randomMove == 0) {
            moveList.add(Move.Down);
        } else if (randomMove == 1) {
            moveList.add(Move.Up);
        } else if (randomMove == 2) {
            moveList.add(Move.Left);
        } else if (randomMove == 3) {
            moveList.add(Move.Right);
        }

    }

在此之后,需要从种群中选择染色体进行交叉。我的交叉函数从最适应的20%种群中随机选择第一个染色体,并从前20%以外的其它位置随机选择第二个染色体。然后对所选染色体进行交叉,并调用突变函数。我认为我最大的问题在于计算每个染色体的适应度。目前,我的适应度函数创建一个2D数组作为网格,按照上面显示的函数生成的移动列表的顺序放置移动,然后循环遍历数组进行适应度计算。(即,在位置[2,1]找到H,则Cord [1,1] [3,1] [2,0]或[2,2]也是H,如果找到H,则只增加发现的键数)。
计算完成后,将删除适应度最低的染色体并添加新染色体,然后对染色体数组列表进行排序。反复执行,直到找到目标解决方案。
如果您想看更多我的代码以证明我实际上已经完成了工作,请告诉我(不想发布太多,以免其他学生只是复制粘贴我的东西)。

根据评论建议,我在我的应用程序上运行了分析器(以前从未使用过,只是一年级计算机科学学生),我最初猜测的问题所在似乎有些不正确。从分析器告诉我的信息来看,主要的瓶颈在于:

  1. 将新染色体与种群中的其他染色体进行比较以确定其位置。我通过实现Comparable接口来完成这个操作:
    public int compareTo(Chromosome other) {
        if(this.fitness >= other.fitness)
                        return 1;
             if(this.fitness ==other.fitness )
                       return 0;
                else
                        return -1;
    }
  1. The other area of issue described is in my actual evolution function, consuming about 40% of the CPU time. A codesample from said method below

     double topPercentile = highestValue;
     topPercentile = topPercentile * .20;
     topPercentile = Math.ceil(topPercentile);
     randomOne = numberGen.nextInt((int) topPercentile);
     //Lower Bount for random two so it comes from outside of top 20%
     int randomTwo = numberGen.nextInt(highestValue - (int) topPercentile);
     randomTwo = randomTwo + 25;
     //System.out.println("Selecting First: " + randomOne + " Selecting Second: " + randomTwo);
     Chromosome firstChrom = (Chromosome) populationList.get(randomOne);
     Chromosome secondChrom = (Chromosome) populationList.get(randomTwo);
     //System.out.println("Selected 2 Chromosones Crossing Over");
     Chromosome resultantChromosome = firstChrom.crossOver(secondChrom);
     populationList.add(resultantChromosome);
     Collections.sort(populationList);
     populationList.remove(highestValue);
     Chromosome bestResult = (Chromosome) populationList.get(0);
    
  2. The other main preformance hit is the inital population seeding which is performed by the first code sample in the post


1
您的compareTo函数从不返回0。 - Stephen Denne
5个回答

5

我相信我受到的最大打击是计算每个染色体的适应度。

如果您不确定,那么我认为您还没有对程序进行分析。
如果您想提高性能,分析是您应该做的第一件事情。


2

不要重复地对人口进行排序,使用一个维护其内容已经排序的集合。(例如:TreeSet)


像优先队列这样的数据结构是否是类似的解决方案? - Zjr8
是的,相似,但 TreeSet 可以给你最好和最坏的,并按顺序迭代。PriorityQueue 只能给出一个端点。它们两个都使得 get(index) 操作棘手。 - Stephen Denne
在使用TreeSet时,获取(index)的最佳替代方法是什么?是使用迭代器和计数器这种方式吗? - Zjr8
你可以将人口存储在多个集合中,也可以将其存储在多个数组中,因为任务的适应度变化很小,所以你几乎可以为每个适应度值创建一个数组。 - Stephen Denne

1

您的随机数生成器种子不需要具备密码学强度。

Random numberGen = new Random();

我发现使用 System.nanoTime() 作为随机数种子并不能提供足够的初始种群变化,使用 new Random() 是否能生成足够随机的结果呢?测试使用普通随机数,可以大幅减少种群初始化函数的运行时间。感谢这个提示。 - Zjr8
在Oracle的JVM中,new Random() 的种子是 ++seedUniquifier + System.nanoTime() - Stephen Denne

1

在种群初始化时,一个小的加速技巧是去除所有测试和分支:

    static Move[] moves = {Move.Down, Move.Up, Move.Left, Move.Right};

    ...

    moveList.add(moves[randomMove]);

谢谢!总的来说,随着这个建议和随机生成的改变,人口 CPU 时间从 30% 减少到约 1.2%。 - Zjr8

1
如果您的适应度度量在各代之间保持一致(即不依赖于种群中的其他成员),那么我希望您至少将其存储在染色体对象中,这样您只需为种群中的每个成员计算一次。有了这个设置,您只需要在每次迭代中计算新生成/组装的染色体的适应度。如果没有更多关于如何计算适应度的信息,很难在该领域提供任何优化建议。

修正健身计算函数仅在生成移动或交叉时创建新染色体时调用。健身功能将计算出的健身结果存储在对象内部。因此,健身功能每染色体仅调用一次。 - Zjr8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接