001 package org.jaga.reproduction.greycodedNumbers;
002
003 import org.jaga.definitions.*;
004 import org.jaga.util.*;
005 import org.jaga.individualRepresentation.greycodedNumbers.*;
006 import org.jaga.reproduction.*;
007
008
009 /**
010 * TODO: Complete these comments.
011 *
012 * <p><u>Project:</u> JAGA - Java API for Genetic Algorithms.</p>
013 *
014 * <p><u>Company:</u> University College London and JAGA.Org
015 * (<a href="http://www.jaga.org" target="_blank">http://www.jaga.org</a>).
016 * </p>
017 *
018 * <p><u>Copyright:</u> (c) 2004 by G. Paperin.<br/>
019 * This program is free software; you can redistribute it and/or modify
020 * it under the terms of the GNU General Public License as published by
021 * the Free Software Foundation, ONLY if you include a note of the original
022 * author(s) in any redistributed/modified copy.<br/>
023 * This program is distributed in the hope that it will be useful,
024 * but WITHOUT ANY WARRANTY; without even the implied warranty of
025 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
026 * GNU General Public License for more details.<br/>
027 * You should have received a copy of the GNU General Public License
028 * along with this program; if not, write to the Free Software
029 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030 * or see http://www.gnu.org/licenses/gpl.html</p>
031 *
032 * @author Greg Paperin (greg@jaga.org)
033 *
034 * @version JAGA public release 1.0 beta
035 */
036
037 public class SimpleBinaryXOver extends XOver {
038
039 private static final Class applicableClass = BinaryEncodedIndividual.class;
040
041 public SimpleBinaryXOver() {
042 super();
043 }
044
045 public SimpleBinaryXOver(double xOverProb) {
046 super(xOverProb);
047 }
048
049 public Class getApplicableClass() {
050 return applicableClass;
051 }
052
053 public Individual[] reproduce(Individual[] parents, GAParameterSet params) {
054 if (parents.length != getRequiredNumberOfParents())
055 throw new IllegalArgumentException("Need " + getRequiredNumberOfParents()
056 + " parents for reproduction (not "
057 + parents.length + ")");
058
059 // Check correct type for parents, get length:
060 int bitLen = checkParentsTypeAndLength(parents);
061
062 // Chance (1 - xover probability) that parents wont be changed:
063 final RandomGenerator rnd = params.getRandomGenerator();
064
065 if (rnd.nextDouble() >= getXOverProbability())
066 return makeCopyOfParents(parents, params);
067
068 // Get parents bitsrings:
069 BitString p1 = ((BinaryEncodedIndividual) parents[0]).getBitStringRepresentation();
070 BitString p2 = ((BinaryEncodedIndividual) parents[1]).getBitStringRepresentation();
071
072 // x-over:
073 final int maxAttempts = params.getMaxBadReproductionAttempts();
074
075 int attempts = 0;
076 boolean kidsAreValid = false;
077 do {
078 kidsAreValid = false;
079 int xPoint = rnd.nextInt(1, bitLen);
080
081 // offspring bit strings:
082 BitString c1 = new BitString(bitLen);
083 BitString c2 = new BitString(bitLen);
084
085 // copy before xover-point:
086 for (int i = 0; i < xPoint; i++) {
087 c1.set(i, p1.get(i));
088 c2.set(i, p2.get(i));
089 }
090
091 // copy after xover-point:
092 for (int i = xPoint; i < bitLen; i++) {
093 c1.set(i, p2.get(i));
094 c2.set(i, p1.get(i));
095 }
096
097 // create children and check if children are valid:
098 NDecimalsIndividual [] kids = createKidsFromEncoding(params, c1, c2);
099 kidsAreValid = kidsSatisfyConstraints(kids, params);
100
101 // return valid kids or have another attempts:
102 if (kidsAreValid)
103 return kids;
104 else
105 attempts++;
106
107 } while(!kidsAreValid && attempts < maxAttempts);
108
109 // all attempts failed:
110 return makeCopyOfParents(parents, params);
111
112 }
113
114 protected Individual [] makeCopyOfParents(Individual [] parents, GAParameterSet params) {
115 Individual [] kids = new Individual[parents.length];
116 for (int i = 0; i < kids.length; i++) {
117 kids[i] = params.getIndividualsFactory().createSpecificIndividual(
118 ((BinaryEncodedIndividual)parents[i]).getBitStringRepresentation(),
119 params);
120 //kids[i] = (BinaryEncodedIndividual) ((BinaryEncodedIndividual) parents[i]).clone();
121 kids[i].setFitness(parents[i].getFitness());
122 }
123 return kids;
124 }
125
126 private int checkParentsTypeAndLength(Individual[] parents) throws IllegalArgumentException {
127 // Now make sure that parents are of right type and equal length:
128 int bitLen = -1;
129 for (int i = 0; i < parents.length; i++) {
130 // Check type:
131 if (!getApplicableClass().isInstance(parents[i]))
132 throw new IllegalArgumentException("SimpleBinaryXOver works only for "
133 + getApplicableClass().getName()
134 + ", but parent is "
135 + parents[i].getClass().getName());
136 if (0 == i) // Remember bit len of first parent:
137 bitLen = ((BinaryEncodedIndividual) parents[i]).getBitStringRepresentation().getLength();
138 else // And compare it to the bit len of all other parents:
139 if (bitLen != ((BinaryEncodedIndividual) parents[i]).getBitStringRepresentation().getLength())
140 throw new IllegalArgumentException("SimpleBinaryXOver works only on "
141 + getApplicableClass() + " of equal representation length ("
142 + bitLen + "!="
143 + ((BinaryEncodedIndividual) parents[i]).getBitStringRepresentation().getLength());
144 }
145 return bitLen;
146 }
147
148 private boolean kidsSatisfyConstraints(NDecimalsIndividual[] kids, GAParameterSet params) {
149 NDecimalsIndividualSimpleFactory fact = (NDecimalsIndividualSimpleFactory) params.getIndividualsFactory();
150 for (int i = 0; i < kids.length; i++)
151 if (!fact.valid(kids[i]))
152 return false;
153 return true;
154 }
155
156 private NDecimalsIndividual [] createKidsFromEncoding(GAParameterSet params, BitString c1, BitString c2) {
157 NDecimalsIndividual [] kids = new NDecimalsIndividual[getRequiredNumberOfParents()];
158 kids[0] = (NDecimalsIndividual)
159 params.getIndividualsFactory().createSpecificIndividual(c1, params);
160 kids[1] = (NDecimalsIndividual)
161 params.getIndividualsFactory().createSpecificIndividual(c2, params);
162 return kids;
163 }
164
165 }