/* Copyright 2006 by Sean Luke Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package ec.es; import ec.*; import ec.util.*; /* * MuCommaLambdaBreeder.java * * Created: Thu Sep 7 17:27:47 2000 * By: Sean Luke */ /** * MuCommaLambdaBreeder is a Breeder which, together with * ESSelection, implements the (mu,lambda) breeding strategy and gathers * the comparison data you can use to implement a 1/5-rule mutation mechanism. * *

Evolution strategies breeders require a "mu" parameter and a "lambda" * parameter for each subpopulation. "mu" refers to the number of parents * from which the new population will be built. "lambda" refers to the * number of children generated by the mu parents. Subpopulation sizes * will change as necessary to accommodate this fact in later generations. * The only rule for initial subpopulation sizes is that they must be * greater than or equal to the mu parameter for that subpopulation. * *

You can now set your initial subpopulation * size to whatever you like, totally independent of lambda and mu, * as long as it is >= mu. * *

MuCommaLambdaBreeder stores mu and lambda values for each subpopulation * in the population, as well as comparisons. A comparison tells you * if >1/5, <1/5 or =1/5 of the new population was better than its * parents (the so-called evolution strategies "one-fifth rule". * Although the comparisons are gathered, no mutation objects are provided * which actually use them -- you're free to use them in any mutation * objects you care to devise which requires them. * *

To do evolution strategies evolution, the * breeding pipelines should contain at least one ESSelection selection method. * While a child is being generated by the pipeline, the ESSelection object will return a parent * from the pool of mu parents. The particular parent is chosen round-robin, so all the parents * will have an equal number of children. It's perfectly fine to have more than one ESSelection * object in the tree, or to call the same one repeatedly during the course of generating a child; * all such objects will consistently return the same parent. They only increment to the next * parent in the pool of mu parents after the child has been created from the pipeline. You can * also mix ESSelection operators with other operators (like Tournament Selection). But you ought * to have at least one ESSelection operator in the pipeline -- else it wouldn't be Evolution * Strategies, would it?

Parameters
es.lambda.subpop-num
int >= 0
Specifies the 'lambda' parameter for the subpopulation.
es.mu.subpop-num
int: a multiple of "lambda"
Specifies the 'mu' parameter for the subpopulation.
* @author Sean Luke * @version 1.0 */ public class MuCommaLambdaBreeder extends Breeder { public static final String P_MU = "mu"; public static final String P_LAMBDA = "lambda"; public int[] mu; public int[] lambda; public Population parentPopulation; public byte[] comparison; public static final byte C_OVER_ONE_FIFTH_BETTER = 1; public static final byte C_UNDER_ONE_FIFTH_BETTER = -1; public static final byte C_EXACTLY_ONE_FIFTH_BETTER = 0; /** Modified by multiple threads, don't fool with this */ public int[] count; public void setup(final EvolutionState state, final Parameter base) { // we're not using the base Parameter p = new Parameter(Initializer.P_POP).push(Population.P_SIZE); int size = state.parameters.getInt(p,null,1); // if size is wrong, we'll let Population complain about it -- for us, we'll just make 0-sized arrays and drop out. mu = new int[size]; lambda = new int[size]; comparison = new byte[size]; // load mu and lambda data for(int x=0;x= 1",ESDefaults.base().push(P_LAMBDA).push(""+x)); mu[x] = state.parameters.getInt(ESDefaults.base().push(P_MU).push(""+x),null,1); if (mu[x]==0) state.output.error("mu must be an integer >= 1",ESDefaults.base().push(P_MU).push(""+x)); else if ((lambda[x] / mu[x]) * mu[x] != lambda[x]) // note integer division state.output.error("mu must be a multiple of lambda", ESDefaults.base().push(P_MU).push(""+x)); } state.output.exitIfErrors(); } /** Sets all subpopulations in pop to the expected lambda size. Does not fill new slots with individuals. */ public Population setToLambda(Population pop, EvolutionState state) { for(int x=0;x lambda[x] / 5.0) // note float division comparison[x] = C_OVER_ONE_FIFTH_BETTER; else if (numChildrenBetter < lambda[x] / 5.0) // note float division comparison[x] = C_UNDER_ONE_FIFTH_BETTER; else comparison[x] = C_EXACTLY_ONE_FIFTH_BETTER; } } // load the parent population parentPopulation = state.population; // MU COMPUTATION // At this point we need to do load our population info // and make sure it jibes with our mu info // the first issue is: is the number of subpopulations // equal to the number of mu's? if (mu.length!=state.population.subpops.length) // uh oh state.output.fatal("For some reason the number of subpops is different than was specified in the file (conflicting with Mu and Lambda storage).",null); // next, load our population, make sure there are no subpopulations smaller than the mu's for(int x=0;x