Genotype.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.6.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.object.Verify;
023 import static org.jenetics.internal.util.object.eq;
024 
025 import java.util.Iterator;
026 import java.util.List;
027 
028 import javax.xml.bind.annotation.XmlAccessType;
029 import javax.xml.bind.annotation.XmlAccessorType;
030 import javax.xml.bind.annotation.XmlAnyElement;
031 import javax.xml.bind.annotation.XmlAttribute;
032 import javax.xml.bind.annotation.XmlRootElement;
033 import javax.xml.bind.annotation.XmlType;
034 import javax.xml.bind.annotation.adapters.XmlAdapter;
035 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
036 
037 import javolution.lang.Immutable;
038 import javolution.lang.Realtime;
039 import javolution.text.Text;
040 import javolution.xml.XMLFormat;
041 import javolution.xml.XMLSerializable;
042 import javolution.xml.stream.XMLStreamException;
043 
044 import org.jenetics.internal.util.HashBuilder;
045 import org.jenetics.internal.util.cast;
046 import org.jenetics.internal.util.jaxb;
047 import org.jenetics.internal.util.model.ModelType;
048 import org.jenetics.internal.util.model.ValueType;
049 
050 import org.jenetics.util.Array;
051 import org.jenetics.util.Factory;
052 import org.jenetics.util.Function;
053 import org.jenetics.util.ISeq;
054 import org.jenetics.util.Seq;
055 import org.jenetics.util.Verifiable;
056 
057 /**
058  * The central class the GA is working with, is the {@code Genotype}. It is the
059  * structural representative of an individual. This class is the encoded problem
060  * solution with one to many {@link Chromosome}.
061  <p><div align="center">
062  <img src="doc-files/Genotype.svg" width="400" height="252" >
063  </p></div>
064  * The chromosomes of a genotype doesn't have to have necessarily the same size.
065  * It is only required that all genes are from the same type and the genes within
066  * a chromosome have the same constraints; e. g. the same min- and max values
067  * for number genes.
068  *
069  * [code]
070  * final Genotype〈DoubleGene〉 genotype = Genotype.of(
071  *     DoubleChromosome.of(0.0, 1.0, 8),
072  *     DoubleChromosome.of(1.0, 2.0, 10),
073  *     DoubleChromosome.of(0.0, 10.0, 9),
074  *     DoubleChromosome.of(0.1, 0.9, 5)
075  * );
076  * [/code]
077  * The code snippet above creates a genotype with the same structure as shown in
078  * the figure above. In this example the {@link DoubleGene} has been chosen as
079  * gene type.
080  *
081  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
082  @since 1.0
083  @version 1.6 &mdash; <em>$Date: 2014-03-04 $</em>
084  */
085 @XmlJavaTypeAdapter(Genotype.Model.Adapter.class)
086 public final class Genotype<G extends Gene<?, G>>
087     implements
088         Factory<Genotype<G>>,
089         Iterable<Chromosome<G>>,
090         Verifiable,
091         XMLSerializable,
092         Realtime,
093         Immutable
094 {
095     private static final long serialVersionUID = 2L;
096 
097     private final ISeq<Chromosome<G>> _chromosomes;
098     private final int _ngenes;
099 
100     //Caching isValid value.
101     private volatile Boolean _valid = null;
102 
103     private Genotype(
104         final ISeq<? extends Chromosome<G>> chromosomes,
105         final int ngenes
106     ) {
107         if (chromosomes.length() == 0) {
108             throw new IllegalArgumentException("No chromosomes given.");
109         }
110 
111         _chromosomes = cast.apply(chromosomes);
112         _ngenes = ngenes;
113     }
114 
115     /**
116      * Create a new Genotype from a given sequence of {@code Chromosomes}.
117      *
118      @param chromosomes The {@code Chromosome} array the {@code Genotype}
119      *         consists of.
120      @throws NullPointerException if {@code chromosomes} is null or one of its
121      *         element.
122      @throws IllegalArgumentException if {@code chromosome.length == 0}.
123      */
124     public Genotype(final ISeq<? extends Chromosome<G>> chromosomes) {
125         this(chromosomes, ngenes(chromosomes));
126     }
127 
128     private static int ngenes(final Seq<? extends Chromosome<?>> chromosomes) {
129         int ngenes = 0;
130         for (int i = chromosomes.length(); --i >= 0;) {
131             ngenes += chromosomes.get(i).length();
132         }
133         return ngenes;
134     }
135 
136     /**
137      * Return the chromosome at the given index. It is guaranteed, that the
138      * returned chromosome is not null.
139      *
140      @param index Chromosome index.
141      @return The Chromosome.
142      @throws IndexOutOfBoundsException if (index < 0 || index >= _length).
143      */
144     public Chromosome<G> getChromosome(final int index) {
145         assert(_chromosomes != null);
146         assert(_chromosomes.get(index!= null);
147 
148         return _chromosomes.get(index);
149     }
150 
151     /**
152      * Return the first chromosome. This is a shortcut for
153      * [code]
154      * final Genotype〈DoubleGene〉 gt = ...
155      * final Chromosome〈DoubleGene〉 chromosome = gt.getChromosome(0);
156      * [/code]
157      *
158      @return The first chromosome.
159      */
160     public Chromosome<G> getChromosome() {
161         assert(_chromosomes != null);
162         assert(_chromosomes.get(0!= null);
163 
164         return _chromosomes.get(0);
165     }
166 
167     /**
168      * Return the first {@link Gene} of the first {@link Chromosome} of this
169      * {@code Genotype}. This is a shortcut for
170      * [code]
171      * final Genotype〈DoubleGene〉 gt = ...
172      * final DoubleGene gene = gt.getChromosome(0).getGene(0);
173      * [/code]
174      *
175      @return the first {@link Gene} of the first {@link Chromosome} of this
176      *         {@code Genotype}.
177      */
178     public G getGene() {
179         assert(_chromosomes != null);
180         assert(_chromosomes.get(0!= null);
181 
182         return _chromosomes.get(0).getGene();
183     }
184 
185 
186     public ISeq<Chromosome<G>> toSeq() {
187         return _chromosomes;
188     }
189 
190     @Override
191     public Iterator<Chromosome<G>> iterator() {
192         return _chromosomes.iterator();
193     }
194 
195     /**
196      * Getting the number of chromosomes of this genotype.
197      *
198      @return number of chromosomes.
199      */
200     public int length() {
201         return _chromosomes.length();
202     }
203 
204     /**
205      * Return the number of genes this genotype consists of. This is the sum of
206      * the number of genes of the genotype chromosomes.
207      *
208      @return Return the number of genes this genotype consists of.
209      */
210     public int getNumberOfGenes() {
211         return _ngenes;
212     }
213 
214     /**
215      * Test if this genotype is valid. A genotype is valid if all its
216      {@link Chromosome}s are valid.
217      *
218      @return true if this genotype is valid, false otherwise.
219      */
220     @Override
221     public boolean isValid() {
222         if (_valid == null) {
223             _valid = _chromosomes.forAll(Verify);
224         }
225         return _valid;
226     }
227 
228     /**
229      * Return a new, random genotype by creating new, random chromosomes (calling
230      * the {@link Chromosome#newInstance()} method) from the chromosomes of this
231      * genotype.
232      */
233     @Override
234     public Genotype<G> newInstance() {
235         final Array<Chromosome<G>> chromosomes = new Array<>(length());
236         for (int i = 0; i < length(); ++i) {
237             chromosomes.set(i, _chromosomes.get(i).newInstance());
238         }
239 
240         return new Genotype<>(chromosomes.toISeq(), _ngenes);
241     }
242 
243     Genotype<G> newInstance(final ISeq<Chromosome<G>> chromosomes) {
244         return new Genotype<>(chromosomes, _ngenes);
245     }
246 
247     @Override
248     public int hashCode() {
249         return HashBuilder.of(getClass()).and(_chromosomes).value();
250     }
251 
252     @Override
253     public boolean equals(final Object o) {
254         if (o == this) {
255             return true;
256         }
257         if (!(instanceof Genotype<?>)) {
258             return false;
259         }
260 
261         final Genotype<?> gt = (Genotype<?>)o;
262         return eq(_chromosomes, gt._chromosomes);
263     }
264 
265     @Override
266     public Text toText() {
267         return new Text(_chromosomes.toString());
268     }
269 
270     @Override
271     public String toString() {
272         return _chromosomes.toString();
273     }
274 
275 
276     /* *************************************************************************
277      *  Property access methods
278      * ************************************************************************/
279 
280     /**
281      * Return a converter which access the chromosome array of this genotype.
282      */
283     public static <T extends Gene<?, T>>
284     Function<Genotype<T>, ISeq<Chromosome<T>>> Chromosomes()
285     {
286         return new Function<Genotype<T>, ISeq<Chromosome<T>>>() {
287             @Override public ISeq<Chromosome<T>> apply(final Genotype<T> value) {
288                 return value.toSeq();
289             }
290         };
291     }
292 
293     /**
294      * Return a converter which access the chromosome with the given index of
295      * this genotype.
296      */
297     public static <T extends Gene<?, T>>
298     Function<Genotype<T>, Chromosome<T>> Chromosome(final int index)
299     {
300         return new Function<Genotype<T>, Chromosome<T>>() {
301             @Override public Chromosome<T> apply(final Genotype<T> value) {
302                 return value.getChromosome(index);
303             }
304         };
305     }
306 
307     /**
308      * Return a converter which access the first chromosome of this genotype.
309      */
310     public static <T extends Gene<?, T>>
311     Function<Genotype<T>, Chromosome<T>> Chromosome()
312     {
313         return new Function<Genotype<T>, Chromosome<T>>() {
314             @Override public Chromosome<T> apply(final Genotype<T> value) {
315                 return value.getChromosome();
316             }
317         };
318     }
319 
320     /**
321      @deprecated Use {@link #Genotype(org.jenetics.util.ISeq)} instead.
322      */
323     @Deprecated
324     public static <G extends Gene<?, G>> Genotype<G> valueOf(
325         final ISeq<? extends Chromosome<G>> chromosomes
326     ) {
327         return new Genotype<>(chromosomes);
328     }
329 
330     /**
331      @deprecated Use {@link #of(Chromosome[])} instead.
332      */
333     @Deprecated
334     @SafeVarargs
335     public static <G extends Gene<?, G>> Genotype<G> valueOf(
336         final Chromosome<G>... chromosomes
337     ) {
338         return of(chromosomes);
339     }
340 
341     /**
342      * Create a new Genotype from a given array of {@code Chromosomes}.
343      *
344      @param chromosomes The {@code Chromosome} array the {@code Genotype}
345      *         consists of.
346      @throws NullPointerException if {@code chromosomes} is null or one of its
347      *         element.
348      @throws IllegalArgumentException if {@code chromosome.length == 0}.
349      */
350     @SafeVarargs
351     public static <G extends Gene<?, G>> Genotype<G> of(
352         final Chromosome<G>... chromosomes
353     ) {
354         return new Genotype<>(Array.of(chromosomes).toISeq());
355     }
356 
357     /* *************************************************************************
358      *  XML object serialization
359      * ************************************************************************/
360 
361     @SuppressWarnings({ "unchecked""rawtypes"})
362     static final XMLFormat<Genotype>
363     XML = new XMLFormat<Genotype>(Genotype.class)
364     {
365         private static final String LENGTH = "length";
366         private static final String NGENES = "ngenes";
367 
368         @Override
369         public Genotype newInstance(
370             final Class<Genotype> cls, final InputElement xml
371         )
372             throws XMLStreamException
373         {
374             final int length = xml.getAttribute(LENGTH, 0);
375             final int ngenes = xml.getAttribute(NGENES, 0);
376             final Array<Chromosome> chromosomes = new Array<>(length);
377             for (int i = 0; i < length; ++i) {
378                 final Chromosome<?> c = xml.getNext();
379                 chromosomes.set(i, c);
380             }
381 
382             return new Genotype(chromosomes.toISeq(), ngenes);
383         }
384         @Override
385         public void write(final Genotype gt, final OutputElement xml)
386             throws XMLStreamException
387         {
388             xml.setAttribute(LENGTH, gt.length());
389             xml.setAttribute(NGENES, gt.getNumberOfGenes());
390             for (int i = 0; i < gt.length(); ++i) {
391                 xml.add(gt._chromosomes.get(i));
392             }
393         }
394         @Override
395         public void read(final InputElement xml, final Genotype gt) {
396         }
397     };
398 
399     /* *************************************************************************
400      *  JAXB object serialization
401      * ************************************************************************/
402 
403     @XmlRootElement(name = "org.jenetics.Genotype")
404     @XmlType(name = "org.jenetics.Genotype")
405     @XmlAccessorType(XmlAccessType.FIELD)
406     @SuppressWarnings({"unchecked""rawtypes"})
407     static final class Model {
408 
409         @XmlAttribute
410         public int length;
411 
412         @XmlAttribute
413         public int ngenes;
414 
415         @XmlAnyElement
416         public List<Object> chromosomes;
417 
418         @ValueType(Genotype.class)
419         @ModelType(Model.class)
420         public static final class Adapter
421             extends XmlAdapter<Model, Genotype>
422         {
423             @Override
424             public Model marshal(final Genotype gtthrows Exception {
425                 final Model model = new Model();
426                 model.length = gt.length();
427                 model.ngenes = gt.getNumberOfGenes();
428                 model.chromosomes = gt.toSeq()
429                     .map(jaxb.Marshaller(gt.getChromosome())).asList();
430 
431                 return model;
432             }
433 
434             @Override
435             public Genotype unmarshal(final Model modelthrows Exception {
436                 final ISeq chs = Array.of(model.chromosomes)
437                     .map(jaxb.Unmarshaller).toISeq();
438 
439                 return new Genotype(chs, model.ngenes);
440             }
441         }
442 
443         public static final Adapter Adapter = new Adapter();
444     }
445 }