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 java.util.Objects.requireNonNull;
023 import static org.jenetics.internal.util.object.eq;
024
025 import javax.xml.bind.annotation.XmlAccessType;
026 import javax.xml.bind.annotation.XmlAccessorType;
027 import javax.xml.bind.annotation.XmlAttribute;
028 import javax.xml.bind.annotation.XmlElement;
029 import javax.xml.bind.annotation.XmlRootElement;
030 import javax.xml.bind.annotation.XmlType;
031 import javax.xml.bind.annotation.adapters.XmlAdapter;
032 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
033
034 import javolution.lang.Immutable;
035 import javolution.lang.Realtime;
036 import javolution.text.Text;
037 import javolution.xml.XMLFormat;
038 import javolution.xml.XMLSerializable;
039 import javolution.xml.stream.XMLStreamException;
040
041 import org.jenetics.internal.util.HashBuilder;
042 import org.jenetics.internal.util.jaxb;
043 import org.jenetics.internal.util.model.ModelType;
044 import org.jenetics.internal.util.model.ValueType;
045
046 import org.jenetics.util.Function;
047 import org.jenetics.util.Verifiable;
048 import org.jenetics.util.functions;
049
050
051 /**
052 * The {@code Phenotype} consists of a {@link Genotype} plus a fitness
053 * {@link Function}, where the fitness {@link Function} represents the
054 * environment where the {@link Genotype} lives.
055 * This class implements the {@link Comparable} interface, to define a natural
056 * order between two {@code Phenotype}s. The natural order of the
057 * {@code Phenotypes} is defined by its fitness value (given by the
058 * fitness {@link Function}. The {@code Phenotype} is immutable and therefore
059 * can't be changed after creation.
060 *
061 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
062 * @since 1.0
063 * @version 1.6 — <em>$Date: 2014-03-04 $</em>
064 */
065 @XmlJavaTypeAdapter(Phenotype.Model.Adapter.class)
066 public final class Phenotype<
067 G extends Gene<?, G>,
068 C extends Comparable<? super C>
069 >
070 implements
071 Comparable<Phenotype<G, C>>,
072 Immutable,
073 Verifiable,
074 XMLSerializable,
075 Realtime,
076 Runnable
077 {
078 private static final long serialVersionUID = 1L;
079
080 private final Genotype<G> _genotype;
081
082 private transient final
083 Function<? super Genotype<G>, ? extends C> _fitnessFunction;
084
085 private transient final
086 Function<? super C, ? extends C> _fitnessScaler;
087
088 private final int _generation;
089
090 //Storing the fitness value for lazy evaluation.
091 private C _rawFitness = null;
092 private C _fitness = null;
093
094 /**
095 * Create a new phenotype from the given arguments.
096 *
097 * @param genotype the genotype of this phenotype.
098 * @param fitnessFunction the fitness function of this phenotype.
099 * @param fitnessScaler the fitness scaler.
100 * @param generation the current generation of the generated phenotype.
101 * @throws NullPointerException if one of the arguments is {@code null}.
102 * @throws IllegalArgumentException if the given {@code generation} is < 0.
103 */
104 public Phenotype(
105 final Genotype<G> genotype,
106 final Function<? super Genotype<G>, ? extends C> fitnessFunction,
107 final Function<? super C, ? extends C> fitnessScaler,
108 final int generation
109 ) {
110 _genotype = requireNonNull(genotype, "Genotype");
111 _fitnessFunction = requireNonNull(fitnessFunction, "Fitness function");
112 _fitnessScaler = requireNonNull(fitnessScaler, "Fitness scaler");
113 if (generation < 0) {
114 throw new IllegalArgumentException(
115 "Generation must not < 0: " + generation
116 );
117 }
118 _generation = generation;
119 }
120
121 /**
122 * This method returns a copy of the {@code Genotype}, to guarantee a
123 * immutable class.
124 *
125 * @return the cloned {@code Genotype} of this {@code Phenotype}.
126 * @throws NullPointerException if one of the arguments is {@code null}.
127 */
128 public Genotype<G> getGenotype() {
129 return _genotype;
130 }
131
132 /**
133 * Evaluates the (raw) fitness values and caches it so the fitness calculation
134 * is performed only once.
135 *
136 * @return this phenotype, for method chaining.
137 */
138 public Phenotype<G, C> evaluate() {
139 if (_rawFitness == null) {
140 _rawFitness = _fitnessFunction.apply(_genotype);
141 _fitness = _fitnessScaler.apply(_rawFitness);
142 }
143 return this;
144 }
145
146 /**
147 * This method simply calls the {@link #evaluate()} method. The purpose of
148 * this method is to have a simple way for concurrent fitness calculation
149 * for expensive fitness values.
150 */
151 @Override
152 public void run() {
153 evaluate();
154 }
155
156 /**
157 * Return the fitness function used by this phenotype to calculate the
158 * (raw) fitness value.
159 *
160 * @return the fitness function.
161 */
162 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() {
163 return _fitnessFunction;
164 }
165
166 /**
167 * Return the fitness scaler used by this phenotype to scale the <i>raw</i>
168 * fitness.
169 *
170 * @return the fitness scaler.
171 */
172 public Function<? super C, ? extends C> getFitnessScaler() {
173 return _fitnessScaler;
174 }
175
176 /**
177 * Return the fitness value of this {@code Phenotype}.
178 *
179 * @return The fitness value of this {@code Phenotype}.
180 */
181 public C getFitness() {
182 evaluate();
183 return _fitness;
184 }
185
186 /**
187 * Return the raw fitness (before scaling) of the phenotype.
188 *
189 * @return The raw fitness (before scaling) of the phenotype.
190 */
191 public C getRawFitness() {
192 evaluate();
193 return _rawFitness;
194 }
195
196 /**
197 * Return the generation this {@link Phenotype} was created.
198 *
199 * @return The generation this {@link Phenotype} was created.
200 */
201 public int getGeneration() {
202 return _generation;
203 }
204
205 /**
206 * Return the age of this phenotype depending on the given current generation.
207 *
208 * @param currentGeneration the current generation evaluated by the GA.
209 * @return the age of this phenotype:
210 * {@code currentGeneration - this.getGeneration()}.
211 */
212 public int getAge(final int currentGeneration) {
213 return currentGeneration - _generation;
214 }
215
216 /**
217 * Test whether this phenotype is valid. The phenotype is valid if its
218 * {@link Genotype} is valid.
219 *
220 * @return true if this phenotype is valid, false otherwise.
221 */
222 @Override
223 public boolean isValid() {
224 return _genotype.isValid();
225 }
226
227 @Override
228 public int compareTo(final Phenotype<G, C> pt) {
229 return getFitness().compareTo(pt.getFitness());
230 }
231
232 @Override
233 public int hashCode() {
234 return HashBuilder.of(getClass()).
235 and(_generation).
236 and(getFitness()).
237 and(getRawFitness()).
238 and(_genotype).value();
239 }
240
241 @Override
242 public boolean equals(Object obj) {
243 if (this == obj) {
244 return true;
245 }
246 if (!(obj instanceof Phenotype<?, ?>)) {
247 return false;
248 }
249
250 final Phenotype<?, ?> pt = (Phenotype<?, ?>)obj;
251 return eq(getFitness(), pt.getFitness()) &&
252 eq(getRawFitness(), pt.getRawFitness()) &&
253 eq(_genotype, pt._genotype) &&
254 eq(_generation, pt._generation);
255 }
256
257 @Override
258 public Text toText() {
259 return _genotype.toText();
260 }
261
262 @Override
263 public String toString() {
264 return toText().toString() + " --> " + getFitness();
265 }
266
267 /**
268 * Factory method for creating a new {@link Phenotype} with the same
269 * {@link Function} and age as this {@link Phenotype}.
270 *
271 * @param genotype the new genotype of the new phenotype.
272 * @param generation date of birth (generation) of the new phenotype.
273 * @return New {@link Phenotype} with the same fitness {@link Function}.
274 * @throws NullPointerException if the {@code genotype} is {@code null}.
275 */
276 Phenotype<G, C> newInstance(final Genotype<G> genotype, final int generation) {
277 requireNonNull(genotype, "Genotype");
278 return Phenotype.of(
279 genotype, _fitnessFunction, _fitnessScaler, generation
280 );
281 }
282
283 /**
284 * Return a new phenotype with the the genotype of this and with new
285 * fitness function, fitness scaler and generation.
286 *
287 * @param function the (new) fitness scaler of the created phenotype.
288 * @param scaler the (new) fitness scaler of the created phenotype
289 * @param generation the generation of the new phenotype.
290 * @return a new phenotype with the given values.
291 * @throws NullPointerException if one of the values is {@code null}.
292 * @throws IllegalArgumentException if the given {@code generation} is < 0.
293 */
294 public Phenotype<G, C> newInstance(
295 final Function<? super Genotype<G>, ? extends C> function,
296 final Function<? super C, ? extends C> scaler,
297 final int generation
298 ) {
299 return of(_genotype, function, scaler, generation);
300 }
301
302 /**
303 * Return a new phenotype with the the genotype of this and with new
304 * fitness function and generation.
305 *
306 * @param function the (new) fitness scaler of the created phenotype.
307 * @param generation the generation of the new phenotype.
308 * @return a new phenotype with the given values.
309 * @throws NullPointerException if one of the values is {@code null}.
310 * @throws IllegalArgumentException if the given {@code generation} is < 0.
311 */
312 public Phenotype<G, C> newInstance(
313 final Function<? super Genotype<G>, ? extends C> function,
314 final int generation
315 ) {
316 return of(_genotype, function, functions.<C>Identity(), generation);
317 }
318
319
320 /* *************************************************************************
321 * Property access methods
322 * ************************************************************************/
323
324 /**
325 * Create a {@link Function} which return the phenotype age when calling
326 * {@code converter.convert(phenotype)}.
327 *
328 * @param currentGeneration the current generation.
329 * @return an age {@link Function}.
330 */
331 public static Function<Phenotype<?, ?>, Integer>
332 Age(final int currentGeneration)
333 {
334 return new Function<Phenotype<?, ?>, Integer>() {
335 @Override public Integer apply(final Phenotype<?, ?> value) {
336 return value.getAge(currentGeneration);
337 }
338 };
339 }
340
341 /**
342 * Create a {@link Function} which return the phenotype generation when
343 * calling {@code converter.convert(phenotype)}.
344 *
345 * @return a generation {@link Function}.
346 */
347 public static Function<Phenotype<?, ?>, Integer> Generation() {
348 return new Function<Phenotype<?, ?>, Integer>() {
349 @Override public Integer apply(final Phenotype<?, ?> value) {
350 return value.getGeneration();
351 }
352 };
353 }
354
355 /**
356 * Create a {@link Function} which return the phenotype fitness when
357 * calling {@code converter.convert(phenotype)}.
358 *
359 * @param <C> the fitness value type.
360 * @return a fitness {@link Function}.
361 */
362 public static <C extends Comparable<? super C>>
363 Function<Phenotype<?, C>, C> Fitness()
364 {
365 return new Function<Phenotype<?, C>, C>() {
366 @Override public C apply(final Phenotype<?, C> value) {
367 return value.getFitness();
368 }
369 };
370 }
371
372 /**
373 * Create a {@link Function} which return the phenotype raw fitness when
374 * calling {@code converter.convert(phenotype)}.
375 *
376 * @param <C> the fitness value type.
377 * @return a raw fitness {@link Function}.
378 *
379 * @deprecated Fixing typo, use {@link #RawFitness()} instead.
380 */
381 @Deprecated
382 public static <C extends Comparable<? super C>>
383 Function<Phenotype<?, C>, C> RawFitnees()
384 {
385 return RawFitness();
386 }
387
388 /**
389 * Create a {@link Function} which return the phenotype raw fitness when
390 * calling {@code converter.convert(phenotype)}.
391 *
392 * @param <C> the fitness value type.
393 * @return a raw fitness {@link Function}.
394 */
395 public static <C extends Comparable<? super C>>
396 Function<Phenotype<?, C>, C> RawFitness()
397 {
398 return new Function<Phenotype<?, C>, C>() {
399 @Override public C apply(final Phenotype<?, C> value) {
400 return value.getRawFitness();
401 }
402 };
403 }
404
405 /**
406 * Create a {@link Function} which return the phenotype genotype when
407 * calling {@code converter.convert(phenotype)}.
408 *
409 * @param <G> the gene type.
410 * @return a genotype {@link Function}.
411 */
412 public static <G extends Gene<?, G>>
413 Function<Phenotype<G, ?>, Genotype<G>> Genotype()
414 {
415 return new Function<Phenotype<G, ?>, Genotype<G>>() {
416 @Override public Genotype<G> apply(final Phenotype<G, ?> value) {
417 return value.getGenotype();
418 }
419 };
420 }
421
422 /**
423 * @deprecated Use {@link #of(Genotype, org.jenetics.util.Function, org.jenetics.util.Function, int)}
424 * instead.
425 */
426 @Deprecated
427 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
428 Phenotype<G, C> valueOf(
429 final Genotype<G> genotype,
430 final Function<Genotype<G>, C> fitnessFunction,
431 final int generation
432 ) {
433 return of(genotype, fitnessFunction, generation);
434 }
435
436 /**
437 * The {@code Genotype} is copied to guarantee an immutable class. Only
438 * the age of the {@code Phenotype} can be incremented.
439 *
440 * @param genotype the genotype of this phenotype.
441 * @param fitnessFunction the fitness function of this phenotype.
442 * @param generation the current generation of the generated phenotype.
443 * @throws NullPointerException if one of the arguments is {@code null}.
444 * @throws IllegalArgumentException if the given {@code generation} is < 0.
445 */
446 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
447 Phenotype<G, C> of(
448 final Genotype<G> genotype,
449 final Function<? super Genotype<G>, C> fitnessFunction,
450 final int generation
451 ) {
452 return of(genotype, fitnessFunction, functions.<C>Identity(), generation);
453 }
454
455 /**
456 * @deprecated Use {@link #of(Genotype, org.jenetics.util.Function, org.jenetics.util.Function, int)}
457 * instead
458 */
459 @Deprecated
460 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
461 Phenotype<G, C> valueOf(
462 final Genotype<G> genotype,
463 final Function<? super Genotype<G>, ? extends C> fitnessFunction,
464 final Function<? super C, ? extends C> fitnessScaler,
465 final int generation
466 ) {
467 return of(genotype, fitnessFunction, fitnessScaler, generation);
468 }
469
470 /**
471 * Create a new phenotype from the given arguments.
472 *
473 * @param genotype the genotype of this phenotype.
474 * @param fitnessFunction the fitness function of this phenotype.
475 * @param fitnessScaler the fitness scaler.
476 * @param generation the current generation of the generated phenotype.
477 * @return a new phenotype object
478 * @throws NullPointerException if one of the arguments is {@code null}.
479 * @throws IllegalArgumentException if the given {@code generation} is < 0.
480 */
481 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
482 Phenotype<G, C> of(
483 final Genotype<G> genotype,
484 final Function<? super Genotype<G>, ? extends C> fitnessFunction,
485 final Function<? super C, ? extends C> fitnessScaler,
486 final int generation
487 ) {
488 return new Phenotype<>(
489 genotype,
490 fitnessFunction,
491 fitnessScaler,
492 generation
493 );
494 }
495
496 /* *************************************************************************
497 * XML object serialization
498 * ************************************************************************/
499
500 @SuppressWarnings({ "unchecked", "rawtypes" })
501 static final XMLFormat<Phenotype>
502 XML = new XMLFormat<Phenotype>(Phenotype.class)
503 {
504 private static final String GENERATION = "generation";
505 private static final String FITNESS = "fitness";
506 private static final String RAW_FITNESS = "raw-fitness";
507
508 @Override
509 public Phenotype newInstance(
510 final Class<Phenotype> cls, final InputElement xml
511 )
512 throws XMLStreamException
513 {
514 final int generation = xml.getAttribute(GENERATION, 0);
515 final Genotype genotype = xml.getNext();
516 final Phenotype pt = new Phenotype(
517 genotype, functions.Identity(), functions.Identity(), generation
518 );
519 pt._fitness = xml.get(FITNESS);
520 pt._rawFitness = xml.get(RAW_FITNESS);
521 return pt;
522 }
523 @Override
524 public void write(final Phenotype pt, final OutputElement xml)
525 throws XMLStreamException
526 {
527 xml.setAttribute(GENERATION, pt._generation);
528 xml.add(pt._genotype);
529 xml.add(pt.getFitness(), FITNESS);
530 xml.add(pt.getRawFitness(), RAW_FITNESS);
531 }
532 @Override
533 public void read(final InputElement xml, final Phenotype gt) {
534 }
535 };
536
537 /* *************************************************************************
538 * JAXB object serialization
539 * ************************************************************************/
540
541 @XmlRootElement(name = "org.jenetics.Phenotype")
542 @XmlType(name = "org.jenetics.Phenotype")
543 @XmlAccessorType(XmlAccessType.FIELD)
544 @SuppressWarnings({ "unchecked", "rawtypes" })
545 final static class Model {
546
547 @XmlAttribute
548 public int generation;
549
550 @XmlElement(name = "org.jenetics.Genotype")
551 public Genotype.Model genotype;
552
553 @XmlJavaTypeAdapter(jaxb.JavolutionElementAdapter.class)
554 @XmlElement(name = "fitness")
555 public Object fitness;
556
557 @XmlJavaTypeAdapter(jaxb.JavolutionElementAdapter.class)
558 @XmlElement(name = "raw-fitness")
559 public Object rawFitness;
560
561 @ValueType(Phenotype.class)
562 @ModelType(Model.class)
563 public final static class Adapter
564 extends XmlAdapter<Model, Phenotype>
565 {
566 @Override
567 public Model marshal(final Phenotype pt) throws Exception {
568 final Model m = new Model();
569 m.generation = pt.getGeneration();
570 m.genotype = Genotype.Model.Adapter.marshal(pt.getGenotype());
571 m.fitness = jaxb.marshal(pt.getFitness());
572 m.rawFitness = jaxb.marshal(pt.getRawFitness());
573 return m;
574 }
575
576 @Override
577 public Phenotype unmarshal(final Model m) throws Exception {
578 final Phenotype pt = new Phenotype(
579 Genotype.Model.Adapter.unmarshal(m.genotype),
580 functions.Identity(),
581 functions.Identity(),
582 m.generation
583 );
584 pt._fitness = (Comparable)m.fitness;
585 pt._rawFitness = (Comparable)m.rawFitness;
586 return pt;
587 }
588 }
589 }
590
591 }
|