    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.math3.genetics;
    018
    019    /**
    020     * Individual in a population. Chromosomes are compared based on their fitness.
    021     * <p>
    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 $Id: Chromosome.java 1416643 2012-12-03 19:37:14Z tn $
    027     */
    028    public abstract class Chromosome implements Comparable<Chromosome>,Fitness {
    029        /** Value assigned when no fitness has been computed yet. */
    030        private static final double NO_FITNESS = Double.NEGATIVE_INFINITY;
    031
    032        /** Cached value of the fitness of this chromosome. */
    033        private double fitness = NO_FITNESS;
    034
    035        /**
    036         * Access the fitness of this chromosome. The bigger the fitness, the better the chromosome.
    037         * <p>
    038         * Computation of fitness is usually very time-consuming task, therefore the fitness is cached.
    039         *
    040         * @return the fitness
    041         */
    042        public double getFitness() {
    043            if (this.fitness == NO_FITNESS) {
    044                // no cache - compute the fitness
    045                this.fitness = fitness();
    046            }
    047            return this.fitness;
    048        }
    049
    050        /**
    051         * Compares two chromosomes based on their fitness. The bigger the fitness, the better the chromosome.
    052         *
    053         * @param another another chromosome to compare
    054         * @return
    055         * <ul>
    056         *   <li>-1 if <code>another</code> is better than <code>this</code></li>
    057         *   <li>1 if <code>another</code> is worse than <code>this</code></li>
    058         *   <li>0 if the two chromosomes have the same fitness</li>
    059         * </ul>
    060         */
    061        public int compareTo(final Chromosome another) {
    062            return ((Double)this.getFitness()).compareTo(another.getFitness());
    063        }
    064
    065        /**
    066         * Returns <code>true</code> iff <code>another</code> has the same representation and therefore the same fitness. By
    067         * default, it returns false -- override it in your implementation if you need it.
    068         *
    069         * @param another chromosome to compare
    070         * @return true if <code>another</code> is equivalent to this chromosome
    071         */
    072        protected boolean isSame(final Chromosome another) {
    073            return false;
    074        }
    075
    076        /**
    077         * Searches the <code>population</code> for another chromosome with the same representation. If such chromosome is
    078         * found, it is returned, if no such chromosome exists, returns <code>null</code>.
    079         *
    080         * @param population Population to search
    081         * @return Chromosome with the same representation, or <code>null</code> if no such chromosome exists.
    082         */
    083        protected Chromosome findSameChromosome(final Population population) {
    084            for (Chromosome anotherChr : population) {
    085                if (this.isSame(anotherChr)) {
    086                    return anotherChr;
    087                }
    088            }
    089            return null;
    090        }
    091
    092        /**
    093         * Searches the population for a chromosome representing the same solution, and if it finds one,
    094         * updates the fitness to its value.
    095         *
    096         * @param population Population to search
    097         */
    098        public void searchForFitnessUpdate(final Population population) {
    099            Chromosome sameChromosome = findSameChromosome(population);
    100            if (sameChromosome != null) {
    101                fitness = sameChromosome.getFitness();
    102            }
    103        }
    104
    105    }