Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 1.459   Methods: 56
NCLOC: 568   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
Configuration.java 92,9% 96,4% 98,2% 95,8%
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.data.config.*;
 15    import org.jgap.event.*;
 16    import org.jgap.impl.*;
 17   
 18    /**
 19    * The Configuration class represents the current configuration of
 20    * plugins and parameters necessary to execute the genetic algorithm (such
 21    * as fitness function, natural selector, genetic operators, and so on).
 22    * <p>
 23    * Note that, while during setup, the settings, flags, and other
 24    * values may be set multiple times. But once the lockSettings() method
 25    * is invoked, they cannot be changed. The default behavior of the
 26    * Genotype constructor is to invoke this method, meaning that
 27    * once a Configuration object is passed to a Genotype, it cannot
 28    * be subsequently modified. There is no mechanism for unlocking
 29    * the settings once they are locked.
 30    * <p>
 31    * Not all configuration options are required. See the documentation
 32    * for each of the respective mutator methods to determine whether
 33    * it is required to provide a value for that setting, and what the
 34    * setting will default to if not.
 35    *
 36    * @author Neil Rotstan
 37    * @author Klaus Meffert
 38    * @since 1.0
 39    */
 40    public class Configuration
 41    implements Configurable, Serializable {
 42    /** String containing the CVS revision. Read out via reflection!*/
 43    private final static String CVS_REVISION = "$Revision: 1.68 $";
 44   
 45    /**
 46    * Constant for class name of JGAP Factory to use. Use as:
 47    * System.setProperty(PROPERTY_JGAPFACTORY_CLASS, "myJGAPFactory");
 48    * If none such property set, class JGAPFactory will be used.
 49    */
 50    public static final String PROPERTY_JGAPFACTORY_CLASS = "JGAPFACTORYCLASS";
 51   
 52    public static final String PROPERTY_FITFUNC_INST = "JGAPFITFUNCINST";
 53   
 54    public static final String PROPERTY_BFITFNC_INST = "JGAPBFITFNCINST";
 55   
 56    public static final String PROPERTY_FITEVAL_INST = "JGAPFITEVALINST";
 57   
 58    public static final String PROPERTY_SAMPLE_CHROM_INST = "JGAPSAMPLECHRMINST";
 59   
 60    public static final String PROPERTY_EVENT_MGR_INST = "JGAPEVNTMGRINST";
 61   
 62    /**
 63    * Constants for toString()
 64    */
 65    public static final String S_CONFIGURATION = "Configuration";
 66   
 67    public static final String S_CONFIGURATION_NAME = "Configuration name";
 68   
 69    public static final String S_POPULATION_SIZE = "Population size";
 70   
 71    public static final String S_MINPOPSIZE = "Minimum pop. size [%]";
 72   
 73    public static final String S_CHROMOSOME_SIZE = "Chromosome size";
 74   
 75    public static final String S_SAMPLE_CHROM = "Sample Chromosome";
 76   
 77    public static final String S_SIZE = "Size";
 78   
 79    public static final String S_TOSTRING = "toString";
 80   
 81    public static final String S_RANDOM_GENERATOR = "Random generator";
 82   
 83    public static final String S_EVENT_MANAGER = "Event manager";
 84   
 85    public static final String S_NONE = "none";
 86   
 87    public static final String S_CONFIGURATION_HANDLER = "Configuration handler";
 88   
 89    public static final String S_FITNESS_FUNCTION = "Fitness function";
 90   
 91    public static final String S_FITNESS_EVALUATOR = "Fitness evaluator";
 92   
 93    public static final String S_GENETIC_OPERATORS = "Genetic operators";
 94   
 95    public static final String S_NATURAL_SELECTORS = "Natural Selectors";
 96   
 97    public static final String S_PRE = "pre";
 98   
 99    public static final String S_POST = "post";
 100   
 101    private ConfigurationConfigurable m_config = new ConfigurationConfigurable();
 102   
 103    /**
 104    * References the current fitness function that will be used to evaluate
 105    * chromosomes during the natural selection process. Note that only this
 106    * or the bulk fitness function may be set - the two are mutually exclusive.
 107    *
 108    * @author Neil Rotstan
 109    * @since 1.0
 110    */
 111    private FitnessFunction m_objectiveFunction;
 112   
 113    /**
 114    * The fitness evaluator. See interface class FitnessEvaluator for details
 115    * @since 2.0 (since 1.1 in class Genotype).
 116    */
 117    private FitnessEvaluator m_fitnessEvaluator;
 118   
 119    /**
 120    * Minimum size guaranteed for population. If zero or below then no ensurance.
 121    */
 122    private int m_minPercentageSizePopulation;
 123   
 124    /**
 125    * References the current bulk fitness function that will be used to
 126    * evaluate chromosomes (in bulk) during the natural selection
 127    * process. Note that only this or the normal fitness function
 128    * may be set - the two are mutually exclusive.
 129    *
 130    * @author Neil Rotstan
 131    * @since 1.0
 132    */
 133    private BulkFitnessFunction m_bulkObjectiveFunction;
 134   
 135    /**
 136    * References a Chromosome that serves as a sample of the Gene setup
 137    * that is to be used. Each gene in the Chromosome should be represented
 138    * with the desired Gene type.
 139    *
 140    * @author Neil Rotstan
 141    * @since 1.0
 142    */
 143    private IChromosome m_sampleChromosome;
 144   
 145    /**
 146    * References the random number generator implementation that is to be
 147    * used for the generation of any random numbers during the various
 148    * genetic operations and processes.
 149    *
 150    * @author Neil Rotstan
 151    * @since 1.0
 152    */
 153    private RandomGenerator m_randomGenerator;
 154   
 155    /**
 156    * References the event manager that is to be used for the notification
 157    * of genetic events and the management of event subscribers.
 158    *
 159    * @author Neil Rotstan
 160    * @since 1.0
 161    */
 162    private transient IEventManager m_eventManager;
 163   
 164    /**
 165    * References the chromosome pool, if any, that is to be used to pool
 166    * discarded Chromosome instances so that they may be recycled later,
 167    * thereby saving memory and the time to construct them from scratch.
 168    *
 169    * @author Neil Rotstan
 170    * @since 1.0
 171    */
 172    private transient IChromosomePool m_chromosomePool;
 173   
 174    /**
 175    * Stores all of the GeneticOperator implementations that are to be used
 176    * to operate upon the chromosomes of a population prior to natural
 177    * selection. Operators will be executed in the order that they are
 178    * added to this list.
 179    *
 180    * @author Klaus Meffert
 181    * @since 1.1
 182    */
 183    private List m_geneticOperators;
 184   
 185    /**
 186    * The number of genes that will be stored in each chromosome in the
 187    * population.
 188    */
 189    private int m_chromosomeSize;
 190   
 191    /**
 192    * Indicates whether the settings of this Configuration instance have
 193    * been locked. Prior to locking, the settings may be set and reset
 194    * as desired. Once this flag is set to true, no settings may be
 195    * altered.
 196    */
 197    private boolean m_settingsLocked;
 198   
 199    /**
 200    * Ordered chain of NaturalSelector's which will be executed before applying
 201    * Genetic Operators.
 202    *
 203    * @author Klaus Meffert
 204    * @since 1.1
 205    */
 206    private ChainOfSelectors m_preSelectors;
 207   
 208    /**
 209    * Ordered chain of NaturalSelector's which will be executed after applying
 210    * Genetic Operators.
 211    *
 212    * @author Klaus Meffert
 213    * @since 1.1
 214    */
 215    private ChainOfSelectors m_postSelectors;
 216   
 217    private int m_sizeNaturalSelectorsPre;
 218   
 219    private int m_sizeNaturalSelectorsPost;
 220   
 221    /**
 222    * Should the fittest chromosome in the population be preserved to the next
 223    * generation when evolving (in Genotype.evolve()) ?
 224    */
 225    private boolean m_preserveFittestIndividual;
 226   
 227    /**
 228    * Indicates how many times the evolve()-method in class Genotype has been
 229    * called. Represents the number of the current population.
 230    *
 231    * @author Klaus Meffert
 232    * @since 2.2
 233    */
 234    private int m_generationNr;
 235   
 236    /**
 237    * The Configuration Handler for this Configurable.
 238    *
 239    * @author Siddhartha Azad
 240    * @since 2.3
 241    */
 242    private transient RootConfigurationHandler m_conHandler;
 243   
 244    /**
 245    * Informative name for output.
 246    *
 247    * @author Klaus Meffert
 248    * @since 2.3
 249    */
 250    private String m_name;
 251   
 252    /**
 253    * True: population size will be kept constant at specified size in
 254    * configuration. False: population size will grow dependently on used
 255    * NaturalSelector's and GeneticOperator's.
 256    * Default is TRUE
 257    *
 258    * @author Klaus Meffert
 259    * @since 2.4
 260    */
 261    private boolean m_keepPopulationSizeConstant;
 262   
 263    /**
 264    * Holds the central configurable factory for creating default objects.
 265    *
 266    * @author Klaus Meffert
 267    * @since 2.6
 268    */
 269    private transient IJGAPFactory m_factory;
 270   
 271    private transient String threadKey;
 272   
 273    /**
 274    * Unique ID for a configuration to distinguish it from other configurations
 275    * instantiated within the same thread.
 276    *
 277    * @author Klaus Meffert
 278    * @since 3.01
 279    */
 280    private String m_id;
 281   
 282  1289 public Configuration() {
 283  1289 this("", null);
 284    }
 285   
 286    /**
 287    * Initialize with default values.
 288    *
 289    * @param a_id unique id for the configuration within the current thread
 290    * @param a_name informative name of the configuration, may be null
 291    *
 292    * @author Neil Rotstan
 293    * @author Klaus Meffert
 294    * @since 1.0
 295    */
 296  3681 public Configuration(String a_id, String a_name) {
 297  3681 m_id = a_id;
 298  3681 setName(a_name);
 299  3681 makeThreadKey();
 300  3681 m_preSelectors = new ChainOfSelectors();
 301  3681 m_postSelectors = new ChainOfSelectors();
 302  3681 m_sizeNaturalSelectorsPre = 0;
 303  3681 m_sizeNaturalSelectorsPost = 0;
 304    // use synchronized list for distributed computing
 305  3681 m_geneticOperators = new Vector();
 306  3681 m_conHandler = new RootConfigurationHandler();
 307  3681 m_conHandler.setConfigurable(this);
 308  3681 m_keepPopulationSizeConstant = true;
 309    // Create factory for being able to configure the used default objects,
 310    // like random generators or fitness evaluators.
 311    // --------------------------------------------------------------------
 312  3681 String clazz = System.getProperty(PROPERTY_JGAPFACTORY_CLASS);
 313  3681 if (clazz != null && clazz.length() > 0) {
 314  2 try {
 315  2 m_factory = (IJGAPFactory) Class.forName(clazz).newInstance();
 316    } catch (Throwable ex) {
 317  1 throw new RuntimeException("Class " + clazz
 318    + " could not be instantiated"
 319    + " as type IJGAPFactory");
 320    }
 321    }
 322    else {
 323  3679 m_factory = new JGAPFactory(false);
 324    }
 325    }
 326   
 327    /**
 328    * Constructs a configuration with an informative name but without a unique
 329    * ID. This practically prevents more than one configurations to be
 330    * instantiated within the same thread.
 331    *
 332    * @param a_name informative name of the configuration, may be null
 333    *
 334    * @author Klaus Meffert
 335    */
 336  2 public Configuration(final String a_name) {
 337  2 this();
 338  2 setName(a_name);
 339    }
 340   
 341    /**
 342    * Reads in the configuration from the given file.
 343    * @param a_configFileName the config file from which to load the
 344    * configuration
 345    * @param a_ignore just there to create distinct signatures :-(
 346    *
 347    * @throws ConfigException
 348    * @throws InvalidConfigurationException
 349    *
 350    * @author Siddhartha Azad
 351    * @since 2.3
 352    */
 353  1 public Configuration(String a_configFileName, boolean a_ignore)
 354    throws ConfigException, InvalidConfigurationException {
 355  1 this();
 356  1 ConfigFileReader.instance().setFileName(a_configFileName);
 357    // Set the configuration statically for constructing classes by the
 358    // default constructor.
 359    // ----------------------------------------------------------------
 360  1 Genotype.setStaticConfiguration(this);
 361    // Read in the config, thus creating instances of configurable classes
 362    // by invoking their default constructor.
 363    // -------------------------------------------------------------------
 364  1 getConfigurationHandler().readConfig();
 365    }
 366   
 367    /**
 368    * SHOULD NOT BE NECESSARY TO CALL UNDER NORMAL CIRCUMSTANCES (may be useful
 369    * for unit tests).<p>
 370    * Reset the configuration so that re-setting parameters such as fitness
 371    * function is possible (without calling this method, an overwriting of a
 372    * previously set fitness function results in a RuntimeException).
 373    *
 374    * @author Klaus Meffert
 375    * @since 3.0
 376    */
 377  2561 public static void reset() {
 378  2561 reset("");
 379    }
 380   
 381  2561 public static void reset(String a_id) {
 382  2561 String threadKey = getThreadKey(Thread.currentThread(), a_id);
 383  2561 System.setProperty(threadKey + Configuration.PROPERTY_FITFUNC_INST, "");
 384  2561 System.setProperty(threadKey + Configuration.PROPERTY_BFITFNC_INST, "");
 385  2561 System.setProperty(threadKey + Configuration.PROPERTY_FITEVAL_INST, "");
 386  2561 System.setProperty(threadKey + Configuration.PROPERTY_SAMPLE_CHROM_INST, "");
 387  2561 System.setProperty(threadKey + Configuration.PROPERTY_EVENT_MGR_INST, "");
 388    }
 389   
 390    /**
 391    * See Configuration.reset().
 392    * @param a_propName the property to reset
 393    *
 394    * @author Klaus Meffert
 395    * @since 3.0
 396    */
 397  2524 public static void resetProperty(String a_propName) {
 398  2524 resetProperty(a_propName, "");
 399    }
 400   
 401  2524 public static void resetProperty(String a_propName, String a_id) {
 402  2524 String threadKey = getThreadKey(Thread.currentThread(), a_id);
 403  2524 System.setProperty(threadKey + a_propName, "");
 404    }
 405   
 406    /**
 407    * @param a_name informative name of the configuration
 408    *
 409    * @author Klaus Meffert
 410    * @since 2.3
 411    */
 412  3685 public void setName(final String a_name) {
 413  3685 m_name = a_name;
 414    }
 415   
 416    /**
 417    * @return informative name of the configuration
 418    *
 419    * @author Klaus Meffert
 420    * @since 2.3
 421    */
 422  10 public String getName() {
 423  10 return m_name;
 424    }
 425   
 426    /**
 427    * Sets the fitness function to be used for this genetic algorithm.
 428    * The fitness function is responsible for evaluating a given
 429    * Chromosome and returning a positive integer that represents its
 430    * worth as a candidate solution. These values are used as a guide by the
 431    * natural to determine which Chromosome instances will be allowed to move
 432    * on to the next round of evolution, and which will instead be eliminated.
 433    * <p>
 434    * Note that it is illegal to set both this fitness function and a bulk
 435    * fitness function. Although one or the other must be set, the two are
 436    * mutually exclusive.
 437    *
 438    * @param a_functionToSet fitness function to be used
 439    *
 440    * @throws InvalidConfigurationException if the fitness function is null, a
 441    * bulk fitness function has already been set, or if this Configuration
 442    * object is locked.
 443    *
 444    * @author Neil Rotstan
 445    * @since 1.1
 446    */
 447  2259 public synchronized void setFitnessFunction(FitnessFunction a_functionToSet)
 448    throws InvalidConfigurationException {
 449  2259 verifyChangesAllowed();
 450    // Sanity check: Make sure that the given fitness function isn't null.
 451    // -------------------------------------------------------------------
 452  2259 if (a_functionToSet == null) {
 453  1 throw new InvalidConfigurationException(
 454    "The FitnessFunction instance may not be null.");
 455    }
 456    // Make sure the bulk fitness function hasn't already been set.
 457    // ------------------------------------------------------------
 458  2258 if (m_bulkObjectiveFunction != null) {
 459  1 throw new InvalidConfigurationException(
 460    "The bulk fitness function and normal fitness function " +
 461    "may not both be set.");
 462    }
 463    // Ensure that no other fitness function has been set in a different
 464    // configuration object within the same thread!
 465    // -----------------------------------------------------------------
 466  2257 checkProperty(PROPERTY_FITFUNC_INST, a_functionToSet,
 467    "Fitness function has already been set differently.");
 468  2254 m_objectiveFunction = a_functionToSet;
 469    }
 470   
 471    /**
 472    * Verifies that a property is not set. If not set, set it, otherwise throw
 473    * a RuntimeException with a_errmsg as text.
 474    * @param a_propname the property to check (the current thread will be
 475    * considered as a part of the property's name, too)
 476    * @param a_obj the object that should be set in charge of the property
 477    * @param a_errmsg the error message to throw in case the property is already
 478    * set for the current thread
 479    *
 480    * @author Klaus Meffert
 481    * @since 3.0
 482    */
 483  11634 protected void checkProperty(String a_propname, Object a_obj, String a_errmsg) {
 484  11634 String instanceHash = System.getProperty(threadKey + a_propname, null);
 485  11634 String key = makeKey(a_obj);
 486  11634 if (instanceHash == null || instanceHash.length() < 1) {
 487  11551 System.setProperty(threadKey + a_propname, key);
 488    }
 489  83 else if (!instanceHash.equals(key)) {
 490  5 throw new RuntimeException(a_errmsg + "\nIf you want to set or construct"
 491    +" a configuration multiple times, please call"
 492    + " static method Configuration.reset() before"
 493    +" each setting!");
 494    }
 495    }
 496   
 497    /**
 498    * @param a_obj the object to make a key for, must not be null
 499    * @return key produced for the object (hashCode() is used, so it should be
 500    * implemented properly!)
 501    *
 502    * @author Klaus Meffert
 503    * @since 3.0
 504    */
 505  11634 protected String makeKey(Object a_obj) {
 506  11634 String key = String.valueOf(a_obj.hashCode())
 507    + a_obj.getClass().getName();
 508  11634 return key;
 509    }
 510   
 511    /**
 512    * Retrieves the fitness function previously setup in this Configuration
 513    * object.
 514    *
 515    * @return the fitness function
 516    *
 517    * @author Neil Rotstan
 518    * @since 1.0
 519    */
 520  6852 public synchronized FitnessFunction getFitnessFunction() {
 521  6852 return m_objectiveFunction;
 522    }
 523   
 524    /**
 525    * Sets the bulk fitness function to be used for this genetic algorithm.
 526    * The bulk fitness function may be used to evaluate and assign fitness
 527    * values to the entire group of candidate Chromosomes in a single batch.
 528    * This can be useful in cases where it's difficult to assign fitness
 529    * values to a Chromosome in isolation from the other candidate
 530    * Chromosomes.
 531    * <p>
 532    * Note that it is illegal to set both a bulk fitness function and a
 533    * normal fitness function. Although one or the other is required, the
 534    * two are mutually exclusive.
 535    *
 536    * @param a_functionToSet bulk fitness function to be used
 537    *
 538    * @throws InvalidConfigurationException if the bulk fitness function is
 539    * null, the normal fitness function has already been set, or if this
 540    * Configuration object is locked
 541    *
 542    * @author Neil Rotstan
 543    * @since 1.0
 544    */
 545  11 public synchronized void setBulkFitnessFunction(
 546    BulkFitnessFunction a_functionToSet)
 547    throws InvalidConfigurationException {
 548  11 verifyChangesAllowed();
 549    // Sanity check: Make sure that the given bulk fitness function
 550    // isn't null.
 551    // ------------------------------------------------------------
 552  11 if (a_functionToSet == null) {
 553  1 throw new InvalidConfigurationException(
 554    "The BulkFitnessFunction instance may not be null.");
 555    }
 556    // Make sure a normal fitness function hasn't already been set.
 557    // ------------------------------------------------------------
 558  10 if (m_objectiveFunction != null) {
 559  1 throw new InvalidConfigurationException(
 560    "The bulk fitness function and normal fitness function " +
 561    "may not both be set.");
 562    }
 563    // Ensure that no other bulk fitness function has been set in a
 564    // different configuration object within the same thread!
 565    // ------------------------------------------------------------
 566  9 checkProperty(PROPERTY_BFITFNC_INST, a_functionToSet,
 567    "Bulk fitness function has already been set differently.");
 568  8 m_bulkObjectiveFunction = a_functionToSet;
 569    }
 570   
 571    /**
 572    * Retrieves the bulk fitness function previously setup in this
 573    * Configuration object.
 574    *
 575    * @return The bulk fitness function
 576    *
 577    * @author Neil Rotstan
 578    * @since 1.0
 579    */
 580  31 public synchronized BulkFitnessFunction getBulkFitnessFunction() {
 581  31 return m_bulkObjectiveFunction;
 582    }
 583   
 584    /**
 585    * Sets the sample Chromosome that is to be used as a guide for the
 586    * construction of other Chromosomes. The Chromosome should be setup
 587    * with each gene represented by the desired concrete Gene implementation
 588    * for that gene position (locus). Anytime a new Chromosome is created,
 589    * it will be constructed with the same Gene setup as that provided in
 590    * this sample Chromosome.
 591    *
 592    * @param a_sampleChromosomeToSet Chromosome to be used as the sample
 593    * @throws InvalidConfigurationException if the given Chromosome is null or
 594    * this Configuration object is locked
 595    *
 596    * @author Neil Rotstan
 597    * @since 1.0
 598    */
 599  2223 public void setSampleChromosome(IChromosome a_sampleChromosomeToSet)
 600    throws InvalidConfigurationException {
 601  2223 verifyChangesAllowed();
 602    // Sanity check: Make sure that the given chromosome isn't null.
 603   
 604    // -----------------------------------------------------------
 605  2223 if (a_sampleChromosomeToSet == null) {
 606  1 throw new InvalidConfigurationException(
 607    "The sample chromosome instance may not be null.");
 608    }
 609  2222 if (a_sampleChromosomeToSet.getConfiguration() == null) {
 610  0 throw new InvalidConfigurationException(
 611    "The sample chromosome's configuration may not be null.");
 612    }
 613    // Ensure that no other sample chromosome has been set in a
 614    // different configuration object within the same thread!
 615    // --------------------------------------------------------
 616  2222 checkProperty(PROPERTY_SAMPLE_CHROM_INST, a_sampleChromosomeToSet,
 617    "Sample chromosome has already been set differently.");
 618  2222 m_sampleChromosome = a_sampleChromosomeToSet;
 619  2222 m_chromosomeSize = m_sampleChromosome.size();
 620    }
 621   
 622    /**
 623    * Retrieves the sample Chromosome that contains the desired Gene setup
 624    * for each respective gene position (locus).
 625    *
 626    * @return sample Chromosome instance
 627    *
 628    * @author Neil Rotstan
 629    * @since 1.0
 630    */
 631  15825 public IChromosome getSampleChromosome() {
 632  15825 return m_sampleChromosome;
 633    }
 634   
 635    /**
 636    * Retrieves the chromosome size being used by this genetic
 637    * algorithm. This value is set automatically when the sample chromosome
 638    * is provided.
 639    *
 640    * @return chromosome size used in this configuration
 641    *
 642    * @author Neil Rotstan
 643    * @since 1.0
 644    */
 645  289 public int getChromosomeSize() {
 646  289 return m_chromosomeSize;
 647    }
 648   
 649    /**
 650    * Sets the natural selector to be used for this genetic algorithm.
 651    * The natural selector is responsible for actually selecting
 652    * which Chromosome instances are allowed to move on to the next
 653    * round of evolution (usually guided by the fitness values
 654    * provided by the fitness function). This setting is required.
 655    *
 656    * @param a_selectorToSet the natural selector to be used
 657    *
 658    * @throws InvalidConfigurationException if the natural selector is null or
 659    * this Configuration object is locked
 660    *
 661    * @author Neil Rotstan
 662    * @since 1.0
 663    * @deprecated use addNaturalSelector(false) instead
 664    */
 665    public synchronized void setNaturalSelector(NaturalSelector a_selectorToSet)
 666    throws InvalidConfigurationException {
 667    addNaturalSelector(a_selectorToSet, false);
 668    }
 669   
 670    /**
 671    * Retrieves the natural selector setup in this Configuration instance.
 672    *
 673    * @return the natural selector
 674    *
 675    * @author Neil Rotstan
 676    * @since 1.0
 677    * @deprecated use getNaturalSelectors(true) or getNaturalSelectors(false)
 678    * to obtain the relevant chain of NaturalSelector's and then call the
 679    * chain's get(index) method
 680    */
 681    public synchronized NaturalSelector getNaturalSelector() {
 682    if (m_sizeNaturalSelectorsPost < 1) {
 683    return null;
 684    }
 685    return getNaturalSelectors(false).get(0);
 686    }
 687   
 688    /**
 689    *
 690    * @param a_processBeforeGeneticOperators boolean
 691    * @param a_index int
 692    * @return NaturalSelector
 693    *
 694    * @author Klaus Meffert
 695    * @since 1.1
 696    */
 697  58 public synchronized NaturalSelector getNaturalSelector(boolean
 698    a_processBeforeGeneticOperators,
 699    int a_index) {
 700  58 if (a_processBeforeGeneticOperators) {
 701  54 if (m_sizeNaturalSelectorsPre <= a_index) {
 702  1 throw new IllegalArgumentException(
 703    "Index of NaturalSelector out of bounds");
 704    }
 705    else {
 706  53 return m_preSelectors.get(a_index);
 707    }
 708    }
 709    else {
 710  4 if (m_sizeNaturalSelectorsPost <= a_index) {
 711  1 throw new IllegalArgumentException(
 712    "Index of NaturalSelector out of bounds");
 713    }
 714    else {
 715  3 return m_postSelectors.get(a_index);
 716    }
 717    }
 718    }
 719   
 720    /**
 721    * Only use for read-only access! Especially don't call clear() for the
 722    * returned ChainOfSelectors object!
 723    * @param a_processBeforeGeneticOperators boolean
 724    * @return ChainOfSelectors
 725    *
 726    * @author Klaus Meffert
 727    * @since 1.1
 728    */
 729  40 public ChainOfSelectors getNaturalSelectors(boolean
 730    a_processBeforeGeneticOperators) {
 731  40 if (a_processBeforeGeneticOperators) {
 732  17 return m_preSelectors;
 733    }
 734    else {
 735  23 return m_postSelectors;
 736    }
 737    }
 738   
 739    /**
 740    *
 741    * @param a_processBeforeGeneticOperators boolean
 742    * @return int
 743    *
 744    * @author Klaus Meffert
 745    * @since 1.1
 746    */
 747  103 public int getNaturalSelectorsSize(boolean a_processBeforeGeneticOperators) {
 748  103 if (a_processBeforeGeneticOperators) {
 749  73 return m_sizeNaturalSelectorsPre;
 750    }
 751    else {
 752  30 return m_sizeNaturalSelectorsPost;
 753    }
 754    }
 755   
 756    /**
 757    * Removes all natural selectors (either pre or post ones)
 758    * @param a_processBeforeGeneticOperators true: remove all selectors
 759    * processed before genetic operators, false: remove the ones processed
 760    * afterwards
 761    *
 762    * @author Klaus Meffert
 763    * @since 2.3
 764    */
 765  12 public void removeNaturalSelectors(boolean a_processBeforeGeneticOperators) {
 766  12 if (a_processBeforeGeneticOperators) {
 767  5 getNaturalSelectors(true);
 768  5 m_sizeNaturalSelectorsPre = 0;
 769    }
 770    else {
 771  7 getNaturalSelectors(false);
 772  7 m_sizeNaturalSelectorsPost = 0;
 773    }
 774    }
 775   
 776    /**
 777    * Sets the random generator to be used for this genetic algorithm.
 778    * The random generator is responsible for generating random numbers,
 779    * which are used throughout the process of genetic evolution and
 780    * selection. This setting is required.
 781    *
 782    * @param a_generatorToSet random generator to be used
 783    *
 784    * @throws InvalidConfigurationException if the random generator is null or
 785    * this object is locked
 786    *
 787    * @author Neil Rotstan
 788    * @since 1.0
 789    */
 790  2700 public synchronized void setRandomGenerator(RandomGenerator a_generatorToSet)
 791    throws InvalidConfigurationException {
 792  2700 verifyChangesAllowed();
 793    // Sanity check: Make sure that the given random generator isn't null.
 794    // -------------------------------------------------------------------
 795  2699 if (a_generatorToSet == null) {
 796  1 throw new InvalidConfigurationException(
 797    "The RandomGenerator instance may not be null.");
 798    }
 799  2698 m_randomGenerator = a_generatorToSet;
 800    }
 801   
 802    /**
 803    * Retrieves the random generator setup in this Configuration instance.
 804    *
 805    * @return the random generator
 806    *
 807    * @author Neil Rotstan
 808    * @since 1.0
 809    */
 810  1524687 public synchronized RandomGenerator getRandomGenerator() {
 811  1524687 return m_randomGenerator;
 812    }
 813   
 814    /**
 815    * Adds a genetic operator for use in this algorithm. Genetic operators
 816    * represent evolutionary steps that, when combined, make up the
 817    * evolutionary process. Examples of genetic operators are reproduction,
 818    * crossover, and mutation. During the evolution process, all of the
 819    * genetic operators added via this method are invoked in the order
 820    * they were added. At least one genetic operator must be provided.
 821    *
 822    * @param a_operatorToAdd The genetic operator to add.
 823    *
 824    * @throws InvalidConfigurationException if the genetic operator is null or
 825    * if this Configuration object is locked
 826    *
 827    * @author Neil Rotstan
 828    * @since 1.0
 829    */
 830  5929 public synchronized void addGeneticOperator(GeneticOperator a_operatorToAdd)
 831    throws InvalidConfigurationException {
 832  5929 verifyChangesAllowed();
 833    // Sanity check: Make sure that the given genetic operator isn't null.
 834    // -------------------------------------------------------------------
 835  5929 if (a_operatorToAdd == null) {
 836  1 throw new InvalidConfigurationException(
 837    "The GeneticOperator instance may not be null.");
 838    }
 839  5928 m_geneticOperators.add(a_operatorToAdd);
 840    }
 841   
 842    /**
 843    * Retrieves the genetic operators setup in this Configuration instance.
 844    * Note that once this Configuration instance is locked, a new,
 845    * immutable list of operators is used and any lists previously
 846    * retrieved with this method will no longer reflect the actual
 847    * list in use.
 848    *
 849    * @return The list of genetic operators
 850    *
 851    * @author Neil Rotstan
 852    * @since 1.0
 853    */
 854  122 public List getGeneticOperators() {
 855  122 return m_geneticOperators;
 856    }
 857   
 858    /**
 859    * Sets the population size to be used for this genetic algorithm.
 860    * The population size is a fixed value that represents the
 861    * number of Chromosomes contained within the Genotype (population).
 862    * This setting is required.
 863    *
 864    * @param a_sizeOfPopulation population size to be used
 865    *
 866    * @throws InvalidConfigurationException if the population size is not
 867    * positive or this object is locked
 868    *
 869    * @author Neil Rotstan
 870    * @since 1.0
 871    */
 872  2295 public synchronized void setPopulationSize(int a_sizeOfPopulation)
 873    throws InvalidConfigurationException {
 874  2295 verifyChangesAllowed();
 875    // Sanity check: Make sure the population size is positive.
 876    // --------------------------------------------------------
 877  2295 if (a_sizeOfPopulation < 1) {
 878  1 throw new InvalidConfigurationException(
 879    "The population size must be positive.");
 880    }
 881  2294 m_config.m_populationSize = a_sizeOfPopulation;
 882    }
 883   
 884    /**
 885    * Retrieves the population size setup in this Configuration instance.
 886    *
 887    * @return population size
 888    */
 889  306 public synchronized int getPopulationSize() {
 890  306 return m_config.m_populationSize;
 891    }
 892   
 893    /**
 894    * Sets the event manager that is to be associated with this configuration.
 895    * The event manager is responsible for the management of event subscribers
 896    * and event notifications.
 897    *
 898    * @param a_eventManagerToSet the EventManager instance to use in this
 899    * configuration
 900    *
 901    * @throws InvalidConfigurationException if the event manager is null
 902    * or this Configuration object is locked
 903    *
 904    * @author Neil Rotstan
 905    * @since 1.0
 906    */
 907  3623 public void setEventManager(IEventManager a_eventManagerToSet)
 908    throws InvalidConfigurationException {
 909  3623 verifyChangesAllowed();
 910    // Sanity check: Make sure that the given event manager isn't null.
 911    // ----------------------------------------------------------------
 912  3623 if (a_eventManagerToSet == null) {
 913  1 throw new InvalidConfigurationException(
 914    "The event manager instance may not be null.");
 915    }
 916    // Ensure that no other event manager has been set in a different
 917    // configuration object within the same thread!
 918    // --------------------------------------------------------------
 919  3622 checkProperty(PROPERTY_EVENT_MGR_INST, a_eventManagerToSet,
 920    "Event manager has already been set differently.");
 921  3621 m_eventManager = a_eventManagerToSet;
 922    }
 923   
 924    /**
 925    * Retrieves the event manager associated with this configuration.
 926    * The event manager is responsible for the management of event subscribers
 927    * and event notifications.
 928    *
 929    * @return the actively configured event manager instance
 930    */
 931  77 public IEventManager getEventManager() {
 932  77 return m_eventManager;
 933    }
 934   
 935    /**
 936    * Sets the ChromosomePool that is to be associated with this
 937    * configuration. The ChromosomePool is used to pool discarded Chromosome
 938    * instances so that they may be recycled later, thereby saving memory and
 939    * the time to construct them from scratch. The presence of a ChromosomePool
 940    * is optional. If none exists, then a new Chromosome will be constructed
 941    * each time one is needed.
 942    *
 943    * @param a_chromosomePoolToSet the ChromosomePool instance to use
 944    * @throws InvalidConfigurationException if this object is locked
 945    *
 946    * @author Neil Rotstan
 947    * @since 1.0
 948    */
 949  2425 public void setChromosomePool(IChromosomePool a_chromosomePoolToSet)
 950    throws InvalidConfigurationException {
 951  2425 verifyChangesAllowed();
 952  2425 m_chromosomePool = a_chromosomePoolToSet;
 953    }
 954   
 955    /**
 956    * Retrieves the ChromosomePool instance, if any, that is associated with
 957    * this configuration. The ChromosomePool is used to pool discarded
 958    * Chromosome instances so that they may be recycled later, thereby
 959    * saving memory and the time to construct them from scratch. The presence
 960    * of a ChromosomePool instance is optional. If none exists, then new
 961    * Chromosomes should be constructed each time one is needed.
 962    *
 963    * @return The ChromosomePool instance associated this configuration, or
 964    * null if none has been provided
 965    *
 966    * @author Neil Rotstan
 967    * @since 1.0
 968    */
 969  19944 public IChromosomePool getChromosomePool() {
 970  19944 return m_chromosomePool;
 971    }
 972   
 973    /**
 974    * Locks all of the settings in this configuration object. Once
 975    * this method is successfully invoked, none of the settings may
 976    * be changed. There is no way to unlock this object once it is locked.
 977    * <p>
 978    * Prior to returning successfully, this method will first invoke the
 979    * verifyStateIsValid() method to make sure that any required configuration
 980    * options have been properly set. If it detects a problem, it will
 981    * throw an InvalidConfigurationException and leave the object unlocked.
 982    * <p>
 983    * It's possible to test whether this object is locked through the
 984    * isLocked() method.
 985    * <p>
 986    * It is ok to lock an object more than once. In that case, this method
 987    * does nothing and simply returns.
 988    *
 989    * @throws InvalidConfigurationException if this Configuration object is
 990    * in an invalid state at the time of invocation
 991    *
 992    * @author Neil Rotstan
 993    * @since 1.0
 994    */
 995  16848 public synchronized void lockSettings()
 996    throws InvalidConfigurationException {
 997  16848 if (!m_settingsLocked) {
 998  1092 verifyStateIsValid();
 999    // Make genetic operators list immutable.
 1000    // --------------------------------------
 1001  1084 m_geneticOperators = Collections.unmodifiableList(m_geneticOperators);
 1002  1084 m_settingsLocked = true;
 1003    }
 1004    }
 1005   
 1006    /**
 1007    * Retrieves the lock status of this object.
 1008    *
 1009    * @return true if this object has been locked by a previous successful
 1010    * call to the lockSettings() method, false otherwise
 1011    *
 1012    * @author Neil Rotstan
 1013    * @since 1.0
 1014    */
 1015  13 public boolean isLocked() {
 1016  13 return m_settingsLocked;
 1017    }
 1018   
 1019    /**
 1020    * Tests the state of this Configuration object to make sure it's valid.
 1021    * This generally consists of verifying that required settings have, in
 1022    * fact, been set. If this object is not in a valid state, then an
 1023    * exception will be thrown detailing the reason the state is not valid.
 1024    *
 1025    * @throws InvalidConfigurationException if the state of this Configuration
 1026    * is not valid. The error message in the exception will detail the reason
 1027    * for invalidity
 1028    *
 1029    * @author Neil Rotstan
 1030    * @since 1.0
 1031    */
 1032  1099 public synchronized void verifyStateIsValid()
 1033    throws InvalidConfigurationException {
 1034    // First, make sure all of the required fields have been set to
 1035    // appropriate values.
 1036    // ------------------------------------------------------------
 1037  1099 if (m_objectiveFunction == null && m_bulkObjectiveFunction == null) {
 1038  5 throw new InvalidConfigurationException(
 1039    "A desired fitness function or bulk fitness function must " +
 1040    "be specified in the active configuration.");
 1041    }
 1042  1094 if (m_sampleChromosome == null) {
 1043  2 throw new InvalidConfigurationException(
 1044    "A sample instance of the desired Chromosome " +
 1045    "setup must be specified in the active configuration.");
 1046    }
 1047  1092 if (m_preSelectors.size() == 0 && m_postSelectors.size() == 0) {
 1048  1 throw new InvalidConfigurationException(
 1049    "At least one desired natural selector must be specified in the"
 1050    + " active configuration.");
 1051    }
 1052  1091 if (m_randomGenerator == null) {
 1053  1 throw new InvalidConfigurationException(
 1054    "A desired random number generator must be specified in the " +
 1055    "active configuration.");
 1056    }
 1057  1090 if (m_eventManager == null) {
 1058  1 throw new InvalidConfigurationException(
 1059    "A desired event manager must be specified in the active " +
 1060    "configuration.");
 1061    }
 1062  1089 if (m_geneticOperators.isEmpty()) {
 1063  2 throw new InvalidConfigurationException(
 1064    "At least one genetic operator must be specified in the " +
 1065    "configuration.");
 1066    }
 1067  1087 if (m_chromosomeSize <= 0) {
 1068  1 throw new InvalidConfigurationException(
 1069    "A chromosome size greater than zero must be specified in " +
 1070    "the active configuration.");
 1071    }
 1072  1086 if (m_config.m_populationSize <= 0) {
 1073  2 throw new InvalidConfigurationException(
 1074    "A genotype size greater than zero must be specified in " +
 1075    "the active configuration.");
 1076    }
 1077  1084 if (m_fitnessEvaluator == null) {
 1078  1 throw new IllegalArgumentException(
 1079    "The fitness evaluator may not be null.");
 1080    }
 1081    // Next, it's critical that each Gene implementation in the sample
 1082    // Chromosome has a working equals() method, or else the genetic
 1083    // engine will end up failing in mysterious and unpredictable ways.
 1084    // We therefore verify right here that this method is working properly
 1085    // in each of the Gene implementations used in the sample Chromosome.
 1086    // -------------------------------------------------------------------
 1087  1083 Gene[] sampleGenes = m_sampleChromosome.getGenes();
 1088  1083 for (int i = 0; i < sampleGenes.length; i++) {
 1089  13618 Gene sampleCopy = sampleGenes[i].newGene();
 1090  13618 sampleCopy.setAllele(sampleGenes[i].getAllele());
 1091  13618 if (! (sampleCopy.equals(sampleGenes[i]))) {
 1092  0 throw new InvalidConfigurationException(
 1093    "The sample Gene at gene position (locus) "
 1094    + i
 1095    + " does not appear to have a working equals() or compareTo()"
 1096    + " method.\n"
 1097    + "It could also be that you forgot to implement method"
 1098    + " newGene() in your Gene implementation.\n"
 1099    + "When tested, the method returned false when comparing "
 1100    + "the sample gene with a gene of the same type and "
 1101    + "possessing the same value (allele).");
 1102    }
 1103    }
 1104    }
 1105   
 1106    /**
 1107    * Makes sure that this Configuration object isn't locked. If it is, then
 1108    * an exception is thrown with an appropriate message indicating
 1109    * that settings in this object may not be altered. This method
 1110    * should be invoked by any mutator method in this object prior
 1111    * to making any state alterations.
 1112    *
 1113    * @throws InvalidConfigurationException if this Configuration object is
 1114    * locked
 1115    *
 1116    * @author Neil Rotstan
 1117    * @since 1.0
 1118    */
 1119  25002 protected void verifyChangesAllowed()
 1120    throws InvalidConfigurationException {
 1121  25002 if (m_settingsLocked) {
 1122  2 throw new InvalidConfigurationException(
 1123    "This Configuration object is locked. Settings may not be " +
 1124    "altered.");
 1125    }
 1126    }
 1127   
 1128    /**
 1129    * Adds a NaturalSelector to the ordered chain of registered
 1130    * NaturalSelector's. It's possible to execute the NaturalSelector before
 1131    * or after (registered) genetic operations have been applied.
 1132    * @param a_selector the selector to be added to the chain
 1133    * @param a_processBeforeGeneticOperators true: execute NaturalSelector
 1134    * before any genetic operator will be applied, false: .. after..
 1135    * @throws InvalidConfigurationException
 1136    *
 1137    * @author Klaus Meffert
 1138    * @since 1.1
 1139    */
 1140  3536 public void addNaturalSelector(NaturalSelector a_selector,
 1141    boolean a_processBeforeGeneticOperators)
 1142    throws InvalidConfigurationException {
 1143  3536 verifyChangesAllowed();
 1144  3536 if (a_processBeforeGeneticOperators) {
 1145  3519 m_preSelectors.addNaturalSelector(a_selector);
 1146  3519 m_sizeNaturalSelectorsPre = m_preSelectors.size();
 1147    }
 1148    else {
 1149  17 m_postSelectors.addNaturalSelector(a_selector);
 1150  17 m_sizeNaturalSelectorsPost = m_postSelectors.size();
 1151    }
 1152    }
 1153   
 1154    /**
 1155    * Minimum size guaranteed for population. This is significant during
 1156    * evolution as natural selectors could select fewer chromosomes for the next
 1157    * generation than the initial population size was.
 1158    * @param a_minimumSizeGuaranteedPercent if zero or below then no ensurance
 1159    * for size given, see Genotype.evolve()
 1160    *
 1161    * @author Klaus Meffert
 1162    */
 1163  2439 public void setMinimumPopSizePercent(int a_minimumSizeGuaranteedPercent) {
 1164  2439 m_minPercentageSizePopulation = a_minimumSizeGuaranteedPercent;
 1165    }
 1166   
 1167  77 public int getMinimumPopSizePercent() {
 1168  77 return m_minPercentageSizePopulation;
 1169    }
 1170   
 1171    /**
 1172    * @return the assigned FitnessEvaluator
 1173    *
 1174    * @author Klaus Meffert
 1175    * @since 2.0
 1176    */
 1177  29312 public FitnessEvaluator getFitnessEvaluator() {
 1178  29312 return m_fitnessEvaluator;
 1179    }
 1180   
 1181    /**
 1182    * Set the fitness evaluator (deciding if a given fitness value is better
 1183    * when it's higher or better when it's lower).
 1184    * @param a_fitnessEvaluator the FitnessEvaluator to be used
 1185    *
 1186    * @author Klaus Meffert
 1187    * @since 2.0
 1188    */
 1189  3525 public void setFitnessEvaluator(FitnessEvaluator a_fitnessEvaluator) {
 1190  3525 if (a_fitnessEvaluator == null) {
 1191  1 throw new IllegalStateException(
 1192    "The fitness evaluator object must not be null!");
 1193    }
 1194    // Ensure that no other fitness evaluator has been set in a
 1195    // different configuration object within the same thread!
 1196    // --------------------------------------------------------
 1197  3524 checkProperty(PROPERTY_FITEVAL_INST, a_fitnessEvaluator,
 1198    "Fitness evaluator has already been set differently.");
 1199  3524 m_fitnessEvaluator = a_fitnessEvaluator;
 1200    }
 1201   
 1202    /**
 1203    * @return true: fittest chromosome should always be transferred to next
 1204    * generation
 1205    *
 1206    * @author Klaus Meffert
 1207    * @since 2.1
 1208    */
 1209  33 public boolean isPreserveFittestIndividual() {
 1210  33 return m_preserveFittestIndividual;
 1211    }
 1212   
 1213    /**
 1214    * Determines whether to save (keep) the fittest individual.
 1215    * @param a_preserveFittest true: always transfer fittest chromosome to next
 1216    * generation
 1217    *
 1218    * @author Klaus Meffert
 1219    * @since 2.1
 1220    */
 1221  8 public void setPreservFittestIndividual(boolean a_preserveFittest) {
 1222  8 m_preserveFittestIndividual = a_preserveFittest;
 1223    }
 1224   
 1225  33 public void incrementGenerationNr() {
 1226  33 m_generationNr++;
 1227    }
 1228   
 1229  13 public int getGenerationNr() {
 1230  13 return m_generationNr;
 1231    }
 1232   
 1233    /**
 1234    * Implementation of the Configurable interface.
 1235    * @return ConfigurationHandler
 1236    * @throws ConfigException
 1237    *
 1238    * @author Siddhartha Azad
 1239    */
 1240  7 public ConfigurationHandler getConfigurationHandler() {
 1241  7 return m_conHandler;
 1242    }
 1243   
 1244    /**
 1245    * @return string representation of the configuration containing all
 1246    * configurable elements
 1247    *
 1248    * @author Klaus Meffert
 1249    * @since 2.3
 1250    */
 1251  2 public String toString() {
 1252  2 String result = S_CONFIGURATION + ":";
 1253    // Basic parameters.
 1254    // -----------------
 1255  2 result += "\n " + S_CONFIGURATION_NAME + ": " + getName();
 1256  2 result += "\n " + S_POPULATION_SIZE + ": " + getPopulationSize();
 1257  2 result += "\n " + S_MINPOPSIZE + ": " + getMinimumPopSizePercent();
 1258  2 result += "\n " + S_CHROMOSOME_SIZE + ": " + getChromosomeSize();
 1259    // Sample chromosome.
 1260    // ------------------
 1261  2 result += "\n " + S_SAMPLE_CHROM + ":\n";
 1262  2 if (getSampleChromosome() == null) {
 1263  0 result += "\n null";
 1264    }
 1265    else {
 1266  2 result += "\n " + S_SIZE + ": " + getSampleChromosome().size();
 1267  2 result += "\n " + S_TOSTRING + ": " + getSampleChromosome().toString();
 1268    }
 1269    // Random generator.
 1270    // -----------------
 1271  2 result += "\n " + S_RANDOM_GENERATOR + ": " +
 1272    getRandomGenerator().getClass().getName();
 1273  2 result += "\n " + S_EVENT_MANAGER + ": ";
 1274    // Event manager.
 1275    // --------------
 1276  2 if (getEventManager() == null) {
 1277  1 result += S_NONE;
 1278    }
 1279    else {
 1280  1 result += getEventManager().getClass().getName();
 1281    }
 1282    // Configuration handler.
 1283    // ----------------------
 1284  2 result += "\n " + S_CONFIGURATION_HANDLER + ": ";
 1285  2 if (getConfigurationHandler() == null) {
 1286  0 result += "null";
 1287    }
 1288    else {
 1289  2 result += getConfigurationHandler().getName();
 1290    }
 1291    // Fitness function.
 1292    // -----------------
 1293  2 result += "\n " + S_FITNESS_FUNCTION + ": ";
 1294  2 if (getFitnessFunction() == null) {
 1295  0 result += "null";
 1296    }
 1297    else {
 1298  2 result += getFitnessFunction().getClass().getName();
 1299    }
 1300    // Fitness evaluator.
 1301    // ------------------
 1302  2 result += "\n " + S_FITNESS_EVALUATOR + ": ";
 1303  2 if (getFitnessEvaluator() == null) {
 1304  0 result += "null";
 1305    }
 1306    else {
 1307  2 result += getFitnessEvaluator().getClass().getName();
 1308    }
 1309    // Genetic operators.
 1310    // ------------------
 1311  2 result += "\n " + S_GENETIC_OPERATORS + ": ";
 1312  2 if (getGeneticOperators() == null) {
 1313  0 result += "null";
 1314    }
 1315    else {
 1316  2 int gensize = getGeneticOperators().size();
 1317  2 if (gensize < 1) {
 1318  1 result += S_NONE;
 1319    }
 1320    else {
 1321  1 for (int i = 0; i < gensize; i++) {
 1322  2 if (i > 0) {
 1323  1 result += "; ";
 1324    }
 1325  2 result += " " + getGeneticOperators().get(i).getClass().getName();
 1326    }
 1327    }
 1328    }
 1329    // Natural selectors (pre).
 1330    // ------------------------
 1331  2 int natsize = getNaturalSelectors(true).size();
 1332  2 result += "\n " + S_NATURAL_SELECTORS + "(" + S_PRE + "): ";
 1333  2 if (natsize < 1) {
 1334  1 result += S_NONE;
 1335    }
 1336    else {
 1337  1 for (int i = 0; i < natsize; i++) {
 1338  2 if (i > 0) {
 1339  1 result += "; ";
 1340    }
 1341  2 result += " " + getNaturalSelectors(true).get(i).getClass().getName();
 1342    }
 1343    }
 1344    // Natural selectors (post).
 1345    // -------------------------
 1346  2 natsize = getNaturalSelectors(false).size();
 1347  2 result += "\n " + S_NATURAL_SELECTORS + "(" + S_POST + "): ";
 1348  2 if (natsize < 1) {
 1349  1 result += "none";
 1350    }
 1351    else {
 1352  1 for (int i = 0; i < natsize; i++) {
 1353  2 if (i > 0) {
 1354  1 result += "; ";
 1355    }
 1356  2 result += " " + getNaturalSelectors(false).get(i).getClass().getName();
 1357    }
 1358    }
 1359  2 return result;
 1360    }
 1361   
 1362    /**
 1363    * See setKeepPopulationSizeConstant for description.
 1364    * @return true: population size will always be the same size
 1365    * (as given with Configuration.setPopulationSize(int)
 1366    *
 1367    * @author Klaus Meffert
 1368    * @since 2.4
 1369    */
 1370  62 public boolean isKeepPopulationSizeConstant() {
 1371  62 return m_keepPopulationSizeConstant;
 1372    }
 1373   
 1374    /**
 1375    * Allows to keep the population size constant after one evolution, even if
 1376    * there is no appropriate instance of NaturalSelector (such as
 1377    * WeightedRouletteSelector) registered with the Configuration.<p>
 1378    * Be aware that keeping the population size constant often means that a
 1379    * higher population size is necessary (e.g. for the MinimizingMakeChange
 1380    * example)!
 1381    * @param a_keepPopSizeConstant true: population size will always be
 1382    * the same size (as given with Configuration.setPopulationSize(int)
 1383    *
 1384    * @author Klaus Meffert
 1385    * @since 2.4
 1386    */
 1387  2403 public void setKeepPopulationSizeConstant(boolean a_keepPopSizeConstant) {
 1388  2403 m_keepPopulationSizeConstant = a_keepPopSizeConstant;
 1389    }
 1390   
 1391  107 public IJGAPFactory getJGAPFactory() {
 1392  107 return m_factory;
 1393    }
 1394   
 1395    class ConfigurationConfigurable
 1396    implements java.io.Serializable {
 1397    /**
 1398    * The number of chromosomes that will be stored in the Genotype.
 1399    */
 1400    int m_populationSize;
 1401    }
 1402   
 1403    /**
 1404    * Builds a string considering the current thread and the given id
 1405    * @param current the current Thread
 1406    * @param a_id a hopefully unique id of the configuration
 1407    *
 1408    * @return string built up
 1409    *
 1410    * @author Klaus Meffert
 1411    * @since 3.01
 1412    */
 1413  8782 protected static String getThreadKey(Thread current, String a_id) {
 1414  8782 return current.toString() + "|" + a_id + "|";
 1415    }
 1416   
 1417    /**
 1418    * @param a_factory the IJGAPFactory to use
 1419    *
 1420    * @author Klaus Meffert
 1421    * @since 3.01
 1422    */
 1423  0 public void setJGAPFactory(IJGAPFactory a_factory) {
 1424  0 m_factory = a_factory;
 1425    }
 1426   
 1427  3697 private void makeThreadKey() {
 1428  3697 Thread current = Thread.currentThread();
 1429  3697 threadKey = getThreadKey(current, m_id);
 1430    }
 1431   
 1432    /**
 1433    * Deserialize the object.
 1434    *
 1435    * @param a_inputStream the ObjectInputStream provided for deserialzation
 1436    * @throws ClassNotFoundException
 1437    * @throws IOException
 1438    *
 1439    * @author Klaus Meffert
 1440    * @since 3.01
 1441    */
 1442  16 private void readObject(ObjectInputStream a_inputStream)
 1443    throws ClassNotFoundException, IOException {
 1444    //always perform the default de-serialization first
 1445  16 a_inputStream.defaultReadObject();
 1446   
 1447  16 makeThreadKey();
 1448    }
 1449   
 1450    /**
 1451    * @return the id of the configuration set
 1452    *
 1453    * @author Klaus Meffert
 1454    * @since 3.1
 1455    */
 1456  2 public String getId() {
 1457  2 return m_id;
 1458    }
 1459    }