Example #1
0
  public static void main(String[] args) throws Exception {
    // Start with a DefaultConfiguration, which comes setup with the
    // most common settings.
    // -------------------------------------------------------------
    Configuration conf = new DefaultConfiguration();

    // Set the fitness function we want to use, which is our
    // MinimizingMakeChangeFitnessFunction that we created earlier.
    // We construct it with the target amount of change provided
    // by the user.
    // ------------------------------------------------------------
    int targetAmount = 88;
    FitnessFunction myFunc = new MinimizingMakeChangeFitnessFunction(targetAmount);

    conf.setFitnessFunction(myFunc);

    // Now we need to tell the Configuration object how we want our
    // Chromosomes to be setup. We do that by actually creating a
    // sample Chromosome and then setting it on the Configuration
    // object. As mentioned earlier, we want our Chromosomes to
    // each have four genes, one for each of the coin types. We
    // want the values of those genes to be integers, which represent
    // how many coins of that type we have. We therefore use the
    // IntegerGene class to represent each of the genes. That class
    // also lets us specify a lower and upper bound, which we set
    // to sensible values for each coin type.
    // --------------------------------------------------------------
    Gene[] sampleGenes = new Gene[4];

    sampleGenes[0] = new IntegerGene(conf, 0, 3); // Quarters
    sampleGenes[1] = new IntegerGene(conf, 0, 2); // Dimes
    sampleGenes[2] = new IntegerGene(conf, 0, 1); // Nickels
    sampleGenes[3] = new IntegerGene(conf, 0, 4); // Pennies

    Chromosome sampleChromosome = new Chromosome(conf, sampleGenes);

    conf.setSampleChromosome(sampleChromosome);

    // Finally, we need to tell the Configuration object how many
    // Chromosomes we want in our population. The more Chromosomes,
    // the larger the number of potential solutions (which is good
    // for finding the answer), but the longer it will take to evolve
    // the population each round. We'll set the population size to
    // 500 here.
    // --------------------------------------------------------------
    conf.setPopulationSize(10);

    Genotype population = Genotype.randomInitialGenotype(conf);
    for (int i = 0; i < MAX_ALLOWED_EVOLUTIONS; i++) {
      population.evolve();
      IChromosome partialSolution = population.getFittestChromosome();
      System.out.println("SoluciĆ³n en iteracion nro " + i + " : ");
      printStatus(partialSolution);
    }
    IChromosome bestSolutionSoFar = population.getFittestChromosome();

    System.out.println("SoluciĆ³n final: ");
    printStatus(bestSolutionSoFar);
  }
 /**
  * Cares that population size is kept constant and does not exceed the desired size.
  *
  * @param a_pop Population
  * @param a_conf Configuration
  */
 protected void keepPopSizeConstant(Population a_pop, Configuration a_conf) {
   if (a_conf.isKeepPopulationSizeConstant()) {
     try {
       a_pop.keepPopSizeConstant();
     } catch (InvalidConfigurationException iex) {
       throw new RuntimeException(iex);
     }
   }
 }
 protected void updateChromosomes(Population a_pop, Configuration a_conf) {
   int currentPopSize = a_pop.size();
   // Ensure all chromosomes are updated.
   // -----------------------------------
   BulkFitnessFunction bulkFunction = a_conf.getBulkFitnessFunction();
   boolean bulkFitFunc = (bulkFunction != null);
   if (!bulkFitFunc) {
     for (int i = 0; i < currentPopSize; i++) {
       IChromosome chrom = a_pop.getChromosome(i);
       chrom.getFitnessValue();
     }
   }
 }
  /**
   * @param config
   * @param chromNode
   * @return chromosome constructed from xml
   */
  public static Chromosome chromosomeFromXml(Configuration config, Node chromNode) {
    // TODO - refactor such that Configuration is not necessary parameter, and simplify
    // exceptions

    if (XmlPersistableChromosome.XML_CHROMOSOME_TAG.equals(chromNode.getNodeName()) == false)
      throw new IllegalArgumentException(
          "node name not " + XmlPersistableChromosome.XML_CHROMOSOME_TAG);

    List genes = new ArrayList();
    NodeList geneNodes = chromNode.getChildNodes();
    for (int i = 0; i < geneNodes.getLength(); ++i) {
      Node geneNode = geneNodes.item(i);
      if (XmlPersistableAllele.NEURON_XML_TAG.equals(geneNode.getNodeName()))
        genes.add(XmlPersistableAllele.neuronFromXml(geneNode));
      else if (XmlPersistableAllele.CONN_XML_TAG.equals(geneNode.getNodeName()))
        genes.add(XmlPersistableAllele.connectionFromXml(geneNode));
    }

    Long id = null;
    Node idNode =
        chromNode.getAttributes().getNamedItem(XmlPersistableChromosome.XML_CHROMOSOME_ID_TAG);
    if (idNode != null) {
      String idStr = idNode.getNodeValue();
      if ((idStr != null) && (idStr.length() > 0)) id = Long.valueOf(idStr);
    }

    Long primaryParentId = null;
    idNode =
        chromNode
            .getAttributes()
            .getNamedItem(XmlPersistableChromosome.XML_CHROMOSOME_PRIMARY_PARENT_ID_TAG);
    if (idNode != null) {
      String idStr = idNode.getNodeValue();
      if ((idStr != null) && (idStr.length() > 0)) primaryParentId = Long.valueOf(idStr);
    }

    Long secondaryParentId = null;
    idNode =
        chromNode
            .getAttributes()
            .getNamedItem(XmlPersistableChromosome.XML_CHROMOSOME_SECONDARY_PARENT_ID_TAG);
    if (idNode != null) {
      String idStr = idNode.getNodeValue();
      if ((idStr != null) && (idStr.length() > 0)) secondaryParentId = Long.valueOf(idStr);
    }

    ChromosomeMaterial material = new ChromosomeMaterial(genes, primaryParentId, secondaryParentId);
    return (id == null)
        ? new Chromosome(material, config.nextChromosomeId())
        : new Chromosome(material, id);
  }
 /**
  * Find and print the solution, return the solution error.
  *
  * @param a_conf the configuration to use
  * @return absolute difference between the required and computed change
  */
 protected int solve(
     Configuration a_conf,
     int a_targetChangeAmount,
     SupergeneChangeFitnessFunction a_fitnessFunction,
     Gene[] a_sampleGenes)
     throws InvalidConfigurationException {
   IChromosome sampleChromosome = new Chromosome(a_conf, a_sampleGenes);
   a_conf.setSampleChromosome(sampleChromosome);
   // Finally, we need to tell the Configuration object how many
   // Chromosomes we want in our population. The more Chromosomes,
   // the larger number of potential solutions (which is good for
   // finding the answer), but the longer it will take to evolve
   // the population (which could be seen as bad). We'll just set
   // the population size to 500 here.
   // ------------------------------------------------------------
   a_conf.setPopulationSize(POPULATION_SIZE);
   // Create random initial population of Chromosomes.
   // ------------------------------------------------
   Genotype population = Genotype.randomInitialGenotype(a_conf);
   int s;
   Evolution:
   // Evolve the population, break if the the change solution is found.
   // -----------------------------------------------------------------
   for (int i = 0; i < MAX_ALLOWED_EVOLUTIONS; i++) {
     population.evolve();
     s =
         Math.abs(
             a_fitnessFunction.amountOfChange(population.getFittestChromosome())
                 - a_targetChangeAmount);
     if (s == 0) {
       break Evolution;
     }
   }
   // Display the best solution we found.
   // -----------------------------------
   IChromosome bestSolutionSoFar = report(a_fitnessFunction, population);
   return Math.abs(a_fitnessFunction.amountOfChange(bestSolutionSoFar) - a_targetChangeAmount);
 }
  /**
   * Executes the genetic algorithm to determine the minimum number of items necessary to make up
   * the given target volume. The solution will then be written to the console.
   *
   * @param a_knapsackVolume the target volume for which this method is attempting to produce the
   *     optimal list of items
   * @throws Exception
   * @author Klaus Meffert
   * @since 2.3
   */
  public static void findItemsForVolume(double a_knapsackVolume) throws Exception {
    // Start with a DefaultConfiguration, which comes setup with the
    // most common settings.
    // -------------------------------------------------------------
    Configuration conf = new DefaultConfiguration();
    conf.setPreservFittestIndividual(true);
    // Set the fitness function we want to use. We construct it with
    // the target volume passed in to this method.
    // ---------------------------------------------------------
    FitnessFunction myFunc = new KnapsackFitnessFunction(a_knapsackVolume);
    conf.setFitnessFunction(myFunc);
    // Now we need to tell the Configuration object how we want our
    // Chromosomes to be setup. We do that by actually creating a
    // sample Chromosome and then setting it on the Configuration
    // object. As mentioned earlier, we want our Chromosomes to each
    // have as many genes as there are different items available. We want the
    // values (alleles) of those genes to be integers, which represent
    // how many items of that type we have. We therefore use the
    // IntegerGene class to represent each of the genes. That class
    // also lets us specify a lower and upper bound, which we set
    // to senseful values (i.e. maximum possible) for each item type.
    // --------------------------------------------------------------
    Gene[] sampleGenes = new Gene[itemVolumes.length];
    for (int i = 0; i < itemVolumes.length; i++) {
      sampleGenes[i] = new IntegerGene(conf, 0, (int) Math.ceil(a_knapsackVolume / itemVolumes[i]));
    }
    IChromosome sampleChromosome = new Chromosome(conf, sampleGenes);
    conf.setSampleChromosome(sampleChromosome);
    // Finally, we need to tell the Configuration object how many
    // Chromosomes we want in our population. The more Chromosomes,
    // the larger number of potential solutions (which is good for
    // finding the answer), but the longer it will take to evolve
    // the population (which could be seen as bad).
    // ------------------------------------------------------------
    conf.setPopulationSize(50);
    // Create random initial population of Chromosomes.
    // Here we try to read in a previous run via XMLManager.readFile(..)
    // for demonstration purpose!
    // -----------------------------------------------------------------
    Genotype population;
    try {
      Document doc = XMLManager.readFile(new File("knapsackJGAP.xml"));
      population = XMLManager.getGenotypeFromDocument(conf, doc);
    } catch (FileNotFoundException fex) {
      population = Genotype.randomInitialGenotype(conf);
    }
    population = Genotype.randomInitialGenotype(conf);
    // Evolve the population. Since we don't know what the best answer
    // is going to be, we just evolve the max number of times.
    // ---------------------------------------------------------------
    for (int i = 0; i < MAX_ALLOWED_EVOLUTIONS; i++) {
      population.evolve();
    }
    // Save progress to file. A new run of this example will then be able to
    // resume where it stopped before!
    // ---------------------------------------------------------------------

    // represent Genotype as tree with elements Chromomes and Genes
    // ------------------------------------------------------------
    DataTreeBuilder builder = DataTreeBuilder.getInstance();
    IDataCreators doc2 = builder.representGenotypeAsDocument(population);
    // create XML document from generated tree
    // ---------------------------------------
    XMLDocumentBuilder docbuilder = new XMLDocumentBuilder();
    Document xmlDoc = (Document) docbuilder.buildDocument(doc2);
    XMLManager.writeFile(xmlDoc, new File("knapsackJGAP.xml"));
    // Display the best solution we found.
    // -----------------------------------
    IChromosome bestSolutionSoFar = population.getFittestChromosome();
    System.out.println(
        "The best solution has a fitness value of " + bestSolutionSoFar.getFitnessValue());
    System.out.println("It contained the following: ");
    int count;
    double totalVolume = 0.0d;
    for (int i = 0; i < bestSolutionSoFar.size(); i++) {
      count = ((Integer) bestSolutionSoFar.getGene(i).getAllele()).intValue();
      if (count > 0) {
        System.out.println("\t " + count + " x " + itemNames[i]);
        totalVolume += itemVolumes[i] * count;
      }
    }
    System.out.println("\nFor a total volume of " + totalVolume + " ccm");
    System.out.println("Expected volume was " + a_knapsackVolume + " ccm");
    System.out.println("Volume difference is " + Math.abs(totalVolume - a_knapsackVolume) + " ccm");
  }
  /**
   * Executes the genetic algorithm to determine the minimum number of coins necessary to make up
   * the given target amount of change. The solution will then be written to System.out.
   *
   * @param a_targetChangeAmount the target amount of change for which this method is attempting to
   *     produce the minimum number of coins
   * @param a_doMonitor true: turn on monitoring for later evaluation of evolution progress
   * @throws Exception
   * @author Neil Rotstan
   * @author Klaus Meffert
   * @since 1.0
   */
  public static void makeChangeForAmount(int a_targetChangeAmount, boolean a_doMonitor)
      throws Exception {
    // Start with a DefaultConfiguration, which comes setup with the
    // most common settings.
    // -------------------------------------------------------------
    Configuration conf = new DefaultConfiguration();
    // Care that the fittest individual of the current population is
    // always taken to the next generation.
    // Consider: With that, the pop. size may exceed its original
    // size by one sometimes!
    // -------------------------------------------------------------
    conf.setPreservFittestIndividual(true);
    conf.setKeepPopulationSizeConstant(false);
    // Set the fitness function we want to use, which is our
    // MinimizingMakeChangeFitnessFunction. We construct it with
    // the target amount of change passed in to this method.
    // ---------------------------------------------------------
    FitnessFunction myFunc = new SampleFitnessFunction(a_targetChangeAmount);
    conf.setFitnessFunction(myFunc);
    if (a_doMonitor) {
      // Turn on monitoring/auditing of evolution progress.
      // --------------------------------------------------
      m_monitor = new EvolutionMonitor();
      conf.setMonitor(m_monitor);
    }
    // Now we need to tell the Configuration object how we want our
    // Chromosomes to be setup. We do that by actually creating a
    // sample Chromosome and then setting it on the Configuration
    // object. As mentioned earlier, we want our Chromosomes to each
    // have four genes, one for each of the coin types. We want the
    // values (alleles) of those genes to be integers, which represent
    // how many coins of that type we have. We therefore use the
    // IntegerGene class to represent each of the genes. That class
    // also lets us specify a lower and upper bound, which we set
    // to sensible values for each coin type.
    // --------------------------------------------------------------
    Gene[] sampleGenes = new Gene[4];
    sampleGenes[0] = new IntegerGene(conf, 0, 98); // Wasser
    sampleGenes[1] = new IntegerGene(conf, 0, 98); // Zucker
    sampleGenes[2] = new IntegerGene(conf, 0, 98); // Saft1
    sampleGenes[3] = new IntegerGene(conf, 0, 98); // Saft2
    IChromosome sampleChromosome = new Chromosome(conf, sampleGenes);
    conf.setSampleChromosome(sampleChromosome);
    // Finally, we need to tell the Configuration object how many
    // Chromosomes we want in our population. The more Chromosomes,
    // the larger number of potential solutions (which is good for
    // finding the answer), but the longer it will take to evolve
    // the population (which could be seen as bad).
    // ------------------------------------------------------------
    conf.setPopulationSize(80);

    // Now we initialize the population randomly, anyway (as an example only)!
    // If you want to load previous results from file, remove the next line!
    // -----------------------------------------------------------------------
    Genotype population = Genotype.randomInitialGenotype(conf);
    // Evolve the population. Since we don't know what the best answer
    // is going to be, we just evolve the max number of times.
    // ---------------------------------------------------------------
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < MAX_ALLOWED_EVOLUTIONS; i++) {
      if (!uniqueChromosomes(population.getPopulation())) {
        throw new RuntimeException("Invalid state in generation " + i);
      }
      if (m_monitor != null) {
        population.evolve(m_monitor);
      } else {
        population.evolve();
      }
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Total evolution time: " + (endTime - startTime) + " ms");
    // Save progress to file. A new run of this example will then be able to
    // resume where it stopped before! --> this is completely optional.
    // ---------------------------------------------------------------------

    // Display the best solution we found.
    // -----------------------------------
    IChromosome bestSolutionSoFar = population.getFittestChromosome();
    double v1 = bestSolutionSoFar.getFitnessValue();
    System.out.println(
        "The best solution has a fitness value of " + bestSolutionSoFar.getFitnessValue());
    bestSolutionSoFar.setFitnessValueDirectly(-1);
    System.out.println("It contains the following: ");
    System.out.println(
        "\t" + SampleFitnessFunction.getNumberOfCoinsAtGene(bestSolutionSoFar, 0) + " ml water.");
    System.out.println(
        "\t" + SampleFitnessFunction.getNumberOfCoinsAtGene(bestSolutionSoFar, 1) + " ml sugar.");
    System.out.println(
        "\t" + SampleFitnessFunction.getNumberOfCoinsAtGene(bestSolutionSoFar, 2) + " ml juice 1.");
    System.out.println(
        "\t" + SampleFitnessFunction.getNumberOfCoinsAtGene(bestSolutionSoFar, 3) + " ml juice 2.");
    System.out.println(
        "For a total of " + SampleFitnessFunction.amountOfChange(bestSolutionSoFar) + " ml.");
  }
  /**
   * Executes the genetic algorithm to determine the minimum number of items necessary to make up
   * the given target volume. The solution will then be written to the console.
   *
   * @param a_knapsackVolume the target volume for which this method is attempting to produce the
   *     optimal list of items
   * @throws Exception
   * @author Klaus Meffert
   * @throws InvalidConfigurationException
   * @since 2.3
   */
  public static void findeBesteParameter() throws InvalidConfigurationException {
    // Start with a DefaultConfiguration, which comes setup with the
    // most common settings.
    // -------------------------------------------------------------
    Configuration conf = new myConfiguration();
    conf.setPreservFittestIndividual(true);

    // TODO: check: viel Mehraufwand?? ja!
    // conf.setAlwaysCaculateFitness(true);

    // Set the fitness function we want to use. We construct it with
    // the target volume passed in to this method.
    // ---------------------------------------------------------
    FitnessFunction myFunc = new EAmyTeamFitnessFunction();
    conf.setFitnessFunction(myFunc);

    // --> myConfiguration
    // conf.addGeneticOperator(new MutationOperator(conf,2));
    // conf.addGeneticOperator(new CrossoverOperator(conf, .2));

    // Now we need to tell the Configuration object how we want our
    // Chromosomes to be setup. We do that by actually creating a
    // sample Chromosome and then setting it on the Configuration
    // object.

    myTeamParameters dummyParam = new myTeamParameters(); // nur fuer min/max

    Gene[] sampleGenes = new Gene[myTeamParameters.ANZAHL_PARAMETER];
    for (int i = 0; i < sampleGenes.length; i++) {
      sampleGenes[i] = new DoubleGene(conf, dummyParam.getMin(i), dummyParam.getMax(i));
    }
    IChromosome sampleChromosome = new Chromosome(conf, sampleGenes);
    conf.setSampleChromosome(sampleChromosome);

    // Finally, we need to tell the Configuration object how many
    // Chromosomes we want in our population. The more Chromosomes,
    // the larger number of potential solutions (which is good for
    // finding the answer), but the longer it will take to evolve
    // the population (which could be seen as bad).
    // ------------------------------------------------------------
    conf.setPopulationSize(POPULATION_SIZE);

    // Create random initial population of Chromosomes.
    // Here we try to read in a previous run via XMLManager.readFile(..)
    // for demonstration purpose!
    // -----------------------------------------------------------------
    Genotype population;
    try {
      Document doc = XMLManager.readFile(new File(XML_FILENAME));
      population = XMLManager.getGenotypeFromDocument(conf, doc);
      // TODO mit zufaelligen auffuellen??
      System.out.println("Alte Population aus Datei gelesen!");
    } catch (Exception fex) {
      population = Genotype.randomInitialGenotype(conf);
    }

    // Evolve the population. Since we don't know what the best answer
    // is going to be, we just evolve the max number of times.
    // ---------------------------------------------------------------

    for (int i = 0; i < MAX_ALLOWED_EVOLUTIONS; i++) {
      System.out.println("\nPopulation Nr. " + i + ":");
      printPopulation(population);

      population.evolve();
    }

    // Save progress to file. A new run of this example will then be able to
    // resume where it stopped before!
    // ---------------------------------------------------------------------

    // represent Genotype as tree with elements Chromomes and Genes
    // ------------------------------------------------------------
    try {
      DataTreeBuilder builder = DataTreeBuilder.getInstance();
      IDataCreators doc2 = builder.representGenotypeAsDocument(population);
      // create XML document from generated tree
      // ---------------------------------------
      XMLDocumentBuilder docbuilder = new XMLDocumentBuilder();
      Document xmlDoc = (Document) docbuilder.buildDocument(doc2);
      XMLManager.writeFile(xmlDoc, new File(XML_FILENAME));
    } catch (Exception e) {
      e.printStackTrace();
    }
    // Display the best solution we found.
    // -----------------------------------
    IChromosome bestSolutionSoFar = population.getFittestChromosome();
    System.out.println(
        "The best solution has a fitness value of "
            + bestSolutionSoFar.getFitnessValueDirectly()
            + " mit folgenden Parametern:");
    printChromosom(bestSolutionSoFar, true);
  }
