Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 667   Methods: 21
NCLOC: 280   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Genotype.java 91,9% 95,5% 90,5% 94%
coverage coverage
 1    /*
 2    * This file is part of JGAP.
 3    *
 4    * JGAP offers a dual license model containing the LGPL as well as the MPL.
 5    *
 6    * For licencing information please see the file license.txt included with JGAP
 7    * or have a look at the top of class org.jgap.Chromosome which representatively
 8    * includes the JGAP license policy applicable for any file delivered with JGAP.
 9    */
 10    package org.jgap;
 11   
 12    import java.io.*;
 13    import java.util.*;
 14    import org.jgap.event.*;
 15   
 16    /**
 17    * Genotypes are fixed-length populations of chromosomes. As an instance of
 18    * a Genotype is evolved, all of its Chromosomes are also evolved. A Genotype
 19    * may be constructed normally via constructor, or the static
 20    * randomInitialGenotype() method can be used to generate a Genotype with a
 21    * randomized Chromosome population.
 22    * <p>
 23    * Please note that among all created Genotype instances there may only be one
 24    * configuration (singleton!), used by all Genotype instances
 25    *
 26    * @author Neil Rotstan
 27    * @author Klaus Meffert
 28    * @since 1.0
 29    */
 30    public class Genotype
 31    implements Serializable, Runnable {
 32    /** String containing the CVS revision. Read out via reflection!*/
 33    private final static String CVS_REVISION = "$Revision: 1.87 $";
 34   
 35    /**
 36    * The current Configuration instance.
 37    * @since 1.0
 38    */
 39    private transient Configuration m_activeConfiguration;
 40   
 41    private transient static Configuration m_staticConfiguration;
 42   
 43    /**
 44    * The array of Chromosomes that makeup the Genotype's population.
 45    * @since 2.0
 46    */
 47    private Population m_population;
 48   
 49    /**
 50    * Constructs a new Genotype instance with the given array of Chromosomes and
 51    * the given active Configuration instance. Note that the Configuration object
 52    * must be in a valid state when this method is invoked, or a
 53    * InvalidConfigurationException will be thrown.
 54    *
 55    * @param a_configuration the Configuration object to use
 56    * @param a_initialChromosomes the Chromosome population to be managed by
 57    * this Genotype instance
 58    * @throws InvalidConfigurationException if the given Configuration object is
 59    * in an invalid state
 60    *
 61    * @author Neil Rotstan
 62    * @author Klaus Meffert
 63    * @since 1.0
 64    * @deprecated use Genotype(Configuration, Population) instead
 65    */
 66    public Genotype(Configuration a_configuration,
 67    IChromosome[] a_initialChromosomes)
 68    throws InvalidConfigurationException {
 69    this(a_configuration, new Population(a_configuration, a_initialChromosomes));
 70    }
 71   
 72    /**
 73    * Constructs a new Genotype instance with the given array of
 74    * Chromosomes and the given active Configuration instance. Note
 75    * that the Configuration object must be in a valid state
 76    * when this method is invoked, or a InvalidconfigurationException
 77    * will be thrown.
 78    *
 79    * @param a_configuration the Configuration object t use
 80    * @param a_population the Chromosome population to be managed by this
 81    * Genotype instance
 82    * @throws InvalidConfigurationException
 83    *
 84    * @author Neil Rotstan
 85    * @author Klaus Meffert
 86    * @since 2.0
 87    */
 88  1087 public Genotype(Configuration a_configuration, Population a_population)
 89    throws InvalidConfigurationException {
 90    // Sanity checks: Make sure neither the Configuration, the array
 91    // of Chromosomes, nor any of the Genes inside the array are null.
 92    // ---------------------------------------------------------------
 93  1087 if (a_configuration == null) {
 94  1 throw new IllegalArgumentException(
 95    "The Configuration instance may not be null.");
 96    }
 97  1086 if (a_population == null) {
 98  1 throw new IllegalArgumentException(
 99    "The Population may not be null.");
 100    }
 101  1085 for (int i = 0; i < a_population.size(); i++) {
 102  20355 if (a_population.getChromosome(i) == null) {
 103  2 throw new IllegalArgumentException(
 104    "The Chromosome instance at index " + i + " of the array of " +
 105    "Chromosomes is null. No Chromosomes instance in this array " +
 106    "may be null.");
 107    }
 108    }
 109  1083 m_population = a_population;
 110    // Lock the settings of the configuration object so that it cannot
 111    // be altered.
 112    // ---------------------------------------------------------------
 113  1083 a_configuration.lockSettings();
 114  1079 m_activeConfiguration = a_configuration;
 115    }
 116   
 117    /**
 118    * Don't use this constructor, it's only for internal use.
 119    *
 120    * @param a_configuration the configuration to use
 121    * @throws InvalidConfigurationException
 122    *
 123    * @author Klaus Meffert
 124    * @since 3.0
 125    */
 126  0 public Genotype(Configuration a_configuration)
 127    throws InvalidConfigurationException {
 128   
 129    }
 130   
 131    /**
 132    * Retrieves the array of Chromosomes that make up the population of this
 133    * Genotype instance.
 134    *
 135    * @return the population of Chromosomes
 136    *
 137    * @author Neil Rotstan
 138    * @author Klaus Meffert
 139    * @since 1.0
 140    * @deprecated uses getPopulation() instead
 141    */
 142    public synchronized IChromosome[] getChromosomes() {
 143    Iterator it = getPopulation().iterator();
 144    IChromosome[] result = new Chromosome[getPopulation().size()];
 145    int i = 0;
 146    while (it.hasNext()) {
 147    result[i++] = (IChromosome) it.next();
 148    }
 149    return result;
 150    }
 151   
 152    /**
 153    * @return the current population of chromosomes
 154    *
 155    * @author Klaus Meffert
 156    * @since 2.1 (?)
 157    */
 158  3248828 public Population getPopulation() {
 159  3248828 return m_population;
 160    }
 161   
 162    /**
 163    * Retrieves the Chromosome in the population with the highest fitness
 164    * value.
 165    *
 166    * @return the Chromosome with the highest fitness value, or null if there
 167    * are no chromosomes in this Genotype
 168    *
 169    * @author Neil Rotstan
 170    * @author Klaus Meffert
 171    * @since 1.0
 172    */
 173  12 public synchronized IChromosome getFittestChromosome() {
 174  12 return getPopulation().determineFittestChromosome();
 175    }
 176   
 177    /**
 178    * Retrieves the Chromosome in the population with the highest fitness
 179    * value within the given indices.
 180    *
 181    * @param a_startIndex the index to start the determination with
 182    * @param a_endIndex the index to end the determination with
 183    * @return the Chromosome with the highest fitness value within the given
 184    * indices, or null if there are no chromosomes in this Genotype
 185    *
 186    * @author Klaus Meffert
 187    * @since 3.0
 188    */
 189  15 public synchronized IChromosome getFittestChromosome(int a_startIndex,
 190    int a_endIndex) {
 191  15 return getPopulation().determineFittestChromosome(a_startIndex, a_endIndex);
 192    }
 193   
 194    /**
 195    * Retrieves the top n Chromsomes in the population (the ones with the best
 196    * fitness values).
 197    *
 198    * @param a_numberOfChromosomes the number of chromosomes desired
 199    * @return the list of Chromosomes with the highest fitness values, or null
 200    * if there are no chromosomes in this Genotype
 201    *
 202    * @author Charles Kevin Hill
 203    * @since 2.4
 204    */
 205  1 public synchronized List getFittestChromosomes(int a_numberOfChromosomes) {
 206  1 return getPopulation().determineFittestChromosomes(a_numberOfChromosomes);
 207    }
 208   
 209    /**
 210    * Evolves the population of Chromosomes within this Genotype. This will
 211    * execute all of the genetic operators added to the present active
 212    * configuration and then invoke the natural selector to choose which
 213    * chromosomes will be included in the next generation population. Note
 214    * that the population size not always remains constant (dependent on the
 215    * NaturalSelectors used!).<p>
 216    * To consecutively call this method, use evolve(int)!!!
 217    *
 218    * @author Neil Rotstan
 219    * @author Klaus Meffert
 220    * @since 1.0
 221    */
 222  31 public synchronized void evolve() {
 223  31 if (m_activeConfiguration == null) {
 224  0 throw new IllegalStateException(
 225    "The Configuration object must be set on this"
 226    + " Genotype prior to evolution.");
 227    }
 228    // Adjust population size to configured size (if wanted).
 229    // Theoretically, this should be done at the end of this method.
 230    // But for optimization issues it is not. If it is the last call to
 231    // evolve() then the resulting population possibly contains more
 232    // chromosomes than the wanted number. But this is no bad thing as
 233    // more alternatives mean better chances having a fit candidate.
 234    // If it is not the last call to evolve() then the next call will
 235    // ensure the correct population size by calling keepPopSizeConstant.
 236    // ------------------------------------------------------------------
 237  31 if (m_activeConfiguration.isKeepPopulationSizeConstant()) {
 238  24 keepPopSizeConstant(getPopulation(),
 239    m_activeConfiguration.getPopulationSize());
 240    }
 241    // Apply certain NaturalSelectors before GeneticOperators will be applied.
 242    // -----------------------------------------------------------------------
 243  30 applyNaturalSelectors(true);
 244    // Execute all of the Genetic Operators.
 245    // -------------------------------------
 246  30 applyGeneticOperators();
 247    // Reset fitness value of genetically operated chromosomes.
 248    // Normally, this should not be necessary as the Chromosome
 249    // class initializes each newly created chromosome with
 250    // FitnessFunction.NO_FITNESS_VALUE. But who knows which
 251    // Chromosome implementation is used...
 252    // --------------------------------------------------------
 253  30 int originalPopSize = m_activeConfiguration.getPopulationSize();
 254  30 int currentPopSize = getPopulation().size();
 255  30 for (int i = originalPopSize; i < currentPopSize; i++) {
 256  3062 IChromosome chrom = getPopulation().getChromosome(i);
 257  3062 chrom.setFitnessValueDirectly(FitnessFunction.NO_FITNESS_VALUE);
 258    }
 259    // Apply certain NaturalSelectors after GeneticOperators have been applied.
 260    // ------------------------------------------------------------------------
 261  30 applyNaturalSelectors(false);
 262    // If a bulk fitness function has been provided, call it.
 263    // ------------------------------------------------------
 264  30 BulkFitnessFunction bulkFunction =
 265    m_activeConfiguration.getBulkFitnessFunction();
 266  30 if (bulkFunction != null) {
 267  1 bulkFunction.evaluate(getPopulation());
 268    }
 269    // Fill up population randomly if size dropped below specified percentage
 270    // of original size.
 271    // ----------------------------------------------------------------------
 272  30 if (m_activeConfiguration.getMinimumPopSizePercent() > 0) {
 273  4 int sizeWanted = m_activeConfiguration.getPopulationSize();
 274  4 int popSize;
 275  4 int minSize = (int) Math.round(sizeWanted *
 276    (double) getConfiguration().
 277    getMinimumPopSizePercent()
 278    / 100);
 279  4 popSize = getPopulation().size();
 280  4 if (popSize < minSize) {
 281  4 IChromosome newChrom;
 282    // try {
 283  4 IChromosome sampleChrom = m_activeConfiguration.getSampleChromosome();
 284  4 Class sampleChromClass = sampleChrom.getClass();
 285  4 IInitializer chromIniter = m_activeConfiguration.getJGAPFactory().
 286    getInitializerFor(sampleChrom, sampleChromClass);
 287  4 while (getPopulation().size() < minSize) {
 288  49 try {
 289  49 newChrom = (IChromosome) chromIniter.perform(sampleChrom,
 290    sampleChromClass, null);
 291    // Chromosome.randomInitialChromosome(m_activeConfiguration);
 292  49 getPopulation().addChromosome(newChrom);
 293    }catch (Exception ex) {
 294  0 throw new RuntimeException(ex);
 295    }
 296    }
 297    // }
 298    // catch (InvalidConfigurationException invex) {
 299    // throw new IllegalStateException(invex.getMessage());
 300    // }
 301    }
 302    }
 303  30 if (m_activeConfiguration.isPreserveFittestIndividual()) {
 304  15 IChromosome fittest = getFittestChromosome(0,
 305    m_activeConfiguration.
 306    getPopulationSize() - 1);
 307  15 if (m_activeConfiguration.isKeepPopulationSizeConstant()) {
 308  12 keepPopSizeConstant(getPopulation(),
 309    m_activeConfiguration.getPopulationSize());
 310    }
 311    // Determine the fittest chromosome in the population.
 312    // ---------------------------------------------------
 313  15 if (!getPopulation().contains(fittest)) {
 314    // Re-add fittest chromosome to current population.
 315    // ------------------------------------------------
 316  8 getPopulation().addChromosome(fittest);
 317    }
 318    }
 319    // Increase number of generation.
 320    // ------------------------------
 321  30 m_activeConfiguration.incrementGenerationNr();
 322    // Fire an event to indicate we've performed an evolution.
 323    // -------------------------------------------------------
 324  30 m_activeConfiguration.getEventManager().fireGeneticEvent(
 325    new GeneticEvent(GeneticEvent.GENOTYPE_EVOLVED_EVENT, this));
 326    }
 327   
 328    /**
 329    * Evolves this Genotype the specified number of times. This is
 330    * equivalent to invoking the standard evolve() method the given number
 331    * of times in a row.
 332    *
 333    * @param a_numberOfEvolutions the number of times to evolve this Genotype
 334    * before returning
 335    *
 336    * @author Klaus Meffert
 337    * @since 1.1
 338    */
 339  12 public void evolve(int a_numberOfEvolutions) {
 340  12 for (int i = 0; i < a_numberOfEvolutions; i++) {
 341  19 evolve();
 342    }
 343  12 if (m_activeConfiguration.isKeepPopulationSizeConstant()) {
 344  7 keepPopSizeConstant(getPopulation(),
 345    m_activeConfiguration.getPopulationSize());
 346    }
 347    }
 348   
 349    /**
 350    * Return a string representation of this Genotype instance,
 351    * useful for display purposes.
 352    *
 353    * @return string representation of this Genotype instance
 354    *
 355    * @author Neil Rotstan
 356    * @since 1.0
 357    */
 358  10 public String toString() {
 359  10 StringBuffer buffer = new StringBuffer();
 360  10 for (int i = 0; i < getPopulation().size(); i++) {
 361  10 buffer.append(getPopulation().getChromosome(i).toString());
 362  10 buffer.append(" [");
 363  10 buffer.append(getPopulation().getChromosome(i).getFitnessValueDirectly());
 364  10 buffer.append("]\n");
 365    }
 366  10 return buffer.toString();
 367    }
 368   
 369    /**
 370    * Convenience method that returns a newly constructed Genotype
 371    * instance configured according to the given Configuration instance.
 372    * The population of Chromosomes will be created according to the setup of
 373    * the sample Chromosome in the Configuration object, but the gene values
 374    * (alleles) will be set to random legal values.
 375    *
 376    * @param a_configuration the current active Configuration object
 377    * @return a newly constructed Genotype instance
 378    *
 379    * @throws IllegalArgumentException if the given Configuration object is null
 380    * @throws InvalidConfigurationException if the given Configuration
 381    * instance is not in a valid state
 382    *
 383    * @author Neil Rotstan
 384    * @author Klaus Meffert
 385    * @since 2.3
 386    */
 387  20 public static Genotype randomInitialGenotype(Configuration
 388    a_configuration)
 389    throws InvalidConfigurationException {
 390  20 if (a_configuration == null) {
 391  1 throw new IllegalArgumentException(
 392    "The Configuration instance may not be null.");
 393    }
 394  19 a_configuration.lockSettings();
 395    // Create an array of chromosomes equal to the desired size in the
 396    // active Configuration and then populate that array with Chromosome
 397    // instances constructed according to the setup in the sample
 398    // Chromosome, but with random gene values (alleles). The Chromosome
 399    // class randomInitialChromosome() method will take care of that for
 400    // us.
 401    // ------------------------------------------------------------------
 402  18 int populationSize = a_configuration.getPopulationSize();
 403  18 IChromosome sampleChrom = a_configuration.getSampleChromosome();
 404  18 IInitializer chromIniter = a_configuration.getJGAPFactory().
 405    getInitializerFor(sampleChrom, sampleChrom.getClass());
 406  18 if (chromIniter == null) {
 407  0 throw new InvalidConfigurationException("No initializer found for class "
 408    + sampleChrom.getClass());
 409    }
 410  18 Population pop = new Population(a_configuration, populationSize);
 411    // Do randomized initialization.
 412    // -----------------------------
 413  18 try {
 414  18 for (int i = 0; i < populationSize; i++) {
 415  15680 pop.addChromosome( (IChromosome) chromIniter.perform(sampleChrom,
 416    sampleChrom.getClass(), null));
 417    }
 418    }
 419    catch (Exception ex) {
 420  1 throw new IllegalStateException(ex.getMessage());
 421    }
 422  17 return new Genotype(a_configuration, pop);
 423    }
 424   
 425    /**
 426    * Compares this Genotype against the specified object. The result is true
 427    * if the argument is an instance of the Genotype class, has exactly the
 428    * same number of chromosomes as the given Genotype, and, for each
 429    * Chromosome in this Genotype, there is an equal chromosome in the
 430    * given Genotype. The chromosomes do not need to appear in the same order
 431    * within the populations.
 432    *
 433    * @param a_other the object to compare against
 434    * @return true if the objects are the same, false otherwise
 435    *
 436    * @author Neil Rotstan
 437    * @author Klaus Meffert
 438    * @since 1.0
 439    */
 440  463324 public boolean equals(Object a_other) {
 441  463324 try {
 442    // First, if the other Genotype is null, then they're not equal.
 443    // -------------------------------------------------------------
 444  463324 if (a_other == null) {
 445  1 return false;
 446    }
 447  463323 Genotype otherGenotype = (Genotype) a_other;
 448    // First, make sure the other Genotype has the same number of
 449    // chromosomes as this one.
 450    // ----------------------------------------------------------
 451  463322 if (getPopulation().size() != otherGenotype.getPopulation().size()) {
 452  1 return false;
 453    }
 454    // Next, prepare to compare the chromosomes of the other Genotype
 455    // against the chromosomes of this Genotype. To make this a lot
 456    // simpler, we first sort the chromosomes in both this Genotype
 457    // and the one we're comparing against. This won't affect the
 458    // genetic algorithm (it doesn't care about the order), but makes
 459    // it much easier to perform the comparison here.
 460    // --------------------------------------------------------------
 461  463321 Collections.sort(getPopulation().getChromosomes());
 462  463321 Collections.sort(otherGenotype.getPopulation().getChromosomes());
 463  463321 for (int i = 0; i < getPopulation().size(); i++) {
 464  463330 if (! (getPopulation().getChromosome(i).equals(
 465    otherGenotype.getPopulation().getChromosome(i)))) {
 466  463270 return false;
 467    }
 468    }
 469  51 return true;
 470    }
 471    catch (ClassCastException e) {
 472  1 return false;
 473    }
 474    }
 475   
 476    /**
 477    * Applies all NaturalSelectors registered with the Configuration.
 478    * @param a_processBeforeGeneticOperators true apply NaturalSelectors
 479    * applicable before GeneticOperators, false: apply the ones applicable
 480    * after GeneticOperators
 481    *
 482    * @author Klaus Meffert
 483    * @since 2.0
 484    */
 485  60 protected void applyNaturalSelectors(
 486    boolean a_processBeforeGeneticOperators) {
 487    /**@todo optionally use working pool*/
 488  60 try {
 489    // Process all natural selectors applicable before executing the
 490    // genetic operators (reproduction, crossing over, mutation...).
 491    // -------------------------------------------------------------
 492  60 int selectorSize = m_activeConfiguration.getNaturalSelectorsSize(
 493    a_processBeforeGeneticOperators);
 494  60 if (selectorSize > 0) {
 495  27 int m_population_size = m_activeConfiguration.getPopulationSize();
 496  27 int m_single_selection_size;
 497  27 Population m_new_population;
 498  27 m_new_population = new Population(m_activeConfiguration,
 499    m_population_size);
 500  27 NaturalSelector selector;
 501    // Repopulate the population of chromosomes with those selected
 502    // by the natural selector. Iterate over all natural selectors.
 503    // ------------------------------------------------------------
 504  27 for (int i = 0; i < selectorSize; i++) {
 505  28 selector = m_activeConfiguration.getNaturalSelector(
 506    a_processBeforeGeneticOperators, i);
 507  28 if (i == selectorSize - 1 && i > 0) {
 508    // Ensure the last NaturalSelector adds the remaining Chromosomes.
 509    // ---------------------------------------------------------------
 510  1 m_single_selection_size = m_population_size - getPopulation().size();
 511    }
 512    else {
 513  27 m_single_selection_size = m_population_size / selectorSize;
 514    }
 515    // Do selection of Chromosomes.
 516    // ----------------------------
 517  28 selector.select(m_single_selection_size, getPopulation(),
 518    m_new_population);
 519    // Clean up the natural selector.
 520    // ------------------------------
 521  28 selector.empty();
 522    }
 523  27 setPopulation(new Population(m_activeConfiguration));
 524  27 getPopulation().addChromosomes(m_new_population);
 525    }
 526    }
 527    catch (InvalidConfigurationException iex) {
 528    // This exception should never be reached
 529  0 throw new IllegalStateException(iex.getMessage());
 530    }
 531    }
 532   
 533    /**
 534    * Applies all GeneticOperators registered with the Configuration.
 535    *
 536    * @author Klaus Meffert
 537    * @since 3.0
 538    */
 539  30 public void applyGeneticOperators() {
 540  30 List geneticOperators = m_activeConfiguration.getGeneticOperators();
 541  30 Iterator operatorIterator = geneticOperators.iterator();
 542  30 while (operatorIterator.hasNext()) {
 543  37 GeneticOperator operator = (GeneticOperator) operatorIterator.next();
 544  37 applyGeneticOperator(operator, getPopulation(),
 545    getPopulation().getChromosomes());
 546   
 547    // List workingPool = new Vector();
 548    // applyGeneticOperator(operator, getPopulation(),
 549    // workingPool);
 550    }
 551    }
 552   
 553    /**
 554    * @return the configuration to use with the Genetic Algorithm
 555    *
 556    * @author Klaus Meffert
 557    * @since 2.0 (?)
 558    */
 559  32 public static Configuration getStaticConfiguration() {
 560  32 return m_staticConfiguration;
 561    }
 562   
 563    /**
 564    * Sets the configuration to use with the Genetic Algorithm.
 565    * @param a_configuration the configuration to use
 566    *
 567    * @author Klaus Meffert
 568    * @since 2.0 (?)
 569    */
 570  1273 public static void setStaticConfiguration(Configuration a_configuration) {
 571  1273 m_staticConfiguration = a_configuration;
 572    }
 573   
 574  16 public Configuration getConfiguration() {
 575  16 return m_activeConfiguration;
 576    }
 577   
 578    /***
 579    * Hashcode function for the genotype, tries to create a unique hashcode for
 580    * the chromosomes within the population. The logic for the hashcode is
 581    *
 582    * Step Result
 583    * ---- ------
 584    * 1 31*0 + hashcode_0 = y(1)
 585    * 2 31*y(1) + hashcode_1 = y(2)
 586    * 3 31*y(2) + hashcode_2 = y(3)
 587    * n 31*y(n-1) + hashcode_n-1 = y(n)
 588    *
 589    * Each hashcode is a number and the binary equivalent is computed and
 590    * returned.
 591    * @return the computed hashcode
 592    *
 593    * @author vamsi
 594    * @since 2.1
 595    */
 596  969 public int hashCode() {
 597  969 int i, size = getPopulation().size();
 598  969 IChromosome s;
 599  969 int twopower = 1;
 600    // For empty genotype we want a special value different from other hashcode
 601    // implementations.
 602    // ------------------------------------------------------------------------
 603  969 int localHashCode = -573;
 604  969 for (i = 0; i < size; i++, twopower = 2 * twopower) {
 605  987 s = getPopulation().getChromosome(i);
 606  987 localHashCode = 31 * localHashCode + s.hashCode();
 607    }
 608  969 return localHashCode;
 609    }
 610   
 611  28 protected void setPopulation(Population a_pop) {
 612  28 m_population = a_pop;
 613    }
 614   
 615    /**
 616    * Overwritable method that calls a GeneticOperator to operate on a given
 617    * population and asks him to store the result in the list of chromosomes.
 618    * Override this method if you want to ensure that a_chromosomes is not
 619    * part of a_population resp. if you want to use a different list.
 620    *
 621    * @param a_operator the GeneticOperator to call
 622    * @param a_population the population to use
 623    * @param a_chromosomes the list of Chromosome objects to return
 624    *
 625    * @author Klaus Meffert
 626    * @since 2.4
 627    */
 628  37 protected void applyGeneticOperator(GeneticOperator a_operator,
 629    Population a_population,
 630    List a_chromosomes) {
 631  37 a_operator.operate(a_population, a_chromosomes);
 632    }
 633   
 634    /**
 635    * Cares that the population size does not exceed the given maximum size.
 636    * @param a_pop the population to keep constant in size
 637    * @param a_maxSize the maximum size allowed for the population
 638    *
 639    * @author Klaus Meffert
 640    * @since 2.5
 641    */
 642  43 protected void keepPopSizeConstant(Population a_pop, int a_maxSize) {
 643  43 int popSize = a_pop.size();
 644    // See request 1213752.
 645    // ---------------------
 646  42 while (popSize > a_maxSize) {
 647    // Remove a chromosome.
 648    // --------------------
 649  53 a_pop.removeChromosome(0);
 650  53 popSize--;
 651    }
 652    }
 653    /**
 654    * If used with a Thread: runs the evolution forever.
 655    * You have to implement a listener to stop computation sometime. See
 656    * examples.simpleBooleanThreaded for a possible implementation of such a
 657    * listener.
 658    *
 659    * @author Klaus Meffert
 660    * @since 3.01
 661    */
 662  0 public void run() {
 663  0 while (!Thread.currentThread().interrupted()) {
 664  0 evolve();
 665    }
 666    }
 667    }