1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package org.apache.commons.math.genetics;
18
19/**
20 * Individual in a population. Chromosomes are compared based on their fitness.
21 *
22 * The chromosomes are IMMUTABLE, and so their fitness is also immutable and
23 * therefore it can be cached.
24 *
25 * @since 2.0
26 * @version $Revision: 811685 $ $Date: 2009-09-05 19:36:48 +0200 (sam. 05 sept. 2009) $
27 */
28public abstract class Chromosome implements Comparable<Chromosome>,Fitness {
29
30    /**
31     * Cached value of the fitness of this chromosome.
32     */
33    private double fitness = Double.MIN_VALUE;
34
35    /**
36     * Access the fitness of this chromosome. The bigger the fitness, the better
37     * the chromosome.
38     *
39     * Computation of fitness is usually very time-consuming task, therefore the
40     * fitness is cached.
41     *
42     * @return the fitness.
43     */
44    public double getFitness() {
45        if (this.fitness == Double.MIN_VALUE) {
46            // no cache - compute the fitness
47            this.fitness = fitness();
48        }
49        return this.fitness;
50    }
51
52    /**
53     * Compares two chromosomes based on their fitness. The bigger the fitness,
54     * the better the chromosome.
55     *
56     * @param another another chromosome to compare
57     * @return
58     * <ul>
59     *     <li>-1 if <code>another</code> is better than <code>this</code></li>
60     *     <li>1 if <code>another</code> is worse than <code>this</code></li>
61     *     <li>0 if the two chromosomes have the same fitness</li>
62     * </ul>
63     */
64    public int compareTo(Chromosome another) {
65        return ((Double)this.getFitness()).compareTo(another.getFitness());
66    }
67
68    /**
69     * Returns <code>true<code> iff <code>another</code> has the same
70     * representation and therefore the same fitness. By default, it returns
71     * false -- override it in your implementation if you need it.
72     * @param another chromosome to compare
73     * @return true if <code>another</code> is equivalent to this chromosome
74     */
75    protected boolean isSame(Chromosome another) {
76        return false;
77    }
78
79    /**
80     * Searches the <code>population</code> for another chromosome with the same
81     * representation. If such chromosome is found, it is returned, if no such
82     * chromosome exists, returns <code>null</code>.
83     *
84     * @param population
85     *            Population to search
86     * @return Chromosome with the same representation, or <code>null</code> if
87     *         no such chromosome exists.
88     */
89    protected Chromosome findSameChromosome(Population population) {
90        for (Chromosome anotherChr : population) {
91            if (this.isSame(anotherChr))
92                return anotherChr;
93        }
94        return null;
95    }
96
97    /**
98     * Searches the population for a chromosome representing the same solution,
99     * and if it finds one, updates the fitness to its value.
100     *
101     * @param population
102     *            Population to search
103     */
104    public void searchForFitnessUpdate(Population population) {
105        Chromosome sameChromosome = findSameChromosome(population);
106        if (sameChromosome != null) {
107            fitness = sameChromosome.getFitness();
108        }
109    }
110
111}
112