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<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 2.0 — <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<DoubleGene> gt = ...
146 * final Chromosome<DoubleGene> 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<DoubleGene> 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 (!(o 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 gt) throws 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 model) throws 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 }
|