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) >= 0 &&
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) == 0 &&
200 Double.compare(((DoubleGene)obj)._min, _min) == 0 &&
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 out) throws IOException {
303 out.writeDouble(_value);
304 out.writeDouble(_min);
305 out.writeDouble(_max);
306 }
307
308 static DoubleGene read(final DataInput in) throws IOException {
309 return of(in.readDouble(), in.readDouble(), in.readDouble());
310 }
311
312 }
|