Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 453   Methods: 17
NCLOC: 260   Classes: 4
 
 Source file Conditionals Statements Methods TOTAL
Evaluator.java 81,2% 91,9% 94,1% 89,7%
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.audit;
 11   
 12    import org.jgap.*;
 13    import java.util.*;
 14   
 15    /**
 16    * Gathers statistical data and returns them on request.
 17    *
 18    * @author Klaus Meffert
 19    * @since 2.2
 20    */
 21    public class Evaluator {
 22    /**@todo implement: overall score calculation (out of best/avg. fitness value
 23    * etc.)
 24    */
 25   
 26    /** String containing the CVS revision. Read out via reflection!*/
 27    private final static String CVS_REVISION = "$Revision: 1.9 $";
 28   
 29    /**
 30    * Each data has its own data container
 31    */
 32    private Map m_permutationData;
 33   
 34    /**
 35    * Stores the run-numbers (indexes) for all permutations submitted
 36    */
 37    private Map m_permutationRuns;
 38   
 39    /**
 40    * For processinf without permutation
 41    */
 42    private KeyedValues2D m_data;
 43   
 44    private PermutingConfiguration m_permConf;
 45   
 46    /**
 47    * Genotype data per permutation per run
 48    */
 49    private Map m_genotypeData;
 50   
 51    /**
 52    * Genotype data per permutation (averaged over all runs)
 53    */
 54    private List m_genotypeDataAvg;
 55   
 56  15 public Evaluator(final PermutingConfiguration a_conf) {
 57  15 if (a_conf == null) {
 58  1 throw new IllegalArgumentException("Configuration must not be null!");
 59    }
 60  14 m_permConf = a_conf;
 61  14 m_data = new KeyedValues2D();
 62  14 m_permutationData = new Hashtable();
 63  14 m_permutationRuns = new Hashtable();
 64  14 m_genotypeData = new Hashtable();
 65  14 m_genotypeDataAvg = new Vector();
 66    }
 67   
 68  2 public boolean hasNext() {
 69  2 return m_permConf.hasNext();
 70    }
 71   
 72  1 public Configuration next()
 73    throws InvalidConfigurationException {
 74  1 return m_permConf.next();
 75    }
 76   
 77  1 public void setValue(double a_value, Comparable a_rowKey,
 78    Comparable a_columnKey) {
 79  1 m_data.setValue(new Double(a_value), a_rowKey, a_columnKey);
 80    // fireDatasetChanged();
 81    }
 82   
 83  2 public Number getValue(Comparable rowKey, Comparable columnKey) {
 84  2 return m_data.getValue(rowKey, columnKey);
 85    }
 86   
 87    /**
 88    * Sets a specific value.
 89    * @param a_permutation int
 90    * @param a_run int
 91    * @param a_value double
 92    * @param a_rowKey Comparable
 93    * @param a_columnKey Comparable
 94    *
 95    * @author Klaus Meffert
 96    * @since 2.2
 97    */
 98  11 public void setValue(int a_permutation, int a_run, double a_value,
 99    Comparable a_rowKey, Comparable a_columnKey) {
 100  11 Object key = createKey(a_permutation, a_run);
 101  11 KeyedValues2D a_data = (KeyedValues2D) m_permutationData.get(
 102    key);
 103  11 if (a_data == null) {
 104  10 a_data = new KeyedValues2D();
 105  10 m_permutationData.put(key, a_data);
 106    }
 107    // Add run-number (index).
 108    // -----------------------
 109  11 addRunNumber(a_permutation, a_run);
 110  11 a_data.setValue(new Double(a_value), a_rowKey, a_columnKey);
 111    }
 112   
 113  20 protected void addRunNumber(int a_permutation, int a_run) {
 114  20 Map v = (Map) m_permutationRuns.get(new Integer(a_permutation));
 115  20 if (v == null) {
 116  13 v = new Hashtable();
 117    }
 118  20 v.put(new Integer(a_run), new Integer(a_run));
 119  20 m_permutationRuns.put(new Integer(a_permutation), v);
 120    }
 121   
 122  5 public Number getValue(int a_permutation, int a_run, Comparable rowKey,
 123    Comparable columnKey) {
 124  5 KeyedValues2D a_data = (KeyedValues2D) m_permutationData.get(
 125    createKey(a_permutation, a_run));
 126  5 if (a_data == null) {
 127  1 return null;
 128    }
 129  4 return a_data.getValue(rowKey, columnKey);
 130    }
 131   
 132  2 public KeyedValues2D getData() {
 133  2 return m_data;
 134    }
 135   
 136  22 protected Object createKey(int a_permutation, int a_run) {
 137  22 return a_permutation + "_" + a_run;
 138    }
 139   
 140    /**
 141    * Calculates the average fitness value curve for a given permutation.
 142    * If permutation -1 is given, a composition of all permutations available
 143    * is created.
 144    * @param a_permutation -1 to use all permutations
 145    * @return DefaultKeyedValues2D list of fitness values, one for each
 146    * individual in the generation
 147    *
 148    * @author Klaus Meffert
 149    * @since 2.2
 150    */
 151  2 public KeyedValues2D calcAvgFitness(int a_permutation) {
 152  2 if (a_permutation == -1) {
 153  1 Iterator it = m_permutationRuns.keySet().iterator();
 154  1 Integer permNumberI;
 155  1 int permNumber;
 156  1 KeyedValues2D result = new KeyedValues2D();
 157  1 while (it.hasNext()) {
 158  2 permNumberI = (Integer) it.next();
 159  2 permNumber = permNumberI.intValue();
 160  2 calcAvgFitnessHelper(permNumber, result);
 161    }
 162  1 return result;
 163    }
 164    else {
 165  1 KeyedValues2D a_data = new KeyedValues2D();
 166  1 calcAvgFitnessHelper(a_permutation, a_data);
 167  1 return a_data;
 168    }
 169    }
 170   
 171  3 protected void calcAvgFitnessHelper(int a_permutation,
 172    final KeyedValues2D result) {
 173    // Determine run-numbers of given permutation.
 174    // -------------------------------------------
 175  3 Map runNumbers = (Map) m_permutationRuns.get(new Integer(a_permutation));
 176  3 if (runNumbers == null) {
 177  0 return;
 178    }
 179    // Loop over all run-numbers.
 180    // --------------------------
 181  3 Iterator it = runNumbers.keySet().iterator();
 182  3 int numRuns = runNumbers.keySet().size();
 183  3 Integer runI;
 184  3 while (it.hasNext()) {
 185  6 runI = (Integer) it.next();
 186    // Determine dataset of given permutation.
 187    // ---------------------------------------
 188  6 KeyedValues2D a_data = (KeyedValues2D) m_permutationData.
 189    get(createKey(a_permutation, runI.intValue()));
 190    // Determine values for current run-number and "add" them to gathered
 191    // data.
 192    // ------------------------------------------------------------------
 193  6 for (int col = 0; col < a_data.getColumnCount(); col++) {
 194  6 for (int row = 0; row < a_data.getRowCount(); row++) {
 195    // Previous value (summation).
 196    // --------------------------.
 197  6 Double d = (Double) result.getValue(a_data.getRowKey(row),
 198    a_data.getColumnKey(col));
 199  6 double newValue;
 200  6 if (d == null) {
 201  4 newValue = 0.0d;
 202    }
 203    else {
 204  2 newValue = d.doubleValue();
 205    }
 206    // Add current value (divided by total number of runs to get an
 207    // averaged value).
 208    // ------------------------------------------------------------
 209  6 newValue +=
 210    a_data.getValue(a_data.getRowKey(row), a_data.getColumnKey(col)).
 211    doubleValue() / numRuns;
 212    // Set averaged value back to result dataset.
 213    // ------------------------------------------
 214  6 result.setValue(new Double(newValue), a_data.getRowKey(row),
 215    a_data.getColumnKey(col));
 216    }
 217    }
 218    }
 219    }
 220   
 221    /**
 222    * Returns a list of lists (i.e. a matrix) to use for output as a table
 223    * @param a_data DefaultKeyedValues2D
 224    * @return List
 225    */
 226    /**@todo implement*/
 227    // public List getTable(KeyedValues2D a_data) {
 228    // return null;
 229    // }
 230   
 231    /**
 232    * Calculates average fitness value improvement per generation.
 233    *
 234    * @param a_permutation int
 235    * @return DefaultKeyedValues2D
 236    *
 237    * @author Klaus Meffert
 238    * @since 2.2
 239    */
 240  0 public KeyedValues2D calcAvgFitnessImpr(int a_permutation) {
 241    /**@todo implement*/
 242    /**@todo is this method used resp. contained in calcPerformance?*/
 243  0 Map runNumbers = (Map) m_permutationRuns.get(new Integer(a_permutation));
 244  0 if (runNumbers == null) {
 245  0 return null;
 246    }
 247    // Map fitnessImpr = new Hashtable();
 248    // Loop over all run-numbers.
 249    // --------------------------
 250  0 Iterator it = runNumbers.keySet().iterator();
 251    // int numRuns = runNumbers.keySet().size();
 252  0 Integer runI;
 253  0 while (it.hasNext()) {
 254  0 runI = (Integer) it.next();
 255    // Determine dataset of given permutation.
 256    // ---------------------------------------
 257  0 KeyedValues2D a_data = (KeyedValues2D) m_permutationData.
 258    get(createKey(a_permutation, runI.intValue()));
 259  0 for (int col = 0; col < a_data.getColumnCount(); col++) {
 260  0 for (int row = 0; row < a_data.getRowCount(); row++) {
 261    }
 262    }
 263    }
 264  0 return null;
 265    }
 266   
 267    /**
 268    *
 269    * @param a_permutation the permutation to determine the number of runs for
 270    * @return the number of runs for the given permutation
 271    */
 272  6 public int getNumberOfRuns(int a_permutation) {
 273  6 Map runNumbers = (Map) m_permutationRuns.get(new Integer(a_permutation));
 274  6 if (runNumbers == null) {
 275  1 return 0;
 276    }
 277    else {
 278  5 return runNumbers.keySet().size();
 279    }
 280    }
 281   
 282    /**
 283    * Stores information contained in the given genotype.
 284    * @param a_permutation int
 285    * @param a_run index of the run proceeded for the given genotype
 286    * @param a_genotype the genotype holding the population of chromosomes
 287    *
 288    * @author Klaus Meffert
 289    * @since 2.2
 290    */
 291  9 public void storeGenotype(int a_permutation, int a_run, Genotype a_genotype) {
 292    /**@todo implement*/
 293    // average and maximum fitness value
 294    //
 295  9 GenotypeData data = new GenotypeData();
 296  9 int generation = a_genotype.getConfiguration().getGenerationNr();
 297  9 data.generation = generation;
 298  9 Population pop = a_genotype.getPopulation();
 299  9 data.hashCode = a_genotype.hashCode();
 300  9 int popSize = pop.size();
 301  9 data.chromosomeData = new ChromosomeData[popSize];
 302  9 data.size = popSize;
 303    // gather data of Chromosomes
 304  9 IChromosome chrom;
 305  9 ChromosomeData chromData;
 306  9 for (int i = 0; i < popSize; i++) {
 307  27 chrom = pop.getChromosome(i);
 308  27 chromData = new ChromosomeData();
 309  27 chromData.fitnessValue = chrom.getFitnessValue();
 310  27 chromData.size = chrom.size();
 311  27 chromData.index = i;
 312  27 data.chromosomeData[i] = chromData;
 313    }
 314  9 String key = a_permutation + "_" + a_run;
 315  9 m_genotypeData.put(key, data);
 316  9 addRunNumber(a_permutation, a_run);
 317    }
 318   
 319  8 public GenotypeData retrieveGenotype(int a_permutation, int a_run) {
 320  8 return (GenotypeData) m_genotypeData.get(a_permutation + "_" + a_run);
 321    }
 322   
 323    /**
 324    * Calculates performance metrics for a given permutation and run stored
 325    * before with storeGenotype, like:
 326    * average fitness, maximum fitness...
 327    * @param a_permutation the permutation to compute the performance metrics
 328    * for
 329    * @return computed statistical data
 330    *
 331    * @author Klaus Meffert
 332    * @since 2.2
 333    */
 334  4 public GenotypeDataAvg calcPerformance(int a_permutation) {
 335  4 int numRuns = getNumberOfRuns(a_permutation);
 336  4 GenotypeData data;
 337  4 GenotypeDataAvg dataAvg = new GenotypeDataAvg();
 338  4 dataAvg.permutation = a_permutation;
 339  4 double sizeAvg = 0.0d;
 340  4 double fitnessAvg = 0.0d;
 341  4 double fitnessBest = -1.0d;
 342  4 double fitnessBestOld = -1.0d;
 343  4 double fitness;
 344  4 int fitnessBestGen = -1;
 345  4 double fitnessAvgChroms;
 346  4 double fitnessDiversityChromsOld = -1.0d;
 347  4 double fitnessBestDeltaAvg = 0.0d;
 348  4 double fitnessDiversity;
 349  4 double fitnessDiversityAvg = 0.0d;
 350  4 int size;
 351  4 ChromosomeData chrom;
 352  4 for (int i = 0; i < numRuns; i++) {
 353  7 data = retrieveGenotype(a_permutation, i);
 354    // generation the genotype data represents
 355  7 if (i == 0) {
 356  4 dataAvg.generation = data.generation;
 357    }
 358    // average number of chromosomes
 359  7 sizeAvg += (double) data.size / numRuns;
 360  7 size = data.size;
 361  7 fitnessAvgChroms = 0.0d;
 362  7 fitnessDiversity = 0.0d;
 363  7 double fitnessBestLocal = -1.0d;
 364  7 for (int j = 0; j < size; j++) {
 365  21 chrom = data.chromosomeData[j];
 366  21 fitness = chrom.fitnessValue;
 367    // diversity of fitness values over all chromosomes
 368  21 if (j > 0) {
 369  14 fitnessDiversity += Math.abs(fitness - fitnessDiversityChromsOld) /
 370    (size - 1);
 371    }
 372  21 fitnessDiversityChromsOld = fitness;
 373    // average fitness value for generation over all Chromosomes
 374  21 fitnessAvgChroms += fitness / size;
 375    // fittest chromosome in generation over all runs
 376  21 if (fitnessBest < fitness) {
 377  14 fitnessBest = fitness;
 378    // memorize generation number in which fittest chromosome appeared
 379  14 fitnessBestGen = data.generation;
 380    }
 381    // fittest chromosome in generation over current runs
 382  21 if (fitnessBestLocal < fitness) {
 383  16 fitnessBestLocal = fitness;
 384    }
 385    }
 386    // average fitness value for generation over all runs
 387  7 fitnessAvg += fitnessAvgChroms / numRuns;
 388    // average fitness delta value for generation over all runs
 389  7 fitnessDiversityAvg += fitnessDiversity / numRuns;
 390    // absolute delta between two adjacent best fitness values
 391  7 if (i > 0) {
 392  3 fitnessBestDeltaAvg += Math.abs(fitnessBestLocal - fitnessBestOld) /
 393    (numRuns - 1);
 394    }
 395  7 fitnessBestOld = fitnessBestLocal;
 396    }
 397  4 dataAvg.sizeAvg = sizeAvg;
 398  4 dataAvg.avgFitnessValue = fitnessAvg;
 399  4 dataAvg.bestFitnessValue = fitnessBest;
 400  4 dataAvg.bestFitnessValueGeneration = fitnessBestGen;
 401  4 dataAvg.avgDiversityFitnessValue = fitnessDiversityAvg;
 402  4 dataAvg.avgBestDeltaFitnessValue = fitnessBestDeltaAvg;
 403    //store computed (averaged) data
 404  4 m_genotypeDataAvg.add(dataAvg);
 405  4 return dataAvg;
 406    }
 407   
 408    /**
 409    * Averaged genotype data (computed over all runs of a permutation)
 410    *
 411    * @author Klaus Meffert
 412    * @since 2.2
 413    */
 414    public class GenotypeDataAvg {
 415    public int permutation;
 416   
 417    public int generation;
 418   
 419    public double sizeAvg;
 420   
 421    public double bestFitnessValue;
 422   
 423    public double avgFitnessValue;
 424   
 425    public int bestFitnessValueGeneration;
 426   
 427    public double avgDiversityFitnessValue;
 428   
 429    public double avgBestDeltaFitnessValue;
 430    }
 431    /**
 432    * Genotype data for one single run
 433    *
 434    * @author Klaus Meffert
 435    * @since 2.2
 436    */
 437    public class GenotypeData {
 438    public int generation;
 439   
 440    public int hashCode;
 441   
 442    public int size;
 443   
 444    public ChromosomeData[] chromosomeData;
 445    }
 446    public class ChromosomeData {
 447    public int index;
 448   
 449    public int size;
 450   
 451    public double fitnessValue;
 452    }
 453    }