001    package org.jaga.reproduction;
002    
003    import java.util.ArrayList;
004    import org.jaga.definitions.*;
005    
006    /**
007     * TODO: Complete these comments.
008     *
009     * <p><u>Project:</u> JAGA - Java API for Genetic Algorithms.</p>
010     *
011     * <p><u>Company:</u> University College London and JAGA.Org
012     *    (<a href="http://www.jaga.org" target="_blank">http://www.jaga.org</a>).
013     * </p>
014     *
015     * <p><u>Copyright:</u> (c) 2004 by G. Paperin.<br/>
016     *    This program is free software; you can redistribute it and/or modify
017     *    it under the terms of the GNU General Public License as published by
018     *    the Free Software Foundation, ONLY if you include a note of the original
019     *    author(s) in any redistributed/modified copy.<br/>
020     *    This program is distributed in the hope that it will be useful,
021     *    but WITHOUT ANY WARRANTY; without even the implied warranty of
022     *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023     *    GNU General Public License for more details.<br/>
024     *    You should have received a copy of the GNU General Public License
025     *    along with this program; if not, write to the Free Software
026     *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
027     *    or see http://www.gnu.org/licenses/gpl.html</p>
028     *
029     * @author Greg Paperin (greg@jaga.org)
030     *
031     * @version JAGA public release 1.0 beta
032     */
033    
034    public class CombinedReproductionAlgorithm implements ReproductionAlgorithm {
035    
036            private ArrayList combinedAlgorithms = new ArrayList(2);
037            private Class applicableClass = Individual.class;
038    
039            public CombinedReproductionAlgorithm() {
040                    super();
041            }
042    
043            public void insertReproductionAlgorithm(int position, ReproductionAlgorithm algorithm) {
044                    if (null == algorithm)
045                            throw new NullPointerException("ReproductionAlgorithm may not be null");
046                    if (position < 0 || combinedAlgorithms.size() < position)
047                            throw new NullPointerException("Position is invalid (" + position + ")");
048                    checkAlgorithmFitsTheOthers(algorithm);
049                    combinedAlgorithms.add(position, algorithm);
050                    updateApplicableClass();
051            }
052    
053            public void setReproductionAlgorithm(int position, ReproductionAlgorithm algorithm) {
054                    if (null == algorithm)
055                            throw new NullPointerException("ReproductionAlgorithm may not be null");
056                    if (position < 0 || combinedAlgorithms.size() <= position)
057                            throw new NullPointerException("Position is invalid (" + position + ")");
058                    checkAlgorithmFitsTheOthers(algorithm);
059                    combinedAlgorithms.set(position, algorithm);
060                    updateApplicableClass();
061            }
062    
063            public int findReproductionAlgorithm(ReproductionAlgorithm algorithm) {
064                    if (null == algorithm)
065                            throw new NullPointerException("ReproductionAlgorithm may not be null");
066                    return combinedAlgorithms.indexOf(algorithm);
067            }
068    
069            public void removeReproductionAlgorithm(int position) {
070                    if (position < 0 || combinedAlgorithms.size() <= position)
071                            throw new NullPointerException("Position is invalid (" + position + ")");
072                    combinedAlgorithms.remove(position);
073                    updateApplicableClass();
074            }
075    
076            public ReproductionAlgorithm getReproductionAlgorithm(int position) {
077                    if (position < 0 || combinedAlgorithms.size() <= position)
078                            throw new NullPointerException("Position is invalid (" + position + ")");
079                    return (ReproductionAlgorithm) combinedAlgorithms.get(position);
080            }
081    
082            public int countCombinedAlgorithms() {
083                    return combinedAlgorithms.size();
084            }
085    
086            private void checkAlgorithmFitsTheOthers(ReproductionAlgorithm algorithm)
087                                                                                                                              throws IllegalArgumentException {
088                    if (!getApplicableClass().isAssignableFrom(algorithm.getApplicableClass()))
089                            throw new IllegalArgumentException("Incompatible ReproductionAlgorithm: "
090                                                                                               + "specified algorithm is of type "
091                                                                                               + algorithm.getClass().getName()
092                                                                                               + ", but must be of type "
093                                                                                               + getApplicableClass().getName());
094                    if (0 > algorithm.getRequiredNumberOfParents())
095                            return;
096                    for (int i = 0; i < combinedAlgorithms.size(); i++) {
097                            int p = ((ReproductionAlgorithm) combinedAlgorithms.get(i)).getRequiredNumberOfParents();
098                            if (0 > p)
099                                    continue;
100                            if (algorithm.getRequiredNumberOfParents() != p)
101                                    throw new IllegalArgumentException("Incompatible ReproductionAlgorithm: "
102                                                                                                       + "should require " + p + " parents, "
103                                                                                                       + "but requires "
104                                                                                                       + algorithm.getRequiredNumberOfParents());
105                    }
106            }
107    
108            private void updateApplicableClass() {
109                    if (0 == combinedAlgorithms.size()) {
110                            applicableClass = Individual.class;
111                    } else {
112                            Class type = getReproductionAlgorithm(0).getApplicableClass();
113                            for (int i = 1; i < countCombinedAlgorithms(); i++) {
114                                    Class t = getReproductionAlgorithm(i).getApplicableClass();
115                                    if (t != type && t.isAssignableFrom(type))
116                                            type = t;
117                            }
118                            applicableClass = type;
119                    }
120            }
121    
122            public Class getApplicableClass() {
123                    return applicableClass;
124            }
125    
126            public Individual[] reproduce(Individual[] parents, GAParameterSet params) {
127                    Individual [] kids = parents;
128                    for (int i = 0; i < combinedAlgorithms.size(); i++) {
129                            ReproductionAlgorithm alg = (ReproductionAlgorithm) combinedAlgorithms.get(i);
130                            kids = alg.reproduce(kids, params);
131                    }
132                    return kids;
133            }
134    
135            public int getRequiredNumberOfParents() {
136                    if (0 == combinedAlgorithms.size())
137                            return -1;
138                    for (int i = 0; i < combinedAlgorithms.size(); i++) {
139                            int p = ((ReproductionAlgorithm) combinedAlgorithms.get(i)).getRequiredNumberOfParents();
140                            if (0 <= p)
141                                    return p;
142                    }
143                    return -1;
144            }
145    
146    }