KickJava   Java API By Example, From Geeks To Geeks.

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


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 implements IPersistentRepresentation {
26   /** String containing the CVS revision. Read out via reflection!*/
27   private static final String JavaDoc CVS_REVISION = "$Revision: 1.42 $";
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   public IntegerGene()
60       throws InvalidConfigurationException {
61     this(Genotype.getStaticConfiguration());
62   }
63
64   /**
65    * Constructs a new IntegerGene with default settings. No bounds will
66    * be put into effect for values (alleles) of this Gene instance, other
67    * than the standard range of integer values.
68    *
69    * @param a_config the configuration to use
70    * @throws InvalidConfigurationException
71    *
72    * @author Klaus Meffert
73    * @since 3.0
74    */

75   public IntegerGene(final Configuration a_config)
76       throws InvalidConfigurationException {
77     this(a_config, Integer.MIN_VALUE, Integer.MAX_VALUE);
78   }
79
80   /**
81    * Constructs a new IntegerGene with the specified lower and upper
82    * bounds for values (alleles) of this Gene instance.
83    *
84    * @param a_config the configuration to use
85    * @param a_lowerBounds the lowest value that this Gene may possess,
86    * inclusive
87    * @param a_upperBounds the highest value that this Gene may possess,
88    * inclusive
89    * @throws InvalidConfigurationException
90    *
91    * @author Klaus Meffert
92    * @since 2.0
93    */

94   public IntegerGene(final Configuration a_config, final int a_lowerBounds,
95                      final int a_upperBounds)
96       throws InvalidConfigurationException {
97     super(a_config);
98     m_lowerBounds = a_lowerBounds;
99     m_upperBounds = a_upperBounds;
100   }
101
102   /**
103    * Provides implementation-independent means for creating new Gene
104    * instances.
105    *
106    * @return a new Gene instance of the same type and with the same setup as
107    * this concrete Gene
108    *
109    * @author Klaus Meffert
110    * @since 2.6 (was newGene since 1.0, moved to BaseGene)
111    */

112   protected Gene newGeneInternal() {
113     try {
114       IntegerGene result = new IntegerGene(getConfiguration(), m_lowerBounds,
115           m_upperBounds);
116       return result;
117     } catch (InvalidConfigurationException iex) {
118       throw new IllegalStateException JavaDoc(iex.getMessage());
119     }
120   }
121
122   /**
123    * Retrieves a string representation of this Gene that includes any
124    * information required to reconstruct it at a later time, such as its
125    * value and internal state. This string will be used to represent this
126    * Gene in XML persistence. This is an optional method but, if not
127    * implemented, XML persistence and possibly other features will not be
128    * available. An UnsupportedOperationException should be thrown if no
129    * implementation is provided.
130    *
131    * @return string representation of this Gene's current state
132    *
133    * @author Neil Rostan
134    * @since 1.0
135    */

136   public String JavaDoc getPersistentRepresentation() {
137     // The persistent representation includes the value, lower bound,
138
// and upper bound. Each is separated by a colon.
139
// --------------------------------------------------------------
140
String JavaDoc s;
141     if (getInternalValue() == null) {
142       s = "null";
143     }
144     else {
145       s = getInternalValue().toString();
146     }
147     return s + PERSISTENT_FIELD_DELIMITER + m_lowerBounds
148         + PERSISTENT_FIELD_DELIMITER + m_upperBounds;
149   }
150
151   /**
152    * Sets the value and internal state of this Gene from the string
153    * representation returned by a previous invocation of the
154    * getPersistentRepresentation() method. This is an optional method but,
155    * if not implemented, XML persistence and possibly other features will not
156    * be available. An UnsupportedOperationException should be thrown if no
157    * implementation is provided.
158    *
159    * @param a_representation the string representation retrieved from a
160    * prior call to the getPersistentRepresentation() method
161    *
162    * @throws UnsupportedOperationException to indicate that no implementation
163    * is provided for this method
164    * @throws UnsupportedRepresentationException if this Gene implementation
165    * does not support the given string representation
166    *
167    * @author Neil Rostan
168    * @since 1.0
169    */

170   public void setValueFromPersistentRepresentation(final String JavaDoc
171       a_representation)
172       throws UnsupportedRepresentationException {
173     if (a_representation != null) {
174       StringTokenizer tokenizer =
175           new StringTokenizer(a_representation,
176                               PERSISTENT_FIELD_DELIMITER);
177       // Make sure the representation contains the correct number of
178
// fields. If not, throw an exception.
179
// -----------------------------------------------------------
180
if (tokenizer.countTokens() != 3) {
181         throw new UnsupportedRepresentationException(
182             "The format of the given persistent representation " +
183             "is not recognized: it does not contain three tokens.");
184       }
185       String JavaDoc valueRepresentation = tokenizer.nextToken();
186       String JavaDoc lowerBoundRepresentation = tokenizer.nextToken();
187       String JavaDoc upperBoundRepresentation = tokenizer.nextToken();
188       // First parse and set the representation of the value.
189
// ----------------------------------------------------
190
if (valueRepresentation.equals("null")) {
191         setAllele(null);
192       }
193       else {
194         try {
195           setAllele(new Integer JavaDoc(Integer.parseInt(valueRepresentation)));
196         } catch (NumberFormatException JavaDoc e) {
197           throw new UnsupportedRepresentationException(
198               "The format of the given persistent representation " +
199               "is not recognized: field 1 does not appear to be " +
200               "an integer value.");
201         }
202       }
203       // Now parse and set the lower bound.
204
// ----------------------------------
205
try {
206         m_lowerBounds =
207             Integer.parseInt(lowerBoundRepresentation);
208       } catch (NumberFormatException JavaDoc e) {
209         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
try {
217         m_upperBounds =
218             Integer.parseInt(upperBoundRepresentation);
219       } catch (NumberFormatException JavaDoc e) {
220         throw new UnsupportedRepresentationException(
221             "The format of the given persistent representation " +
222             "is not recognized: field 3 does not appear to be " +
223             "an integer value.");
224       }
225     }
226   }
227
228   /**
229    * Retrieves the int value of this Gene, which may be more convenient in
230    * some cases than the more general getAllele() method.
231    *
232    * @return the int value of this Gene
233    *
234    * @author Neil Rostan
235    * @since 1.0
236    */

237   public int intValue() {
238     return ( (Integer JavaDoc) getAllele()).intValue();
239   }
240
241   /**
242    * Sets the value (allele) of this Gene to a random Integer value between
243    * the lower and upper bounds (if any) of this Gene.
244    *
245    * @param a_numberGenerator the random number generator that should be
246    * used to create any random values. It's important to use this generator to
247    * maintain the user's flexibility to configure the genetic engine to use the
248    * random number generator of their choice
249    *
250    * @author Neil Rostan
251    * @author Klaus Meffert
252    * @since 1.0
253    */

254   public void setToRandomValue(final RandomGenerator a_numberGenerator) {
255     double randomValue = (m_upperBounds - m_lowerBounds) *
256         a_numberGenerator.nextDouble() +
257         m_lowerBounds;
258     setAllele(new Integer JavaDoc( (int) Math.round(randomValue)));
259   }
260
261   /**
262    * Compares to objects by first casting them into their expected type
263    * (e.g. Integer for IntegerGene) and then calling the compareTo-method
264    * of the casted type.
265    * @param a_o1 first object to be compared, always is not null
266    * @param a_o2 second object to be compared, always is not null
267    * @return a negative integer, zero, or a positive integer as this object
268    * is less than, equal to, or greater than the object provided for comparison
269    *
270    * @author Neil Rostan
271    * @since 1.0
272    */

273   protected int compareToNative(final Object JavaDoc a_o1, final Object JavaDoc a_o2) {
274     return ( (Integer JavaDoc) a_o1).compareTo( (Integer JavaDoc) a_o2);
275   }
276
277   /**
278    * Maps the value of this IntegerGene to within the bounds specified by
279    * the m_upperBounds and m_lowerBounds instance variables. The value's
280    * relative position within the integer range will be preserved within the
281    * bounds range (in other words, if the value is about halfway between the
282    * integer max and min, then the resulting value will be about halfway
283    * between the upper bounds and lower bounds). If the value is null or
284    * is already within the bounds, it will be left unchanged.
285    *
286    * @author Neil Rostan
287    * @author Klaus Meffert
288    * @since 1.0
289    */

290   protected void mapValueToWithinBounds() {
291     if (getAllele() != null) {
292       Integer JavaDoc i_value = ( (Integer JavaDoc) getAllele());
293       // If the value exceeds either the upper or lower bounds, then
294
// map the value to within the legal range. To do this, we basically
295
// calculate the distance between the value and the integer min,
296
// determine how many bounds units that represents, and then add
297
// that number of units to the upper bound.
298
// -----------------------------------------------------------------
299
if (i_value.intValue() > m_upperBounds ||
300           i_value.intValue() < m_lowerBounds) {
301         RandomGenerator rn;
302         if (getConfiguration() != null) {
303           rn = getConfiguration().getRandomGenerator();
304         }
305         else {
306           rn = new StockRandomGenerator();
307         }
308         setAllele(new Integer JavaDoc(rn.nextInt(m_upperBounds - m_lowerBounds) +
309                               m_lowerBounds));
310       }
311     }
312   }
313
314   /**
315    * See interface Gene for description.
316    * @param a_index ignored (because there is only 1 atomic element)
317    * @param a_percentage percentage of mutation (greater than -1 and smaller
318    * than 1)
319    *
320    * @author Klaus Meffert
321    * @since 1.1
322    */

323   public void applyMutation(final int a_index, final double a_percentage) {
324     double range = (m_upperBounds - m_lowerBounds) * a_percentage;
325     if (getAllele() == null) {
326       setAllele(new Integer JavaDoc( (int) range + m_lowerBounds));
327     }
328     else {
329       int newValue = (int) Math.round(intValue() + range);
330       setAllele(new Integer JavaDoc(newValue));
331     }
332   }
333
334   /**
335    * Modified hashCode() function to return different hashcodes for differently
336    * ordered genes in a chromosome.
337    * @return -1 if no allele set, otherwise value return by BaseGene.hashCode()
338    *
339    * @author Klaus Meffert
340    * @since 2.2
341    */

342   public int hashCode() {
343     if (getInternalValue() == null) {
344       return -1;
345     }
346     else {
347       return super.hashCode();
348     }
349   }
350
351   /**
352    * @return string representation of this Gene's value that may be useful for
353    * display purposes
354    *
355    * @author Klaus Meffert
356    * @since 2.4
357    */

358   public String JavaDoc toString() {
359     String JavaDoc s = "IntegerGene(" + m_lowerBounds + "," + m_upperBounds + ")"
360         + "=";
361     if (getInternalValue() == null) {
362       s += "null";
363     }
364     else {
365       s += getInternalValue().toString();
366     }
367     return s;
368   }
369
370   /**
371    * @return the lower bounds of the integer gene
372    *
373    * @author Klaus Meffert
374    * @since 2.6
375    */

376   public int getLowerBounds() {
377     return m_lowerBounds;
378   }
379
380   /**
381    * @return the upper bounds of the integer gene
382    *
383    * @author Klaus Meffert
384    * @since 2.6
385    */

386   public int getUpperBounds() {
387     return m_upperBounds;
388   }
389 }
390
Popular Tags