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