Java与提高遗传算法的效率

Java与提高遗传算法的效率,java,performance,genetic-algorithm,Java,Performance,Genetic Algorithm,我想知道我是否能得到一些关于提高实现遗传算法的程序的整体效率的建议。是的,这是一个作业问题,但我已经自己完成了作业,我只是在寻找一种方法让它表现得更好 我的程序现在读取一个给定的由h或p组成的链。(例如:hpphph)对于每个H和P,它生成一个随机移动(上、下、左、右),并将移动添加到“染色体”对象中包含的arrayList中。开始时,该程序为10000条染色体生成19个移动 SecureRandom sec = new SecureRandom(); byte[] sbuf =

我想知道我是否能得到一些关于提高实现遗传算法的程序的整体效率的建议。是的,这是一个作业问题,但我已经自己完成了作业,我只是在寻找一种方法让它表现得更好

我的程序现在读取一个给定的由h或p组成的链。(例如:hpphph)对于每个H和P,它生成一个随机移动(上、下、左、右),并将移动添加到“染色体”对象中包含的arrayList中。开始时,该程序为10000条染色体生成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);
        }

    }
  • 另一个问题是我的实际进化函数,它消耗了大约40%的CPU时间。下面所述方法的代码样本

     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);
    
  • 另一个主要的性能命中是初始总体播种,它由post中的第一个代码样本执行

  • 我相信我受到最大打击的领域是计算每个染色体的适合度

    如果您不确定,那么我假定您尚未在程序上运行探查器。

    如果您想提高性能,分析是您应该做的第一件事。

    如果您的适应度度量跨代一致(即不依赖于群体中的其他成员),那么我希望您至少将其存储在染色体对象中,以便只为群体中的每个成员计算一次。有了它,你只需要在每次迭代中计算新生成/组装的染色体的适合度。如果没有关于如何计算适合度的更多信息,则很难在该领域提供任何优化。

    与其重复对人口进行排序,不如使用一个保持其内容已排序的集合。(例如TreeSet)

    您的随机数生成器种子不需要加密性很强

    Random numberGen = new Random();
    

    播种种群时的一个小加速是删除所有测试和分支:

        static Move[] moves = {Move.Down, Move.Up, Move.Left, Move.Right};
    
        ...
    
        moveList.add(moves[randomMove]);
    

    更正只有在生成移动时,或在创建新染色体时发生交叉时,才会调用适应度计算函数。适应度函数将计算出的适应度存储在对象内部。因此,每个染色体只调用一次fitness函数您的compareTo函数从不返回0我发现,使用System.nanoTime()播种随机数并没有在初始总体中提供足够的变化,仅使用new random()会生成足够随机的结果。测试只使用一个正常的随机变量,它大大减少了人口播种函数的运行时间。感谢您在
    ++seedUniquifier+System.nanoTime()
    (在Oracle的JVM中)上提供的提示
    new Random()
    种子,谢谢!总的来说,有了这个建议和随机生成的变化,总体CPU时间从30%减少到了1.2%左右。PriorityQueue是类似的解决方案吗?是的,类似,但TreeSet可以提供最好和最坏的结果,并按顺序迭代。优先级队列只能给出一端。这两种方法都使获取(索引)变得棘手。使用树集时,获取(索引)的最佳替代方法是什么?它会使用迭代器和计数器之类的处理吗?或者是,或者将填充存储在多个集合中。赋值的适应度变化似乎很小,因此每个适应度值可以有一个数组。
        static Move[] moves = {Move.Down, Move.Up, Move.Left, Move.Right};
    
        ...
    
        moveList.add(moves[randomMove]);