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