KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgap > impl > FixedBinaryGene


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 implements IPersistentRepresentation {
34   /** String containing the CVS revision. Read out via reflection!*/
35   private final static String JavaDoc CVS_REVISION = "$Revision: 1.37 $";
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   public FixedBinaryGene(final Configuration a_config, final int a_length)
53       throws InvalidConfigurationException {
54     super(a_config);
55     if (a_length < 1) {
56       throw new IllegalArgumentException JavaDoc("Length must be greater than zero!");
57     }
58     m_length = a_length;
59     int bufSize = m_length / WORD_LEN_BITS;
60     if (0 != m_length % WORD_LEN_BITS) {
61       ++bufSize;
62     }
63     m_value = new int[bufSize];
64     for (int i = 0; i < bufSize; i++) {
65       m_value[i] = 0;
66     }
67   }
68
69   protected Gene newGeneInternal() {
70     try {
71       FixedBinaryGene result = new FixedBinaryGene(getConfiguration(), m_length);
72       return result;
73     }
74     catch (InvalidConfigurationException iex) {
75       throw new IllegalStateException JavaDoc(iex.getMessage());
76     }
77   }
78
79   public FixedBinaryGene(final Configuration a_config,
80                          final FixedBinaryGene a_toCopy)
81       throws InvalidConfigurationException {
82     super(a_config);
83     m_length = a_toCopy.getLength();
84     int bufSize = m_length / WORD_LEN_BITS;
85     if (0 != m_length % WORD_LEN_BITS) {
86       ++bufSize;
87     }
88     m_value = new int[bufSize];
89     System.arraycopy(a_toCopy.getValue(), 0, m_value, 0, m_value.length);
90   }
91
92   protected int[] getValue() {
93     return m_value;
94   }
95
96   public int getLength() {
97     return m_length;
98   }
99
100   public Object JavaDoc clone() {
101     try {
102       return new FixedBinaryGene(getConfiguration(), this);
103     }
104     catch (InvalidConfigurationException iex) {
105       throw new IllegalStateException JavaDoc(iex.getMessage());
106     }
107   }
108
109   public void setAllele(final Object JavaDoc a_newValue) {
110     if (a_newValue == null) {
111       throw new IllegalArgumentException JavaDoc("Allele must not be null!");
112     }
113     if ( ( (int[]) a_newValue).length != getLength()) {
114       throw new IllegalArgumentException JavaDoc("Length of allele must be equal to"
115                                          + " fixed length set ("
116                                          + getLength()
117                                          + ")");
118     }
119     if (getConstraintChecker() != null) {
120       if (!getConstraintChecker().verify(this, a_newValue, null, -1)) {
121         return;
122       }
123     }
124     int[] bits = (int[]) a_newValue;
125     for (int i = 0; i < bits.length; i++) {
126       setBit(i, bits[i]);
127     }
128   }
129
130   public Object JavaDoc getAllele() {
131     int[] bits = new int[getLength()];
132     for (int i = 0; i < getLength(); i++) {
133       if (getBit(i)) {
134         bits[i] = 1;
135       }
136       else {
137         bits[i] = 0;
138       }
139     }
140     return bits;
141   }
142
143   public int[] getIntValues() {
144     return m_value;
145   }
146
147   public boolean getBit(final int a_index) {
148     checkIndex(a_index);
149     return getUnchecked(a_index);
150   }
151
152   public void setBit(final int a_index, final boolean a_value) {
153     checkIndex(a_index);
154     setUnchecked(a_index, a_value);
155   }
156
157   public void setBit(final int a_index, final int a_value) {
158     if (a_value > 0) {
159       if (a_value != 1) {
160         throw new IllegalArgumentException JavaDoc("Only values 0 and 1 are valid!");
161       }
162       setBit(a_index, true);
163     }
164     else {
165       if (a_value != 0) {
166         throw new IllegalArgumentException JavaDoc("Only values 0 and 1 are valid!");
167       }
168       setBit(a_index, false);
169     }
170   }
171
172   public void setBit(final int a_from, final int a_to, final boolean a_value) {
173     checkSubLength(a_from, a_to);
174     for (int i = a_from; i < a_to; i++) {
175       setUnchecked(i, a_value);
176     }
177   }
178
179   public void setBit(final int a_from, final int a_to,
180                      final FixedBinaryGene a_values) {
181     if (a_values.getLength() == 0) {
182       throw new IllegalArgumentException JavaDoc("Length of values must be > 0");
183     }
184     checkSubLength(a_from, a_to);
185     int iV = 0;
186     for (int i = a_from; i <= a_to; i++, iV++) {
187       if (iV >= a_values.getLength()) {
188         iV = 0;
189       }
190       setUnchecked(i, a_values.getUnchecked(iV));
191     }
192   }
193
194   public FixedBinaryGene substring(final int a_from, final int a_to) {
195     try {
196       int len = checkSubLength(a_from, a_to);
197       FixedBinaryGene substring = new FixedBinaryGene(getConfiguration(), len);
198       for (int i = a_from; i <= a_to; i++) {
199         substring.setUnchecked(i - a_from, getUnchecked(i));
200       }
201       return substring;
202     }
203     catch (InvalidConfigurationException iex) {
204       throw new IllegalStateException JavaDoc(iex.getMessage());
205     }
206   }
207
208   public void flip(final int a_index) {
209     checkIndex(a_index);
210     int segment = a_index / WORD_LEN_BITS;
211     int offset = a_index % WORD_LEN_BITS;
212     int mask = 0x1 << (WORD_LEN_BITS - offset - 1);
213     m_value[segment] ^= mask;
214   }
215
216   protected int checkSubLength(final int a_from, final int a_to) {
217     checkIndex(a_from);
218     checkIndex(a_to);
219     int sublen = a_to - a_from + 1;
220     if (0 >= sublen) {
221       throw new IllegalArgumentException JavaDoc("must have 'from' <= 'to', but has "
222                                          + a_from + " > " + a_to);
223     }
224     return sublen;
225   }
226
227   protected void checkIndex(final int a_index) {
228     if (a_index < 0 || a_index >= getLength()) {
229       throw new IndexOutOfBoundsException JavaDoc("index is " + a_index
230                                           + ", but must be in [0, "
231                                           + (getLength() - 1) + "]");
232     }
233   }
234
235   protected boolean getUnchecked(final int a_index) {
236     int segment = a_index / WORD_LEN_BITS;
237     int offset = a_index % WORD_LEN_BITS;
238     int mask = 0x1 << (WORD_LEN_BITS - offset - 1);
239     return 0 != (m_value[segment] & mask);
240   }
241
242   public void setUnchecked(final int a_index, final boolean a_value) {
243     int segment = a_index / WORD_LEN_BITS;
244     int offset = a_index % WORD_LEN_BITS;
245     int mask = 0x1 << (WORD_LEN_BITS - offset - 1);
246     if (a_value) {
247       m_value[segment] |= mask;
248     }
249     else {
250       m_value[segment] &= ~mask;
251     }
252   }
253
254   public String JavaDoc getPersistentRepresentation() {
255     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   public void setValueFromPersistentRepresentation(String JavaDoc a_representation)
276       throws UnsupportedRepresentationException {
277     if (a_representation != null) {
278       if (isValidRepresentation(a_representation)) {
279         a_representation = a_representation.substring(1,
280             a_representation.length() - 1);
281         StringTokenizer st = new StringTokenizer(a_representation, ",");
282         int index = 0;
283         while (st.hasMoreTokens()) {
284           int i = Integer.parseInt(st.nextToken());
285           setBit(index++, i);
286         }
287         if (index < getLength()) {
288           throw new UnsupportedRepresentationException(
289               "Invalid gene representation: " + a_representation);
290         }
291       }
292       else {
293         throw new UnsupportedRepresentationException(
294             "Invalid gene representation: " + a_representation);
295       }
296     }
297     else {
298       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   private boolean isValidRepresentation(final String JavaDoc a_representation) {
312     if (!a_representation.startsWith("[") || !a_representation.endsWith("]")) {
313       return false;
314     }
315     return true;
316   }
317
318   public void setToRandomValue(final RandomGenerator a_numberGenerator) {
319     if (a_numberGenerator == null) {
320       throw new IllegalArgumentException JavaDoc("Random Generator must not be null!");
321     }
322     int len = getLength();
323     for (int i = 0; i < len; i++) {
324       setBit(i, a_numberGenerator.nextBoolean());
325     }
326   }
327
328   /**
329    * @return String representation
330    *
331    * @author Klaus Meffert
332    * @since 2.0
333    */

334   public String JavaDoc toString() {
335     int len = getLength();
336     String JavaDoc s = "FixedBinaryGene[";
337     int value;
338     for (int i = 0; i < len; i++) {
339       if (getBit(i)) {
340         value = 1;
341       }
342       else {
343         value = 0;
344       }
345       if (i == 0) {
346         s += value;
347       }
348       else {
349         s += "," + value;
350       }
351     }
352     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   public int size() {
362     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   public void applyMutation(final int a_index, final double a_percentage) {
376     if (a_index < 0 || a_index >= getLength()) {
377       throw new IllegalArgumentException JavaDoc(
378           "Index must be between 0 and getLength() - 1");
379     }
380     if (a_percentage > 0) {
381       // change to 1
382
// ---------------
383
if (!getBit(a_index)) {
384         setBit(a_index, true);
385       }
386     }
387     else if (a_percentage < 0) {
388       // change to 0
389
// ---------------
390
if (getBit(a_index)) {
391         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   public int compareTo(final Object JavaDoc a_other) {
415     FixedBinaryGene otherGene = (FixedBinaryGene) a_other;
416     // First, if the other gene is null, then this is the greater gene.
417
// ----------------------------------------------------------------
418
if (otherGene == null) {
419       return 1;
420     }
421     int thisLen = getLength();
422     int otherLen = otherGene.getLength();
423     if (thisLen != otherLen) {
424       if (thisLen > otherLen) {
425         return 1;
426       }
427       else {
428         return -1;
429       }
430     }
431     boolean b1, b2;
432     for (int i = 0; i < thisLen; i++) {
433       b1 = getBit(i);
434       b2 = otherGene.getBit(i);
435       if (b1) {
436         if (!b2) {
437           return 1;
438         }
439       }
440       else {
441         if (b2) {
442           return -1;
443         }
444       }
445     }
446     // Compare application data, if possible.
447
// --------------------------------------
448
if (isCompareApplicationData()) {
449       return compareApplicationData(getApplicationData(),
450                                     otherGene.getApplicationData());
451     }
452     else {
453       return 0;
454     }
455   }
456
457   /**
458    * Not called as getAllele() is overridden.
459    * @return same as getAllele()
460    */

461   protected Object JavaDoc getInternalValue() {
462     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   public int hashCode() {
475     int result = 0;
476     for (int i = 0; i < m_value.length; i++) {
477       if (m_value[i] == 0) {
478         result += 31 * result + 47;
479       }
480       else {
481         result += 31 * result + 91;
482       }
483     }
484     return result;
485   }
486 }
487
Popular Tags