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.impl;
013
014import java.util.Iterator;
015import java.util.LinkedList;
016import java.util.List;
017import java.util.Set;
018
019import org.biojava.bio.BioError;
020import org.biojava.bio.symbol.IllegalAlphabetException;
021import org.biojava.bio.symbol.IllegalSymbolException;
022import org.biojava.utils.ChangeVetoException;
023import org.biojavax.ga.GAStoppingCriteria;
024import org.biojavax.ga.Organism;
025import org.biojavax.ga.Population;
026import org.biojavax.ga.functions.CrossOverFunction;
027import org.biojavax.ga.functions.MutationFunction;
028import org.biojavax.ga.functions.SelectionFunction;
029
030/**
031 * A simple implementation of the <code>GeneticAlgorithm</code> interface it
032 * is not intended that this class be overidden, hence it is final. It is much
033 * better to overide <code>AbstractGeneticAlgorithm</code>.
034 *
035 * @author Mark Schreiber
036 * @author Susanne Merz
037 * @author Andreas Dr&auml;ger
038 * @version 1.1
039 * @since 1.5
040 */
041
042public final class SimpleGeneticAlgorithm extends AbstractGeneticAlgorithm {
043        private int            generation       = 0;
044
045        private LinkedList      crossResults;
046
047        public SimpleGeneticAlgorithm() {
048                crossResults = new LinkedList();
049        }
050
051        public SimpleGeneticAlgorithm(Population pop, MutationFunction mutFunc,
052            CrossOverFunction xFunc, SelectionFunction selFunc) {
053                crossResults = new LinkedList();
054                try {
055                        setPopulation(pop);
056                        setCrossOverFunction(xFunc);
057                        setMutationFunction(mutFunc);
058                        setSelectionFunction(selFunc);
059                } catch (ChangeVetoException ex) {
060                        // can't veto changes on an unconstructed object
061                }
062        }
063
064        /**
065         * The current generation
066         *
067         * @return an int giving the generation number
068         */
069        public int getGeneration() {
070                return generation;
071        }
072
073        /**
074         * Get a List containing details of all the cross over events during the run.
075         * If <code>run(GAStoppingCriteria stoppingCriteria) has not yet been called
076         * the list will be empty</code>.
077         * This implementation only stores a buffer of the last 100 crosses for memory
078         * reasons.
079         *
080         * @return a <code>List</code> of GACrossResult objects.
081         */
082        public List getCrossResults() {
083                return crossResults;
084        }
085
086        public synchronized void run(GAStoppingCriteria stoppingCriteria)
087            throws ChangeVetoException, IllegalAlphabetException,
088            IllegalSymbolException {
089                while (stoppingCriteria.stop(this) != true) {
090                        // select the fit for reproduction
091                        getSelectionFunction().select(getPopulation(), this);
092
093                        // cross pairs of individuals
094                        Set partners = getPopulation().getOrganisms();
095                        for (Iterator it = partners.iterator(); it.hasNext();) {
096                                Organism a = (Organism) it.next();
097                                if (it.hasNext()) {
098                                        Organism b = (Organism) it.next();
099
100                                        try {
101                                                for (int i = 0; i < a.getChromosomes().length
102                                                    && i < b.getChromosomes().length; i++) {
103
104                                                        crossResults.addLast(getCrossOverFunction().performCrossOver(
105                                                            a.getChromosomes()[i], b.getChromosomes()[i]));
106
107                                                        while (crossResults.size() > 100) {
108                                                                crossResults.removeFirst();
109                                                        }
110                                                }
111                                        } catch (ChangeVetoException ex) {
112                                                // shouldn't happen as long as sensible implementations of
113                                                // SymbolList
114                                                // are used.
115                                                throw new BioError("Unmodifiable chromosome", ex);
116                                        }
117                                } else {
118                                        break;
119                                }
120                        }
121
122                        // mutate
123                        for (Iterator it = getPopulation().organisms(); it.hasNext();) {
124                                Organism o = (Organism) it.next();
125                                for (int i = 0; i < o.getChromosomes().length; i++) {
126                                        getMutationFunction().mutate(o.getChromosomes()[i]);
127                                }
128        o.setFitness(getFitnessFunction().fitness(o, population, this));
129                        }
130
131                        generation++;
132                }
133        }
134
135}