IntegerGene.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-5.2.0).
003  * Copyright (c) 2007-2020 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics;
021 
022 import static java.lang.String.format;
023 import static io.jenetics.internal.util.Hashes.hash;
024 import static io.jenetics.internal.util.SerialIO.readInt;
025 import static io.jenetics.internal.util.SerialIO.writeInt;
026 import static io.jenetics.util.RandomRegistry.random;
027 
028 import java.io.DataInput;
029 import java.io.DataOutput;
030 import java.io.IOException;
031 import java.io.InvalidObjectException;
032 import java.io.ObjectInputStream;
033 import java.io.Serializable;
034 import java.util.Random;
035 
036 import io.jenetics.internal.math.Randoms;
037 import io.jenetics.util.ISeq;
038 import io.jenetics.util.IntRange;
039 import io.jenetics.util.MSeq;
040 import io.jenetics.util.Mean;
041 
042 /**
043  * NumericGene implementation which holds a 32 bit integer number.
044  *
045  <p>This is a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html">
046  * value-based</a> class; use of identity-sensitive operations (including
047  * reference equality ({@code ==}), identity hash code, or synchronization) on
048  * instances of {@code IntegerGene} may have unpredictable results and should
049  * be avoided.
050  *
051  @see IntegerChromosome
052  *
053  * @implNote
054  * This class is immutable and thread-safe.
055  *
056  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
057  @since 2.0
058  @version 5.2
059  */
060 public final class IntegerGene
061     implements
062         NumericGene<Integer, IntegerGene>,
063         Mean<IntegerGene>,
064         Comparable<IntegerGene>,
065         Serializable
066 {
067 
068     private static final long serialVersionUID = 2L;
069 
070     private final int _value;
071     private final int _min;
072     private final int _max;
073 
074     /**
075      * Create a new random {@code IntegerGene} with the given value and the
076      * given range. If the {@code value} isn't within the interval [min, max],
077      * no exception is thrown. In this case the method
078      {@link IntegerGene#isValid()} returns {@code false}.
079      *
080      @param value the value of the gene.
081      @param min the minimal valid value of this gene (inclusively).
082      @param max the maximal valid value of this gene (inclusively).
083      */
084     private IntegerGene(final int value, final int min, final int max) {
085         _value = value;
086         _min = min;
087         _max = max;
088     }
089 
090     @Deprecated
091     @Override
092     public Integer getAllele() {
093         return _value;
094     }
095 
096     @Deprecated
097     @Override
098     public Integer getMin() {
099         return _min;
100     }
101 
102     @Deprecated
103     @Override
104     public Integer getMax() {
105         return _max;
106     }
107 
108     /**
109      * Return the range of {@code this} gene.
110      *
111      @since 4.4
112      *
113      @return the range of {@code this} gene
114      */
115     public IntRange range() {
116         return IntRange.of(_min, _max);
117     }
118 
119     @Override
120     public byte byteValue() {
121         return (byte)_value;
122     }
123 
124     @Override
125     public short shortValue() {
126         return (short)_value;
127     }
128 
129     @Override
130     public int intValue() {
131         return _value;
132     }
133 
134     @Override
135     public long longValue() {
136         return _value;
137     }
138 
139     @Override
140     public float floatValue() {
141         return (float)_value;
142     }
143 
144     @Override
145     public double doubleValue() {
146         return _value;
147     }
148 
149     @Override
150     public boolean isValid() {
151         return _value >= _min && _value <= _max;
152     }
153 
154     @Override
155     public int compareTo(final IntegerGene other) {
156         return Integer.compare(_value, other._value);
157     }
158 
159     @Override
160     public IntegerGene mean(final IntegerGene that) {
161         return IntegerGene.of(_value + (that._value - _value)/2, _min, _max);
162     }
163 
164     /**
165      * Create a new gene from the given {@code value} and the gene context.
166      *
167      @since 5.0
168      @param value the value of the new gene.
169      @return a new gene with the given value.
170      */
171     public IntegerGene newInstance(final int value) {
172         return IntegerGene.of(value, _min, _max);
173     }
174 
175     @Override
176     public IntegerGene newInstance(final Integer number) {
177         return IntegerGene.of(number, _min, _max);
178     }
179 
180     @Override
181     public IntegerGene newInstance(final Number number) {
182         return IntegerGene.of(number.intValue(), _min, _max);
183     }
184 
185     @Override
186     public IntegerGene newInstance() {
187         return IntegerGene.of(nextInt(random(), _min, _max), _min, _max);
188     }
189 
190     @Override
191     public int hashCode() {
192         return hash(_value, hash(_min, hash(_max)));
193     }
194 
195     @Override
196     public boolean equals(final Object obj) {
197         return obj == this ||
198             obj instanceof IntegerGene &&
199             ((IntegerGene)obj)._value == _value &&
200             ((IntegerGene)obj)._min == _min &&
201             ((IntegerGene)obj)._max == _max;
202     }
203 
204     @Override
205     public String toString() {
206         return String.format("[%s]", _value);
207     }
208 
209     /* *************************************************************************
210      * Static factory methods.
211      * ************************************************************************/
212 
213     /**
214      * Create a new random {@code IntegerGene} with the given value and the
215      * given range. If the {@code value} isn't within the interval [min, max],
216      * no exception is thrown. In this case the method
217      {@link IntegerGene#isValid()} returns {@code false}.
218      *
219      @param value the value of the gene.
220      @param min the minimal valid value of this gene (inclusively).
221      @param max the maximal valid value of this gene (inclusively).
222      @return a new {@code IntegerGene} with the given {@code value}
223      */
224     public static IntegerGene of(final int value, final int min, final int max) {
225         return new IntegerGene(value, min, max);
226     }
227 
228     /**
229      * Create a new random {@code IntegerGene} with the given value and the
230      * given range. If the {@code value} isn't within the interval [min, max],
231      * no exception is thrown. In this case the method
232      {@link IntegerGene#isValid()} returns {@code false}.
233      *
234      @since 3.2
235      *
236      @param value the value of the gene.
237      @param range the integer range to use
238      @return a new {@code IntegerGene} with the give {@code value}
239      @throws NullPointerException if the given {@code range} is {@code null}.
240      */
241     public static IntegerGene of(final int value, final IntRange range) {
242         return IntegerGene.of(value, range.min(), range.max());
243     }
244 
245     /**
246      * Create a new random {@code IntegerGene}. It is guaranteed that the value of
247      * the {@code IntegerGene} lies in the interval [min, max].
248      *
249      @param min the minimal valid value of this gene (inclusively).
250      @param max the maximal valid value of this gene (inclusively).
251      @return a new random {@code IntegerGene}
252      */
253     public static IntegerGene of(final int min, final int max) {
254         return of(nextInt(random(), min, max), min, max);
255     }
256 
257     /**
258      * Create a new random {@code IntegerGene}. It is guaranteed that the value of
259      * the {@code IntegerGene} lies in the interval [min, max].
260      *
261      @since 3.2
262      *
263      @param range the integer range to use
264      @return a new random {@code IntegerGene}
265      @throws NullPointerException if the given {@code range} is {@code null}.
266      */
267     public static IntegerGene of(final IntRange range) {
268         return of(nextInt(random(), range.min(), range.max()), range);
269     }
270 
271     static ISeq<IntegerGene> seq(
272         final int min,
273         final int max,
274         final IntRange lengthRange
275     ) {
276         final Random r = random();
277         return MSeq.<IntegerGene>ofLength(Randoms.nextInt(lengthRange, r))
278             .fill(() -> new IntegerGene(nextInt(r, min, max), min, max))
279             .toISeq();
280     }
281 
282     /**
283      * Returns a pseudo-random, uniformly distributed int value between min and
284      * max (min and max included).
285      *
286      @param random the random engine to use for calculating the random int
287      *        value
288      @param min lower bound for generated integer
289      @param max upper bound for generated integer
290      @return a random integer greater than or equal to {@code min} and
291      *         less than or equal to {@code max}
292      @throws IllegalArgumentException if {@code min > max}
293      @throws NullPointerException if the given {@code random}
294      *         engine is {@code null}.
295      */
296     static int nextInt(
297         final Random random,
298         final int min, final int max
299     ) {
300         if (min > max) {
301             throw new IllegalArgumentException(format(
302                 "Min >= max: %d >= %d", min, max
303             ));
304         }
305 
306         final int diff = max - min + 1;
307         int result = 0;
308 
309         if (diff <= 0) {
310             do {
311                 result = random.nextInt();
312             while (result < min || result > max);
313         else {
314             result = random.nextInt(diff+ min;
315         }
316 
317         return result;
318     }
319 
320 
321     /* *************************************************************************
322      *  Java object serialization
323      * ************************************************************************/
324 
325     private Object writeReplace() {
326         return new Serial(Serial.INTEGER_GENE, this);
327     }
328 
329     private void readObject(final ObjectInputStream stream)
330         throws InvalidObjectException
331     {
332         throw new InvalidObjectException("Serialization proxy required.");
333     }
334 
335     void write(final DataOutput outthrows IOException {
336         writeInt(_value, out);
337         writeInt(_min, out);
338         writeInt(_max, out);
339     }
340 
341     static IntegerGene read(final DataInput inthrows IOException {
342         return of(readInt(in), readInt(in), readInt(in));
343     }
344 
345 }