Example #9
0
  public static void main(String[] args) throws InvalidConfigurationException {

    // Reading data from xml
    try {
      new InputData().readFromFile(XML_TEST_FILENAME);
    } catch (SAXException e) {
      System.out.println(e.getMessage());
    } catch (IOException e) {
      System.out.println(e.getMessage());
    } catch (ParserConfigurationException e) {
      System.out.println(e.getMessage());
    }

    // Configuration conf = new DefaultConfiguration();
    Configuration conf = new Configuration("myconf");
    TimetableFitnessFunction fitnessFunction = new TimetableFitnessFunction();
    InitialConstraintChecker timetableConstraintChecker = new InitialConstraintChecker();

    // Creating genes
    Gene[] testGenes = new Gene[CHROMOSOME_SIZE];
    for (int i = 0; i < CHROMOSOME_SIZE; i++) {
      testGenes[i] =
          new GroupClassTeacherLessonTimeSG(
              conf,
              new Gene[] {
                new GroupGene(conf, 1),
                new ClassGene(conf, 1),
                new TeacherGene(conf, 1),
                new LessonGene(conf, 1),
                new TimeGene(conf, 1)
              });
    }
    System.out.println("==================================");
    // Creating chromosome
    Chromosome testChromosome;
    testChromosome = new Chromosome(conf, testGenes);
    testChromosome.setConstraintChecker(timetableConstraintChecker);
    // Setup configuration
    conf.setSampleChromosome(testChromosome);
    conf.setPopulationSize(POPULATION_SIZE);
    conf.setFitnessFunction(fitnessFunction); // add fitness function

    BestChromosomesSelector myBestChromosomesSelector = new BestChromosomesSelector(conf);
    conf.addNaturalSelector(myBestChromosomesSelector, false);

    conf.setRandomGenerator(new StockRandomGenerator());
    conf.setEventManager(new EventManager());
    conf.setFitnessEvaluator(new DefaultFitnessEvaluator());

    CrossoverOperator myCrossoverOperator = new CrossoverOperator(conf);
    conf.addGeneticOperator(myCrossoverOperator);

    TimetableMutationOperator myMutationOperator = new TimetableMutationOperator(conf);
    conf.addGeneticOperator(myMutationOperator);

    conf.setKeepPopulationSizeConstant(false);

    // Creating genotype
    //        Population pop = new Population(conf, testChromosome);
    //        Genotype population = new Genotype(conf, pop);
    Genotype population = Genotype.randomInitialGenotype(conf);

    System.out.println("Our Chromosome: \n " + testChromosome.getConfiguration().toString());

    System.out.println("------------evolution-----------------------------");

    // Begin evolution
    Calendar cal = Calendar.getInstance();
    start_t = cal.getTimeInMillis();
    for (int i = 0; i < MAX_EVOLUTIONS; i++) {
      System.out.println(
          "generation#: " + i + " population size:" + (Integer) population.getPopulation().size());
      if (population.getFittestChromosome().getFitnessValue() >= THRESHOLD) break;
      population.evolve();
    }
    cal = Calendar.getInstance();
    finish_t = cal.getTimeInMillis();

    System.out.println("--------------end of evolution--------------------");
    Chromosome fittestChromosome = (Chromosome) population.getFittestChromosome();
    System.out.println(
        "-------------The best chromosome---fitness="
            + fittestChromosome.getFitnessValue()
            + "---");
    System.out.println("                Group Class Time");
    for (int i = 0; i < CHROMOSOME_SIZE; i++) {
      GroupClassTeacherLessonTimeSG s =
          (GroupClassTeacherLessonTimeSG) fittestChromosome.getGene(i);
      System.out.println(
          "Gene "
              + i
              + " contains: "
              + (Integer) s.geneAt(GROUP).getAllele()
              + " "
              + (Integer) s.geneAt(CLASS).getAllele()
              + " "
              + (Integer) s.geneAt(TEACHER).getAllele()
              + " "
              + (Integer) s.geneAt(LESSON).getAllele()
              + " "
              + (Integer) s.geneAt(TIME).getAllele());
      // GroupGene gg = (GroupGene)s.geneAt(GROUP);
      // System.out.println("gg's idGroup"+gg.getAllele()+" gg.getGroupSize()"+ gg.getGroupSize() );
    }

    System.out.println("Elapsed time:" + (double) (finish_t - start_t) / 1000 + "s");

    // Display the best solution

    OutputData od = new OutputData();
    od.printToConsole(fittestChromosome);

    // Write population to the disk
    try {
      od.printToFile(population, GENOTYPE_FILENAME, BEST_CHROMOSOME_FILENAME);
    } catch (IOException e) {
      System.out.println("IOException raised! " + e.getMessage());
    }
  }
  /**
   * Evolves the population of chromosomes within a genotype. This will execute all of the genetic
   * operators added to the present active configuration and then invoke the natural selector to
   * choose which chromosomes will be included in the next generation population.
   *
   * @param a_pop the population to evolve
   * @param a_conf the configuration to use for evolution
   * @return evolved population
   * @author Klaus Meffert
   * @since 3.2
   */
  public Population evolve(Population a_pop, Configuration a_conf) {
    Population pop = a_pop;
    int originalPopSize = a_conf.getPopulationSize();
    boolean monitorActive = a_conf.getMonitor() != null;
    IChromosome fittest = null;
    // If first generation: Set age to one to allow genetic operations,
    // see CrossoverOperator for an illustration.
    // ----------------------------------------------------------------
    if (a_conf.getGenerationNr() == 0) {
      int size = pop.size();
      for (int i = 0; i < size; i++) {
        IChromosome chrom = pop.getChromosome(i);
        chrom.increaseAge();
      }
    } else {
      // Select fittest chromosome in case it should be preserved and we are
      // not in the very first generation.
      // -------------------------------------------------------------------
      if (a_conf.isPreserveFittestIndividual()) {
        /** @todo utilize jobs. In pop do also utilize jobs, especially for fitness computation */
        fittest = pop.determineFittestChromosome(0, pop.size() - 1);
      }
    }
    if (a_conf.getGenerationNr() > 0) {
      // Adjust population size to configured size (if wanted).
      // Theoretically, this should be done at the end of this method.
      // But for optimization issues it is not. If it is the last call to
      // evolve() then the resulting population possibly contains more
      // chromosomes than the wanted number. But this is no bad thing as
      // more alternatives mean better chances having a fit candidate.
      // If it is not the last call to evolve() then the next call will
      // ensure the correct population size by calling keepPopSizeConstant.
      // ------------------------------------------------------------------
      keepPopSizeConstant(pop, a_conf);
    }
    // Ensure fitness value of all chromosomes is udpated.
    // ---------------------------------------------------
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES1,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    updateChromosomes(pop, a_conf);
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES1,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    // Apply certain NaturalSelectors before GeneticOperators will be executed.
    // ------------------------------------------------------------------------
    pop = applyNaturalSelectors(a_conf, pop, true);
    // Execute all of the Genetic Operators.
    // -------------------------------------
    applyGeneticOperators(a_conf, pop);
    // Reset fitness value of genetically operated chromosomes.
    // Normally, this should not be necessary as the Chromosome class
    // initializes each newly created chromosome with
    // FitnessFunction.NO_FITNESS_VALUE. But who knows which Chromosome
    // implementation is used...
    // ----------------------------------------------------------------
    int currentPopSize = pop.size();
    for (int i = originalPopSize; i < currentPopSize; i++) {
      IChromosome chrom = pop.getChromosome(i);
      chrom.setFitnessValueDirectly(FitnessFunction.NO_FITNESS_VALUE);
      // Mark chromosome as new-born.
      // ----------------------------
      chrom.resetAge();
      // Mark chromosome as being operated on.
      // -------------------------------------
      chrom.increaseOperatedOn();
    }
    // Increase age of all chromosomes which are not modified by genetic
    // operations.
    // -----------------------------------------------------------------
    int size = Math.min(originalPopSize, currentPopSize);
    for (int i = 0; i < size; i++) {
      IChromosome chrom = pop.getChromosome(i);
      chrom.increaseAge();
      // Mark chromosome as not being operated on.
      // -----------------------------------------
      chrom.resetOperatedOn();
    }
    // If a bulk fitness function has been provided, call it.
    // ------------------------------------------------------
    BulkFitnessFunction bulkFunction = a_conf.getBulkFitnessFunction();
    if (bulkFunction != null) {
      if (monitorActive) {
        // Monitor that bulk fitness will be called for evaluation.
        // --------------------------------------------------------
        a_conf
            .getMonitor()
            .event(
                IEvolutionMonitor.MONITOR_EVENT_BEFORE_BULK_EVAL,
                a_conf.getGenerationNr(),
                new Object[] {bulkFunction, pop});
      }
      /** @todo utilize jobs: bulk fitness function is not so important for a prototype! */
      bulkFunction.evaluate(pop);
      if (monitorActive) {
        // Monitor that bulk fitness has been called for evaluation.
        // ---------------------------------------------------------
        a_conf
            .getMonitor()
            .event(
                IEvolutionMonitor.MONITOR_EVENT_AFTER_BULK_EVAL,
                a_conf.getGenerationNr(),
                new Object[] {bulkFunction, pop});
      }
    }
    // Ensure fitness value of all chromosomes is udpated.
    // ---------------------------------------------------
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES2,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    updateChromosomes(pop, a_conf);
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES2,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    // Apply certain NaturalSelectors after GeneticOperators have been applied.
    // ------------------------------------------------------------------------
    pop = applyNaturalSelectors(a_conf, pop, false);
    // Fill up population randomly if size dropped below specified percentage
    // of original size.
    // ----------------------------------------------------------------------
    if (a_conf.getMinimumPopSizePercent() > 0) {
      int sizeWanted = a_conf.getPopulationSize();
      int popSize;
      int minSize = (int) Math.round(sizeWanted * (double) a_conf.getMinimumPopSizePercent() / 100);
      popSize = pop.size();
      if (popSize < minSize) {
        IChromosome newChrom;
        IChromosome sampleChrom = a_conf.getSampleChromosome();
        Class sampleChromClass = sampleChrom.getClass();
        IInitializer chromIniter =
            a_conf.getJGAPFactory().getInitializerFor(sampleChrom, sampleChromClass);
        while (pop.size() < minSize) {
          try {
            /**
             * @todo utilize jobs as initialization may be time-consuming as invalid combinations
             *     may have to be filtered out
             */
            newChrom = (IChromosome) chromIniter.perform(sampleChrom, sampleChromClass, null);
            if (monitorActive) {
              // Monitor that fitness value of chromosomes is being updated.
              // -----------------------------------------------------------
              a_conf
                  .getMonitor()
                  .event(
                      IEvolutionMonitor.MONITOR_EVENT_BEFORE_ADD_CHROMOSOME,
                      a_conf.getGenerationNr(),
                      new Object[] {pop, newChrom});
            }
            pop.addChromosome(newChrom);
          } catch (Exception ex) {
            throw new RuntimeException(ex);
          }
        }
      }
    }
    IChromosome newFittest = reAddFittest(pop, fittest);
    if (monitorActive && newFittest != null) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_READD_FITTEST,
              a_conf.getGenerationNr(),
              new Object[] {pop, fittest});
    }

    // Increase number of generations.
    // -------------------------------
    a_conf.incrementGenerationNr();
    // Fire an event to indicate we've performed an evolution.
    // -------------------------------------------------------
    m_lastPop = pop;
    m_lastConf = a_conf;
    a_conf
        .getEventManager()
        .fireGeneticEvent(new GeneticEvent(GeneticEvent.GENOTYPE_EVOLVED_EVENT, this));
    return pop;
  }