2011-01-12 17 views
3

Hey Guys、 遺伝的アルゴリズムを実装するプログラムの全体的な効率を上げるためにアドバイスを受けることができるのだろうかと思っていました。はい、これは課題の質問ですが、私はすでに自分で課題を完了しており、それをよりうまく実行する方法を探しています。 Problem Description Javaと遺伝的アルゴリズムの効率を高める

私のプログラムは現在、構成要素、hまたはp(例hphpphhphpphphhpphph)各HおよびPに対して、ランダム移動(Up、Down、Left、Right)を生成し、「Chromosome」オブジェクトに含まれるarrayListに移動を追加します。これはクロスオーバーの集団からの染色体の選択を来た後、プログラムが10,000染色体

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); 
     } 

    } 

のための19点の移動を生成している開始時に。私のクロスオーバ機能は、人口の最も適格な20%から無作為に選ばれた最初の染色体と、上位20%の外側から無作為に選ばれた最初の染色体を選択します。選択された染色体が交差し、突然変異関数が呼び出される。私が最も大きなヒットを取っているのは、各染色体の適性を計算することだと私は信じています。現在、私のフィットネス機能は、グリッドとして動作する2次元配列を作成し、上に示した関数によって生成された移動リストから順番に移動し、配列をループしてフィットネス計算を行います。 (IEが見つけられ、場所[2,1]のHがコード[1,1] [3,1] [2,0]または[2,2] Hでもあり、Hが見つかった場合は結合が見つかった)

計算が完了したら、最も適合しない染色体が母集団から除去され、新しいものが追加され、染色体の配列リストがソートされます。すすぎ、目標の解が見つかるまで繰り返す

あなたが私のコードの多くを見たいと思ったら、私は実際に助けを求める前に仕事をしました。私は教えたくありません。パスタの私のもの)

コメントで示唆したように、私は自分のアプリケーションでプロファイラを走らせています(最初の1年間はCSの学生ではありませんでした)。プロファイラーが私に言っているように、大きなホットスポットは次のように見えます。

1)新しい染色体と集団内の他のものとを比較してその位置を決定するとき。私はComparableを実装することでこれをやっています。

public int compareTo(Chromosome other) { 
    if(this.fitness >= other.fitness) 
        return 1; 
     if(this.fitness ==other.fitness) 
        return 0; 
      else 
        return -1; 



} 
2)説明されている他の領域は、実際の進化機能であり、CPU時間の約40%を消費します。

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); 

3以下とする方法からcodesample)その他の主なpreformanceのヒットは、私は私がいるエリアを信じる

+1

私はそれをプロファイルし、ポストの結果は、フィットネス演算機能を修正し –

答えて

2

母集団を繰り返しソートするのではなく、ソート済みの内容を保持するコレクションを使用します。 (TreeSetなど)

+0

PriorityQueueのようなものは同様のソリューションですか? – Zjr8

+0

はい、類似していますが、TreeSetは最高と最悪を与え、順番に反復することができます。 PriorityQueueは片方だけを与えることができます。どちらもget(索引)をトリッキーにします。 –

+0

TreeSetを使用するときにget(index)するのに最適な方法は何ですか? iteratorとcounterを使っているのでしょうか? – Zjr8

5

の記事で最初のコードサンプルで行われinital人口播種あります最大のヒットを取ることは、各染色体の適性を計算することです

私はあなたがまだプログラムでプロファイラを実行していないと仮定します。
パフォーマンスを向上させたい場合は、まずプロファイリングが必要です。

+0

を返すことはありません – Zjr8

1

あなたの適応度が世代間で一貫している場合(つまり、人口の他のメンバーに依存していない)、少なくとも私はChromosomeオブジェクトにその値を格納しているので、人口のメンバーごとに1回だけ計算することを願っています。それで、各反復で新たに生成/組み立てられた染色体の適合度を計算するだけです。どのようにフィットネスが計算されるかについての詳細な情報がなければ、その領域で任意の最適化を提供することは困難です。

+0

移動が生成されているとき、または新しい染色体が作成されたときに交差する場合にのみ呼び出されます。フィットネス関数は、計算されたフィットネスをオブジェクトの内部に格納します。したがって、フィットネス機能は染色体ごとに1回しか呼び出されません – Zjr8

1

乱数ジェネレータシードは、暗号的に強力である必要はありません。

Random numberGen = new Random(); 
+0

System.nanoTime()でランダムにシードすると初期の母集団に十分なバリエーションが得られないことがわかりました。通常のランダムを使用してテストすると、人口播種機能の実行時間が大幅に短縮されます。先端のおかげです。 – Zjr8

+0

'++のseedUniquifier + System.nanoTime()'(OracleのJVM内)に '新しいRandom()'シード –

1

マイナースピードアップあなたの人口を播種すると、すべてのテストや分岐を削除することです:

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

    ... 

    moveList.add(moves[randomMove]); 
あなたのcompareTo機能がオーケー0
+0

ありがとう!全体的にこの提案とランダム世代の変更により、人口CPU時間は30%から約1.2%に減少しました – Zjr8

関連する問題