/*
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.*;
/*
* KozaBuilder.java
*
* Created: Sun Oct 29 22:35:34 EST 2006
* By: Sean Luke
*/
/*
KozaBuilder is an abstract superclass of three tree builders: GROW, FULL, and RAMPED HALF-AND-HALF,
all described in I/II. As all three classes specify a minimum and maximum depth, these instance
variables and setup methods appear here; but they are described in detail in the relevant subclasses
(GrowBuilder, HalfBuilder, and FullBuilder).
Parameters
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.)
@author Sean Luke
@version 1.0
*/
public abstract class KozaBuilder extends GPNodeBuilder
{
public static final String P_MAXDEPTH = "max-depth";
public static final String P_MINDEPTH = "min-depth";
/** The largest maximum tree depth RAMPED HALF-AND-HALF can specify. */
public int maxDepth;
/** The smallest maximum tree depth RAMPED HALF-AND-HALF can specify. */
public int minDepth;
public void setup(final EvolutionState state, final Parameter base)
{
super.setup(state,base);
Parameter def = defaultBase();
// load maxdepth and mindepth, check that maxdepth>0, mindepth>0, maxdepth>=mindepth
maxDepth = state.parameters.getInt(base.push(P_MAXDEPTH),def.push(P_MAXDEPTH),1);
if (maxDepth<=0)
state.output.fatal("The Max Depth for a KozaBuilder must be at least 1.",
base.push(P_MAXDEPTH),def.push(P_MAXDEPTH));
minDepth = state.parameters.getInt(base.push(P_MINDEPTH),def.push(P_MINDEPTH),1);
if (minDepth<=0)
state.output.fatal("The Min Depth for a KozaBuilder must be at least 1.",
base.push(P_MINDEPTH),def.push(P_MINDEPTH));
if (maxDepth= Min Depth for a KozaBuilder",
base.push(P_MAXDEPTH),def.push(P_MAXDEPTH));
}
/** A private recursive method which builds a FULL-style tree for newRootedTree(...) */
protected GPNode fullNode(final EvolutionState state,
final int current,
final int max,
final GPType type,
final int thread,
final GPNodeParent parent,
final int argposition,
final GPFunctionSet set)
{
// fullNode can mess up if there are no available terminals for a given type. If this occurs,
// and we find ourselves unable to pick a terminal when we want to do so, we will issue a warning,
// and pick a nonterminal, violating the "FULL" contract. This can lead to pathological situations
// where the system will continue to go on and on unable to stop because it can't pick a terminal,
// resulting in running out of memory or some such. But there are cases where we'd want to let
// this work itself out.
boolean triedTerminals = false; // did we try -- and fail -- to fetch a terminal?
int t = type.type;
GPNode[] terminals = set.terminals[t];
GPNode[] nonterminals = set.nonterminals[t];
GPNode[] nodes = set.nodes[t];
if (nodes.length == 0)
errorAboutNoNodeWithType(type, state); // total failure
// pick a terminal when we're at max depth or if there are NO nonterminals
if (( current+1 >= max || // Now pick if we're at max depth
warnAboutNonterminal(nonterminals.length==0, type, false, state)) && // OR if there are NO nonterminals!
// this will freak out the static checkers
(triedTerminals = true) && // [first set triedTerminals]
terminals.length != 0) // AND if there are available terminals
{
GPNode n = (GPNode)(terminals[state.random[thread].nextInt(terminals.length)].lightClone());
n.resetNode(state,thread); // give ERCs a chance to randomize
n.argposition = (byte)argposition;
n.parent = parent;
return n;
}
// else force a nonterminal unless we have no choice
else
{
if (triedTerminals) warnAboutNoTerminalWithType(type, false, state); // we tried terminals and we're here because there were none!
GPNode[] nodesToPick = set.nonterminals[type.type];
if (nodesToPick==null || nodesToPick.length ==0) // no nonterminals, hope the guy knows what he's doing!
nodesToPick = set.terminals[type.type]; // this can only happen with the warning about nonterminals above
GPNode n = (GPNode)(nodesToPick[state.random[thread].nextInt(nodesToPick.length)].lightClone());
n.resetNode(state,thread); // give ERCs a chance to randomize
n.argposition = (byte)argposition;
n.parent = parent;
// Populate the node...
GPType[] childtypes = n.constraints(((GPInitializer)state.initializer)).childtypes;
for(int x=0;x= max) && // Now pick if we're at max depth
// this will freak out the static checkers
(triedTerminals = true) && // [first set triedTerminals]
terminals.length != 0) // AND if there are available terminals
{
GPNode n = (GPNode)(terminals[state.random[thread].nextInt(terminals.length)].lightClone());
n.resetNode(state,thread); // give ERCs a chance to randomize
n.argposition = (byte)argposition;
n.parent = parent;
return n;
}
// else pick a random node
else
{
if (triedTerminals) warnAboutNoTerminalWithType(type, false, state); // we tried terminals and we're here because there were none!
GPNode n = (GPNode)(nodes[state.random[thread].nextInt(nodes.length)].lightClone());
n.resetNode(state,thread); // give ERCs a chance to randomize
n.argposition = (byte)argposition;
n.parent = parent;
// Populate the node...
GPType[] childtypes = n.constraints(((GPInitializer)state.initializer)).childtypes;
for(int x=0;x
Ads help maintain this website.