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