LongChromosome.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-4.3.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 import java.util.stream.IntStream;
027 import java.util.stream.LongStream;
028 
029 import io.jenetics.internal.util.reflect;
030 import io.jenetics.util.ISeq;
031 import io.jenetics.util.IntRange;
032 import io.jenetics.util.LongRange;
033 import io.jenetics.util.MSeq;
034 
035 /**
036  * Numeric chromosome implementation which holds 64 bit integer numbers.
037  *
038  @see LongGene
039  *
040  * @implNote
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.3
046  */
047 public class LongChromosome
048     extends AbstractBoundedChromosome<Long, LongGene>
049     implements
050         NumericChromosome<Long, LongGene>,
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 LongChromosome(
070         final ISeq<LongGene> 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 LongGene}s (inclusively).
082      @param max the max value of the {@link LongGene}s (inclusively).
083      @param lengthRange the allowed length range of the chromosome.
084      @throws NullPointerException if one of the arguments is {@code null}.
085      @throws IllegalArgumentException if the length is smaller than one
086      *
087      @deprecated Use {@link #of(long, long, IntRange)} instead.
088      */
089     @Deprecated
090     public LongChromosome(
091         final Long min,
092         final Long max,
093         final IntRange lengthRange
094     ) {
095         this(LongGene.seq(min, max, lengthRange), lengthRange);
096         _valid = true;
097     }
098 
099     /**
100      * Create a new random {@code LongChromosome}.
101      *
102      @param min the min value of the {@link LongGene}s (inclusively).
103      @param max the max value of the {@link LongGene}s (inclusively).
104      @param length the length of the chromosome.
105      @throws NullPointerException if one of the arguments is {@code null}.
106      @throws IllegalArgumentException if the {@code length} is smaller than
107      *         one.
108      *
109      @deprecated Use {@link #of(long, long, int)} instead.
110      */
111     @Deprecated
112     public LongChromosome(final Long min, final Long max, final int length) {
113         this(min, max, IntRange.of(length));
114     }
115 
116     /**
117      * Create a new random {@code LongChromosome} of length one.
118      *
119      @param min the minimal value of this chromosome (inclusively).
120      @param max the maximal value of this chromosome (inclusively).
121      @throws NullPointerException if one of the arguments is {@code null}.
122      *
123      @deprecated Use {@link #of(long, long)} instead.
124      */
125     @Deprecated
126     public LongChromosome(final Long min, final Long max) {
127         this(min, max, 1);
128     }
129 
130     @Override
131     public LongChromosome newInstance(final ISeq<LongGene> genes) {
132         return new LongChromosome(genes, lengthRange());
133     }
134 
135     @Override
136     public LongChromosome newInstance() {
137         return of(_min, _max, lengthRange());
138     }
139 
140     /**
141      * Returns a sequential stream of the alleles with this chromosome as its
142      * source.
143      *
144      @since 4.3
145      *
146      @return a sequential stream of alleles
147      */
148     public LongStream longStream() {
149         return IntStream.range(0, length()).mapToLong(this::longValue);
150     }
151 
152     /**
153      * Returns an long array containing all of the elements in this chromosome
154      * in proper sequence.  If the chromosome fits in the specified array, it is
155      * returned therein. Otherwise, a new array is allocated with the length of
156      * this chromosome.
157      *
158      @since 3.0
159      *
160      @param array the array into which the elements of this chromosomes are to
161      *        be stored, if it is big enough; otherwise, a new array is
162      *        allocated for this purpose.
163      @return an array containing the elements of this chromosome
164      @throws NullPointerException if the given {@code array} is {@code null}
165      */
166     public long[] toArray(final long[] array) {
167         final long[] a = array.length >= length() ? array : new long[length()];
168         for (int i = length(); --i >= 0;) {
169             a[i= longValue(i);
170         }
171 
172         return a;
173     }
174 
175     /**
176      * Returns an long array containing all of the elements in this chromosome
177      * in proper sequence.
178      *
179      @since 3.0
180      *
181      @return an array containing the elements of this chromosome
182      */
183     public long[] toArray() {
184         return toArray(new long[length()]);
185     }
186 
187 
188     /* *************************************************************************
189      * Static factory methods.
190      * ************************************************************************/
191 
192     /**
193      * Create a new {@code LongChromosome} with the given genes.
194      *
195      @param genes the genes of the chromosome.
196      @return a new chromosome with the given genes.
197      @throws IllegalArgumentException if the length of the genes array is
198      *         empty.
199      @throws NullPointerException if the given {@code genes} are {@code null}
200      */
201     public static LongChromosome of(final LongGene... genes) {
202         return new LongChromosome(ISeq.of(genes), IntRange.of(genes.length));
203     }
204 
205     /**
206      * Create a new {@code LongChromosome} with the given genes.
207      *
208      @since 4.3
209      *
210      @param genes the genes of the chromosome.
211      @return a new chromosome with the given genes.
212      @throws NullPointerException if the given {@code genes} are {@code null}
213      @throws IllegalArgumentException if the length of the genes array is
214      *         empty.
215      */
216     public static LongChromosome of(final Iterable<LongGene> genes) {
217         final ISeq<LongGene> values = ISeq.of(genes);
218         return new LongChromosome(values, IntRange.of(values.length()));
219     }
220 
221     /**
222      * Create a new random chromosome.
223      *
224      @since 4.0
225      *
226      @param min the min value of the {@link LongGene}s (inclusively).
227      @param max the max value of the {@link LongGene}s (inclusively).
228      @param lengthRange the allowed length range of the chromosome.
229      @return a new {@code IntegerChromosome} with the given parameter
230      @throws IllegalArgumentException if the length of the gene sequence is
231      *         empty, doesn't match with the allowed length range, the minimum
232      *         or maximum of the range is smaller or equal zero or the given
233      *         range size is zero.
234      @throws NullPointerException if the given {@code lengthRange} is
235      *         {@code null}
236      */
237     public static LongChromosome of(
238         final long min,
239         final long max,
240         final IntRange lengthRange
241     ) {
242         final ISeq<LongGene> values = LongGene.seq(min, max, lengthRange);
243         return new LongChromosome(values, lengthRange);
244     }
245 
246     /**
247      * Create a new random {@code LongChromosome}.
248      *
249      @param min the min value of the {@link LongGene}s (inclusively).
250      @param max the max value of the {@link LongGene}s (inclusively).
251      @param length the length of the chromosome.
252      @return a new {@code LongChromosome} with the given gene parameters.
253      @throws IllegalArgumentException if the {@code length} is smaller than
254      *         one.
255      */
256     public static LongChromosome of(
257         final long min,
258         final long max,
259         final int length
260     ) {
261         return of(min, max, IntRange.of(length));
262     }
263 
264     /**
265      * Create a new random chromosome.
266      *
267      @since 4.0
268      *
269      @param range the integer range of the chromosome.
270      @param lengthRange the allowed length range of the chromosome.
271      @return a new {@code LongChromosome} with the given parameter
272      @throws IllegalArgumentException if the length of the gene sequence is
273      *         empty, doesn't match with the allowed length range, the minimum
274      *         or maximum of the range is smaller or equal zero or the given
275      *         range size is zero.
276      @throws NullPointerException if the given {@code lengthRange} is
277      *         {@code null}
278      */
279     public static LongChromosome of(
280         final LongRange range,
281         final IntRange lengthRange
282     ) {
283         return of(range.getMin(), range.getMax(), lengthRange);
284     }
285 
286     /**
287      * Create a new random {@code LongChromosome}.
288      *
289      @since 3.2
290      *
291      @param range the long range of the chromosome.
292      @param length the length of the chromosome.
293      @return a new random {@code LongChromosome}
294      @throws NullPointerException if the given {@code range} is {@code null}
295      @throws IllegalArgumentException if the {@code length} is smaller than
296      *         one.
297      */
298     public static LongChromosome of(final LongRange range, final int length) {
299         return of(range.getMin(), range.getMax(), length);
300     }
301 
302     /**
303      * Create a new random {@code LongChromosome} of length one.
304      *
305      @param min the minimal value of this chromosome (inclusively).
306      @param max the maximal value of this chromosome (inclusively).
307      @return a new {@code LongChromosome} with the given gene parameters.
308      */
309     public static LongChromosome of(final long min, final long max) {
310         return of(min, max, 1);
311     }
312 
313     /**
314      * Create a new random {@code LongChromosome} of length one.
315      *
316      @since 3.2
317      *
318      @param range the long range of the chromosome.
319      @return a new random {@code LongChromosome} of length one
320      @throws NullPointerException if the given {@code range} is {@code null}
321      */
322     public static LongChromosome of(final LongRange range) {
323         return of(range.getMin(), range.getMax());
324     }
325 
326 
327     /* *************************************************************************
328      *  Java object serialization
329      * ************************************************************************/
330 
331     private void writeObject(final ObjectOutputStream out)
332         throws IOException
333     {
334         out.defaultWriteObject();
335 
336         out.writeInt(length());
337         out.writeObject(lengthRange());
338         out.writeLong(_min);
339         out.writeLong(_max);
340 
341         for (LongGene gene : _genes) {
342             out.writeLong(gene.getAllele());
343         }
344     }
345 
346     private void readObject(final ObjectInputStream in)
347         throws IOException, ClassNotFoundException
348     {
349         in.defaultReadObject();
350 
351         final MSeq<LongGene> genes = MSeq.ofLength(in.readInt());
352         reflect.setField(this, "_lengthRange", in.readObject());
353         reflect.setField(this, "_min", in.readLong());
354         reflect.setField(this, "_max", in.readLong());
355 
356         for (int i = 0; i < genes.length(); ++i) {
357             genes.set(i, LongGene.of(in.readLong(), _min, _max));
358         }
359 
360         reflect.setField(this, "_genes", genes.toISeq());
361     }
362 
363 }