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