Phenotype.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.0.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.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static org.jenetics.internal.util.Equality.eq;
025 
026 import java.io.Serializable;
027 import java.util.function.Function;
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.Equality;
039 import org.jenetics.internal.util.Hash;
040 import org.jenetics.internal.util.jaxb;
041 
042 import org.jenetics.util.Verifiable;
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-12-28 $</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 = 4L;
070 
071     private final Genotype<G> _genotype;
072 
073     private final Function<? super Genotype<G>, ? extends C> _function;
074     private final Function<? super C, ? extends C> _scaler;
075 
076     private final long _generation;
077 
078     // Storing the fitness value for lazy evaluation.
079     private C _rawFitness = null;
080     private C _fitness = null;
081 
082     /**
083      * Create a new phenotype from the given arguments.
084      *
085      @param genotype the genotype of this phenotype.
086      @param generation the current generation of the generated phenotype.
087      @param function the fitness function of this phenotype.
088      @param scaler the fitness scaler.
089      @throws NullPointerException if one of the arguments is {@code null}.
090      @throws IllegalArgumentException if the given {@code generation} is
091      *         {@code < 0}.
092      */
093     private Phenotype(
094         final Genotype<G> genotype,
095         final long generation,
096         final Function<? super Genotype<G>, ? extends C> function,
097         final Function<? super C, ? extends C> scaler
098     ) {
099         _genotype = requireNonNull(genotype, "Genotype");
100         _function = requireNonNull(function, "Fitness function");
101         _scaler = requireNonNull(scaler, "Fitness scaler");
102         if (generation < 0) {
103             throw new IllegalArgumentException(format(
104                 "Generation must not < 0 and was %s.", generation
105             ));
106         }
107         _generation = generation;
108     }
109 
110     /**
111      * This method returns a copy of the {@code Genotype}, to guarantee a
112      * immutable class.
113      *
114      @return the cloned {@code Genotype} of this {@code Phenotype}.
115      @throws NullPointerException if one of the arguments is {@code null}.
116      */
117     public Genotype<G> getGenotype() {
118         return _genotype;
119     }
120 
121     /**
122      * Evaluates the (raw) fitness values and caches it so the fitness calculation
123      * is performed only once.
124      *
125      @return this phenotype, for method chaining.
126      */
127     public Phenotype<G, C> evaluate() {
128         if (_rawFitness == null) {
129             _rawFitness = _function.apply(_genotype);
130             _fitness = _scaler.apply(_rawFitness);
131         }
132         return this;
133     }
134 
135     /**
136      * This method simply calls the {@link #evaluate()} method. The purpose of
137      * this method is to have a simple way for concurrent fitness calculation
138      * for expensive fitness values.
139      */
140     @Override
141     public void run() {
142         evaluate();
143     }
144 
145     /**
146      * Return the fitness function used by this phenotype to calculate the
147      * (raw) fitness value.
148      *
149      @return the fitness function.
150      */
151     public Function<? super Genotype<G>, ? extends C> getFitnessFunction() {
152         return _function;
153     }
154 
155     /**
156      * Return the fitness scaler used by this phenotype to scale the <i>raw</i>
157      * fitness.
158      *
159      @return the fitness scaler.
160      */
161     public Function<? super C, ? extends C> getFitnessScaler() {
162         return _scaler;
163     }
164 
165     /**
166      * Return the fitness value of this {@code Phenotype}.
167      *
168      @return The fitness value of this {@code Phenotype}.
169      */
170     public C getFitness() {
171         evaluate();
172         return _fitness;
173     }
174 
175     /**
176      * Return the raw fitness (before scaling) of the phenotype.
177      *
178      @return The raw fitness (before scaling) of the phenotype.
179      */
180     public C getRawFitness() {
181         evaluate();
182         return _rawFitness;
183     }
184 
185     /**
186      * Return the generation this {@link Phenotype} was created.
187      *
188      @return The generation this {@link Phenotype} was created.
189      */
190     public long getGeneration() {
191         return _generation;
192     }
193 
194     /**
195      * Return the age of this phenotype depending on the given current generation.
196      *
197      @param currentGeneration the current generation evaluated by the GA.
198      @return the age of this phenotype:
199      *          {@code currentGeneration - this.getGeneration()}.
200      */
201     public long getAge(final long currentGeneration) {
202         return currentGeneration - _generation;
203     }
204 
205     /**
206      * Test whether this phenotype is valid. The phenotype is valid if its
207      {@link Genotype} is valid.
208      *
209      @return true if this phenotype is valid, false otherwise.
210      */
211     @Override
212     public boolean isValid() {
213         return _genotype.isValid();
214     }
215 
216     @Override
217     public int compareTo(final Phenotype<G, C> pt) {
218         return getFitness().compareTo(pt.getFitness());
219     }
220 
221     @Override
222     public int hashCode() {
223         return Hash.of(getClass())
224                 .and(_generation)
225                 .and(getFitness())
226                 .and(getRawFitness())
227                 .and(_genotype).value();
228     }
229 
230     @Override
231     public boolean equals(final Object obj) {
232         return Equality.of(this, obj).test(pt ->
233             eq(getFitness(), pt.getFitness()) &&
234             eq(getRawFitness(), pt.getRawFitness()) &&
235             eq(_genotype, pt._genotype&&
236             eq(_generation, pt._generation)
237         );
238     }
239 
240     @Override
241     public String toString() {
242         return _genotype.toString() " --> " + getFitness();
243     }
244 
245     /**
246      * Factory method for creating a new {@link Phenotype} with the same
247      {@link Function} and age as this {@link Phenotype}.
248      *
249      @param genotype the new genotype of the new phenotype.
250      @param generation date of birth (generation) of the new phenotype.
251      @return New {@link Phenotype} with the same fitness {@link Function}.
252      @throws NullPointerException if the {@code genotype} is {@code null}.
253      */
254     Phenotype<G, C> newInstance(
255         final Genotype<G> genotype,
256         final long generation
257     ) {
258         return of(genotype, generation, _function, _scaler);
259     }
260 
261     /**
262      * Return a new phenotype with the the genotype of this and with new
263      * fitness function, fitness scaler and generation.
264      *
265      @param generation the generation of the new phenotype.
266      @param function the (new) fitness scaler of the created phenotype.
267      @param scaler the (new) fitness scaler of the created phenotype
268      @return a new phenotype with the given values.
269      @throws NullPointerException if one of the values is {@code null}.
270      @throws IllegalArgumentException if the given {@code generation} is
271      *         {@code < 0}.
272      */
273     public Phenotype<G, C> newInstance(
274         final long generation,
275         final Function<? super Genotype<G>, ? extends C> function,
276         final Function<? super C, ? extends C> scaler
277     ) {
278         return of(_genotype, generation, function, scaler);
279     }
280 
281     /**
282      * Return a new phenotype with the the genotype of this and with new
283      * fitness function and generation.
284      *
285      @param generation the generation of the new phenotype.
286      @param function the (new) fitness scaler of the created phenotype.
287      @return a new phenotype with the given values.
288      @throws NullPointerException if one of the values is {@code null}.
289      @throws IllegalArgumentException if the given {@code generation} is
290      *         {@code < 0}.
291      */
292     public Phenotype<G, C> newInstance(
293         final long generation,
294         final Function<? super Genotype<G>, ? extends C> function
295     ) {
296         return of(_genotype, generation, function, a -> a);
297     }
298 
299     /**
300      * The {@code Genotype} is copied to guarantee an immutable class. Only
301      * the age of the {@code Phenotype} can be incremented.
302      *
303      @param <G> the gene type of the chromosome
304      @param <C> the fitness value type
305      @param genotype the genotype of this phenotype.
306      @param generation the current generation of the generated phenotype.
307      @param function the fitness function of this phenotype.
308      @return a new phenotype from the given parameters
309      @throws NullPointerException if one of the arguments is {@code null}.
310      @throws IllegalArgumentException if the given {@code generation} is
311      *         {@code < 0}.
312      */
313     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
314     Phenotype<G, C> of(
315         final Genotype<G> genotype,
316         final long generation,
317         final Function<? super Genotype<G>, C> function
318     ) {
319         return of(
320             genotype,
321             generation,
322             function,
323             function instanceof Serializable ?
324                 (Function<? super C, ? extends C> & Serializable)a -> a :
325                 a -> a
326         );
327     }
328 
329     /**
330      * Create a new phenotype from the given arguments.
331      *
332      @param <G> the gene type of the chromosome
333      @param <C> the fitness value type
334      @param genotype the genotype of this phenotype.
335      @param generation the current generation of the generated phenotype.
336      @param function the fitness function of this phenotype.
337      @param scaler the fitness scaler.
338      @return a new phenotype object
339      @throws NullPointerException if one of the arguments is {@code null}.
340      @throws IllegalArgumentException if the given {@code generation} is
341      *         {@code < 0}.
342      */
343     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
344     Phenotype<G, C> of(
345         final Genotype<G> genotype,
346         final long generation,
347         final Function<? super Genotype<G>, ? extends C> function,
348         final Function<? super C, ? extends C> scaler
349     ) {
350         return new Phenotype<>(
351             genotype,
352             generation,
353             function,
354             scaler
355         );
356     }
357 
358     /* *************************************************************************
359      *  JAXB object serialization
360      * ************************************************************************/
361 
362     @XmlRootElement(name = "phenotype")
363     @XmlType(name = "org.jenetics.Phenotype")
364     @XmlAccessorType(XmlAccessType.FIELD)
365     @SuppressWarnings({ "unchecked""rawtypes" })
366     final static class Model {
367 
368         @XmlAttribute(name = "generation", required = true)
369         public long generation;
370 
371         @XmlElement(name = "genotype", required = true, nillable = false)
372         public Genotype.Model genotype;
373 
374         @XmlElement(name = "fitness", required = true, nillable = false)
375         public Object fitness;
376 
377         @XmlElement(name = "raw-fitness", required = true, nillable = false)
378         public Object rawFitness;
379 
380         public final static class Adapter
381             extends XmlAdapter<Model, Phenotype>
382         {
383             @Override
384             public Model marshal(final Phenotype ptthrows Exception {
385                 final Model m = new Model();
386                 m.generation = pt.getGeneration();
387                 m.genotype = Genotype.Model.ADAPTER.marshal(pt.getGenotype());
388                 m.fitness = jaxb.marshal(pt.getFitness());
389                 m.rawFitness = jaxb.marshal(pt.getRawFitness());
390                 return m;
391             }
392 
393             @Override
394             public Phenotype unmarshal(final Model mthrows Exception {
395                 final Phenotype pt = new Phenotype(
396                     Genotype.Model.ADAPTER.unmarshal(m.genotype),
397                     m.generation,
398                     Function.identity(),
399                     Function.identity()
400                 );
401                 pt._fitness = (Comparable)m.fitness;
402                 pt._rawFitness = (Comparable)m.rawFitness;
403                 return pt;
404             }
405         }
406     }
407 
408 }