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