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