The lifeCycle-method in my MatrixCreatureContainer-class throws a stack overflow error after about 3-4k iterations. Why is that? I assume it has something to do with memory allocation, but I cannot figure out how to solve it. I tried reading about the java garbage collector, but nothing I did seemed to help.
public class MatrixCreatureContainer {
private final static int NUMBER_OF_CREATURES = 20;
private static Random rand;
public static void main(String[] args){
rand = new Random();
List<MatrixCreature> population = new ArrayList<MatrixCreature>();
for(int i = 0; i < NUMBER_OF_CREATURES ; i++){
population.add(new MatrixCreature());
}
Collections.sort(population);
lifeCycle(population,0, 4000);
}
private static void lifeCycle(List<MatrixCreature> population, int generation, int iterations){
if (generation == iterations) return;
List<MatrixCreature> newPopulation = new ArrayList<MatrixCreature>();
while(population.size() != 0){
MatrixCreature mother = population.remove(rand.nextInt(population.size()));
MatrixCreature father = population.remove(rand.nextInt(population.size()));
newPopulation.add(new MatrixCreature(mother,father));
newPopulation.add(new MatrixCreature(mother,father));
newPopulation.add(new MatrixCreature(mother,father));
}
Collections.sort(newPopulation);
newPopulation = newPopulation.subList(0,NUMBER_OF_CREATURES);
lifeCycle(newPopulation,generation + 1, iterations);
}
}
The MatrixCreature-class basically only holds an integer array (int[]) of 20 integers. The constructor takes in two other matrixCreatures, and combines the arrays of two the matrixCreatures given, with a small chance of mutation. Each matrixCreature gets a score (where 0 is the best) of how close the sum of the numbers in the array is to 55. It's that score the population of each generation in the MatrixCreatureContainer is sorted by, such that the 20 "best" of each generation survives.
I can post the code to the MatrixCreature-class if it's relevant.
Thanks in advance :)
-Boye
With this call:
lifeCycle(population,0, 4000);
you're basically asking for a stack with 4000 frames (at least - see later). That isn't totally beyond reason, but in fact there's no reason to make this recursive at all. You can easily just change the method to be iterative - and even remove the generation
parameter:
private static void lifeCycle(List<MatrixCreature> population, int iterations) {
for (int generation = 0; generation < iterations; generation++) {
// Body of previous method here
}
}
Additionally, you keep creating views using newPopulation = newPopulation.subList(...)
. You probably don't want to do that - it means that every operation will need to go through a huge number of stack frames, as each call to a view will delegate to its underlying list... and if that's another view, it needs to keep going, etc. Icky. If those view calls actually require a couple of stack frames per "layer" you could easily end up with a stack of around 12K calls in your original code...
I would suggest creating a copy of the relevant portion of the list on each iteration instead - and then returning the final list.
See more on this question at Stackoverflow