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