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 — <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 (!(o 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 gt) throws 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 model) throws 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 }
|