2016-12-27 9 views
2

Javaで遺伝的アルゴリズムを作成する際に問題があります。私はオンラインのGAコンテストで競合しています。私はインデックス0に毎回最良の結果を保存しようとしていますが、元のインデックスへの参照になります。私が残りのインデックスを進化させるとき、それが最良のメンバーの元のインデックスを進化させるなら、私はそれを失うことを意味します。Javaでの遺伝的アルゴリズムの問​​題

私は、オブジェクトデータをint配列に変換し、そこから新しいオブジェクトを作成するgetCloneメソッドでシミングを試みました。

個々のクラス:

class Individual { 
    public int[] angle; 
    public int[] thrust; 
    public double fitness; 
    public Individual(){ 
     angle = new int[2]; 
     thrust = new int[2]; 
     for (int i = 0; i < 2; i++) {  
      this.angle[i] = ThreadLocalRandom.current().nextInt(0, 37) - 18; 
      this.thrust[i] = ThreadLocalRandom.current().nextInt(0, 202); 
      this.thrust[i] = ((this.thrust[i] == 201) ? 650 : this.thrust[i]); 
     } 
     this.fitness = Double.MIN_VALUE; 
    } 

    public Individual(int[][] genes, double f){ 
     this.fitness = f; 
     angle = new int[2]; 
     thrust = new int[2]; 
     this.angle[0] = genes[0][0]; 
     this.angle[1] = genes[0][1]; 
     this.thrust[0] = genes[1][0]; 
     this.thrust[1] = genes[1][1];  
    } 

    public Individual getClone() { 
     int[][] genes = new int[2][2]; 
     genes[0][0] = (int)this.angle[0]; 
     genes[0][1] = (int)this.angle[1]; 
     genes[1][0] = (int)this.thrust[0]; 
     genes[1][1] = (int)this.thrust[1]; 
     return (new Individual(genes, this.fitness)); 
    } 

    public Individual crossover(Individual other) { 
     int[][] genes = new int[2][2]; 
     genes[0][0] = (int)((this.angle[0] + other.angle[0])/2); 
     genes[0][1] = (int)((this.angle[1] + other.angle[1])/2); 
     genes[1][0] = ((this.thrust[0] == 650 || other.thrust[0] == 650) ? 650: (int)((this.thrust[0] + other.thrust[0])/2)); 
     genes[1][1] = ((this.thrust[1] == 650 || other.thrust[1] == 650) ? 650: (int)((this.thrust[1] + other.thrust[1])/2)); 
     return (new Individual(genes, Double.MIN_VALUE)); 
    } 

    public void mutate() { 
     for (int i = 0; i < 2; i++) { 
      if(ThreadLocalRandom.current().nextInt(0, 2)==1) { 
       this.angle[i] = ThreadLocalRandom.current().nextInt(0, 37) - 18; 
      } 
      if(ThreadLocalRandom.current().nextInt(0, 2)==1) { 
       this.thrust[i] = ThreadLocalRandom.current().nextInt(0, 202); 
       this.thrust[i] = ((this.thrust[i] == 201) ? 650 : this.thrust[i]); 
      } 
     } 
    } 

人口クラス:SIMクラスから

class Population { 
    public Individual[] individuals; 

    public Population(int populationSize) { 
     individuals = new Individual[populationSize]; 
     for (int i = 0; i < populationSize; i ++) { 
      individuals[i] = new Individual(); 
     } 
    } 

    public void resetFitness() { 
     for (int i = 0; i < individuals.length; i++) { 
      individuals[i].fitness = Double.MIN_VALUE; 
     } 
    } 
    public void setIndividual(int i, Individual indiv) { 
     individuals[i] = indiv.getClone(); 
    } 

    public Individual getIndividual(int i) { 
     return individuals[i].getClone(); 
    } 

    public int size() { 
     return this.individuals.length;  
    } 
    public Individual getFittest() { 
     int fittest = 0; 
     // Loop through individuals to find fittest 
     for (int i = 0; i < individuals.length; i++) { 
      if (individuals[i].fitness > individuals[fittest].fitness) { 
       fittest = i; 
      } 
     } 
     return individuals[fittest].getClone(); 
    } 
} 

必需:

class simGA { 
    private Population pop; 
    private final static int TSIZE = 5; //tournement size 

