001 /*
002 * Copyright 2011 Christian Kumpe http://kumpe.de/christian/java
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package de.kumpe.hadooptimizer;
017
018 import org.apache.commons.math.random.RandomGenerator;
019
020 /**
021 * The base class of configurations for evolutionary algorithms based
022 * {@link Optimizer optimizers}.
023 * <p>
024 * It contains some of the main components for the evolution cycle of an
025 * evolutionary algorithm:
026 * <ul>
027 * <li>The {@link Halter} to {@link Halter#halt(java.util.Collection) check} if
028 * the evolution cycle has terminated.
029 * <li>The {@link Mutator} to {@link Mutator#mutate(Object) mutate} the
030 * children.
031 * <li>The {@link Evaluator} to {@link Evaluator#evaluate(Object) evaluate} the
032 * mutants.
033 * <li>The {@link #setPreserveParents(boolean) flag} to indicate if the parents
034 * should be merged with the newly created and evaluated individuals of the
035 * current generation.
036 * <li>The number of {@link #getParents() parents} that will be selected for the
037 * next generation.
038 * </ul>
039 *
040 * @param <I>
041 * the individuals' type
042 *
043 * @author <a href="http://kumpe.de/christian/java">Christian Kumpe</a>
044 */
045 public abstract class EaOptimizerConfigurationBase<I> extends
046 OptimizerConfiguration<I> {
047 private static final long serialVersionUID = 1L;
048
049 private Halter<I> halter;
050 private Mutator<I> mutator;
051 private Evaluator<I> evaluator;
052 private int parents = 1;
053 private boolean preserveParents;
054
055 /**
056 * {@inheritDoc}
057 * <p>
058 * Additionally calls
059 * {@link #injectRandomGenerator(Object, RandomGenerator)} on the given
060 * {@link #setHalter(Halter) halter}, {@link #setMutator(Mutator) mutator}
061 * and {@link #setEvaluator(Evaluator) evaluator}.
062 */
063 @Override
064 public void injectRandomGenerator(final RandomGenerator randomGenerator) {
065 super.injectRandomGenerator(randomGenerator);
066
067 injectRandomGenerator(halter, randomGenerator);
068 injectRandomGenerator(mutator, randomGenerator);
069 injectRandomGenerator(evaluator, randomGenerator);
070 }
071
072 /**
073 * {@inheritDoc}
074 * <p>
075 * Additionally verifies that a {@link #setHalter(Halter) halter},
076 * {@link #setMutator(Mutator) mutator} and {@link #setEvaluator(Evaluator)
077 * evaluator} has been set.
078 *
079 * @throws IllegalStateException
080 * {@inheritDoc}
081 */
082 @Override
083 public void validate() {
084 super.validate();
085
086 if (null == halter) {
087 throw new IllegalStateException(
088 "A Halter has to be set in the configuration.");
089 }
090 if (null == mutator) {
091 throw new IllegalStateException(
092 "A Mutator has to be set in the configuration.");
093 }
094 if (null == evaluator) {
095 throw new IllegalStateException(
096 "A Evaluator has to be set in the configuration.");
097 }
098 }
099
100 /**
101 * @return the configured {@link Halter}; <code>null</code> if none has been
102 * set
103 */
104 public final Halter<I> getHalter() {
105 return halter;
106 }
107
108 /**
109 * @param halter
110 * the {@link Halter} for this configuration
111 *
112 * @throws NullPointerException
113 * if {@code halter} is <code>null</code>
114 */
115 public final void setHalter(final Halter<I> halter) {
116 if (null == halter) {
117 throw new NullPointerException("halter may not be null.");
118 }
119
120 this.halter = halter;
121 }
122
123 /**
124 * @return the configured {@link Mutator}; <code>null</code> if none has
125 * been set
126 */
127 public final Mutator<I> getMutator() {
128 return mutator;
129 }
130
131 /**
132 * @param mutator
133 * the {@link Mutator} for this configuration
134 *
135 * @throws NullPointerException
136 * if {@code mutator} is <code>null</code>
137 */
138 public final void setMutator(final Mutator<I> mutator) {
139 if (null == mutator) {
140 throw new NullPointerException("mutator may not be null.");
141 }
142
143 this.mutator = mutator;
144 }
145
146 /**
147 * @return the configured {@link Evaluator}; <code>null</code> if none has
148 * been set
149 */
150 public final Evaluator<I> getEvaluator() {
151 return evaluator;
152 }
153
154 /**
155 * @param evaluator
156 * the {@link Evaluator} for this configuration
157 *
158 * @throws NullPointerException
159 * if {@code evaluator} is <code>null</code>
160 */
161 public final void setEvaluator(final Evaluator<I> evaluator) {
162 if (null == evaluator) {
163 throw new NullPointerException("evaluator may not be null.");
164 }
165
166 this.evaluator = evaluator;
167 }
168
169 /**
170 * @return the configured number of parents
171 * @see #setParents(int)
172 */
173 public final int getParents() {
174 assert 0 < parents;
175
176 return parents;
177 }
178
179 /**
180 * Sets the number of parents in the evolution cycle.
181 * <p>
182 * For an E(μ+/,λ)-evolution strategy, this would sets μ.
183 * <p>
184 * The default-value is {@code 1}.
185 *
186 * @param parents
187 * the number of parents
188 *
189 * @throws IllegalArgumentException
190 * if {@code parents} is zero or negative
191 */
192 public final void setParents(final int parents) {
193 if (0 >= parents) {
194 throw new IllegalArgumentException(
195 "parents must be greater than zero");
196 }
197
198 this.parents = parents;
199 }
200
201 /**
202 * @return <code>true</code> if parents will be preserved in the next
203 * evolution cycle; <code>false</code> if parents will be discarded
204 */
205 public final boolean isPreserveParents() {
206 return preserveParents;
207 }
208
209 /**
210 * @param preserveParents
211 * <code>true</code> if parents should be preserved in the next
212 * evolution cycle; <code>false</code> if parents should be
213 * discarded
214 */
215 public final void setPreserveParents(final boolean preserveParents) {
216 this.preserveParents = preserveParents;
217 }
218
219 @Override
220 public int hashCode() {
221 final int prime = 31;
222 int result = super.hashCode();
223 result = prime * result
224 + (evaluator == null ? 0 : evaluator.hashCode());
225 result = prime * result + (halter == null ? 0 : halter.hashCode());
226 result = prime * result + (mutator == null ? 0 : mutator.hashCode());
227 result = prime * result + parents;
228 result = prime * result + (preserveParents ? 1231 : 1237);
229 return result;
230 }
231
232 @Override
233 public boolean equals(final Object obj) {
234 if (this == obj) {
235 return true;
236 }
237 if (!super.equals(obj)) {
238 return false;
239 }
240 if (!(obj instanceof EaOptimizerConfigurationBase)) {
241 return false;
242 }
243 final EaOptimizerConfigurationBase<?> other = (EaOptimizerConfigurationBase<?>) obj;
244 if (evaluator == null) {
245 if (other.evaluator != null) {
246 return false;
247 }
248 } else if (!evaluator.equals(other.evaluator)) {
249 return false;
250 }
251 if (halter == null) {
252 if (other.halter != null) {
253 return false;
254 }
255 } else if (!halter.equals(other.halter)) {
256 return false;
257 }
258 if (mutator == null) {
259 if (other.mutator != null) {
260 return false;
261 }
262 } else if (!mutator.equals(other.mutator)) {
263 return false;
264 }
265 if (parents != other.parents) {
266 return false;
267 }
268 if (preserveParents != other.preserveParents) {
269 return false;
270 }
271 return true;
272 }
273 }