Created
January 6, 2011 07:20
-
-
Save fearofcode/767644 to your computer and use it in GitHub Desktop.
Optimize the sphere function in N dimensions using the WatchMaker framework. the function is simply just (x_1*x_1, ..., x_n*x_n) with a single global minimum at (0, ..., 0).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.eccasts.watchmakerexample; | |
import java.util.*; | |
import org.uncommons.maths.random.*; | |
import org.uncommons.watchmaker.framework.*; | |
import org.uncommons.watchmaker.framework.factories.AbstractCandidateFactory; | |
import org.uncommons.watchmaker.framework.operators.DoubleArrayCrossover; | |
import org.uncommons.watchmaker.framework.operators.EvolutionPipeline; | |
import org.uncommons.watchmaker.framework.selection.RouletteWheelSelection; | |
import org.uncommons.watchmaker.framework.termination.Stagnation; | |
public class FunctionOptimizer { | |
public static void main(String[] args) { | |
new FunctionOptimizer().work(); | |
} | |
private void work() { | |
int dimension = 10; | |
double max = 5.0; | |
double min = -max; | |
int populationSize = 50; | |
int crossoverPoints = 2; | |
double mutationProbability = 0.02; | |
CandidateFactory<double[]> factory = new ArrayFactory(dimension, min, | |
max); | |
List<EvolutionaryOperator<double[]>> operators = new ArrayList<EvolutionaryOperator<double[]>>( | |
dimension); | |
operators.add(new DoubleArrayCrossover(crossoverPoints)); | |
operators.add(new DoubleArrayMutation(new Probability( | |
mutationProbability))); | |
EvolutionaryOperator<double[]> pipeline = new EvolutionPipeline<double[]>( | |
operators); | |
EvolutionEngine<double[]> engine = new GenerationalEvolutionEngine<double[]>( | |
factory, pipeline, new SphereFunction(dimension), | |
new RouletteWheelSelection(), new MersenneTwisterRNG()); | |
engine.addEvolutionObserver(new EvolutionLogger()); | |
double[] best = engine.evolve(populationSize, 5, new Stagnation(100, | |
false)); | |
System.out.printf("(%f, %f)\n", best[0], best[1]); | |
} | |
private static class DoubleArrayMutation implements | |
EvolutionaryOperator<double[]> { | |
private Probability p; | |
public DoubleArrayMutation(Probability p) { | |
this.p = p; | |
} | |
@Override | |
public List<double[]> apply(List<double[]> selectedCandidates, | |
Random rng) { | |
List<double[]> newCandidates = new ArrayList<double[]>( | |
selectedCandidates.size()); | |
newCandidates.addAll(selectedCandidates); | |
for (int i = 0; i < newCandidates.size(); i++) { | |
if (p.nextEvent(rng)) { | |
double[] mutated = newCandidates.get(i); | |
int dimension = rng.nextInt(mutated.length); | |
mutated[dimension] += rng.nextGaussian(); | |
newCandidates.set(i, mutated); | |
} | |
} | |
return newCandidates; | |
} | |
} | |
private static class SphereFunction implements FitnessEvaluator<double[]> { | |
private int dimension; | |
public SphereFunction(int dimension) { | |
this.dimension = dimension; | |
} | |
@Override | |
public double getFitness(double[] candidate, | |
List<? extends double[]> population) { | |
double sum = 0.0; | |
for (int i = 0; i < dimension; i++) | |
sum += candidate[i] * candidate[i]; | |
return sum; | |
} | |
@Override | |
public boolean isNatural() { | |
return false; | |
} | |
} | |
private static class ArrayFactory extends | |
AbstractCandidateFactory<double[]> implements | |
CandidateFactory<double[]> { | |
private int dimension; | |
private double min; | |
private double max; | |
public ArrayFactory(int dimension, double min, double max) { | |
super(); | |
this.dimension = dimension; | |
this.min = min; | |
this.max = max; | |
} | |
@Override | |
public List<double[]> generateInitialPopulation(int populationSize, | |
Random rng) { | |
List<double[]> population = new ArrayList<double[]>(); | |
for (int i = 1; i <= populationSize; i++) | |
population.add(generateRandomCandidate(rng)); | |
return population; | |
} | |
@Override | |
public List<double[]> generateInitialPopulation(int populationSize, | |
Collection<double[]> seedCandidates, Random rng) { | |
List<double[]> population = new ArrayList<double[]>(); | |
population.addAll(seedCandidates); | |
for (int i = 1; i <= populationSize - seedCandidates.size(); i++) | |
population.add(generateRandomCandidate(rng)); | |
return population; | |
} | |
@Override | |
public double[] generateRandomCandidate(Random rng) { | |
double[] candidate = new double[dimension]; | |
for (int i = 0; i < dimension; i++) | |
candidate[i] = rng.nextDouble() * (max - min) + min; | |
return candidate; | |
} | |
} | |
private static class EvolutionLogger implements EvolutionObserver<double[]> { | |
public void populationUpdate(PopulationData<? extends double[]> data) { | |
System.out.printf("Generation %d: %f\n", | |
data.getGenerationNumber(), data.getBestCandidateFitness()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sample output:
Generation 0: 41.005461
Generation 1: 41.005461
Generation 2: 29.073731
Generation 3: 29.073731
Generation 4: 26.090030
Generation 5: 12.761137
Generation 6: 12.324053
Generation 7: 12.324053
Generation 8: 8.163833
Generation 9: 8.163833
Generation 10: 7.605173
Generation 11: 6.859394
Generation 12: 6.859394
Generation 13: 6.267017
Generation 14: 5.526149
Generation 15: 5.526149
Generation 16: 4.117264
Generation 17: 4.117264
Generation 18: 4.117264
Generation 19: 3.253360
Generation 20: 3.253360
Generation 21: 3.182631
Generation 22: 3.182631
Generation 23: 3.182631
Generation 24: 3.182631
Generation 25: 3.182631
Generation 26: 3.182631
Generation 27: 3.182631
Generation 28: 3.022274
Generation 29: 3.022274
Generation 30: 3.022274
Generation 31: 2.956309
Generation 32: 2.139559
Generation 33: 2.139559
Generation 34: 2.139559
Generation 35: 2.073594
Generation 36: 2.073594
Generation 37: 1.866171
Generation 38: 1.866171
Generation 39: 1.866171
Generation 40: 1.866171
Generation 41: 1.866171
Generation 42: 1.866171
Generation 43: 1.683505
Generation 44: 1.617540
Generation 45: 1.617540
Generation 46: 1.476083
Generation 47: 1.410118
Generation 48: 1.410118
Generation 49: 1.369466
Generation 50: 1.369466
Generation 51: 1.369466
Generation 52: 1.369466
Generation 53: 1.369466
Generation 54: 1.369466
Generation 55: 1.369466
Generation 56: 1.369466
Generation 57: 1.369466
Generation 58: 1.369466
Generation 59: 1.369466
Generation 60: 1.369466
Generation 61: 1.369466
Generation 62: 1.198429
Generation 63: 1.004684
Generation 64: 1.004684
Generation 65: 1.004684
Generation 66: 1.004684
Generation 67: 1.004684
Generation 68: 1.004684
Generation 69: 1.004684
Generation 70: 1.004684
Generation 71: 1.004684
Generation 72: 1.004684
Generation 73: 1.004684
Generation 74: 1.004684
Generation 75: 1.004684
Generation 76: 0.895295
Generation 77: 0.895295
Generation 78: 0.895295
Generation 79: 0.895295
Generation 80: 0.895295
Generation 81: 0.895295
Generation 82: 0.895295
Generation 83: 0.895295
Generation 84: 0.895295
Generation 85: 0.895295
Generation 86: 0.895295
Generation 87: 0.895295
Generation 88: 0.895295
Generation 89: 0.895295
Generation 90: 0.895295
Generation 91: 0.895295
Generation 92: 0.818323
Generation 93: 0.818323
Generation 94: 0.818323
Generation 95: 0.818323
Generation 96: 0.720707
Generation 97: 0.720707
Generation 98: 0.696470
Generation 99: 0.696470
Generation 100: 0.696470
Generation 101: 0.619499
Generation 102: 0.619499
Generation 103: 0.619499
Generation 104: 0.619499
Generation 105: 0.619499
Generation 106: 0.619499
Generation 107: 0.619499
Generation 108: 0.619499
Generation 109: 0.619499
Generation 110: 0.619499
Generation 111: 0.619499
Generation 112: 0.619499
Generation 113: 0.619499
Generation 114: 0.282092
Generation 115: 0.282092
Generation 116: 0.282092
Generation 117: 0.282092
Generation 118: 0.282092
Generation 119: 0.282069
Generation 120: 0.282069
Generation 121: 0.282069
Generation 122: 0.282069
Generation 123: 0.282069
Generation 124: 0.282069
Generation 125: 0.282069
Generation 126: 0.282069
Generation 127: 0.282069
Generation 128: 0.282069
Generation 129: 0.282069
Generation 130: 0.282069
Generation 131: 0.282069
Generation 132: 0.282069
Generation 133: 0.282069
Generation 134: 0.276666
Generation 135: 0.276666
Generation 136: 0.276666
Generation 137: 0.276666
Generation 138: 0.276666
Generation 139: 0.276666
Generation 140: 0.276666
Generation 141: 0.221498
Generation 142: 0.221498
Generation 143: 0.221498
Generation 144: 0.221498
Generation 145: 0.221498
Generation 146: 0.221498
Generation 147: 0.221498
Generation 148: 0.221498
Generation 149: 0.221498
Generation 150: 0.221498
Generation 151: 0.221498
Generation 152: 0.221498
Generation 153: 0.221498
Generation 154: 0.221498
Generation 155: 0.221498
Generation 156: 0.221498
Generation 157: 0.221498
Generation 158: 0.221498
Generation 159: 0.221498
Generation 160: 0.168143
Generation 161: 0.168143
Generation 162: 0.168143
Generation 163: 0.168143
Generation 164: 0.168143
Generation 165: 0.168143
Generation 166: 0.168143
Generation 167: 0.168143
Generation 168: 0.168143
Generation 169: 0.168143
Generation 170: 0.168143
Generation 171: 0.168143
Generation 172: 0.168143
Generation 173: 0.168143
Generation 174: 0.168143
Generation 175: 0.168143
Generation 176: 0.168143
Generation 177: 0.168143
Generation 178: 0.168143
Generation 179: 0.168143
Generation 180: 0.168143
Generation 181: 0.168143
Generation 182: 0.094495
Generation 183: 0.094495
Generation 184: 0.094495
Generation 185: 0.094495
Generation 186: 0.094495
Generation 187: 0.094495
Generation 188: 0.094495
Generation 189: 0.094495
Generation 190: 0.094495
Generation 191: 0.094495
Generation 192: 0.094495
Generation 193: 0.094495
Generation 194: 0.094495
Generation 195: 0.094495
Generation 196: 0.094495
Generation 197: 0.094495
Generation 198: 0.094495
Generation 199: 0.094495
Generation 200: 0.094495
Generation 201: 0.094495
Generation 202: 0.076542
Generation 203: 0.076542
Generation 204: 0.076542
Generation 205: 0.075018
Generation 206: 0.075018
Generation 207: 0.075018
Generation 208: 0.073250
Generation 209: 0.073250
Generation 210: 0.064376
Generation 211: 0.064376
Generation 212: 0.053868
Generation 213: 0.053868
Generation 214: 0.052344
Generation 215: 0.049053
Generation 216: 0.049053
Generation 217: 0.049053
Generation 218: 0.049053
Generation 219: 0.049053
Generation 220: 0.049053
Generation 221: 0.049053
Generation 222: 0.049053
Generation 223: 0.049053
Generation 224: 0.049053
Generation 225: 0.049053
Generation 226: 0.049053
Generation 227: 0.049053
Generation 228: 0.049053
Generation 229: 0.049053
Generation 230: 0.049053
Generation 231: 0.049053
Generation 232: 0.049053
Generation 233: 0.049053
Generation 234: 0.049053
Generation 235: 0.049053
Generation 236: 0.049053
Generation 237: 0.049053
Generation 238: 0.049053
Generation 239: 0.049053
Generation 240: 0.049053
Generation 241: 0.049053
Generation 242: 0.049053
Generation 243: 0.049053
Generation 244: 0.049053
Generation 245: 0.049053
Generation 246: 0.049053
Generation 247: 0.049053
Generation 248: 0.049053
Generation 249: 0.045467
Generation 250: 0.045467
Generation 251: 0.045467
Generation 252: 0.045467
Generation 253: 0.045467
Generation 254: 0.045467
Generation 255: 0.045467
Generation 256: 0.045467
Generation 257: 0.045467
Generation 258: 0.045467
Generation 259: 0.034026
Generation 260: 0.034026
Generation 261: 0.034026
Generation 262: 0.034026
Generation 263: 0.030440
Generation 264: 0.030440
Generation 265: 0.030440
Generation 266: 0.030440
Generation 267: 0.030440
Generation 268: 0.030440
Generation 269: 0.030440
Generation 270: 0.030440
Generation 271: 0.030440
Generation 272: 0.030440
Generation 273: 0.030440
Generation 274: 0.030440
Generation 275: 0.030440
Generation 276: 0.030440
Generation 277: 0.030440
Generation 278: 0.030440
Generation 279: 0.030440
Generation 280: 0.030440
Generation 281: 0.030440
Generation 282: 0.030440
Generation 283: 0.030440
Generation 284: 0.030440
Generation 285: 0.030440
Generation 286: 0.030440
Generation 287: 0.030440
Generation 288: 0.030440
Generation 289: 0.030440
Generation 290: 0.030440
Generation 291: 0.030440
Generation 292: 0.030440
Generation 293: 0.030440
Generation 294: 0.030440
Generation 295: 0.030440
Generation 296: 0.030440
Generation 297: 0.030440
Generation 298: 0.030440
Generation 299: 0.030440
Generation 300: 0.030440
Generation 301: 0.030440
Generation 302: 0.030440
Generation 303: 0.030440
Generation 304: 0.030440
Generation 305: 0.030440
Generation 306: 0.030440
Generation 307: 0.030440
Generation 308: 0.028640
Generation 309: 0.028640
Generation 310: 0.028640
Generation 311: 0.028640
Generation 312: 0.028640
Generation 313: 0.028640
Generation 314: 0.028640
Generation 315: 0.028640
Generation 316: 0.028640
Generation 317: 0.028640
Generation 318: 0.028640
Generation 319: 0.028640
Generation 320: 0.028640
Generation 321: 0.028640
Generation 322: 0.028640
Generation 323: 0.028640
Generation 324: 0.028640
Generation 325: 0.028640
Generation 326: 0.028640
Generation 327: 0.028640
Generation 328: 0.028640
Generation 329: 0.028640
Generation 330: 0.028640
Generation 331: 0.028640
Generation 332: 0.028640
Generation 333: 0.025690
Generation 334: 0.025690
Generation 335: 0.025690
Generation 336: 0.025690
Generation 337: 0.025690
Generation 338: 0.025690
Generation 339: 0.025690
Generation 340: 0.025690
Generation 341: 0.025690
Generation 342: 0.025690
Generation 343: 0.025690
Generation 344: 0.025690
Generation 345: 0.025690
Generation 346: 0.025690
Generation 347: 0.025690
Generation 348: 0.025690
Generation 349: 0.025690
Generation 350: 0.025690
Generation 351: 0.025690
Generation 352: 0.025690
Generation 353: 0.025690
Generation 354: 0.025690
Generation 355: 0.025690
Generation 356: 0.025690
Generation 357: 0.025690
Generation 358: 0.025690
Generation 359: 0.025690
Generation 360: 0.025690
Generation 361: 0.025690
Generation 362: 0.025690
Generation 363: 0.025690
Generation 364: 0.024011
Generation 365: 0.024011
Generation 366: 0.024011
Generation 367: 0.024011
Generation 368: 0.024011
Generation 369: 0.024011
Generation 370: 0.024011
Generation 371: 0.024011
Generation 372: 0.024011
Generation 373: 0.024011
Generation 374: 0.024011
Generation 375: 0.024011
Generation 376: 0.024011
Generation 377: 0.024011
Generation 378: 0.024011
Generation 379: 0.024011
Generation 380: 0.024011
Generation 381: 0.024011
Generation 382: 0.024011
Generation 383: 0.024011
Generation 384: 0.024011
Generation 385: 0.024011
Generation 386: 0.024011
Generation 387: 0.024011
Generation 388: 0.024011
Generation 389: 0.024011
Generation 390: 0.024011
Generation 391: 0.024011
Generation 392: 0.024011
Generation 393: 0.024011
Generation 394: 0.024011
Generation 395: 0.024011
Generation 396: 0.024011
Generation 397: 0.024011
Generation 398: 0.024011
Generation 399: 0.024011
Generation 400: 0.024011
Generation 401: 0.024011
Generation 402: 0.024011
Generation 403: 0.024011
Generation 404: 0.024011
Generation 405: 0.024011
Generation 406: 0.024011
Generation 407: 0.024011
Generation 408: 0.024011
Generation 409: 0.024011
Generation 410: 0.024011
Generation 411: 0.024011
Generation 412: 0.024011
Generation 413: 0.024011
Generation 414: 0.024011
Generation 415: 0.024011
Generation 416: 0.024011
Generation 417: 0.024011
Generation 418: 0.024011
Generation 419: 0.024011
Generation 420: 0.024011
Generation 421: 0.024011
Generation 422: 0.024011
Generation 423: 0.024011
Generation 424: 0.024011
Generation 425: 0.024011
Generation 426: 0.024011
Generation 427: 0.024011
Generation 428: 0.024011
Generation 429: 0.024011
Generation 430: 0.024011
Generation 431: 0.024011
Generation 432: 0.024011
Generation 433: 0.024011
Generation 434: 0.024011
Generation 435: 0.024011
Generation 436: 0.024011
Generation 437: 0.024011
Generation 438: 0.024011
Generation 439: 0.024011
Generation 440: 0.024011
Generation 441: 0.024011
Generation 442: 0.024011
Generation 443: 0.024011
Generation 444: 0.024011
Generation 445: 0.024011
Generation 446: 0.024011
Generation 447: 0.024011
Generation 448: 0.024011
Generation 449: 0.024011
Generation 450: 0.024011
Generation 451: 0.024011
Generation 452: 0.024011
Generation 453: 0.024011
Generation 454: 0.024011
Generation 455: 0.024011
Generation 456: 0.024011
Generation 457: 0.024011
Generation 458: 0.024011
Generation 459: 0.024011
Generation 460: 0.024011
Generation 461: 0.024011
Generation 462: 0.024011
Generation 463: 0.024011
Generation 464: 0.024011
(0.008798, -0.026056)
You can see it starts out bad, rapidly converges, and then stagnates at about 0.02.