Genotype.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.7.0).
003  * Copyright (c) 2007-2016 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@gmx.at)
019  */
020 package org.jenetics;
021 
022 import static org.jenetics.internal.util.Equality.eq;
023 import static org.jenetics.util.ISeq.toISeq;
024 
025 import java.io.Serializable;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.stream.Stream;
029 
030 import javax.xml.bind.annotation.XmlAccessType;
031 import javax.xml.bind.annotation.XmlAccessorType;
032 import javax.xml.bind.annotation.XmlAttribute;
033 import javax.xml.bind.annotation.XmlElement;
034 import javax.xml.bind.annotation.XmlRootElement;
035 import javax.xml.bind.annotation.XmlType;
036 import javax.xml.bind.annotation.adapters.XmlAdapter;
037 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
038 
039 import org.jenetics.internal.util.Hash;
040 import org.jenetics.internal.util.jaxb;
041 
042 import org.jenetics.util.Factory;
043 import org.jenetics.util.ISeq;
044 import org.jenetics.util.MSeq;
045 import org.jenetics.util.Seq;
046 import org.jenetics.util.Verifiable;
047 
048 /**
049  * The central class the GA is working with, is the {@code Genotype}. It is the
050  * structural representative of an individual. This class is the encoded problem
051  * solution with one to many {@link Chromosome}.
052  <p>
053  <img alt="Genotype" src="doc-files/Genotype.svg" width="400" height="252" >
054  </p>
055  * The chromosomes of a genotype doesn't have to have necessarily the same size.
056  * It is only required that all genes are from the same type and the genes within
057  * a chromosome have the same constraints; e. g. the same min- and max values
058  * for number genes.
059  *
060  <pre>{@code
061  * final Genotype<DoubleGene> genotype = Genotype.of(
062  *     DoubleChromosome.of(0.0, 1.0, 8),
063  *     DoubleChromosome.of(1.0, 2.0, 10),
064  *     DoubleChromosome.of(0.0, 10.0, 9),
065  *     DoubleChromosome.of(0.1, 0.9, 5)
066  * );
067  * }</pre>
068  * The code snippet above creates a genotype with the same structure as shown in
069  * the figure above. In this example the {@link DoubleGene} has been chosen as
070  * gene type.
071  *
072  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
073  @since 1.0
074  @version 3.0
075  */
076 @XmlJavaTypeAdapter(Genotype.Model.Adapter.class)
077 public final class Genotype<G extends Gene<?, G>>
078     implements
079         Factory<Genotype<G>>,
080         Iterable<Chromosome<G>>,
081         Verifiable,
082         Serializable
083 {
084     private static final long serialVersionUID = 3L;
085 
086     private final ISeq<Chromosome<G>> _chromosomes;
087     private final int _ngenes;
088 
089     //Caching isValid value.
090     private volatile Boolean _valid = null;
091 
092     private Genotype(
093         final ISeq<? extends Chromosome<G>> chromosomes,
094         final int ngenes
095     ) {
096         if (chromosomes.isEmpty()) {
097             throw new IllegalArgumentException("No chromosomes given.");
098         }
099 
100         _chromosomes = ISeq.upcast(chromosomes);
101         _ngenes = ngenes;
102     }
103 
104     /**
105      * Create a new Genotype from a given sequence of {@code Chromosomes}.
106      *
107      @param chromosomes The {@code Chromosome} array the {@code Genotype}
108      *         consists of.
109      @throws NullPointerException if {@code chromosomes} is null or one of its
110      *         element.
111      @throws IllegalArgumentException if {@code chromosome.length == 0}.
112      */
113     Genotype(final ISeq<? extends Chromosome<G>> chromosomes) {
114         this(chromosomes, ngenes(chromosomes));
115     }
116 
117     private static int ngenes(final Seq<? extends Chromosome<?>> chromosomes) {
118         return chromosomes.stream()
119             .mapToInt(c -> c.length())
120             .sum();
121     }
122 
123     /**
124      * Return the chromosome at the given index. It is guaranteed, that the
125      * returned chromosome is not null.
126      *
127      @param index Chromosome index.
128      @return The Chromosome.
129      @throws IndexOutOfBoundsException if
130      *         {@code (index < 0 || index >= _length)}.
131      */
132     public Chromosome<G> getChromosome(final int index) {
133         assert _chromosomes != null;
134         assert _chromosomes.get(index!= null;
135 
136         return _chromosomes.get(index);
137     }
138 
139     /**
140      * Return the first chromosome. This is a shortcut for
141      <pre>{@code
142      * final Genotype<DoubleGene>; gt = ...
143      * final Chromosome<DoubleGene> chromosome = gt.getChromosome(0);
144      * }</pre>
145      *
146      @return The first chromosome.
147      */
148     public Chromosome<G> getChromosome() {
149         assert _chromosomes != null;
150         assert _chromosomes.get(0!= null;
151 
152         return _chromosomes.get(0);
153     }
154 
155     /**
156      * Return the first {@link Gene} of the first {@link Chromosome} of this
157      * {@code Genotype}. This is a shortcut for
158      <pre>{@code
159      * final Genotype<DoubleGene> gt = ...
160      * final DoubleGene gene = gt.getChromosome(0).getGene(0);
161      * }</pre>
162      *
163      @return the first {@link Gene} of the first {@link Chromosome} of this
164      *         {@code Genotype}.
165      */
166     public G getGene() {
167         assert _chromosomes != null;
168         assert _chromosomes.get(0!= null;
169 
170         return _chromosomes.get(0).getGene();
171     }
172 
173     /**
174      * Return the gene from the given chromosome- and gene index. This is a
175      * shortcut for {@code gt.getChromosome(chromosomeIndex).getGene(geneIndex)}.
176      *
177      @since 3.0
178      *
179      @param chromosomeIndex the chromosome index
180      @param geneIndex the gene index within the chromosome
181      @return the gene with the given indexes
182      @throws IndexOutOfBoundsException if the given indexes are not within the
183      *         allowed range
184      */
185     public G get(final int chromosomeIndex, final int geneIndex) {
186         return getChromosome(chromosomeIndex).getGene(geneIndex);
187     }
188 
189     public ISeq<Chromosome<G>> toSeq() {
190         return _chromosomes;
191     }
192 
193     @Override
194     public Iterator<Chromosome<G>> iterator() {
195         return _chromosomes.iterator();
196     }
197 
198     /**
199      * Returns a sequential {@code Stream} of chromosomes with this genotype as
200      * its source.
201      *
202      @since 3.4
203      *
204      @return a sequential {@code Stream} of chromosomes
205      */
206     public Stream<Chromosome<G>> stream() {
207         return _chromosomes.stream();
208     }
209 
210     /**
211      * Getting the number of chromosomes of this genotype.
212      *
213      @return number of chromosomes.
214      */
215     public int length() {
216         return _chromosomes.length();
217     }
218 
219     /**
220      * Return the number of genes this genotype consists of. This is the sum of
221      * the number of genes of the genotype chromosomes.
222      *
223      @return Return the number of genes this genotype consists of.
224      */
225     public int getNumberOfGenes() {
226         return _ngenes;
227     }
228 
229     /**
230      * Test if this genotype is valid. A genotype is valid if all its
231      {@link Chromosome}s are valid.
232      *
233      @return true if this genotype is valid, false otherwise.
234      */
235     @Override
236     public boolean isValid() {
237         Boolean valid = _valid;
238         if (valid == null) {
239             valid = _chromosomes.forAll(Verifiable::isValid);
240             _valid = valid;
241         }
242 
243         return _valid;
244     }
245 
246     /**
247      * Return a new, random genotype by creating new, random chromosomes (calling
248      * the {@link Chromosome#newInstance()} method) from the chromosomes of this
249      * genotype.
250      */
251     @Override
252     public Genotype<G> newInstance() {
253         return new Genotype<>(_chromosomes.map(Factory::newInstance), _ngenes);
254     }
255 
256     Genotype<G> newInstance(final ISeq<Chromosome<G>> chromosomes) {
257         return new Genotype<>(chromosomes, _ngenes);
258     }
259 
260     @Override
261     public int hashCode() {
262         return Hash.of(getClass()).and(_chromosomes).value();
263     }
264 
265     @Override
266     public boolean equals(final Object obj) {
267         return obj instanceof Genotype<?> &&
268             eq(_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      *  JAXB object serialization
348      * ************************************************************************/
349 
350     @XmlRootElement(name = "genotype")
351     @XmlType(name = "org.jenetics.Genotype")
352     @XmlAccessorType(XmlAccessType.FIELD)
353     @SuppressWarnings({"unchecked""rawtypes"})
354     static final class Model {
355 
356         @XmlAttribute(name = "length", required = true)
357         public int length;
358 
359         @XmlAttribute(name = "ngenes", required = true)
360         public int ngenes;
361 
362         @XmlElement(name = "chromosome", required = true, nillable = false)
363         public List chromosomes;
364 
365         public static final class Adapter
366             extends XmlAdapter<Model, Genotype>
367         {
368             @Override
369             public Model marshal(final Genotype gtthrows Exception {
370                 final Model model = new Model();
371                 model.length = gt.length();
372                 model.ngenes = gt.getNumberOfGenes();
373                 model.chromosomes = gt.toSeq()
374                     .map(jaxb.Marshaller(gt.getChromosome()))
375                     .asList();
376 
377                 return model;
378             }
379 
380             @Override
381             public Genotype unmarshal(final Model modelthrows Exception {
382                 final ISeq chs = (ISeq)model.chromosomes.stream()
383                     .map(jaxb.Unmarshaller(model.chromosomes.get(0)))
384                     .collect(toISeq());
385 
386                 return new Genotype(chs, model.ngenes);
387             }
388         }
389 
390         public static final Adapter ADAPTER = new Adapter();
391     }
392 }