DoubleChromosome.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-4.1.0).
003  * Copyright (c) 2007-2018 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 java.io.IOException;
023 import java.io.ObjectInputStream;
024 import java.io.ObjectOutputStream;
025 import java.io.Serializable;
026 
027 import io.jenetics.internal.util.Equality;
028 import io.jenetics.internal.util.Hash;
029 import io.jenetics.internal.util.reflect;
030 import io.jenetics.util.DoubleRange;
031 import io.jenetics.util.ISeq;
032 import io.jenetics.util.IntRange;
033 import io.jenetics.util.MSeq;
034 
035 /**
036  * Numeric chromosome implementation which holds 64 bit floating point numbers.
037  *
038  @see DoubleGene
039  *
040  * @implSpec
041  * This class is immutable and thread-safe.
042  *
043  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
044  @since 1.6
045  @version 4.0
046  */
047 public class DoubleChromosome
048     extends AbstractBoundedChromosome<Double, DoubleGene>
049     implements
050         NumericChromosome<Double, DoubleGene>,
051         Serializable
052 {
053     private static final long serialVersionUID = 2L;
054 
055     /**
056      * Create a new chromosome from the given {@code genes} and the allowed
057      * length range of the chromosome.
058      *
059      @since 4.0
060      *
061      @param genes the genes that form the chromosome.
062      @param lengthRange the allowed length range of the chromosome
063      @throws NullPointerException if one of the arguments is {@code null}.
064      @throws IllegalArgumentException if the length of the gene sequence is
065      *         empty, doesn't match with the allowed length range, the minimum
066      *         or maximum of the range is smaller or equal zero or the given
067      *         range size is zero.
068      */
069     protected DoubleChromosome(
070         final ISeq<DoubleGene> genes,
071         final IntRange lengthRange
072     ) {
073         super(genes, lengthRange);
074     }
075 
076     /**
077      * Create a new random chromosome.
078      *
079      @since 4.0
080      *
081      @param min the min value of the {@link DoubleGene}s (inclusively).
082      @param max the max value of the {@link DoubleGene}s (exclusively).
083      @param lengthRange the allowed length range of the chromosome. The start
084      *        of the range is inclusively and the range end exclusively
085      @throws NullPointerException if one of the arguments is {@code null}.
086      @throws IllegalArgumentException if the length is smaller than one
087      */
088     public DoubleChromosome(
089         final Double min,
090         final Double max,
091         final IntRange lengthRange
092     ) {
093         this(DoubleGene.seq(min, max, lengthRange), lengthRange);
094         _valid = true;
095     }
096 
097     /**
098      * Create a new random {@code DoubleChromosome}.
099      *
100      @param min the min value of the {@link DoubleGene}s (inclusively).
101      @param max the max value of the {@link DoubleGene}s (exclusively).
102      @param length the length of the chromosome.
103      @throws NullPointerException if one of the arguments is {@code null}.
104      @throws IllegalArgumentException if the length is smaller than one
105      */
106     public DoubleChromosome(final Double min,final Double max,final int length) {
107         this(min, max, IntRange.of(length));
108     }
109 
110     /**
111      * Create a new random {@code DoubleChromosome} of length one.
112      *
113      @param min the minimal value of this chromosome (inclusively).
114      @param max the maximal value of this chromosome (exclusively).
115      @throws NullPointerException if one of the arguments is {@code null}.
116      */
117     public DoubleChromosome(final Double min, final Double max) {
118         this(min, max, 1);
119     }
120 
121     /**
122      * Returns an double array containing all of the elements in this chromosome
123      * in proper sequence.  If the chromosome fits in the specified array, it is
124      * returned therein. Otherwise, a new array is allocated with the length of
125      * this chromosome.
126      *
127      @since 3.0
128      *
129      @param array the array into which the elements of this chromosomes are to
130      *        be stored, if it is big enough; otherwise, a new array is
131      *        allocated for this purpose.
132      @return an array containing the elements of this chromosome
133      @throws NullPointerException if the given {@code array} is {@code null}
134      */
135     public double[] toArray(final double[] array) {
136         final double[] a = array.length >= length() ? array : new double[length()];
137         for (int i = length(); --i >= 0;) {
138             a[i= doubleValue(i);
139         }
140 
141         return a;
142     }
143 
144     /**
145      * Returns an double array containing all of the elements in this chromosome
146      * in proper sequence.
147      *
148      @since 3.0
149      *
150      @return an array containing the elements of this chromosome
151      */
152     public double[] toArray() {
153         return toArray(new double[length()]);
154     }
155 
156     /**
157      * Create a new {@code DoubleChromosome} with the given genes.
158      *
159      @param genes the genes of the chromosome.
160      @return a new chromosome with the given genes.
161      @throws IllegalArgumentException if the length of the genes array is
162      *         empty.
163      */
164     public static DoubleChromosome of(final DoubleGene... genes) {
165         return new DoubleChromosome(ISeq.of(genes), IntRange.of(genes.length));
166     }
167 
168     /**
169      * Create a new random chromosome.
170      *
171      @since 4.0
172      *
173      @param min the min value of the {@link DoubleGene}s (inclusively).
174      @param max the max value of the {@link DoubleGene}s (exclusively).
175      @param lengthRange the allowed length range of the chromosome.
176      @return a new {@code DoubleChromosome} with the given parameter
177      @throws IllegalArgumentException if the length of the gene sequence is
178      *         empty, doesn't match with the allowed length range, the minimum
179      *         or maximum of the range is smaller or equal zero or the given
180      *         range size is zero.
181      @throws NullPointerException if the given {@code lengthRange} is
182      *         {@code null}
183      */
184     public static DoubleChromosome of(
185         final double min,
186         final double max,
187         final IntRange lengthRange
188     ) {
189         return new DoubleChromosome(min, max, lengthRange);
190     }
191 
192     /**
193      * Create a new random {@code DoubleChromosome}.
194      *
195      @param min the min value of the {@link DoubleGene}s (inclusively).
196      @param max the max value of the {@link DoubleGene}s (exclusively).
197      @param length the length of the chromosome.
198      @return a new {@code DoubleChromosome} with the given parameter
199      @throws IllegalArgumentException if the {@code length} is smaller than
200      *         one.
201      */
202     public static DoubleChromosome of(
203         final double min,
204         final double max,
205         final int length
206     ) {
207         return new DoubleChromosome(min, max, length);
208     }
209 
210     /**
211      * Create a new random chromosome.
212      *
213      @since 4.0
214      *
215      @param range the integer range of the chromosome.
216      @param lengthRange the allowed length range of the chromosome.
217      @return a new {@code DoubleChromosome} with the given parameter
218      @throws IllegalArgumentException if the length of the gene sequence is
219      *         empty, doesn't match with the allowed length range, the minimum
220      *         or maximum of the range is smaller or equal zero or the given
221      *         range size is zero.
222      @throws NullPointerException if the given {@code lengthRange} is
223      *         {@code null}
224      */
225     public static DoubleChromosome of(
226         final DoubleRange range,
227         final IntRange lengthRange
228     ) {
229         return new DoubleChromosome(range.getMin(), range.getMax(), lengthRange);
230     }
231 
232     /**
233      * Create a new random {@code DoubleChromosome}.
234      *
235      @since 3.2
236      *
237      @param range the integer range of the chromosome.
238      @param length the length of the chromosome.
239      @return a new random {@code DoubleChromosome}
240      @throws NullPointerException if the given {@code range} is {@code null}
241      @throws IllegalArgumentException if the {@code length} is smaller than
242      *         one.
243      */
244     public static DoubleChromosome of(final DoubleRange range, final int length) {
245         return new DoubleChromosome(range.getMin(), range.getMax(), length);
246     }
247 
248     /**
249      * Create a new random {@code DoubleChromosome} of length one.
250      *
251      @param min the minimal value of this chromosome (inclusively).
252      @param max the maximal value of this chromosome (exclusively).
253      @return a new {@code DoubleChromosome} with the given parameter
254      */
255     public static DoubleChromosome of(final double min, final double max) {
256         return new DoubleChromosome(min, max);
257     }
258 
259     /**
260      * Create a new random {@code DoubleChromosome} of length one.
261      *
262      @since 3.2
263      *
264      @param range the double range of the chromosome.
265      @return a new random {@code DoubleChromosome} of length one
266      @throws NullPointerException if the given {@code range} is {@code null}
267      */
268     public static DoubleChromosome of(final DoubleRange range) {
269         return new DoubleChromosome(range.getMin(), range.getMax());
270     }
271 
272     @Override
273     public DoubleChromosome newInstance(final ISeq<DoubleGene> genes) {
274         return new DoubleChromosome(genes, lengthRange());
275     }
276 
277     @Override
278     public DoubleChromosome newInstance() {
279         return new DoubleChromosome(_min, _max, lengthRange());
280     }
281 
282     @Override
283     public int hashCode() {
284         return Hash.of(getClass()).and(super.hashCode()).value();
285     }
286 
287     @Override
288     public boolean equals(final Object obj) {
289         return Equality.of(this, obj).test(super::equals);
290     }
291 
292 
293     /* *************************************************************************
294      *  Java object serialization
295      * ************************************************************************/
296 
297     private void writeObject(final ObjectOutputStream out)
298         throws IOException
299     {
300         out.defaultWriteObject();
301 
302         out.writeInt(length());
303         out.writeObject(lengthRange());
304         out.writeDouble(_min);
305         out.writeDouble(_max);
306 
307         for (DoubleGene gene : _genes) {
308             out.writeDouble(gene.getAllele());
309         }
310     }
311 
312     private void readObject(final ObjectInputStream in)
313         throws IOException, ClassNotFoundException
314     {
315         in.defaultReadObject();
316 
317         final MSeq<DoubleGene> genes = MSeq.ofLength(in.readInt());
318         reflect.setField(this, "_lengthRange", in.readObject());
319         reflect.setField(this, "_min", in.readDouble());
320         reflect.setField(this, "_max", in.readDouble());
321 
322         for (int i = 0; i < genes.length(); ++i) {
323             genes.set(i, new DoubleGene(in.readDouble(), _min, _max));
324         }
325 
326         reflect.setField(this, "_genes", genes.toISeq());
327     }
328 
329 }