DoubleGene.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 io.jenetics.internal.math.Randoms.nextDouble;
023 import static io.jenetics.internal.util.Hashes.hash;
024 import static io.jenetics.util.RandomRegistry.random;
025 
026 import java.io.DataInput;
027 import java.io.DataOutput;
028 import java.io.IOException;
029 import java.io.InvalidObjectException;
030 import java.io.ObjectInputStream;
031 import java.io.Serializable;
032 import java.util.Random;
033 
034 import io.jenetics.internal.math.Randoms;
035 import io.jenetics.util.DoubleRange;
036 import io.jenetics.util.ISeq;
037 import io.jenetics.util.IntRange;
038 import io.jenetics.util.MSeq;
039 import io.jenetics.util.Mean;
040 
041 /**
042  * Implementation of the NumericGene which holds a 64 bit floating point number.
043  *
044  <p>This is a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html">
045  * value-based</a> class; use of identity-sensitive operations (including
046  * reference equality ({@code ==}), identity hash code, or synchronization) on
047  * instances of {@code DoubleGene} may have unpredictable results and should
048  * be avoided.
049  *
050  @see DoubleChromosome
051  *
052  * @implNote
053  * This class is immutable and thread-safe.
054  *
055  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
056  @since 1.6
057  @version 5.2
058  */
059 public final class DoubleGene
060     implements
061         NumericGene<Double, DoubleGene>,
062         Mean<DoubleGene>,
063         Comparable<DoubleGene>,
064         Serializable
065 {
066 
067     private static final long serialVersionUID = 2L;
068 
069     private final double _value;
070     private final double _min;
071     private final double _max;
072 
073     /**
074      * Create a new random {@code DoubleGene} with the given value and the
075      * given range. If the {@code value} isn't within the interval [min, max),
076      * no exception is thrown. In this case the method
077      {@link DoubleGene#isValid()} returns {@code false}.
078      *
079      @param value the value of the gene.
080      @param min the minimal valid value of this gene (inclusively).
081      @param max the maximal valid value of this gene (exclusively).
082      */
083     private DoubleGene(final double value, final double min, final double max) {
084         _value = value;
085         _min = min;
086         _max = max;
087     }
088 
089     @Deprecated
090     @Override
091     public Double getAllele() {
092         return _value;
093     }
094 
095     @Deprecated
096     @Override
097     public Double getMin() {
098         return _min;
099     }
100 
101     @Deprecated
102     @Override
103     public Double getMax() {
104         return _max;
105     }
106 
107     /**
108      * Return the range of {@code this} gene.
109      *
110      @since 4.4
111      *
112      @return the range of {@code this} gene
113      */
114     public DoubleRange range() {
115         return DoubleRange.of(_min, _max);
116     }
117 
118     @Override
119     public byte byteValue() {
120         return (byte)_value;
121     }
122 
123     @Override
124     public short shortValue() {
125         return (short)_value;
126     }
127 
128     @Override
129     public int intValue() {
130         return (int)_value;
131     }
132 
133     @Override
134     public long longValue() {
135         return (long)_value;
136     }
137 
138     @Override
139     public float floatValue() {
140         return (float)_value;
141     }
142 
143     @Override
144     public double doubleValue() {
145          return _value;
146     }
147 
148     @Override
149     public boolean isValid() {
150         return Double.compare(_value, _min>= &&
151             Double.compare(_value, _max<= 0;
152     }
153 
154     @Override
155     public int compareTo(final DoubleGene other) {
156         return Double.compare(_value, other._value);
157     }
158 
159     @Override
160     public DoubleGene mean(final DoubleGene that) {
161         return of(_value + (that._value - _value)/2.0, _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 DoubleGene newInstance(final double value) {
172         return DoubleGene.of(value, _min, _max);
173     }
174 
175     @Override
176     public DoubleGene newInstance(final Double value) {
177         return of(value, _min, _max);
178     }
179 
180     @Override
181     public DoubleGene newInstance(final Number number) {
182         return of(number.doubleValue(), _min, _max);
183     }
184 
185     @Override
186     public DoubleGene newInstance() {
187         return of(nextDouble(_min, _max, random()), _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 DoubleGene &&
199             Double.compare(((DoubleGene)obj)._value, _value== &&
200             Double.compare(((DoubleGene)obj)._min, _min== &&
201             Double.compare(((DoubleGene)obj)._max, _max== 0;
202     }
203 
204     @Override
205     public String toString() {
206         return String.format("[%s]", _value);
207     }
208 
209 
210     /* *************************************************************************
211      * Static factory methods.
212      * ************************************************************************/
213 
214     /**
215      * Create a new random {@code DoubleGene} with the given value and the
216      * given range. If the {@code value} isn't within the interval [min, max),
217      * no exception is thrown. In this case the method
218      {@link DoubleGene#isValid()} returns {@code false}.
219      *
220      @param value the value of the gene.
221      @param min the minimal valid value of this gene (inclusively).
222      @param max the maximal valid value of this gene (exclusively).
223      @return a new {@code DoubleGene} with the given parameter
224      */
225     public static DoubleGene of(
226         final double value,
227         final double min,
228         final double max
229     ) {
230         return new DoubleGene(value, min, max);
231     }
232 
233     /**
234      * Create a new random {@code DoubleGene} with the given value and the
235      * given range. If the {@code value} isn't within the interval [min, max),
236      * no exception is thrown. In this case the method
237      {@link DoubleGene#isValid()} returns {@code false}.
238      *
239      @since 3.2
240      *
241      @param value the value of the gene.
242      @param range the double range to use
243      @return a new random {@code DoubleGene}
244      @throws NullPointerException if the given {@code range} is {@code null}.
245      */
246     public static DoubleGene of(final double value, final DoubleRange range) {
247         return of(value, range.min(), range.max());
248     }
249 
250     /**
251      * Create a new random {@code DoubleGene}. It is guaranteed that the value
252      * of the {@code DoubleGene} lies in the interval [min, max).
253      *
254      @param min the minimal valid value of this gene (inclusively).
255      @param max the maximal valid value of this gene (exclusively).
256      @return a new {@code DoubleGene} with the given parameter
257      */
258     public static DoubleGene of(final double min, final double max) {
259         return of(nextDouble(min, max, random()), min, max);
260     }
261 
262     /**
263      * Create a new random {@code DoubleGene}. It is guaranteed that the value
264      * of the {@code DoubleGene} lies in the interval [min, max).
265      *
266      @since 3.2
267      *
268      @param range the double range to use
269      @return a new {@code DoubleGene} with the given parameter
270      @throws NullPointerException if the given {@code range} is {@code null}.
271      */
272     public static DoubleGene of(final DoubleRange range) {
273         return of(nextDouble(range.min(), range.max(), random()), range);
274     }
275 
276     static ISeq<DoubleGene> seq(
277         final double min,
278         final double max,
279         final IntRange lengthRange
280     ) {
281         final Random r = random();
282         return MSeq.<DoubleGene>ofLength(Randoms.nextInt(lengthRange, r))
283             .fill(() -> new DoubleGene(nextDouble(min, max, r), min, max))
284             .toISeq();
285     }
286 
287 
288     /* *************************************************************************
289      *  Java object serialization
290      * ************************************************************************/
291 
292     private Object writeReplace() {
293         return new Serial(Serial.DOUBLE_GENE, this);
294     }
295 
296     private void readObject(final ObjectInputStream stream)
297         throws InvalidObjectException
298     {
299         throw new InvalidObjectException("Serialization proxy required.");
300     }
301 
302     void write(final DataOutput outthrows IOException {
303         out.writeDouble(_value);
304         out.writeDouble(_min);
305         out.writeDouble(_max);
306     }
307 
308     static DoubleGene read(final DataInput inthrows IOException {
309         return of(in.readDouble(), in.readDouble(), in.readDouble());
310     }
311 
312 }