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