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