Phenotype.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.9.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 
025 import java.io.IOException;
026 import java.io.ObjectInputStream;
027 import java.io.ObjectOutputStream;
028 import java.io.Serializable;
029 import java.util.Objects;
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.Lazy;
042 import org.jenetics.internal.util.jaxb;
043 import org.jenetics.internal.util.reflect;
044 
045 import org.jenetics.util.Verifiable;
046 
047 /**
048  * The {@code Phenotype} consists of a {@link Genotype} plus a fitness
049  {@link Function}, where the fitness {@link Function} represents the
050  * environment where the {@link Genotype} lives.
051  * This class implements the {@link Comparable} interface, to define a natural
052  * order between two {@code Phenotype}s. The natural order of the
053  * {@code Phenotypes} is defined by its fitness value (given by the
054  * fitness {@link Function}. The {@code Phenotype} is immutable and therefore
055  * can't be changed after creation.
056  <p>
057  * The evaluation of the fitness function is performed lazily. Either by calling
058  * one of the fitness accessors ({@link #getFitness()} or {@link #getRawFitness()})
059  * of through the <i>evaluation</i> methods {@link #run()} or {@link #evaluate()}.
060  * Since the {@code Phenotype} implements the {@link Runnable} interface, it is
061  * easily possible to perform the fitness function evaluation concurrently, by
062  * putting it into an {@link java.util.concurrent.ExecutorService}.
063  *
064  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
065  @since 1.0
066  @version 3.7
067  */
068 @XmlJavaTypeAdapter(Phenotype.Model.Adapter.class)
069 public final class Phenotype<
070     extends Gene<?, G>,
071     extends Comparable<? super C>
072 >
073     implements
074         Comparable<Phenotype<G, C>>,
075         Verifiable,
076         Serializable,
077         Runnable
078 {
079     private static final long serialVersionUID = 5L;
080 
081     private final transient Function<? super Genotype<G>, ? extends C> _function;
082     private final transient Function<? super C, ? extends C> _scaler;
083 
084     private final Genotype<G> _genotype;
085     private final long _generation;
086 
087     private final Lazy<C> _rawFitness;
088     private final Lazy<C> _fitness;
089 
090     /**
091      * Create a new phenotype from the given arguments.
092      *
093      @param genotype the genotype of this phenotype.
094      @param generation the current generation of the generated phenotype.
095      @param function the fitness function of this phenotype.
096      @param scaler the fitness scaler.
097      @throws NullPointerException if one of the arguments is {@code null}.
098      @throws IllegalArgumentException if the given {@code generation} is
099      *         {@code < 0}.
100      */
101     private Phenotype(
102         final Genotype<G> genotype,
103         final long generation,
104         final Function<? super Genotype<G>, ? extends C> function,
105         final Function<? super C, ? extends C> scaler
106     ) {
107         _genotype = requireNonNull(genotype, "Genotype");
108         _function = requireNonNull(function, "Fitness function");
109         _scaler = requireNonNull(scaler, "Fitness scaler");
110         if (generation < 0) {
111             throw new IllegalArgumentException(format(
112                 "Generation must not < 0 and was %s.", generation
113             ));
114         }
115         _generation = generation;
116 
117         _rawFitness = Lazy.of(() -> _function.apply(_genotype));
118         _fitness = Lazy.of(() -> _scaler.apply(_rawFitness.get()));
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         getFitness();
140         return this;
141     }
142 
143     /**
144      * This method simply calls the {@link #evaluate()} method. The purpose of
145      * this method is to have a simple way for concurrent fitness calculation
146      * for expensive fitness values.
147      */
148     @Override
149     public void run() {
150         evaluate();
151     }
152 
153     /**
154      * Return the fitness function used by this phenotype to calculate the
155      * (raw) fitness value.
156      *
157      @return the fitness function.
158      */
159     public Function<? super Genotype<G>, ? extends C> getFitnessFunction() {
160         return _function;
161     }
162 
163     /**
164      * Return the fitness scaler used by this phenotype to scale the <i>raw</i>
165      * fitness.
166      *
167      @return the fitness scaler.
168      */
169     public Function<? super C, ? extends C> getFitnessScaler() {
170         return _scaler;
171     }
172 
173     /**
174      * Return the fitness value of this {@code Phenotype}.
175      *
176      @return The fitness value of this {@code Phenotype}.
177      */
178     public C getFitness() {
179         return _fitness.get();
180     }
181 
182     /**
183      * Return the raw fitness (before scaling) of the phenotype.
184      *
185      @return The raw fitness (before scaling) of the phenotype.
186      */
187     public C getRawFitness() {
188         return _rawFitness.get();
189     }
190 
191     /**
192      * Return the generation this {@link Phenotype} was created.
193      *
194      @return The generation this {@link Phenotype} was created.
195      */
196     public long getGeneration() {
197         return _generation;
198     }
199 
200     /**
201      * Return the age of this phenotype depending on the given current generation.
202      *
203      @param currentGeneration the current generation evaluated by the GA.
204      @return the age of this phenotype:
205      *          {@code currentGeneration - this.getGeneration()}.
206      */
207     public long getAge(final long currentGeneration) {
208         return currentGeneration - _generation;
209     }
210 
211     /**
212      * Test whether this phenotype is valid. The phenotype is valid if its
213      {@link Genotype} is valid.
214      *
215      @return true if this phenotype is valid, false otherwise.
216      */
217     @Override
218     public boolean isValid() {
219         return _genotype.isValid();
220     }
221 
222     @Override
223     public int compareTo(final Phenotype<G, C> pt) {
224         return getFitness().compareTo(pt.getFitness());
225     }
226 
227     @Override
228     public int hashCode() {
229         int hash = 17;
230         hash += 31*_generation + 37;
231         hash += 31*Objects.hashCode(getFitness()) 37;
232         hash += 31*Objects.hashCode(getRawFitness()) 37;
233         hash += 31*_genotype.hashCode() 37;
234         return hash;
235     }
236 
237     @Override
238     public boolean equals(final Object obj) {
239         return obj instanceof Phenotype<?, ?> &&
240             Objects.equals(getFitness()((Phenotype<?, ?>obj).getFitness()) &&
241             Objects.equals(getRawFitness()((Phenotype<?, ?>)obj).getRawFitness()) &&
242             Objects.equals(_genotype, ((Phenotype<?, ?>)obj)._genotype&&
243             _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 }