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