/*
Copyright 2006 by Sean Luke
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package ec.gp.breed;
import ec.*;
import ec.util.*;
import ec.gp.*;
/*
* RehangPipeline.java
*
* Created: Wed Dec 15 21:41:30 1999
* By: Sean Luke
*/
/**
* RehangPipeline picks a nonterminal node other than the root
* and "rehangs" it as
* a new root. Imagine if the tree were nodes connected with string.
* Grab the new node and pick it up, letting the other nodes hang
* underneath it as a new "root". That's in effect what you're doing.
*
* Important Note: Because it must be free of any constraints
* by nature, RehangPipeline does not work with strong typing. You must
* not have more than one type defined in order to use RehangPipeline.
*
*
RehangPipeline picks a random tree, then picks randomly from
* all the nonterminals in the tree other than the root, and rehangs the
* chosen nonterminal
* as the new root. If its chosen tree has no nonterminals, it repeats
* the choose-tree process. If after tries times
* it has failed to find a tree with nonterminals (other than the root),
* it gives up and simply
* copies the individual. As you might guess, determining if a tree has
* nonterminals is very fast, so tries can be pretty large with
* little to no detriment to evolution speed.
*
*
"Rehanging" is complicated to describe. First, you pick a random
* child of your chosen nonterminal n,
* and remove this subtree from the tree.
* Call this subtree T. Next, you set the nonterminal as a new root; its
* former parent p now fills the slot left behind by the missing subtree.
* The p's former parent q now fills the slot left behind by
* n. q's former parent r now fills the slot left behind
* by p, and so on. This proceeds all the way up to the old root, which
* will be left with one empty slot (where its former child was that is now its new
* parent). This slot is then filled with T
Typical Number of Individuals Produced Per produce(...) call
...as many as the source produces
Number of Sources
1
Parameters
base.tries
int >= 1
(number of times to try finding valid pairs of nodes)
base.tree.0
0 < int < (num trees in individuals), if exists
(tree chosen for mutation; if parameter doesn't exist, tree is picked at random)
Default Base
gp.breed.rehang
* @author Sean Luke
* @version 1.0
*/
public class RehangPipeline extends GPBreedingPipeline
{
public static final String P_REHANG = "rehang";
public static final String P_NUM_TRIES = "tries";
public static final int NUM_SOURCES = 1;
/** The number of times the pipeline tries to find a tree with a
nonterminal before giving up and just copying the individual. */
int numTries;
/** Is our tree fixed? If not, this is -1 */
int tree;
public Parameter defaultBase() { return GPBreedDefaults.base().push(P_REHANG); }
public int numSources() { return NUM_SOURCES; }
public void setup(final EvolutionState state, final Parameter base)
{
super.setup(state,base);
Parameter def = defaultBase();
numTries = state.parameters.getInt(base.push(P_NUM_TRIES),
def.push(P_NUM_TRIES),1);
if (numTries == 0)
state.output.fatal("RehangPipeline has an invalid number of tries (it must be >= 1).",base.push(P_NUM_TRIES),def.push(P_NUM_TRIES));
if (((GPInitializer)state.initializer).numAtomicTypes + ((GPInitializer)state.initializer).numSetTypes > 1)
state.output.fatal("RehangPipeline only works when there is only one type (the system is typeless", base,def);
tree = TREE_UNFIXED;
if (state.parameters.exists(base.push(P_TREE).push(""+0),
def.push(P_TREE).push(""+0)))
{
tree = state.parameters.getInt(base.push(P_TREE).push(""+0),
def.push(P_TREE).push(""+0),0);
if (tree==-1)
state.output.fatal("Tree fixed value, if defined, must be >= 0");
}
}
private int numRehangableNodes(final GPNode root, int soFar)
{
// we don't include the tree root
for(int x=0;x0) soFar++; // rehangable
for(int x=0;x0) // rehangable
{
num--;
if (num==-1) // found it
{
rehangableNode = root;
return num;
}
}
for(int x=0;x= i.trees.length))
// uh oh
state.output.fatal("RehangPipeline attempted to fix tree.0 to a value which was out of bounds of the array of the individual's trees. Check the pipeline's fixed tree values -- they may be negative or greater than the number of trees in an individual");
GPIndividual j;
if (sources[0] instanceof BreedingPipeline)
// it's already a copy, so just smash the tree in
{
j=i;
}
else // need to copy it
{
j = (GPIndividual)(i.lightClone());
// Fill in various tree information that didn't get filled in there
j.trees = new GPTree[i.trees.length];
for(int x=0;x1) t = state.random[thread].nextInt(i.trees.length);
else t = 0;
else t = tree;
// is the tree rehangable?
if (j.trees[t].child.children.length==0) continue; // uh oh, try again
boolean rehangable = false;
for(int y=0;y0) // nonterminal
{ rehangable = true; break; }
if (!rehangable) continue; // the root's children are all terminals
int numrehang = numRehangableNodes(j.trees[t].child,0);
pickRehangableNode(j.trees[t].child,
state.random[thread].nextInt(numrehang));
rehang(state,thread,rehangableNode,j.trees[t].child);
j.evaluated = false;
}
// add the new individual, replacing its previous source
inds[q] = j;
}
return n;
}
}
Ads help maintain this website.