/* Copyright 2006 by Sean Luke Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package ec.gp.koza; import ec.*; import ec.gp.*; import ec.util.*; /* * HalfBuilder.java * * Created: Thu Oct 7 18:03:49 1999 * By: Sean Luke */ /** HalfBuilder is a GPNodeBuilder which implements the RAMPED HALF-AND-HALF tree building method described in Koza I/II.
RAMPED HALF-AND-HALF works by choosing a random integer d between minDepth and maxDepth, inclusive. It then grows a tree of depth 1 to d inclusive. (1-pickGrowProbability) of the time (by default, 0.5) it grows a tree using the FULL method, which generates full trees of exactly depth d. (pickGrowProbability) of the time, it grows a tree using the GROW method, which may generate trees of any size between 1 and d inclusive.
Actually, claiming to implement the Koza I/II approach is a bit of a fib -- Koza's original code is somewhat ad-hoc. In the Koza approach, d is chosen in a kind of round-robin fashion rather than at random, if RAMPED HALF/HALF is used. Also, for all three algorithms (RAMPED HALF/HALF, GROW, FULL), the algorithm will not generate a tree consisting of a single terminal, unless forced to.
This implementation instead follows lil-gp's approach, which is to choose d at random from between minDepth and maxDepth, inclusive, and to allow trees consisting of single terminals.
Determining what various algorithms do is a little confusing, mostly because the source code for lil-gp and Koza don't actually quite do what they claim. The table below lists the depth values actually used (counting nodes, rather than edges, for depth). It's probably not what you had expected!
Koza I Min |
Koza I Max |
Koza II Min |
Koza II Max |
lil-gp Min |
lil-gp Max |
ECJ Min |
ECJ Max |
|
GROW (mut) |
5 |
5 |
5 |
5 |
|
|
5 |
5 |
GROW (new) |
7 |
7 |
6? 7? |
6? 7? |
3 |
7 |
5 |
5 |
FULL (new) |
7 |
7 |
6? 7? |
6? 7? |
3 |
7 |
|
|
HALF (new) |
2 |
6 |
2 |
5? 6? |
3 |
7 |
2 |
6 |
This algorithm ignores requestedSize, so no pipelines can ask it to grow a tree of a specific fixed size. The algorithm also ignores any user-provided size distributions.
Parameters
base.growp 0.0 <= float <= 1.0 |
(the likelihood of choosing GROW (as opposed to FULL)> |
base.min-depth int >= 1 |
(smallest "maximum" depth the builder may use for building a tree. 2 is the default.) |
base.max-depth int >= base.min-depth |
(largest "maximum" depth the builder may use for building a tree. 6 is the default.) |
Default Base
gp.koza.half
* @author Sean Luke
* @version 1.0
*/
public class HalfBuilder extends KozaBuilder
{
public static final String P_HALFBUILDER = "half";
public static final String P_PICKGROWPROBABILITY = "growp";
/** The likelihood of using GROW over FULL. */
public float pickGrowProbability;
public Parameter defaultBase()
{
return GPKozaDefaults.base().push(P_HALFBUILDER);
}
public void setup(final EvolutionState state, final Parameter base)
{
super.setup(state,base);
Parameter def = defaultBase();
pickGrowProbability = state.parameters.getFloatWithMax(
base.push(P_PICKGROWPROBABILITY),
def.push(P_PICKGROWPROBABILITY),0.0f,1.0f);
if (pickGrowProbability < 0.0f)
state.output.fatal("The Pick-Grow Probability for HalfBuilder must be a floating-point value between 0.0 and 1.0 inclusive.", base.push(P_MAXDEPTH),def.push(P_MAXDEPTH));
}
public GPNode newRootedTree(final EvolutionState state,
final GPType type,
final int thread,
final GPNodeParent parent,
final GPFunctionSet set,
final int argposition,
final int requestedSize)
{
if (state.random[thread].nextFloat() < pickGrowProbability)
return growNode(state,0,state.random[thread].nextInt(maxDepth-minDepth+1) + minDepth,type,thread,parent,argposition,set);
else
return fullNode(state,0,state.random[thread].nextInt(maxDepth-minDepth+1) + minDepth,type,thread,parent,argposition,set);
}
}