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 — <em>$Date: 2013-12-06 $</em>
053 */
054 public final class Phenotype<
055 G extends Gene<?, G>,
056 C 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
|