001    package org.jaga.masterAlgorithm;
002    
003    
004    import org.jaga.util.FittestIndividualResult;
005    import org.jaga.selection.*;
006    import org.jaga.definitions.*;
007    import java.util.Arrays;
008    
009    
010    /**
011     * TODO: Complete these comments.
012     *
013     * <p><u>Project:</u> JAGA - Java API for Genetic Algorithms.</p>
014     *
015     * <p><u>Company:</u> University College London and JAGA.Org
016     *    (<a href="http://www.jaga.org" target="_blank">http://www.jaga.org</a>).
017     * </p>
018     *
019     * <p><u>Copyright:</u> (c) 2004 by G. Paperin.<br/>
020     *    This program is free software; you can redistribute it and/or modify
021     *    it under the terms of the GNU General Public License as published by
022     *    the Free Software Foundation, ONLY if you include a note of the original
023     *    author(s) in any redistributed/modified copy.<br/>
024     *    This program is distributed in the hope that it will be useful,
025     *    but WITHOUT ANY WARRANTY; without even the implied warranty of
026     *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
027     *    GNU General Public License for more details.<br/>
028     *    You should have received a copy of the GNU General Public License
029     *    along with this program; if not, write to the Free Software
030     *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
031     *    or see http://www.gnu.org/licenses/gpl.html</p>
032     *
033     * @author Greg Paperin (greg@jaga.org)
034     *
035     * @version JAGA public release 1.0 beta
036     */
037    
038    public class ElitistGA extends ReusableSimpleGA {
039    
040            private double eliteProportion = 0.2;//propotion
041            private double badProportion = 0.05;
042    
043            public ElitistGA() {}
044    
045            public ElitistGA(double eliteProportion) {
046                    setEliteProportion(eliteProportion);
047            }
048    
049            public ElitistGA(double eliteProportion, double badProportion) {
050                    setEliteProportion(eliteProportion);
051                    setBadProportion(badProportion);
052            }
053    
054    
055            public ElitistGA(GAParameterSet parameters, double eliteProportion) {
056                    super(parameters);
057                    setEliteProportion(eliteProportion);
058            }
059    
060            public ElitistGA(GAParameterSet parameters, double eliteProportion, double badProportion) {
061                    super(parameters);
062                    setEliteProportion(eliteProportion);
063                    setBadProportion(badProportion);
064            }
065    
066    
067            public double getEliteProportion() {
068                    return this.eliteProportion;
069            }
070    
071            public void setEliteProportion(double eliteProportion) {
072                    if (eliteProportion < 0 || 1 < eliteProportion)
073                            throw new IllegalArgumentException("Elite proportion must be in [0, 1]");
074                    this.eliteProportion = eliteProportion;
075            }
076    
077            public double getBadProportion() {
078                    return this.badProportion;
079            }
080    
081            public void setBadProportion(double badProportion) {
082                    if (badProportion < 0 || 1 < badProportion)
083                            throw new IllegalArgumentException("Bad proportion must be in [0, 1]");
084                    this.badProportion = badProportion;
085            }
086    
087            protected Population generateNextPopulation(Population oldPop, int age,
088                                                                                                    GAResult result, GAParameterSet params) {
089    
090                    FittestIndividualResult res = (FittestIndividualResult) result;
091                    Population newPop = createEmptyPopulation(params);
092                    final IndividualsFactory fact = params.getIndividualsFactory();
093    
094                    // Cut bad:
095    
096                    Individual [] pop = oldPop.getAllMembers();
097                    Arrays.sort(pop, new AbsoluteFitnessIndividualComparator());
098                    int cutSize = (int) ((double) pop.length * (1.0 - badProportion));
099                    Individual [] cutPop = new Individual[cutSize];
100                    System.arraycopy(pop, pop.length - cutSize, cutPop, 0, cutSize);
101                      // the population we want is cutPop
102                    // Copy elite:
103    
104                    int eliteSize = (int) ((double) params.getPopulationSize() * getEliteProportion());
105                    int p = cutSize - 1;
106                    while (newPop.getSize() < eliteSize) {
107                            Individual kid = fact.createSpecificIndividual(cutPop[p], params);
108                            kid.setFitness(cutPop[p].getFitness());
109                            newPop.add(kid);
110                            if (--p < 0)
111                                    p = cutSize - 1;
112                    }
113    
114                    // Copy rest:
115    
116                    while (newPop.getSize() < params.getPopulationSize()) {
117    
118                            Individual [] parents = selectForReproduction(oldPop, age, params);
119                            notifySelectedForReproduction(parents, oldPop, age, result, params);
120    
121                            Individual [] children = haveSex(parents, params);
122                            for (int i = 0; i < children.length; i++) {
123                                    if (null != children[i].getFitness())
124                                            continue;
125                                    updateIndividualFitness(children[i], oldPop, age, params);
126                                    if (children[i].getFitness().isBetter(res.getBestFitness()))
127                                            res.setFittestIndividual(children[i]);
128                            }
129    
130                            notifyReproduced(children, parents, oldPop, age, result, params);
131                            newPop.addAll(children);
132                    }
133    
134                    return newPop;
135            }
136    }