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