public void runGA()
    {
        filenameBase = "GA_" + populationSize + "_" + iterations + "_" + crossoverRate + "_" + mutationRate;
        
        //Init data files
        initCSV();
        initPlainFile();
        
        for (int cIteration = 0; cIteration < iterations; cIteration++)
        {
            int sumFitness = 0;
            
            //Stats to save
            int avgFitness = 0;
            int bestFitness = -10000;
            int worstFitness = 10000;
            int bestFitIndex = -1;
            
            //Calculate fitness values for the whole population
            for (int i = 0; i < populationSize; i++)
            {
                int newFitness = fitnessFunc.calculateFitness(population.get(i));
                fitnessValues[i] = newFitness;
                sumFitness += newFitness;
                
                if (newFitness > bestFitness) 
                {
                    bestFitness = newFitness;
                    bestFitIndex = i;
                }
                if (newFitness < worstFitness) 
                {
                    worstFitness = newFitness;
                }
                
                if (debug) System.out.println(population.get(i).toString() + ": " + fitnessValues[i]);
            }
            
            System.out.println("Generation: " + cIteration + ", Best fitness: " + bestFitness);
            
            avgFitness = (int)((double)sumFitness / (double)populationSize);
            
            //Dump stats to file
            saveToCSV(cIteration, worstFitness, avgFitness, bestFitness);
            saveToPlainFile(cIteration, worstFitness, avgFitness, bestFitness);
            
            //Dump param data diffs
            fitnessFunc.saveParamDiffsData(cIteration, population.get(bestFitIndex));
            
            //Generate new population for next iteration
            genNewPopulation(sumFitness);
        }
    }