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