Genotype.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-2.0.2).
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.object.Verify;
023 import static org.jenetics.internal.util.object.eq;
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.HashBuilder;
039 import org.jenetics.internal.util.cast;
040 import org.jenetics.internal.util.jaxb;
041 
042 import org.jenetics.util.Array;
043 import org.jenetics.util.Factory;
044 import org.jenetics.util.Function;
045 import org.jenetics.util.ISeq;
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 2.0 &mdash; <em>$Date: 2014-03-31 $</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 = cast.apply(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     public 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         int ngenes = 0;
120         for (int i = chromosomes.length(); --i >= 0;) {
121             ngenes += chromosomes.get(i).length();
122         }
123         return ngenes;
124     }
125 
126     /**
127      * Return the chromosome at the given index. It is guaranteed, that the
128      * returned chromosome is not null.
129      *
130      @param index Chromosome index.
131      @return The Chromosome.
132      @throws IndexOutOfBoundsException if
133      *         {@code (index < 0 || index >= _length)}.
134      */
135     public Chromosome<G> getChromosome(final int index) {
136         assert(_chromosomes != null);
137         assert(_chromosomes.get(index!= null);
138 
139         return _chromosomes.get(index);
140     }
141 
142     /**
143      * Return the first chromosome. This is a shortcut for
144      * [code]
145      * final Genotype&lt;DoubleGene&gt; gt = ...
146      * final Chromosome&lt;DoubleGene&gt; chromosome = gt.getChromosome(0);
147      * [/code]
148      *
149      @return The first chromosome.
150      */
151     public Chromosome<G> getChromosome() {
152         assert(_chromosomes != null);
153         assert(_chromosomes.get(0!= null);
154 
155         return _chromosomes.get(0);
156     }
157 
158     /**
159      * Return the first {@link Gene} of the first {@link Chromosome} of this
160      * {@code Genotype}. This is a shortcut for
161      * [code]
162      * final Genotype&lt;DoubleGene&gt; gt = ...
163      * final DoubleGene gene = gt.getChromosome(0).getGene(0);
164      * [/code]
165      *
166      @return the first {@link Gene} of the first {@link Chromosome} of this
167      *         {@code Genotype}.
168      */
169     public G getGene() {
170         assert(_chromosomes != null);
171         assert(_chromosomes.get(0!= null);
172 
173         return _chromosomes.get(0).getGene();
174     }
175 
176 
177     public ISeq<Chromosome<G>> toSeq() {
178         return _chromosomes;
179     }
180 
181     @Override
182     public Iterator<Chromosome<G>> iterator() {
183         return _chromosomes.iterator();
184     }
185 
186     /**
187      * Getting the number of chromosomes of this genotype.
188      *
189      @return number of chromosomes.
190      */
191     public int length() {
192         return _chromosomes.length();
193     }
194 
195     /**
196      * Return the number of genes this genotype consists of. This is the sum of
197      * the number of genes of the genotype chromosomes.
198      *
199      @return Return the number of genes this genotype consists of.
200      */
201     public int getNumberOfGenes() {
202         return _ngenes;
203     }
204 
205     /**
206      * Test if this genotype is valid. A genotype is valid if all its
207      {@link Chromosome}s are valid.
208      *
209      @return true if this genotype is valid, false otherwise.
210      */
211     @Override
212     public boolean isValid() {
213         if (_valid == null) {
214             _valid = _chromosomes.forAll(Verify);
215         }
216         return _valid;
217     }
218 
219     /**
220      * Return a new, random genotype by creating new, random chromosomes (calling
221      * the {@link Chromosome#newInstance()} method) from the chromosomes of this
222      * genotype.
223      */
224     @Override
225     public Genotype<G> newInstance() {
226         final Array<Chromosome<G>> chromosomes = new Array<>(length());
227         for (int i = 0; i < length(); ++i) {
228             chromosomes.set(i, _chromosomes.get(i).newInstance());
229         }
230 
231         return new Genotype<>(chromosomes.toISeq(), _ngenes);
232     }
233 
234     Genotype<G> newInstance(final ISeq<Chromosome<G>> chromosomes) {
235         return new Genotype<>(chromosomes, _ngenes);
236     }
237 
238     @Override
239     public int hashCode() {
240         return HashBuilder.of(getClass()).and(_chromosomes).value();
241     }
242 
243     @Override
244     public boolean equals(final Object o) {
245         if (o == this) {
246             return true;
247         }
248         if (!(instanceof Genotype<?>)) {
249             return false;
250         }
251 
252         final Genotype<?> gt = (Genotype<?>)o;
253         return eq(_chromosomes, gt._chromosomes);
254     }
255 
256     @Override
257     public String toString() {
258         return _chromosomes.toString();
259     }
260 
261 
262     /* *************************************************************************
263      *  Property access methods
264      * ************************************************************************/
265 
266     /**
267      * Return a converter which access the chromosome array of this genotype.
268      *
269      @param <T> the gene type
270      @return a function object which returns the chromosomes for this genotype.
271      */
272     public static <T extends Gene<?, T>>
273     Function<Genotype<T>, ISeq<Chromosome<T>>> Chromosomes()
274     {
275         return new Function<Genotype<T>, ISeq<Chromosome<T>>>() {
276             @Override public ISeq<Chromosome<T>> apply(final Genotype<T> value) {
277                 return value.toSeq();
278             }
279         };
280     }
281 
282     /**
283      * Return a converter which access the chromosome with the given index of
284      * this genotype.
285      *
286      @param <T> the gene type
287      @param index the index of the chromosome
288      @return a function object which returns the chromosome at the given index.
289      */
290     public static <T extends Gene<?, T>>
291     Function<Genotype<T>, Chromosome<T>> Chromosome(final int index)
292     {
293         return new Function<Genotype<T>, Chromosome<T>>() {
294             @Override public Chromosome<T> apply(final Genotype<T> value) {
295                 return value.getChromosome(index);
296             }
297         };
298     }
299 
300     /**
301      * Return a converter which access the first chromosome of this genotype.
302      *
303      @param <T> the gene type
304      @return a function object which returns the first chromosome of this
305      *         genotype.
306      */
307     public static <T extends Gene<?, T>>
308     Function<Genotype<T>, Chromosome<T>> Chromosome()
309     {
310         return new Function<Genotype<T>, Chromosome<T>>() {
311             @Override public Chromosome<T> apply(final Genotype<T> value) {
312                 return value.getChromosome();
313             }
314         };
315     }
316 
317     /**
318      * Create a new Genotype from a given array of {@code Chromosomes}.
319      *
320      @param <G> the gene type
321      @param chromosomes The {@code Chromosome} array the {@code Genotype}
322      *         consists of.
323      @return a new {@code Genotype} from the given chromosomes
324      @throws NullPointerException if {@code chromosomes} is null or one of its
325      *         element.
326      @throws IllegalArgumentException if {@code chromosome.length == 0}.
327      */
328     @SafeVarargs
329     public static <G extends Gene<?, G>> Genotype<G> of(
330         final Chromosome<G>... chromosomes
331     ) {
332         return new Genotype<>(Array.of(chromosomes).toISeq());
333     }
334 
335     /* *************************************************************************
336      *  JAXB object serialization
337      * ************************************************************************/
338 
339     @XmlRootElement(name = "genotype")
340     @XmlType(name = "org.jenetics.Genotype")
341     @XmlAccessorType(XmlAccessType.FIELD)
342     @SuppressWarnings({"unchecked""rawtypes"})
343     static final class Model {
344 
345         @XmlAttribute(name = "length", required = true)
346         public int length;
347 
348         @XmlAttribute(name = "ngenes", required = true)
349         public int ngenes;
350 
351         @XmlElement(name = "chromosome", required = true, nillable = false)
352         public List chromosomes;
353 
354         public static final class Adapter
355             extends XmlAdapter<Model, Genotype>
356         {
357             @Override
358             public Model marshal(final Genotype gtthrows Exception {
359                 final Model model = new Model();
360                 model.length = gt.length();
361                 model.ngenes = gt.getNumberOfGenes();
362                 model.chromosomes = gt.toSeq()
363                     .map(jaxb.Marshaller(gt.getChromosome()))
364                     .asList();
365 
366                 return model;
367             }
368 
369             @Override
370             public Genotype unmarshal(final Model modelthrows Exception {
371                 final ISeq chs = Array.of(model.chromosomes)
372                     .map(jaxb.Unmarshaller(model.chromosomes.get(0)))
373                     .toISeq();
374 
375                 return new Genotype(chs, model.ngenes);
376             }
377         }
378 
379         public static final Adapter ADAPTER = new Adapter();
380     }
381 }