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 }