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