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;
015
016import org.biojava.utils.AbstractChangeable;
017import org.biojava.utils.ChangeEvent;
018import org.biojava.utils.ChangeSupport;
019import org.biojava.utils.ChangeVetoException;
020import org.biojavax.ga.GeneticAlgorithm;
021import org.biojavax.ga.Organism;
022import org.biojavax.ga.Population;
023import org.biojavax.ga.functions.CrossOverFunction;
024import org.biojavax.ga.functions.FitnessFunction;
025import org.biojavax.ga.functions.MutationFunction;
026import org.biojavax.ga.functions.SelectionFunction;
027
028/**
029 * Base class from which most implementations of GeneticAlgorithm will inherit.
030 *
031 * @author Mark Schreiber
032 * @author Susanne Merz
033 * @author Andreas Dräger
034 * @version 1.1
035 * @since 1.5
036 */
037
038public abstract class AbstractGeneticAlgorithm extends AbstractChangeable
039    implements GeneticAlgorithm {
040
041        protected Population        population;
042
043        private CrossOverFunction       crossF;
044
045        private SelectionFunction       selectF;
046
047        private MutationFunction        mutF;
048
049        private FitnessFunction   fit;
050
051        protected AbstractGeneticAlgorithm() {
052                population = new SimplePopulation();
053        }
054
055        public final CrossOverFunction getCrossOverFunction() {
056                return crossF;
057        }
058
059        /*
060         * (non-Javadoc)
061         *
062         * @see org.biojavax.ga.GeneticAlgorithm#getFitnessFunction()
063         */
064        public FitnessFunction getFitnessFunction() {
065                return fit;
066        }
067
068        public final MutationFunction getMutationFunction() {
069                return mutF;
070        }
071
072        public final Population getPopulation() {
073                return population;
074        }
075
076        public final SelectionFunction getSelectionFunction() {
077                return selectF;
078        }
079
080        /**
081         * Assigns a fitness value to each organism within the population according to
082         * the currently set fitness function. If no population or no fitness function
083         * is set, nothing will happen.
084         */
085        public void initPopulation() {
086                if ((population != null) && (fit != null))
087                  for (Iterator i = population.getOrganisms().iterator(); i.hasNext();) {
088                          Organism o = (Organism) i.next();
089                          o.setFitness(fit.fitness(o, population, this));
090                  }
091        }
092
093        public final void setCrossOverFunction(CrossOverFunction function)
094            throws ChangeVetoException {
095                if (!hasListeners()) {
096                        this.crossF = function;
097                } else {
098                        ChangeEvent ce = new ChangeEvent(this, GeneticAlgorithm.POPULATION,
099                            function, this.crossF);
100                        ChangeSupport changeSupport = super
101                            .getChangeSupport(GeneticAlgorithm.POPULATION);
102                        synchronized (changeSupport) {
103                                changeSupport.firePreChangeEvent(ce);
104                                this.crossF = function;
105                                changeSupport.firePostChangeEvent(ce);
106                        }
107                }
108        }
109
110        /*
111         * (non-Javadoc)
112         *
113         * @see org.biojavax.ga.GeneticAlgorithm#setFitnessFunction(org.biojavax.ga.functions.FitnessFunction)
114         */
115        public final void setFitnessFunction(FitnessFunction func)
116            throws ChangeVetoException {
117                if (!hasListeners()) {
118                        fit = func;
119                        initPopulation();
120                } else {
121                        ChangeEvent ce = new ChangeEvent(this, GeneticAlgorithm.FITNESS_FUNCTION,
122                            func, fit);
123                        ChangeSupport changeSupport = super
124                            .getChangeSupport(GeneticAlgorithm.FITNESS_FUNCTION);
125                        synchronized (changeSupport) {
126                                changeSupport.firePreChangeEvent(ce);
127                                fit = func;
128                                changeSupport.firePostChangeEvent(ce);
129                        }
130                }
131        }
132
133        public final void setMutationFunction(MutationFunction function)
134            throws ChangeVetoException {
135                if (!hasListeners()) {
136                        this.mutF = function;
137                } else {
138                        ChangeEvent ce = new ChangeEvent(this, GeneticAlgorithm.POPULATION,
139                            function, this.mutF);
140                        ChangeSupport changeSupport = super
141                            .getChangeSupport(GeneticAlgorithm.POPULATION);
142                        synchronized (changeSupport) {
143                                changeSupport.firePreChangeEvent(ce);
144                                this.mutF = function;
145                                changeSupport.firePostChangeEvent(ce);
146                        }
147                }
148        }
149
150        public final void setPopulation(Population pop) throws ChangeVetoException {
151                if (!hasListeners()) {
152                        population = pop;
153                        initPopulation();
154                } else {
155                        ChangeEvent ce = new ChangeEvent(this, GeneticAlgorithm.POPULATION, pop,
156                            this.population);
157                        ChangeSupport changeSupport = super
158                            .getChangeSupport(GeneticAlgorithm.POPULATION);
159                        synchronized (changeSupport) {
160                                changeSupport.firePreChangeEvent(ce);
161                                population = pop;
162                                changeSupport.firePostChangeEvent(ce);
163                        }
164                }
165        }
166
167        public final void setSelectionFunction(SelectionFunction function)
168            throws ChangeVetoException {
169                if (!hasListeners()) {
170                        this.selectF = function;
171                } else {
172                        ChangeEvent ce = new ChangeEvent(this, GeneticAlgorithm.POPULATION,
173                            function, this.selectF);
174                        ChangeSupport changeSupport = super
175                            .getChangeSupport(GeneticAlgorithm.POPULATION);
176                        synchronized (changeSupport) {
177                                changeSupport.firePreChangeEvent(ce);
178                                this.selectF = function;
179                                changeSupport.firePostChangeEvent(ce);
180                        }
181                }
182        }
183}