Genotype.java
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(_chromosomes37;
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(+ 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 }