| 
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<DoubleGene> 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 — <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<DoubleGene> gt = ...
 144      * final Chromosome<DoubleGene> 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<DoubleGene> 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(1 +  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<DoubleGene> 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 gt) throws 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 model) throws 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 }
 |