Phenotype.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 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 &mdash; <em>$Date: 2014-03-04 $</em>
064  */
065 @XmlJavaTypeAdapter(Phenotype.Model.Adapter.class)
066 public final class Phenotype<
067     extends Gene<?, G>,
068     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 ptthrows 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 mthrows 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 }