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