001/*
002 * BioJava development code This code may be freely distributed and modified
003 * under the terms of the GNU Lesser General Public Licence. This should be
004 * distributed with the code. If you do not have a copy, see:
005 * http://www.gnu.org/copyleft/lesser.html Copyright for this code is held
006 * jointly by the individual authors. These should be listed in @author doc
007 * comments. For more information on the BioJava project and its aims, or to
008 * join the biojava-l mailing list, visit the home page at:
009 * http://www.biojava.org/
010 */
011
012package org.biojavax.ga.functions;
013
014import java.util.Iterator;
015
016import org.biojava.bio.BioError;
017import org.biojava.utils.ChangeType;
018import org.biojava.utils.ChangeVetoException;
019import org.biojavax.ga.GeneticAlgorithm;
020import org.biojavax.ga.Organism;
021import org.biojavax.ga.Population;
022
023/**
024 * Selects Organisms for Replication and returns the offspring.
025 *
026 * @author Mark Schreiber
027 * @author Susanne Merz
028 * @author Andreas Dräger
029 * @version 1.1
030 * @since 1.5
031 */
032
033public interface SelectionFunction {
034        /**
035         * Selects all members of a population for replication
036         */
037        public static SelectionFunction DEFAULT = new SelectAll();
038
039        /**
040         * Selects a <code>Population</code> of <code>Organisms</code> for
041         * replication based on their fitness.
042         *
043         * @param pop
044         *          the <code>Population</code> to select from.
045         * @param genAlg
046         *          the parent <code>GeneticAlgorithm</code>.
047         * @return the <code>Organism</code>s selected
048         * @throws ChangeVetoException
049         *           if the function attempts to change the population and it is
050         *           vetoed.
051         */
052        public Population select(Population pop, GeneticAlgorithm genAlg)
053            throws ChangeVetoException;
054
055        /*-----------INNER CLASSES---------------------------------*/
056
057        /**
058         * <p>
059         * Selects individuals who's fitness exceeds a threshold value.
060         * </p>
061         *
062         * @author Mark Schreiber
063         * @version 1.0
064         */
065        public final class Threshold implements SelectionFunction {
066                private double  cutoff;
067
068                public Threshold(double cutoff) {
069                        this.cutoff = cutoff;
070                }
071
072                public double getCutoff() {
073                        return cutoff;
074                }
075
076                /**
077                 * Selects individuals whose fitness (as determined by the
078                 * <code>FitnessFunction</code>) is more than the cutoff. Removes those
079                 * that aren't.
080                 *
081                 * @param pop
082                 *          the <code>Population</code> to select from.
083                 * @param genAlg
084                 *          the parent <code>GeneticAlgorithm</code>
085                 * @return the <code>Population</code> of selected individuals.
086                 */
087                public Population select(Population pop, GeneticAlgorithm genAlg) {
088                        for (Iterator i = pop.getOrganisms().iterator(); i.hasNext();) {
089                                Organism o = (Organism) i.next();
090                                try {
091                                        double fitness[] = o.getFitness();
092                                        boolean remove = false;
093                                        for (int j = 0; (j < fitness.length) && !remove; j++)
094                                                if (fitness[j] < cutoff) remove = true;
095                                        if (remove) {
096                                                pop.removeOrganism(o);
097                                                // System.out.println("removing organism "+o.getName());
098                                        }
099                                } catch (ChangeVetoException ex) {
100                                        throw new BioError(
101                                            "population has been locked, cannot select individuals", ex);
102                                }
103                        }
104                        return pop;
105                }
106        }
107
108        public final class SelectAll implements SelectionFunction {
109                public Population select(Population pop, GeneticAlgorithm genAlg) {
110                        return pop;
111                }
112
113                /**
114                 * @throws UnsupportedOperationException
115                 *           as there is no <code>FitnessFunction</code> for this class
116                 * @return you won't get this far, trust me!
117                 */
118                public FitnessFunction getFitnessFunction() {
119                        throw new UnsupportedOperationException(
120                            "No FitnessFunction defined for SelectAll SelectionFunction");
121                }
122
123                /**
124                 * @param func
125                 *          you could try this but it will throw a
126                 *          <code>ChangeVetoException</code>
127                 * @throws ChangeVetoException
128                 *           you Cannot set the <code>FitnessFunction</code> of a
129                 *           <code>SelectAll</code> <code>SelectionFunction</code>"
130                 */
131                public void setFitnessFunction(FitnessFunction func)
132                    throws ChangeVetoException {
133                        throw new ChangeVetoException(
134                            "Cannot set the FitnessFunction of SelectAll SelectionFunction");
135                }
136        }
137}