Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 375   Methods: 15
NCLOC: 153   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DoubleGene.java 94,4% 96,4% 100% 96,6%
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.impl;
 11   
 12    import java.util.*;
 13    import org.jgap.*;
 14   
 15    /**
 16    * A Gene implementation that supports a double values for its allele.
 17    * Upper and lower bounds may optionally be provided to restrict the range
 18    * of legal values allowed by this Gene instance.
 19    * Partly copied from IntegerGene.
 20    *
 21    * @author Klaus Meffert
 22    * @since 1.1
 23    */
 24    public class DoubleGene
 25    extends NumberGene {
 26    /** String containing the CVS revision. Read out via reflection!*/
 27    private final static String CVS_REVISION = "$Revision: 1.36 $";
 28   
 29    /**
 30    * The upper bounds of values represented by this Gene. If not explicitly
 31    * provided by the user, this should be set to Double.MAX_VALUE.
 32    */
 33    private double m_upperBound;
 34   
 35    /**
 36    * The lower bounds of values represented by this Gene. If not explicitly
 37    * provided by the user, this should be set to Double.MIN_VALUE
 38    */
 39    private double m_lowerBound;
 40   
 41    /**
 42    * Constructs a new DoubleGene with default settings. No bounds will
 43    * be put into effect for values (alleles) of this Gene instance, other
 44    * than the standard range of double values.<p>
 45    * Attention: The configuration used is the one set with the static method
 46    * Genotype.setConfiguration.
 47    * @throws InvalidConfigurationException
 48    *
 49    * @author Neil Rotstan
 50    * @author Klaus Meffert
 51    * @since 1.1
 52    */
 53  1 public DoubleGene()
 54    throws InvalidConfigurationException {
 55  1 this(Genotype.getStaticConfiguration());
 56    }
 57   
 58    /**
 59    * Constructs a new DoubleGene with default settings. No bounds will
 60    * be put into effect for values (alleles) of this Gene instance, other
 61    * than the standard range of double values.
 62    * @param a_config the configuration to use
 63    * @throws InvalidConfigurationException
 64    *
 65    * @author Klaus Meffert
 66    * @since 3.0
 67    */
 68  5446 public DoubleGene(final Configuration a_config)
 69    throws InvalidConfigurationException {
 70  5446 this(a_config, - (Double.MAX_VALUE / 2),
 71    Double.MAX_VALUE / 2);
 72    }
 73   
 74    /**
 75    * Constructs a new DoubleGene with the specified lower and upper
 76    * bounds for values (alleles) of this Gene instance.
 77    *
 78    * @param a_config the configuration to use
 79    * @param a_lowerBound the lowest value that this Gene may possess,
 80    * inclusive
 81    * @param a_upperBound the highest value that this Gene may possess,
 82    * inclusive
 83    * @throws InvalidConfigurationException
 84    *
 85    * @author Klaus Meffert
 86    * @since 2.0
 87    */
 88  18054 public DoubleGene(final Configuration a_config, final double a_lowerBound,
 89    final double a_upperBound)
 90    throws InvalidConfigurationException {
 91  18054 super(a_config);
 92  18054 m_lowerBound = a_lowerBound;
 93  18054 m_upperBound = a_upperBound;
 94    }
 95   
 96    /**
 97    * Provides an implementation-independent means for creating new Gene
 98    * instances.
 99    *
 100    * @return a new Gene instance of the same type and with the same
 101    * setup as this concrete Gene
 102    *
 103    * @author Klaus Meffert
 104    * @since 1.1
 105    */
 106  12515 protected Gene newGeneInternal() {
 107  12515 try {
 108  12515 DoubleGene result = new DoubleGene(getConfiguration(), m_lowerBound,
 109    m_upperBound);
 110  12515 return result;
 111    }
 112    catch (InvalidConfigurationException iex) {
 113  0 throw new IllegalStateException(iex.getMessage());
 114    }
 115    }
 116   
 117    /**
 118    * Retrieves a string representation of this Gene that includes any
 119    * information required to reconstruct it at a later time, such as its
 120    * value and internal state. This string will be used to represent this
 121    * Gene in XML persistence. This is an optional method but, if not
 122    * implemented, XML persistence and possibly other features will not be
 123    * available. An UnsupportedOperationException should be thrown if no
 124    * implementation is provided.
 125    *
 126    * @return a string representation of this Gene's current state.
 127    *
 128    * @author Klaus Meffert
 129    * @since 1.1
 130    */
 131  22 public String getPersistentRepresentation() {
 132    // The persistent representation includes the value, lower bound,
 133    // and upper bound. Each is separated by a colon.
 134    // --------------------------------------------------------------
 135  22 String s;
 136  22 if (getInternalValue() == null) {
 137  6 s = "null";
 138    }
 139    else {
 140  16 s = getInternalValue().toString();
 141    }
 142  22 return s + PERSISTENT_FIELD_DELIMITER + m_lowerBound
 143    + PERSISTENT_FIELD_DELIMITER + m_upperBound;
 144    }
 145   
 146    /**
 147    * Sets the value and internal state of this Gene from the string
 148    * representation returned by a previous invocation of the
 149    * getPersistentRepresentation() method. This is an optional method but,
 150    * if not implemented, XML persistence and possibly other features will not
 151    * be available. An UnsupportedOperationException should be thrown if no
 152    * implementation is provided.
 153    *
 154    * @param a_representation the string representation retrieved from a
 155    * prior call to the getPersistentRepresentation() method
 156    *
 157    * @throws UnsupportedOperationException to indicate that no implementation
 158    * is provided for this method
 159    * @throws UnsupportedRepresentationException if this Gene implementation
 160    * does not support the given string representation
 161    *
 162    * @author Klaus Meffert
 163    * @since 1.1
 164    */
 165  20 public void setValueFromPersistentRepresentation(String a_representation)
 166    throws UnsupportedRepresentationException {
 167  20 if (a_representation != null) {
 168  19 StringTokenizer tokenizer =
 169    new StringTokenizer(a_representation,
 170    PERSISTENT_FIELD_DELIMITER);
 171    // Make sure the representation contains the correct number of
 172    // fields. If not, throw an exception.
 173    // -----------------------------------------------------------
 174  19 if (tokenizer.countTokens() != 3) {
 175  1 throw new UnsupportedRepresentationException(
 176    "The format of the given persistent representation " +
 177    "is not recognized: it does not contain three tokens.");
 178    }
 179  18 String valueRepresentation = tokenizer.nextToken();
 180  18 String lowerBoundRepresentation = tokenizer.nextToken();
 181  18 String upperBoundRepresentation = tokenizer.nextToken();
 182    // First parse and set the representation of the value.
 183    // ----------------------------------------------------
 184  18 if (valueRepresentation.equals("null")) {
 185  3 setAllele(null);
 186    }
 187    else {
 188  15 try {
 189  15 setAllele(new Double(Double.parseDouble(valueRepresentation)));
 190    }
 191    catch (NumberFormatException e) {
 192  1 throw new UnsupportedRepresentationException(
 193    "The format of the given persistent representation " +
 194    "is not recognized: field 1 does not appear to be " +
 195    "a double value.");
 196    }
 197    }
 198    // Now parse and set the lower bound.
 199    // ----------------------------------
 200  17 try {
 201  17 m_lowerBound =
 202    Double.parseDouble(lowerBoundRepresentation);
 203    }
 204    catch (NumberFormatException e) {
 205  1 throw new UnsupportedRepresentationException(
 206    "The format of the given persistent representation " +
 207    "is not recognized: field 2 does not appear to be " +
 208    "a double value.");
 209    }
 210    // Now parse and set the upper bound.
 211    // ----------------------------------
 212  16 try {
 213  16 m_upperBound =
 214    Double.parseDouble(upperBoundRepresentation);
 215    }
 216    catch (NumberFormatException e) {
 217  1 throw new UnsupportedRepresentationException(
 218    "The format of the given persistent representation " +
 219    "is not recognized: field 3 does not appear to be " +
 220    "a double value.");
 221    }
 222    }
 223    }
 224   
 225    /**
 226    * Retrieves the double value of this Gene, which may be more convenient in
 227    * some cases than the more general getAllele() method.
 228    *
 229    * @return the double value of this Gene
 230    * @since 1.1
 231    */
 232  36 public double doubleValue() {
 233  36 return ( (Double) getAllele()).doubleValue();
 234    }
 235   
 236    /**
 237    * Sets the value (allele) of this Gene to a random Double value between
 238    * the lower and upper bounds (if any) of this Gene.
 239    *
 240    * @param a_numberGenerator the random number generator that should be used
 241    * to create any random values. It's important to use this generator to
 242    * maintain the user's flexibility to configure the genetic engine to use the
 243    * random number generator of their choice
 244    *
 245    * @author Klaus Meffert
 246    * @since 1.1
 247    */
 248  7 public void setToRandomValue(RandomGenerator a_numberGenerator) {
 249    // maps the randomly determined value to the current bounds.
 250    // ---------------------------------------------------------
 251  7 setAllele(new Double( (m_upperBound - m_lowerBound) *
 252    a_numberGenerator.nextDouble() + m_lowerBound));
 253    }
 254   
 255    /**
 256    * Compares to objects by first casting them into their expected type
 257    * (e.g. Integer for IntegerGene) and then calling the compareTo-method
 258    * of the casted type.
 259    * @param o1 first object to be compared, always is not null
 260    * @param o2 second object to be compared, always is not null
 261    * @return a negative integer, zero, or a positive integer as this object
 262    * is less than, equal to, or greater than the object provided for comparison
 263    *
 264    * @since 1.1
 265    */
 266  121213 protected int compareToNative(Object o1, Object o2) {
 267  121213 return ( (Double) o1).compareTo( (Double) o2);
 268    }
 269   
 270    /**
 271    * Maps the value of this DoubleGene to within the bounds specified by
 272    * the m_upperBounds and m_lowerBounds instance variables. The value's
 273    * relative position within the double range will be preserved within the
 274    * bounds range (in other words, if the value is about halfway between the
 275    * double max and min, then the resulting value will be about halfway
 276    * between the upper bounds and lower bounds). If the value is null or
 277    * is already within the bounds, it will be left unchanged.
 278    *
 279    * @author Neil Rotstan
 280    * @author Klaus Meffert
 281    * @since 1.1
 282    */
 283  2520 protected void mapValueToWithinBounds() {
 284  2520 if (getAllele() != null) {
 285  315 Double d_value = ( (Double) getAllele());
 286    // If the value exceeds either the upper or lower bounds, then
 287    // map the value to within the legal range. To do this, we basically
 288    // calculate the distance between the value and the double min,
 289    // then multiply it with a random number and then care that the lower
 290    // boundary is added.
 291    // ------------------------------------------------------------------
 292  313 if (d_value.doubleValue() > m_upperBound ||
 293    d_value.doubleValue() < m_lowerBound) {
 294  9 RandomGenerator rn;
 295  9 if (getConfiguration() != null) {
 296  9 rn = getConfiguration().getRandomGenerator();
 297    }
 298    else {
 299  0 rn = new StockRandomGenerator();
 300    }
 301  9 setAllele(new Double(rn.nextDouble()
 302    * (m_upperBound - m_lowerBound) + m_lowerBound));
 303    }
 304    }
 305    }
 306   
 307    /**
 308    * See interface Gene for description.
 309    * @param index ignored (because there is only 1 atomic element)
 310    * @param a_percentage percentage of mutation (greater than -1 and smaller
 311    * than 1)
 312    *
 313    * @author Klaus Meffert
 314    * @since 1.1
 315    */
 316  8 public void applyMutation(int index, double a_percentage) {
 317  8 double range = (m_upperBound - m_lowerBound) * a_percentage;
 318  8 double newValue = doubleValue() + range;
 319  7 setAllele(new Double(newValue));
 320    }
 321   
 322    /**
 323    * Modified hashCode() function to return different hashcodes for differently
 324    * ordered genes in a chromosome.
 325    * @return -3 if no allele set, otherwise value return by BaseGene.hashCode()
 326    *
 327    * @author Klaus Meffert
 328    * @since 2.2
 329    */
 330  8735 public int hashCode() {
 331  8735 if (getInternalValue() == null) {
 332  8730 return -3;
 333    }
 334    else {
 335  5 return super.hashCode();
 336    }
 337    }
 338   
 339    /**
 340    * @return string representation of this Gene's value that may be useful for
 341    * display purposes
 342    *
 343    * @author Klaus Meffert
 344    * @since 2.4
 345    */
 346  7 public String toString() {
 347  7 String s = "DoubleGene(" + m_lowerBound + "," + m_upperBound + ")"
 348    + "=";
 349  7 if (getInternalValue() == null) {
 350  1 s += "null";
 351    }
 352    else {
 353  6 s += getInternalValue().toString();
 354    }
 355  7 return s;
 356    }
 357   
 358    /**
 359    * @return the lower bound set
 360    * @author Klaus Meffert
 361    * @since 3.0
 362    */
 363  2 public double getLowerBound() {
 364  2 return m_lowerBound;
 365    }
 366   
 367    /**
 368    * @return the upper bound set
 369    * @author Klaus Meffert
 370    * @since 3.0
 371    */
 372  2 public double getUpperBound() {
 373  2 return m_upperBound;
 374    }
 375    }