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 static io.jenetics.internal.util.Equality.eq;
023
024 import java.io.Serializable;
025 import java.util.Iterator;
026 import java.util.Objects;
027 import java.util.function.ToIntFunction;
028 import java.util.stream.Stream;
029
030 import io.jenetics.internal.util.Hash;
031 import io.jenetics.util.Factory;
032 import io.jenetics.util.ISeq;
033 import io.jenetics.util.MSeq;
034 import io.jenetics.util.Seq;
035 import io.jenetics.util.Verifiable;
036
037 /**
038 * The central class the GA is working with, is the {@code Genotype}. It is the
039 * structural representative of an individual. This class is the encoded problem
040 * solution with one to many {@link Chromosome}.
041 * <p>
042 * <img alt="Genotype" src="doc-files/Genotype.svg" width="400" height="252" >
043 * </p>
044 * The chromosomes of a genotype doesn't have to have necessarily the same size.
045 * It is only required that all genes are from the same type and the genes within
046 * a chromosome have the same constraints; e. g. the same min- and max values
047 * for number genes.
048 *
049 * <pre>{@code
050 * final Genotype<DoubleGene> genotype = Genotype.of(
051 * DoubleChromosome.of(0.0, 1.0, 8),
052 * DoubleChromosome.of(1.0, 2.0, 10),
053 * DoubleChromosome.of(0.0, 10.0, 9),
054 * DoubleChromosome.of(0.1, 0.9, 5)
055 * );
056 * }</pre>
057 * The code snippet above creates a genotype with the same structure as shown in
058 * the figure above. In this example the {@link DoubleGene} has been chosen as
059 * gene type.
060 *
061 * @see Chromosome
062 * @see Phenotype
063 *
064 * @implSpec
065 * This class is immutable and thread-safe.
066 *
067 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
068 * @since 1.0
069 * @version 4.0
070 */
071 public final class Genotype<G extends Gene<?, G>>
072 implements
073 Factory<Genotype<G>>,
074 Iterable<Chromosome<G>>,
075 Verifiable,
076 Serializable
077 {
078 private static final long serialVersionUID = 3L;
079
080 private final ISeq<Chromosome<G>> _chromosomes;
081 private final int _ngenes;
082
083 //Caching isValid value.
084 private volatile Boolean _valid = null;
085
086 private Genotype(
087 final ISeq<? extends Chromosome<G>> chromosomes,
088 final int ngenes
089 ) {
090 if (chromosomes.isEmpty()) {
091 throw new IllegalArgumentException("No chromosomes given.");
092 }
093
094 _chromosomes = ISeq.upcast(chromosomes);
095 _ngenes = ngenes;
096 }
097
098 /**
099 * Create a new Genotype from a given sequence of {@code Chromosomes}.
100 *
101 * @param chromosomes The {@code Chromosome} array the {@code Genotype}
102 * consists of.
103 * @throws NullPointerException if {@code chromosomes} is null or one of its
104 * element.
105 * @throws IllegalArgumentException if {@code chromosome.length == 0}.
106 */
107 Genotype(final ISeq<? extends Chromosome<G>> chromosomes) {
108 this(chromosomes, ngenes(chromosomes));
109 }
110
111 private static int ngenes(final Seq<? extends Chromosome<?>> chromosomes) {
112 return chromosomes.stream()
113 .mapToInt((ToIntFunction<Chromosome<?>>)Chromosome::length)
114 .sum();
115 }
116
117 /**
118 * Return the chromosome at the given index. It is guaranteed, that the
119 * returned chromosome is not null.
120 *
121 * @param index Chromosome index.
122 * @return The Chromosome.
123 * @throws IndexOutOfBoundsException if
124 * {@code (index < 0 || index >= _length)}.
125 */
126 public Chromosome<G> getChromosome(final int index) {
127 assert _chromosomes != null;
128 assert _chromosomes.get(index) != null;
129
130 return _chromosomes.get(index);
131 }
132
133 /**
134 * Return the first chromosome. This is a shortcut for
135 * <pre>{@code
136 * final Genotype<DoubleGene>; gt = ...
137 * final Chromosome<DoubleGene> chromosome = gt.getChromosome(0);
138 * }</pre>
139 *
140 * @return The first chromosome.
141 */
142 public Chromosome<G> getChromosome() {
143 assert _chromosomes != null;
144 assert _chromosomes.get(0) != null;
145
146 return _chromosomes.get(0);
147 }
148
149 /**
150 * Return the first {@link Gene} of the first {@link Chromosome} of this
151 * {@code Genotype}. This is a shortcut for
152 * <pre>{@code
153 * final Genotype<DoubleGene> gt = ...
154 * final DoubleGene gene = gt.getChromosome(0).getGene(0);
155 * }</pre>
156 *
157 * @return the first {@link Gene} of the first {@link Chromosome} of this
158 * {@code Genotype}.
159 */
160 public G getGene() {
161 assert _chromosomes != null;
162 assert _chromosomes.get(0) != null;
163
164 return _chromosomes.get(0).getGene();
165 }
166
167 /**
168 * Return the gene from the given chromosome- and gene index. This is a
169 * shortcut for {@code gt.getChromosome(chromosomeIndex).getGene(geneIndex)}.
170 *
171 * @since 3.0
172 *
173 * @param chromosomeIndex the chromosome index
174 * @param geneIndex the gene index within the chromosome
175 * @return the gene with the given indexes
176 * @throws IndexOutOfBoundsException if the given indexes are not within the
177 * allowed range
178 */
179 public G get(final int chromosomeIndex, final int geneIndex) {
180 return getChromosome(chromosomeIndex).getGene(geneIndex);
181 }
182
183 /**
184 * Return the chromosome at the given index. It is guaranteed, that the
185 * returned chromosome is not null.
186 *
187 * @see #getChromosome(int)
188 * @since 4.0
189 *
190 * @param chromosomeIndex Chromosome index.
191 * @return The Chromosome.
192 * @throws IndexOutOfBoundsException if
193 * {@code (index < 0 || index >= _length)}.
194 */
195 public Chromosome<G> get(final int chromosomeIndex) {
196 return getChromosome(chromosomeIndex);
197 }
198
199 public ISeq<Chromosome<G>> toSeq() {
200 return _chromosomes;
201 }
202
203 @Override
204 public Iterator<Chromosome<G>> iterator() {
205 return _chromosomes.iterator();
206 }
207
208 /**
209 * Returns a sequential {@code Stream} of chromosomes with this genotype as
210 * its source.
211 *
212 * @since 3.4
213 *
214 * @return a sequential {@code Stream} of chromosomes
215 */
216 public Stream<Chromosome<G>> stream() {
217 return _chromosomes.stream();
218 }
219
220 /**
221 * Getting the number of chromosomes of this genotype.
222 *
223 * @return number of chromosomes.
224 */
225 public int length() {
226 return _chromosomes.length();
227 }
228
229 /**
230 * Return the number of genes this genotype consists of. This is the sum of
231 * the number of genes of the genotype chromosomes.
232 *
233 * @return Return the number of genes this genotype consists of.
234 */
235 public int geneCount() {
236 return _ngenes;
237 }
238
239 /**
240 * Test if this genotype is valid. A genotype is valid if all its
241 * {@link Chromosome}s are valid.
242 *
243 * @return true if this genotype is valid, false otherwise.
244 */
245 @Override
246 public boolean isValid() {
247 Boolean valid = _valid;
248 if (valid == null) {
249 valid = _chromosomes.forAll(Verifiable::isValid);
250 _valid = valid;
251 }
252
253 return _valid;
254 }
255
256 /**
257 * Return a new, random genotype by creating new, random chromosomes (calling
258 * the {@link Chromosome#newInstance()} method) from the chromosomes of this
259 * genotype.
260 */
261 @Override
262 public Genotype<G> newInstance() {
263 return new Genotype<>(_chromosomes.map(Factory::newInstance), _ngenes);
264 }
265
266 Genotype<G> newInstance(final ISeq<Chromosome<G>> chromosomes) {
267 return new Genotype<>(chromosomes, _ngenes);
268 }
269
270 @Override
271 public int hashCode() {
272 int hash = 17;
273 hash += 31*Objects.hashCode(_chromosomes) + 37;
274 return hash;
275 }
276
277 @Override
278 public boolean equals(final Object obj) {
279 return obj == this ||
280 obj instanceof Genotype<?> &&
281 eq(_chromosomes, ((Genotype<?>)obj)._chromosomes);
282 }
283
284 @Override
285 public String toString() {
286 return _chromosomes.toString();
287 }
288
289 /**
290 * Create a new {@code Genotype} from a given array of {@code Chromosomes}.
291 *
292 * @since 3.0
293 *
294 * @param <G> the gene type
295 * @param first the first {@code Chromosome} of the {@code Genotype}
296 * @param rest the rest of the genotypes chromosomes.
297 * @return a new {@code Genotype} from the given chromosomes
298 * @throws NullPointerException if {@code chromosomes} is {@code null} or
299 * one of its element.
300 */
301 @SafeVarargs
302 public static <G extends Gene<?, G>> Genotype<G> of(
303 final Chromosome<G> first,
304 final Chromosome<G>... rest
305 ) {
306 final MSeq<Chromosome<G>> seq = MSeq.ofLength(1 + rest.length);
307 seq.set(0, first);
308 for (int i = 0; i < rest.length; ++i) {
309 seq.set(i + 1, rest[i]);
310 }
311 return new Genotype<>(seq.toISeq());
312 }
313
314 /**
315 * Create a new {@code Genotype} which consists of {@code n} chromosomes,
316 * which are created by the given {@code factory}. This method can be used
317 * for easily creating a <i>gene matrix</i>. The following example will
318 * create a 10x5 {@code DoubleGene} <i>matrix</i>.
319 *
320 * <pre>{@code
321 * final Genotype<DoubleGene> gt = Genotype
322 * .of(DoubleChromosome.of(0.0, 1.0, 10), 5);
323 * }</pre>
324 *
325 * @since 3.0
326 *
327 * @param <G> the gene type
328 * @param factory the factory which creates the chromosomes this genotype
329 * consists of
330 * @param n the number of chromosomes this genotype consists of
331 * @return new {@code Genotype} containing {@code n} chromosomes
332 * @throws IllegalArgumentException if {@code n < 1}.
333 * @throws NullPointerException if the {@code factory} is {@code null}.
334 */
335 public static <G extends Gene<?, G>> Genotype<G>
336 of(final Factory<? extends Chromosome<G>> factory, final int n) {
337 final ISeq<Chromosome<G>> ch = ISeq.of(factory::newInstance, n);
338 return new Genotype<>(ch);
339 }
340
341 /**
342 * Create a new {@code Genotype} from a given array of {@code chromosomes}.
343 *
344 * @since 3.0
345 *
346 * @param <G> the gene type
347 * @param chromosomes the {@code Chromosome}s the returned genotype consists
348 * of
349 * @return a new {@code Genotype} from the given chromosomes
350 * @throws NullPointerException if {@code chromosomes} is {@code null} or
351 * one of its element.
352 * @throws IllegalArgumentException if {@code chromosome.length() < 1}.
353 */
354 public static <G extends Gene<?, G>> Genotype<G>
355 of(final Iterable<? extends Chromosome<G>> chromosomes) {
356 return new Genotype<>(ISeq.of(chromosomes));
357 }
358
359 }
|