    public simGA (int poolsize) { 
     this.pop = new Population(poolsize); 
    } 

    public Individual search(int generations, int totalMoves) { 
     //this.pop.resetFitness(); 
     for (int g = 0; g < generations; g++) { 
      for (int i = 0; i < this.pop.individuals.length; i++) { 
       this.pop.individuals[i].fitness = sim(this.pop.individuals[i],totalMoves); 
      } 
      System.err.print("Generation " + g + " "); 
      this.pop = evolvePopulation(this.pop); 
     } 
     return pop.getFittest(); 
    } 

    private Population evolvePopulation(Population p) { 
     //save fittest 
     Population tempPop = new Population(p.individuals.length); 
     tempPop.setIndividual(0, p.getFittest().getClone()); 
     System.err.print("Best move: " + tempPop.individuals[0].fitness); 
     System.err.println(); 
     for (int i = 1; i < p.individuals.length; i++) { 
      Individual indiv1 = tournamentSelection(p); 
      Individual indiv2 = tournamentSelection(p); 
      Individual newIndiv = indiv1.crossover(indiv2); 
      newIndiv.mutate(); 
      tempPop.setIndividual(i, newIndiv.getClone()); 
     } 
     return tempPop; 
    } 

    // Select individuals for crossover 
    private Individual tournamentSelection(Population pop) { 
     // Create a tournament population 
     Population tournament = new Population(TSIZE); 
     // For each place in the tournament get a random individual 
     for (int i = 0; i < TSIZE; i++) { 
      int randomId = ThreadLocalRandom.current().nextInt(1, this.pop.individuals.length); 
      tournament.setIndividual(i, pop.getIndividual(randomId).getClone()); 
     } 
     // Get the fittest 
     return tournament.getFittest().getClone(); 
    } 

    private double sim(Individual s, int moves) { 
     return score; //score of simmed moves 
    } 

どのように私は最高の個人が救われることを確認することができます、参照としてではない?最高のスコアを印刷するときにエラーが発生すると、スコアが失われ、悪いスコアリングが選択されることがあります。私はそれが必ずしもオブジェクトのクローンニングの問題ではないと思う、私はちょうどうまくシミュレートされているゲームオブジェクトを複製し、それぞれの実行をリセットすることができます。

私が言ったように、これはコンテスト用なので、サイト上でライブラリを使用することはできません。また、完全なコードを投稿していない理由は、シミュレータの複雑さです。ちょうど離れて与えられる。しかし、紙の上で動いたときの動きのために期待通りのスコアが戻ってくると言えば十分です。

NWSへの応答として、私はgetCloneメソッドがディープコピーを実行していると思いました。

遺伝的アルゴリズム上のwikiやその他の知識の横に使用リファレンス:http://www.theprojectspot.com/tutorial-post/creating-a-genetic-algorithm-for-beginners/3

私はインデックス0で個人をresimmingないことによってそれを固定しているが、これは問題に関連していない私のコードと他の問題があることを意味します。

+0

これはディープコピーとシャローコピーの問題ではありませんか? – NWS

+0

を保存するには、新しいオブジェクトを作成し、すべての属性値に格納する必要があります。いくつかのカスでは、私はこの新しいオブジェクトのコレクションを格納することを好む。 – bilelovitch

答えて

1
Individual newIndiv = indiv1.crossover(indiv2); 

上記の行は、フィットネスをDouble.MIN_VALUEにリセットしています。したがって、evolvePopulationが呼び出されるたびに、インデックス0の個人のみが適切です。

+0

それは正しいですが、私はそれを保持したいときにインデックス0で個人を失い続けます。 –

+0

この行はすべてのインデックスをリセットします: 'this.pop.individuals [i] .fitness = sim(this.pop.individuals [i]、totalMoves);' – Azodious

1

私はインデックス0で個人をリミットしないことで修正しました。しかし、これは、以前と同じ時点から同じ個人をリミットすると、それが変更されるべきではないため、フィットネス。

関連する問題