001 package org.jaga.individualRepresentation.greycodedNumbers;
002
003 import org.jaga.definitions.*;
004 import org.jaga.util.*;
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 NDecimalsIndividualSimpleFactory implements IndividualsFactory {
035
036 private int individualSize = 1;
037 private double decimalScale = 1000000; // 10^6 i.e., 6 digits
038 private int precision = 64; // bits
039 private RangeConstraint [] constraints = new RangeConstraint [] {null};
040
041 public NDecimalsIndividualSimpleFactory() {}
042
043 public NDecimalsIndividualSimpleFactory(int varsPerIndividual, int decPrecision,
044 int representationLen) {
045 setIndividualSize(varsPerIndividual);
046 setDecimalScale(decPrecision);
047 setPrecision(representationLen);
048 }
049
050 public int getDecimalScale() {
051 double scal = Math.log(decimalScale) / Math.log(10); // i.e. log(10, scale)
052 return (byte) scal;
053 }
054
055 public void setDecimalScale(int val) {
056 if (val < 0 || 20 < val)
057 throw new IllegalArgumentException("Decimal scale (" + val
058 + ") not supported, use 10^0 - 10^20");
059 decimalScale = Math.pow(10, val);
060 }
061
062 public int getIndividualSize() {
063 return individualSize;
064 }
065
066 public void setIndividualSize(int size) {
067 RangeConstraint [] newConstraints = new RangeConstraint[size];
068
069 for (int i = 0; i < Math.min(size, this.individualSize); i++)
070 newConstraints[i] = this.constraints[i];
071
072 for (int i = Math.min(size, this.individualSize); i < size; i++)
073 newConstraints[i] = null;
074
075 this.individualSize = size;
076 this.constraints = newConstraints;
077 }
078
079 /**
080 * Gets the constraint for individuals' variable with specified index.
081 *
082 * @param variableIndex the index of the variable inside the individuals to
083 * which the constraint applies.
084 *
085 * @return the constraint vor variables at the specified index.
086 */
087 public RangeConstraint getConstraint(int variableIndex) {
088 return constraints[variableIndex];
089 }
090
091 /**
092 * Sets the constraints for individuals' variable at the specified index.
093 *
094 * @param variableIndex index of the variable to which the consteraint applies.
095 * @param constraint the constraint.
096 */
097 public void setConstraint(int variableIndex, RangeConstraint constraint) {
098 constraints[variableIndex] = constraint;
099 }
100
101 public int getPrecision() {
102 return precision;
103 }
104
105 public void setPrecision(int val) {
106 precision = val;
107 }
108
109 /**
110 * Checks if the values of the specified individual are in the ranges
111 * specified by constraints of this factory.
112 *
113 * @param indiv some individual
114 *
115 * @return <code>true</code> if all values encoded by this individual are inside the
116 * ranges specified by the constrains applicable to this factory;
117 * <code>false</code> otherwise.
118 */
119 public boolean valid(NDecimalsIndividual indiv) {
120
121 // check if individual's settings match this factiory:
122 if (indiv.getDecimalScale() != this.getDecimalScale()
123 || indiv.getSize() != this.getIndividualSize()
124 || indiv.getPrecision() != this.getPrecision()) {
125 throw new IllegalArgumentException("The given individual (" + indiv
126 + ") is likely not created by this factory.");
127 }
128
129 // check all values of the individual:
130 for (int i = 0; i < indiv.getSize(); i++) {
131 double minmax[] = getAllowedRange(i);
132 double val = indiv.getDoubleValue(i);
133 if (val < minmax[0])
134 return false;
135 if (val > minmax[1])
136 return false;
137 }
138 return true;
139 }
140
141 public Individual createDefaultIndividual(GAParameterSet params) {
142 // Create a default individual:
143 NDecimalsIndividual indiv = new NDecimalsIndividual(individualSize, decimalScale, precision);
144
145 // If some value is out of range, set it in the middle of range:
146 for (int valInd = 0; valInd < individualSize; valInd++) {
147 double [] minmax = getAllowedRange(valInd);
148 if (indiv.getDoubleValue(valInd) < minmax[0] || minmax[1] < indiv.getDoubleValue(valInd)) {
149 double val = 0.5 * minmax[0] + 0.5 * minmax[1];
150 indiv.setDoubleValue(valInd, val);
151 }
152 }
153
154 return indiv;
155 }
156
157 public Individual createRandomIndividual(GAParameterSet params) {
158 // create an individual:
159 NDecimalsIndividual indiv = new NDecimalsIndividual(individualSize, decimalScale, precision);
160
161 // set all values to uniformly distributed random values:
162 for (int valInd = 0; valInd < individualSize; valInd++) {
163 double [] minmax = getAllowedRange(valInd);
164 double val = params.getRandomGenerator().nextDouble(minmax[0], minmax[1]);
165 indiv.setDoubleValue(valInd, val);
166 }
167 return indiv;
168 }
169
170 public Individual createSpecificIndividual(Object init, GAParameterSet params) {
171
172 if (null == init)
173 throw new NullPointerException("Initialisation value for NDecimalsIndividual my not be null");
174
175 if (init instanceof NDecimalsIndividual)
176 return createSpecificIndividual((NDecimalsIndividual) init);
177
178 if (init instanceof BitString)
179 return createSpecificIndividual((BitString) init);
180
181 if (init instanceof BitString)
182 return createSpecificIndividual((BitString) init);
183
184 if (init instanceof double [])
185 return createSpecificIndividual((double []) init);
186
187 throw new ClassCastException("Initialisation value for NDecimalsIndividual "
188 + "must be of type BitString or Double (but is "
189 + init.getClass() + ")");
190 }
191
192 public Individual createSpecificIndividual(NDecimalsIndividual initVal) {
193 NDecimalsIndividual indiv = new NDecimalsIndividual(individualSize, decimalScale, precision);
194 indiv.setBitStringRepresentation(initVal.getBitStringRepresentation());
195 return indiv;
196 }
197
198 public Individual createSpecificIndividual(BitString initVal) {
199 NDecimalsIndividual indiv = new NDecimalsIndividual(individualSize, decimalScale, precision);
200 indiv.setBitStringRepresentation(initVal);
201 return indiv;
202 }
203
204 public Individual createSpecificIndividual(double [] initVal) {
205 NDecimalsIndividual indiv = new NDecimalsIndividual(individualSize, decimalScale, precision);
206 for (int i = 0; i < individualSize; i++) {
207 indiv.setDoubleValue(i, initVal[i]);
208 }
209 return indiv;
210 }
211
212 private double [] getAllowedRange(int varInd) throws IllegalArgumentException {
213
214 // use these if no constraint applies:
215 final double veryLargePositive = 0.99 * (Long.MAX_VALUE / decimalScale);
216 final double veryLargeNegative = 0.99 * (Long.MIN_VALUE / decimalScale);
217
218 // get constraint:
219 RangeConstraint constr = constraints[varInd];
220
221 // return range:
222 if (null == constr)
223 return new double[] {veryLargeNegative, veryLargePositive};
224
225 return new double [] {Math.max(constr.getMinValue(), veryLargeNegative),
226 Math.min(constr.getMaxValue(), veryLargePositive)};
227 }
228
229 }