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 }