Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 486   Methods: 30
NCLOC: 329   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
FixedBinaryGene.java 96,8% 96,3% 96,7% 96,5%
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 two possible values (alleles, 1 and 0)
 17    * with a fixed length of alleles.
 18    * <p>
 19    * NOTE: Since this Gene implementation only supports two different
 20    * values (1 and 0), there's only a 50% chance that invocation
 21    * of the setToRandomValue() method will actually change the value of
 22    * this Gene (if it has a value). As a result, it may be desirable to
 23    * use a higher overall mutation rate when this Gene implementation
 24    * is in use.
 25    * <p>
 26    * Partly adapted stuff from the JAGA (Java API for Genetic Algorithms)
 27    * package (see <a href="http://www.jaga.org">jaga</a>).
 28    *
 29    * @author Klaus Meffert
 30    * @since 2.0
 31    */
 32    public class FixedBinaryGene
 33    extends BaseGene {
 34    /** String containing the CVS revision. Read out via reflection!*/
 35    private final static String CVS_REVISION = "$Revision: 1.36 $";
 36   
 37    private int m_length;
 38   
 39    private int[] m_value;
 40   
 41    private static final int WORD_LEN_BITS = 32;
 42   
 43    /**
 44    *
 45    * @param a_config the configuration to use
 46    * @param a_length the fixed length of the gene
 47    * @throws InvalidConfigurationException
 48    *
 49    * @author Klaus Meffert
 50    * @since 2.0
 51    */
 52  6643 public FixedBinaryGene(final Configuration a_config, final int a_length)
 53    throws InvalidConfigurationException {
 54  6643 super(a_config);
 55  6643 if (a_length < 1) {
 56  2 throw new IllegalArgumentException("Length must be greater than zero!");
 57    }
 58  6641 m_length = a_length;
 59  6641 int bufSize = m_length / WORD_LEN_BITS;
 60  6641 if (0 != m_length % WORD_LEN_BITS) {
 61  6639 ++bufSize;
 62    }
 63  6641 m_value = new int[bufSize];
 64  6641 for (int i = 0; i < bufSize; i++) {
 65  9798 m_value[i] = 0;
 66    }
 67    }
 68   
 69  2216 protected Gene newGeneInternal() {
 70  2216 try {
 71  2216 FixedBinaryGene result = new FixedBinaryGene(getConfiguration(), m_length);
 72  2216 return result;
 73    }
 74    catch (InvalidConfigurationException iex) {
 75  0 throw new IllegalStateException(iex.getMessage());
 76    }
 77    }
 78   
 79  5 public FixedBinaryGene(final Configuration a_config,
 80    final FixedBinaryGene a_toCopy)
 81    throws InvalidConfigurationException {
 82  5 super(a_config);
 83  5 m_length = a_toCopy.getLength();
 84  5 int bufSize = m_length / WORD_LEN_BITS;
 85  5 if (0 != m_length % WORD_LEN_BITS) {
 86  5 ++bufSize;
 87    }
 88  5 m_value = new int[bufSize];
 89  5 System.arraycopy(a_toCopy.getValue(), 0, m_value, 0, m_value.length);
 90    }
 91   
 92  6 protected int[] getValue() {
 93  6 return m_value;
 94    }
 95   
 96  85995 public int getLength() {
 97  85995 return m_length;
 98    }
 99   
 100  4 public Object clone() {
 101  4 try {
 102  4 return new FixedBinaryGene(getConfiguration(), this);
 103    }
 104    catch (InvalidConfigurationException iex) {
 105  0 throw new IllegalStateException(iex.getMessage());
 106    }
 107    }
 108   
 109  2261 public void setAllele(final Object a_newValue) {
 110  2261 if (a_newValue == null) {
 111  1 throw new IllegalArgumentException("Allele must not be null!");
 112    }
 113  2260 if ( ( (int[]) a_newValue).length != getLength()) {
 114  2 throw new IllegalArgumentException("Length of allele must be equal to"
 115    + " fixed length set ("
 116    + getLength()
 117    + ")");
 118    }
 119  2256 if (getConstraintChecker() != null) {
 120  2 if (!getConstraintChecker().verify(this, a_newValue, null, -1)) {
 121  1 return;
 122    }
 123    }
 124  2255 int[] bits = (int[]) a_newValue;
 125  2255 for (int i = 0; i < bits.length; i++) {
 126  11232 setBit(i, bits[i]);
 127    }
 128    }
 129   
 130  2221 public Object getAllele() {
 131  2221 int[] bits = new int[getLength()];
 132  2221 for (int i = 0; i < getLength(); i++) {
 133  11083 if (getBit(i)) {
 134  2 bits[i] = 1;
 135    }
 136    else {
 137  11081 bits[i] = 0;
 138    }
 139    }
 140  2221 return bits;
 141    }
 142   
 143  2 public int[] getIntValues() {
 144  2 return m_value;
 145    }
 146   
 147  49236 public boolean getBit(final int a_index) {
 148  49236 checkIndex(a_index);
 149  49236 return getUnchecked(a_index);
 150    }
 151   
 152  11275 public void setBit(final int a_index, final boolean a_value) {
 153  11275 checkIndex(a_index);
 154  11275 setUnchecked(a_index, a_value);
 155    }
 156   
 157  11251 public void setBit(final int a_index, final int a_value) {
 158  11251 if (a_value > 0) {
 159  95 if (a_value != 1) {
 160  2 throw new IllegalArgumentException("Only values 0 and 1 are valid!");
 161    }
 162  93 setBit(a_index, true);
 163    }
 164    else {
 165  11156 if (a_value != 0) {
 166  1 throw new IllegalArgumentException("Only values 0 and 1 are valid!");
 167    }
 168  11155 setBit(a_index, false);
 169    }
 170    }
 171   
 172  4 public void setBit(final int a_from, final int a_to, final boolean a_value) {
 173  4 checkSubLength(a_from, a_to);
 174  3 for (int i = a_from; i < a_to; i++) {
 175  12 setUnchecked(i, a_value);
 176    }
 177    }
 178   
 179  2 public void setBit(final int a_from, final int a_to,
 180    final FixedBinaryGene a_values) {
 181  2 if (a_values.getLength() == 0) {
 182  0 throw new IllegalArgumentException("Length of values must be > 0");
 183    }
 184  2 checkSubLength(a_from, a_to);
 185  2 int iV = 0;
 186  2 for (int i = a_from; i <= a_to; i++, iV++) {
 187  10 if (iV >= a_values.getLength()) {
 188  1 iV = 0;
 189    }
 190  10 setUnchecked(i, a_values.getUnchecked(iV));
 191    }
 192    }
 193   
 194  2 public FixedBinaryGene substring(final int a_from, final int a_to) {
 195  2 try {
 196  2 int len = checkSubLength(a_from, a_to);
 197  1 FixedBinaryGene substring = new FixedBinaryGene(getConfiguration(), len);
 198  1 for (int i = a_from; i <= a_to; i++) {
 199  5 substring.setUnchecked(i - a_from, getUnchecked(i));
 200    }
 201  1 return substring;
 202    }
 203    catch (InvalidConfigurationException iex) {
 204  0 throw new IllegalStateException(iex.getMessage());
 205    }
 206    }
 207   
 208  4 public void flip(final int a_index) {
 209  4 checkIndex(a_index);
 210  3 int segment = a_index / WORD_LEN_BITS;
 211  3 int offset = a_index % WORD_LEN_BITS;
 212  3 int mask = 0x1 << (WORD_LEN_BITS - offset - 1);
 213  3 m_value[segment] ^= mask;
 214    }
 215   
 216  8 protected int checkSubLength(final int a_from, final int a_to) {
 217  8 checkIndex(a_from);
 218  8 checkIndex(a_to);
 219  7 int sublen = a_to - a_from + 1;
 220  7 if (0 >= sublen) {
 221  1 throw new IllegalArgumentException("must have 'from' <= 'to', but has "
 222    + a_from + " > " + a_to);
 223    }
 224  6 return sublen;
 225    }
 226   
 227  60531 protected void checkIndex(final int a_index) {
 228  60531 if (a_index < 0 || a_index >= getLength()) {
 229  2 throw new IndexOutOfBoundsException("index is " + a_index
 230    + ", but must be in [0, "
 231    + (getLength() - 1) + "]");
 232    }
 233    }
 234   
 235  49251 protected boolean getUnchecked(final int a_index) {
 236  49251 int segment = a_index / WORD_LEN_BITS;
 237  49251 int offset = a_index % WORD_LEN_BITS;
 238  49251 int mask = 0x1 << (WORD_LEN_BITS - offset - 1);
 239  49251 return 0 != (m_value[segment] & mask);
 240    }
 241   
 242  11302 public void setUnchecked(final int a_index, final boolean a_value) {
 243  11302 int segment = a_index / WORD_LEN_BITS;
 244  11302 int offset = a_index % WORD_LEN_BITS;
 245  11302 int mask = 0x1 << (WORD_LEN_BITS - offset - 1);
 246  11302 if (a_value) {
 247  122 m_value[segment] |= mask;
 248    }
 249    else {
 250  11180 m_value[segment] &= ~mask;
 251    }
 252    }
 253   
 254  2 public String getPersistentRepresentation() {
 255  2 return toString();
 256    }
 257   
 258    /**
 259    * Sets the value and internal state of this Gene from the string
 260    * representation returned by a previous invocation of the
 261    * getPersistentRepresentation() method. This is an optional method but,
 262    * if not implemented, XML persistence and possibly other features will not
 263    * be available. An UnsupportedOperationException should be thrown if no
 264    * implementation is provided.
 265    *
 266    * @param a_representation the string representation retrieved from a
 267    * prior call to the getPersistentRepresentation() method
 268    *
 269    * @throws UnsupportedRepresentationException if this Gene implementation
 270    * does not support the given string representation
 271    *
 272    * @author Klaus Meffert
 273    * @since 2.0
 274    */
 275  8 public void setValueFromPersistentRepresentation(String a_representation)
 276    throws UnsupportedRepresentationException {
 277  8 if (a_representation != null) {
 278  6 if (isValidRepresentation(a_representation)) {
 279  4 a_representation = a_representation.substring(1,
 280    a_representation.length() - 1);
 281  4 StringTokenizer st = new StringTokenizer(a_representation, ",");
 282  4 int index = 0;
 283  4 while (st.hasMoreTokens()) {
 284  17 int i = Integer.parseInt(st.nextToken());
 285  17 setBit(index++, i);
 286    }
 287  4 if (index < getLength()) {
 288  1 throw new UnsupportedRepresentationException(
 289    "Invalid gene representation: " + a_representation);
 290    }
 291    }
 292    else {
 293  2 throw new UnsupportedRepresentationException(
 294    "Invalid gene representation: " + a_representation);
 295    }
 296    }
 297    else {
 298  2 throw new UnsupportedRepresentationException(
 299    "The input parameter must not be null!");
 300    }
 301    }
 302   
 303    /**
 304    * Verifies if the String is a valid representation of this Gene type
 305    * in general (bit values will not be checked)
 306    * @param a_representation the representation to check
 307    * @return true: representation is valid in general
 308    * @author Klaus Meffert
 309    * @since 2.0
 310    */
 311  6 private boolean isValidRepresentation(final String a_representation) {
 312  6 if (!a_representation.startsWith("[") || !a_representation.endsWith("]")) {
 313  2 return false;
 314    }
 315  4 return true;
 316    }
 317   
 318  4 public void setToRandomValue(final RandomGenerator a_numberGenerator) {
 319  4 if (a_numberGenerator == null) {
 320  1 throw new IllegalArgumentException("Random Generator must not be null!");
 321    }
 322  3 int len = getLength();
 323  3 for (int i = 0; i < len; i++) {
 324  21 setBit(i, a_numberGenerator.nextBoolean());
 325    }
 326    }
 327   
 328    /**
 329    * @return String representation
 330    *
 331    * @author Klaus Meffert
 332    * @since 2.0
 333    */
 334  12 public String toString() {
 335  12 int len = getLength();
 336  12 String s = "FixedBinaryGene[";
 337  12 int value;
 338  12 for (int i = 0; i < len; i++) {
 339  44 if (getBit(i)) {
 340  16 value = 1;
 341    }
 342    else {
 343  28 value = 0;
 344    }
 345  44 if (i == 0) {
 346  12 s += value;
 347    }
 348    else {
 349  32 s += "," + value;
 350    }
 351    }
 352  12 return s + "]";
 353    }
 354   
 355    /**
 356    * @return the size of the gene, i.e the number of atomic elements
 357    *
 358    * @author Klaus Meffert
 359    * @since 2.0
 360    */
 361  4 public int size() {
 362  4 return m_value.length;
 363    }
 364   
 365    /**
 366    * Applies a mutation of a given intensity (percentage) onto the atomic
 367    * element at given index
 368    * @param a_index index of atomic element, between 0 and size()-1
 369    * @param a_percentage percentage of mutation (greater than -1 and smaller
 370    * than 1)
 371    *
 372    * @author Klaus Meffert
 373    * @since 2.0
 374    */
 375  11 public void applyMutation(final int a_index, final double a_percentage) {
 376  11 if (a_index < 0 || a_index >= getLength()) {
 377  1 throw new IllegalArgumentException(
 378    "Index must be between 0 and getLength() - 1");
 379    }
 380  10 if (a_percentage > 0) {
 381    // change to 1
 382    // ---------------
 383  6 if (!getBit(a_index)) {
 384  1 setBit(a_index, true);
 385    }
 386    }
 387  4 else if (a_percentage < 0) {
 388    // change to 0
 389    // ---------------
 390  3 if (getBit(a_index)) {
 391  2 setBit(a_index, false);
 392    }
 393    }
 394    }
 395   
 396    /**
 397    * Compares this Gene with the specified object for order. A
 398    * 0 value is considered to be less than a 1 value. A null value
 399    * is considered to be less than any non-null value.
 400    * A Gene is greater than another one of the same length if it has more 1's
 401    * than the other one. If there is the same number of 1's the Gene with the
 402    * highest value (binary to int) is greater.
 403    *
 404    * @param a_other the FixedBinaryGene to be compared
 405    * @return a negative integer, zero, or a positive integer as this object
 406    * is less than, equal to, or greater than the specified object.
 407    *
 408    * @throws ClassCastException if the specified object's type prevents it
 409    * from being compared to this Gene
 410    *
 411    * @author Klaus Meffert
 412    * @since 2.0
 413    */
 414  10833 public int compareTo(final Object a_other) {
 415  10833 FixedBinaryGene otherGene = (FixedBinaryGene) a_other;
 416    // First, if the other gene is null, then this is the greater gene.
 417    // ----------------------------------------------------------------
 418  3816 if (otherGene == null) {
 419  2 return 1;
 420    }
 421  3814 int thisLen = getLength();
 422  3814 int otherLen = otherGene.getLength();
 423  3814 if (thisLen != otherLen) {
 424  2 if (thisLen > otherLen) {
 425  1 return 1;
 426    }
 427    else {
 428  1 return -1;
 429    }
 430    }
 431  3812 boolean b1, b2;
 432  3812 for (int i = 0; i < thisLen; i++) {
 433  19014 b1 = getBit(i);
 434  19014 b2 = otherGene.getBit(i);
 435  19014 if (b1) {
 436  11 if (!b2) {
 437  3 return 1;
 438    }
 439    }
 440    else {
 441  19003 if (b2) {
 442  3 return -1;
 443    }
 444    }
 445    }
 446    // Compare application data, if possible.
 447    // --------------------------------------
 448  3806 if (isCompareApplicationData()) {
 449  0 return compareApplicationData(getApplicationData(),
 450    otherGene.getApplicationData());
 451    }
 452    else {
 453  3806 return 0;
 454    }
 455    }
 456   
 457    /**
 458    * Not called as getAllele() is overridden.
 459    * @return same as getAllele()
 460    */
 461  0 protected Object getInternalValue() {
 462  0 return m_value;
 463    }
 464   
 465    /**
 466    * Modified hashCode() function to return different hashcodes for differently
 467    * ordered genes in a chromosome --> does not work as internal value always
 468    * initialized!
 469    * @return this Gene's hash code
 470    *
 471    * @author Klaus Meffert
 472    * @since 2.2
 473    */
 474  8630 public int hashCode() {
 475  8630 int result = 0;
 476  8630 for (int i = 0; i < m_value.length; i++) {
 477  8630 if (m_value[i] == 0) {
 478  8624 result += 31 * result + 47;
 479    }
 480    else {
 481  6 result += 31 * result + 91;
 482    }
 483    }
 484  8630 return result;
 485    }
 486    }