У меня возникли проблемы с созданием генетического алгоритма в java. Я конкурирую в онлайн-конкурсе GA. Я пытаюсь сохранить лучший результат каждый раз обратно в индекс 0, но он просто становится ссылкой на исходный индекс. Значение, когда я развиваю остальные индексы, если он развивает исходный индекс лучших членов, я его теряю.Генетический алгоритм в Java-проблемах
Я пробовал обрезать его методом getClone, который преобразует данные объектов в массив int и создает из него новый объект.
Индивидуальный класс: класс
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]);
}
}
}
Население:
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
}
Как я могу убедиться, что лучший индивидуальный становится сохранен , а не как ссылка? Когда я печатаю ошибку, лучший результат, иногда она теряется и выбирается худший результат. Я не думаю, что это обязательно проблема клонирования объекта, я могу клонировать игровые объекты, которые имитируются просто отлично, перезагружая их каждый прогон.
Как я уже сказал, это конкурс, поэтому я не могу использовать какие-либо библиотеки на сайте, а также причина, по которой я не размещаю полный код, тонкости симулятора, который сам оценивает ходы, быть просто отданным. Но хватит, чтобы сказать, что баллы возвращаются, как и ожидалось, при движении на бумаге.
Ответ от IWS, я думал, что мой метод getClone выполняет глубокую копию.
Reference используется рядом виками и других знаний о генетических алгоритмах: http://www.theprojectspot.com/tutorial-post/creating-a-genetic-algorithm-for-beginners/3
Я установил его не resimming индивида с индексом 0. Однако это означает, что есть другая проблема с моим кодом, не связанным с вопросом.
Разве это не глубокая копия или проблема с мелкой копией? – NWS
, чтобы сохранить его, вы должны создать новый объект и сохранить во всех значениях атрибута. В некоторых случаях я предпочитаю хранить коллекцию этого нового объекта. – bilelovitch