Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 563   Methods: 30
NCLOC: 246   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Population.java 100% 99,2% 96,7% 99%
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.util.*;
 15   
 16    /**
 17    * List of chromosomes held in the Genotype (or possibly later in the
 18    * Configuration object).
 19    *
 20    * @author Klaus Meffert
 21    * @since 2.0
 22    */
 23    public class Population
 24    implements Serializable {
 25    /** String containing the CVS revision. Read out via reflection!*/
 26    private static final String CVS_REVISION = "$Revision: 1.50 $";
 27   
 28    /**
 29    * The array of Chromosomes that makeup the Genotype's population.
 30    */
 31    private List m_chromosomes;
 32   
 33    /**
 34    * The fittest Chromosome of the population.
 35    */
 36    private IChromosome m_fittestChromosome;
 37   
 38    /**
 39    * Indicates whether at least one of the chromosomes has been changed
 40    * (deleted, added, modified).
 41    */
 42    private boolean m_changed;
 43   
 44    /**
 45    * Indicates that the list of Chromosomes has been sorted.
 46    */
 47    private boolean m_sorted;
 48   
 49    private /*transient*/ Configuration m_config;
 50   
 51    /*
 52    *
 53    * @author Klaus Meffert
 54    * @since 3.0
 55    */
 56  4639 public Population(final Configuration a_config)
 57    throws InvalidConfigurationException {
 58  4639 this(a_config, 100);
 59    }
 60   
 61    /*
 62    * Constructs the Population from a list of Chromosomes.
 63    * @param a_chromosomes the Chromosome's to be used for building the
 64    * Population
 65    *
 66    * @author Klaus Meffert
 67    * @since 2.0
 68    */
 69  113 public Population(final Configuration a_config,
 70    final IChromosome[] a_chromosomes)
 71    throws InvalidConfigurationException {
 72  113 this(a_config, a_chromosomes.length);
 73  113 synchronized(m_chromosomes) {
 74  113 for (int i = 0; i < a_chromosomes.length; i++) {
 75  4047 m_chromosomes.add(a_chromosomes[i]);
 76    }
 77    }
 78  113 setChanged(true);
 79    }
 80   
 81    /*
 82    * Constructs an empty Population with the given initial size.
 83    * @param a_size the initial size of the empty Population. The initial size
 84    * is not fix, it is just for optimized list creation.
 85    *
 86    * @author Klaus Meffert
 87    * @since 2.0
 88    */
 89  4819 public Population(final Configuration a_config, final int a_size)
 90    throws InvalidConfigurationException {
 91  4819 if (a_config == null) {
 92  4 throw new InvalidConfigurationException("Configuration must not be null!");
 93    }
 94  4815 m_config = a_config;
 95    // Use a synchronized list (important for distributed computing!)
 96  4815 m_chromosomes = new Vector(a_size);
 97  4814 setChanged(true);
 98    }
 99   
 100    /*
 101    * Constructs an empty Population with initial array size 100.
 102    *
 103    * @author Klaus Meffert
 104    * @since 2.0
 105    */
 106  0 public Population()
 107    throws InvalidConfigurationException {
 108  0 this(Genotype.getStaticConfiguration());
 109    }
 110   
 111  51 public Configuration getConfiguration() {
 112  51 return m_config;
 113    }
 114   
 115    /**
 116    * Adds a Chromosome to this Population. Does nothing when given null.
 117    *
 118    * @param a_toAdd the Chromosome to add
 119    *
 120    * @author Klaus Meffert
 121    * @since 2.0
 122    */
 123  22753 public void addChromosome(final IChromosome a_toAdd) {
 124  22753 if (a_toAdd != null) {
 125  22752 synchronized(m_chromosomes) {
 126  22752 m_chromosomes.add(a_toAdd);
 127    }
 128  22752 setChanged(true);
 129    }
 130    }
 131   
 132    /**
 133    * Adds all the Chromosomes in the given Population.
 134    * Does nothing on null or an empty Population.
 135    *
 136    * @param a_population the Population to add
 137    *
 138    * @author Klaus Meffert
 139    * @since 2.0
 140    */
 141  30 public void addChromosomes(final Population a_population) {
 142  30 if (a_population != null) {
 143  29 synchronized(m_chromosomes) {
 144  29 m_chromosomes.addAll(a_population.getChromosomes());
 145    }
 146    // The following would do the same:
 147    // if (a_population.getChromosomes() != null) {
 148    // int size = a_population.getChromosomes().size();
 149    // for (int i = 0; i < size; i++) {
 150    // IChromosome chrom = a_population.getChromosome(i);
 151    // m_chromosomes.add(chrom);
 152    // }
 153    // }
 154  29 setChanged(true);
 155    }
 156    }
 157   
 158    /**
 159    * Replaces all chromosomes in the population with the give list of
 160    * chromosomes.
 161    * @param a_chromosomes the chromosomes to make the population up from
 162    *
 163    * @author Klaus Meffert
 164    */
 165  9 public void setChromosomes(final List a_chromosomes) {
 166  9 synchronized(m_chromosomes) {
 167  9 m_chromosomes = a_chromosomes;
 168    }
 169  9 setChanged(true);
 170    }
 171   
 172    /**
 173    * Sets in the given Chromosome on the given index in the list of chromosomes.
 174    * If the given index is exceeding the list by one, the chromosome is
 175    * appended.
 176    *
 177    * @param a_index the index to set the Chromosome in
 178    * @param a_chromosome the Chromosome to be set
 179    *
 180    * @author Klaus Meffert
 181    * @since 2.0
 182    */
 183  4 public void setChromosome(final int a_index, final IChromosome a_chromosome) {
 184  4 if (m_chromosomes.size() == a_index) {
 185  1 addChromosome(a_chromosome);
 186    }
 187    else {
 188  3 synchronized(m_chromosomes) {
 189  3 m_chromosomes.set(a_index, a_chromosome);
 190    }
 191  2 setChanged(true);
 192    }
 193    }
 194   
 195    /**
 196    * @return the list of Chromosome's in the Population. Don't modify the
 197    * retrieved list by using clear(), remove(int) etc. If you do so, you need to
 198    * call setChanged(true)
 199    *
 200    * @author Klaus Meffert
 201    * @since 2.0
 202    */
 203  930529 public List getChromosomes() {
 204  930529 return m_chromosomes;
 205    }
 206   
 207    /**
 208    * Returns a Chromosome at given index in the Population.
 209    * @param a_index the index of the Chromosome to be returned
 210    * @return Chromosome at given index in the Population
 211    *
 212    * @author Klaus Meffert
 213    * @since 2.0
 214    */
 215  965739 public IChromosome getChromosome(final int a_index) {
 216  965739 return (IChromosome) m_chromosomes.get(a_index);
 217    }
 218   
 219    /**
 220    * @return number of Chromosome's in the Population
 221    *
 222    * @author Klaus Meffert
 223    * @since 2.0
 224    */
 225  1413012 public int size() {
 226  1413012 return m_chromosomes.size();
 227    }
 228   
 229    /**
 230    * @return Iterator for the Chromosome list in the Population. Please be aware
 231    * that using remove() forces you to call setChanged(true)
 232    *
 233    * @author Klaus Meffert
 234    * @since 2.0
 235    */
 236  14 public Iterator iterator() {
 237  14 return m_chromosomes.iterator();
 238    }
 239   
 240    /**
 241    * @return the Population converted into a list of Chromosome's
 242    *
 243    * @author Klaus Meffert, Dan Clark
 244    * @since 2.0
 245    */
 246  30 public IChromosome[] toChromosomes() {
 247  30 return (IChromosome[]) m_chromosomes.toArray(
 248    new IChromosome[m_chromosomes.size()]);
 249    }
 250   
 251    /**
 252    * Determines the fittest Chromosome in the population (the one with the
 253    * highest fitness value) and memorizes it. This is an optimized version
 254    * compared to calling determineFittesChromosomes(1).
 255    * @return the fittest Chromosome of the population
 256    *
 257    * @author Klaus Meffert
 258    * @since 2.0
 259    */
 260  33 public IChromosome determineFittestChromosome() {
 261  33 if (!m_changed && m_fittestChromosome != null) {
 262  7 return m_fittestChromosome;
 263    }
 264  26 Iterator it = m_chromosomes.iterator();
 265  26 FitnessEvaluator evaluator = getConfiguration().getFitnessEvaluator();
 266  26 double bestFitness;
 267  26 if (evaluator.isFitter(2.0d, 1.0d)) {
 268  23 bestFitness = -1.0d;
 269    }
 270    else {
 271  3 bestFitness = Double.MAX_VALUE;
 272    }
 273  26 double fitness;
 274  26 while (it.hasNext()) {
 275  6859 IChromosome chrom = (IChromosome) it.next();
 276  6859 fitness = chrom.getFitnessValue();
 277  6859 if (evaluator.isFitter(fitness, bestFitness)
 278    || m_fittestChromosome == null) {
 279  137 m_fittestChromosome = chrom;
 280  137 bestFitness = fitness;
 281    }
 282    }
 283  26 setChanged(false);
 284  26 return m_fittestChromosome;
 285    }
 286   
 287    /**
 288    * Determines the fittest Chromosome in the population (the one with the
 289    * highest fitness value) within the given indices and memorizes it. This is
 290    * an optimized version compared to calling determineFittesChromosomes(1).
 291    * @param a_startIndex index to begin the evaluation with
 292    * @param a_endIndex index to end the evaluation with
 293    * @return the fittest Chromosome of the population within the given indices
 294    *
 295    * @author Klaus Meffert
 296    * @since 3.0
 297    */
 298  15 public IChromosome determineFittestChromosome(int a_startIndex, int a_endIndex) {
 299  15 double bestFitness = -1.0d;
 300  15 FitnessEvaluator evaluator = getConfiguration().getFitnessEvaluator();
 301  15 double fitness;
 302  15 int startIndex = Math.max(0, a_startIndex);
 303  15 int endIndex = Math.min(m_chromosomes.size() - 1, a_endIndex);
 304  15 for (int i = startIndex; i < endIndex; i++) {
 305  75 IChromosome chrom = (IChromosome) m_chromosomes.get(i);
 306  75 fitness = chrom.getFitnessValue();
 307  75 if (evaluator.isFitter(fitness, bestFitness)
 308    || m_fittestChromosome == null) {
 309  15 m_fittestChromosome = chrom;
 310  15 bestFitness = fitness;
 311    }
 312    }
 313  15 return m_fittestChromosome;
 314    }
 315   
 316    /**
 317    * Mark that for the population the fittest chromosome may have changed.
 318    *
 319    * @param a_changed true: population's fittest chromosome may have changed,
 320    * false: fittest chromosome evaluated earlier is still valid
 321    *
 322    * @author Klaus Meffert
 323    * @since 2.2
 324    */
 325  27808 protected void setChanged(final boolean a_changed) {
 326  27808 m_changed = a_changed;
 327  27808 setSorted(false);
 328    }
 329   
 330    /**
 331    * @return true: population's chromosomes (maybe) were changed,
 332    * false: not changed for sure
 333    *
 334    * @since 2.6
 335    */
 336  10 public boolean isChanged() {
 337  10 return m_changed;
 338    }
 339   
 340    /**
 341    * Mark the population as sorted.
 342    * @param a_sorted true: mark population as sorted
 343    *
 344    * @author Klaus Meffert
 345    * @since 2.6
 346    */
 347  27816 protected void setSorted(final boolean a_sorted) {
 348  27816 m_sorted = a_sorted;
 349    }
 350   
 351    /**
 352    * Determines whether the given chromosome is contained within the population.
 353    * @param a_chromosome the chromosome to check
 354    * @return true: chromosome contained within population
 355    *
 356    * @author Klaus Meffert
 357    * @since 2.1
 358    */
 359  20 public boolean contains(final IChromosome a_chromosome) {
 360  20 return m_chromosomes.contains(a_chromosome);
 361    }
 362   
 363    /**
 364    * Removes a chromosome in the list at the given index. Method has package
 365    * visibility to signal that this is a method not to be used outside the
 366    * JGAP kernel under normal circumstances.
 367    *
 368    * @param a_index index of chromosome to be removed in list
 369    * @return removed Chromosome
 370    *
 371    * @author Klaus Meffert
 372    * @since 2.4
 373    */
 374  58 IChromosome removeChromosome(final int a_index) {
 375  58 if (a_index < 0 || a_index >= size()) {
 376  3 throw new IllegalArgumentException("Index must be within bounds!");
 377    }
 378  55 setChanged(true);
 379  55 return (IChromosome) m_chromosomes.remove(a_index);
 380    }
 381   
 382    /**
 383    * Sorts the Chromosome list and returns the fittest n Chromosomes in
 384    * the population.
 385    * @param a_numberOfChromosomes number of top performer chromosomes to be
 386    * returned
 387    * @return list of the fittest n Chromosomes of the population, or the fittest
 388    * x Chromosomes with x = number of chromosomes in case n > x.
 389    *
 390    * @author Charles Kevin Hill
 391    * @since 2.4
 392    */
 393  15 public List determineFittestChromosomes(final int a_numberOfChromosomes) {
 394  15 int numberOfChromosomes = Math.min(a_numberOfChromosomes,
 395    getChromosomes().size());
 396  15 if (numberOfChromosomes <= 0) {
 397  1 return null;
 398    }
 399  14 if (!m_changed && m_sorted) {
 400  8 return getChromosomes().subList(0, numberOfChromosomes);
 401    }
 402    // Sort the list of chromosomes using the fitness comparator
 403  6 sortByFitness();
 404    // Return the top n chromosomes
 405  6 return getChromosomes().subList(0, numberOfChromosomes);
 406    }
 407   
 408    /**
 409    * Sorts the chromosomes within the population according to their fitness
 410    * value using ChromosomFitnessComparator.
 411    *
 412    * @author Klaus Meffert
 413    * @since 2.6
 414    */
 415  8 public void sortByFitness() {
 416    // The following construction could be cached but wrt that the
 417    // evaluator registered with the configuration could change
 418    // --> Don't cache it!
 419  8 sort(new ChromosomeFitnessComparator(getConfiguration().
 420    getFitnessEvaluator()));
 421  8 setChanged(false);
 422  8 setSorted(true);
 423  8 m_fittestChromosome = (IChromosome) m_chromosomes.get(0);
 424    }
 425   
 426    /**
 427    * Sorts the chromosomes within the population utilzing the given comparator.
 428    *
 429    * @param a_comparator the comparator to utilize for sorting
 430    *
 431    * @author Klaus Meffert
 432    * @since 2.6
 433    */
 434  8 protected void sort(Comparator a_comparator) {
 435  8 Collections.sort(getChromosomes(), a_comparator);
 436    }
 437   
 438    /**
 439    * Returns the genotype of the population, i.e. the list of genes in the
 440    * population.
 441    * @param a_resolveCompositeGenes true: split encountered CompositeGenes
 442    * into their single (atomic) genes
 443    * @return genotype of the population
 444    *
 445    * @author Klaus Meffert
 446    * @since 2.3
 447    */
 448  6 public List getGenome(final boolean a_resolveCompositeGenes) {
 449  6 List result = new Vector();
 450  6 List chroms = getChromosomes();
 451  6 int len = chroms.size();
 452  6 for (int i = 0; i < len; i++) {
 453  10 IChromosome chrom = (IChromosome) chroms.get(i);
 454  10 Gene[] genes = chrom.getGenes();
 455  10 int len2 = genes.length;
 456  10 for (int j = 0; j < len2; j++) {
 457  22 Gene gene = genes[j];
 458  22 if (a_resolveCompositeGenes && gene instanceof ICompositeGene) {
 459  1 addCompositeGene(result, (ICompositeGene) gene);
 460    }
 461    else {
 462  21 addAtomicGene(result, gene);
 463    }
 464    }
 465    }
 466  6 return result;
 467    }
 468   
 469    /**
 470    * Adds all the genes of a CompositeGene to a result list.
 471    * Method calls itself recursively.
 472    *
 473    * @param a_result the list to add to
 474    * @param a_gene the gene to start with
 475    *
 476    * @author Klaus Meffert
 477    * @since 2.3
 478    */
 479  3 private void addCompositeGene(final List a_result, final Gene a_gene) {
 480  3 if (a_gene instanceof ICompositeGene) {
 481  1 int len = a_gene.size();
 482  1 for (int i = 0; i < len; i++) {
 483  2 addCompositeGene(a_result, ( (ICompositeGene) a_gene).geneAt(i));
 484    }
 485    }
 486    else {
 487  2 addAtomicGene(a_result, a_gene);
 488    }
 489    }
 490   
 491    /**
 492    * Helper method for addCompositeGene
 493    * @param a_result List
 494    * @param a_gene Gene
 495    *
 496    * @author Klaus Meffert
 497    * @since 2.3
 498    */
 499  23 private void addAtomicGene(final List a_result, final Gene a_gene) {
 500  23 a_result.add(a_gene);
 501    }
 502   
 503  4 public boolean isSorted() {
 504  4 return m_sorted;
 505    }
 506   
 507    /**
 508    * The equals-method.
 509    * @param a_pop the population instance to compare with
 510    * @return true: given object equal to comparing one
 511    *
 512    * @author Klaus Meffert
 513    * @since 2.6
 514    */
 515  25 public boolean equals(Object a_pop) {
 516  25 try {
 517  25 return compareTo(a_pop) == 0;
 518    }
 519    catch (ClassCastException e) {
 520    // If the other object isn't an Population instance
 521    // then we're not equal.
 522    // ------------------------------------------------
 523  2 return false;
 524    }
 525    }
 526   
 527    /**
 528    * This method is not producing symmetric results as -1 is more often returned
 529    * than 1 (see description of return value).
 530    *
 531    * @param a_pop the other population to compare
 532    * @return 1: a_pop is null or having fewer chromosomes or equal number
 533    * of chromosomes but at least one not contained. 0: both populations
 534    * containing exactly the same chromosomes. -1: this population contains fewer
 535    * chromosomes than a_pop
 536    *
 537    * @author Klaus Meffert
 538    * @since 2.6
 539    */
 540  29 public int compareTo(Object a_pop) {
 541  29 Population other = (Population) a_pop;
 542  27 if (a_pop == null) {
 543  1 return 1;
 544    }
 545  26 int size1 = size();
 546  26 int size2 = other.size();
 547  26 if (size1 != size2) {
 548  2 if (size1 < size2) {
 549  1 return -1;
 550    }
 551    else {
 552  1 return 1;
 553    }
 554    }
 555  24 List chroms2 = other.getChromosomes();
 556  24 for (int i = 0; i < size1; i++) {
 557  1206 if (!chroms2.contains(m_chromosomes.get(i))) {
 558  1 return 1;
 559    }
 560    }
 561  23 return 0;
 562    }
 563    }