001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  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    package org.apache.commons.math.genetics;
018    
019    /**
020     * Individual in a population. Chromosomes are compared based on their fitness.
021     *
022     * The chromosomes are IMMUTABLE, and so their fitness is also immutable and
023     * therefore it can be cached.
024     *
025     * @since 2.0
026     * @version $Revision: 811685 $ $Date: 2009-09-05 19:36:48 +0200 (sam. 05 sept. 2009) $
027     */
028    public abstract class Chromosome implements Comparable<Chromosome>,Fitness {
029    
030        /**
031         * Cached value of the fitness of this chromosome.
032         */
033        private double fitness = Double.MIN_VALUE;
034    
035        /**
036         * Access the fitness of this chromosome. The bigger the fitness, the better
037         * the chromosome.
038         *
039         * Computation of fitness is usually very time-consuming task, therefore the
040         * fitness is cached.
041         *
042         * @return the fitness.
043         */
044        public double getFitness() {
045            if (this.fitness == Double.MIN_VALUE) {
046                // no cache - compute the fitness
047                this.fitness = fitness();
048            }
049            return this.fitness;
050        }
051    
052        /**
053         * Compares two chromosomes based on their fitness. The bigger the fitness,
054         * the better the chromosome.
055         *
056         * @param another another chromosome to compare
057         * @return
058         * <ul>
059         *     <li>-1 if <code>another</code> is better than <code>this</code></li>
060         *     <li>1 if <code>another</code> is worse than <code>this</code></li>
061         *     <li>0 if the two chromosomes have the same fitness</li>
062         * </ul>
063         */
064        public int compareTo(Chromosome another) {
065            return ((Double)this.getFitness()).compareTo(another.getFitness());
066        }
067    
068        /**
069         * Returns <code>true<code> iff <code>another</code> has the same
070         * representation and therefore the same fitness. By default, it returns
071         * false -- override it in your implementation if you need it.
072         * @param another chromosome to compare
073         * @return true if <code>another</code> is equivalent to this chromosome
074         */
075        protected boolean isSame(Chromosome another) {
076            return false;
077        }
078    
079        /**
080         * Searches the <code>population</code> for another chromosome with the same
081         * representation. If such chromosome is found, it is returned, if no such
082         * chromosome exists, returns <code>null</code>.
083         *
084         * @param population
085         *            Population to search
086         * @return Chromosome with the same representation, or <code>null</code> if
087         *         no such chromosome exists.
088         */
089        protected Chromosome findSameChromosome(Population population) {
090            for (Chromosome anotherChr : population) {
091                if (this.isSame(anotherChr))
092                    return anotherChr;
093            }
094            return null;
095        }
096    
097        /**
098         * Searches the population for a chromosome representing the same solution,
099         * 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    }