/*
  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.*;

/* 
 * InternalCrossoverPipeline.java
 * 
 * Created: Wed Dec 15 21:41:30 1999
 * By: Sean Luke
 */

/**
 * InternalCrossoverPipeline picks two subtrees from somewhere within an individual,
 * and crosses them over.  Before doing so, it checks to make sure that the
 * subtrees come from trees with the same tree constraints, that the subtrees
 * are swap-compatible with each other, that the new individual does not violate
 * depth constraints, and that one subtree does not contain the other.  It tries
 * tries times to find a valid subtree pair to cross over.  Failing this,
 * it just copies the individual.
 *

 

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.maxdepth
int >= 1
(maximum valid depth of the crossed-over individual's trees)
base.ns.0
classname, inherits and != GPNodeSelector
(GPNodeSelector for subtree 0.
base.ns.1
classname, inherits and != GPNodeSelector,
or String same
(GPNodeSelector for subtree 1. If value is same, then ns.1 a copy of whatever ns.0 is)
base.tree.0
0 < int < (num trees in individuals), if exists
(first tree for the crossover; if parameter doesn't exist, tree is picked at random)
base.tree.1
0 < int < (num trees in individuals), if exists
(second tree for the crossover; if parameter doesn't exist, tree is picked at random. This tree must have the same GPTreeConstraints as tree.0, if tree.0 is defined.)

Default Base
gp.breed.internal-xover

Parameter bases

base.ns.n
nodeselectn (n is 0 or 1)
* @author Sean Luke * @version 1.0 */ public class InternalCrossoverPipeline extends GPBreedingPipeline { private static final long serialVersionUID = 1; public static final String P_INTERNALCROSSOVER = "internal-xover"; public static final String P_NUM_TRIES = "tries"; public static final String P_MAXDEPTH = "maxdepth"; public static final int NUM_SOURCES = 1; /** How the pipeline chooses the first subtree */ public GPNodeSelector nodeselect0; /** How the pipeline chooses the second subtree */ public GPNodeSelector nodeselect1; /** How many times the pipeline attempts to pick nodes until it gives up. */ public int numTries; /** The deepest tree the pipeline is allowed to form. Single terminal trees are depth 1. */ public int maxDepth; /** Is the first tree fixed? If not, this is -1 */ public int tree1; /** Is the second tree fixed? If not, this is -1 */ public int tree2; public Parameter defaultBase() { return GPBreedDefaults.base().push(P_INTERNALCROSSOVER); } public int numSources() { return NUM_SOURCES; } public Object clone() { InternalCrossoverPipeline c = (InternalCrossoverPipeline)(super.clone()); // deep-cloned stuff c.nodeselect0 = (GPNodeSelector)(nodeselect0.clone()); c.nodeselect1 = (GPNodeSelector)(nodeselect1.clone()); return c; } public void setup(final EvolutionState state, final Parameter base) { super.setup(state,base); Parameter def = defaultBase(); Parameter p = base.push(P_NODESELECTOR).push("0"); Parameter d = def.push(P_NODESELECTOR).push("0"); nodeselect0 = (GPNodeSelector) (state.parameters.getInstanceForParameter( p,d, GPNodeSelector.class)); nodeselect0.setup(state,p); p = base.push(P_NODESELECTOR).push("1"); d = def.push(P_NODESELECTOR).push("1"); if (state.parameters.exists(p,d) && state.parameters.getString(p,d).equals(V_SAME)) // can't just copy it this time; the selectors // use internal caches. So we have to clone it no matter what nodeselect1 = (GPNodeSelector)(nodeselect0.clone()); else { nodeselect1 = (GPNodeSelector) (state.parameters.getInstanceForParameter( p,d, GPNodeSelector.class)); nodeselect1.setup(state,p); } numTries = state.parameters.getInt(base.push(P_NUM_TRIES), def.push(P_NUM_TRIES),1); if (numTries == 0) state.output.fatal("InternalCrossover Pipeline has an invalid number of tries (it must be >= 1).",base.push(P_NUM_TRIES),def.push(P_NUM_TRIES)); maxDepth = state.parameters.getInt(base.push(P_MAXDEPTH),def.push(P_MAXDEPTH),1); if (maxDepth==0) state.output.fatal("InternalCrossover Pipeline has an invalid maximum depth (it must be >= 1).",base.push(P_MAXDEPTH),def.push(P_MAXDEPTH)); tree1 = TREE_UNFIXED; if (state.parameters.exists(base.push(P_TREE).push(""+0), def.push(P_TREE).push(""+0))) { tree1 = state.parameters.getInt(base.push(P_TREE).push(""+0), def.push(P_TREE).push(""+0),0); if (tree1==-1) state.output.fatal("Tree fixed value, if defined, must be >= 0"); } tree2 = TREE_UNFIXED; if (state.parameters.exists(base.push(P_TREE).push(""+1), def.push(P_TREE).push(""+1))) { tree2 = state.parameters.getInt(base.push(P_TREE).push(""+1), def.push(P_TREE).push(""+1),0); if (tree2==-1) state.output.fatal("Tree fixed value, if defined, must be >= 0"); } } /** Returns true if inner1 and inner2 do not contain one another */ private boolean noContainment(GPNode inner1, GPNode inner2) { GPNodeParent current = inner1; while(current != null && current instanceof GPNode) { if (current==inner2) return false; // inner2 contains inner1 current = ((GPNode)current).parent; } current = inner2; while(current != null && current instanceof GPNode) { if (current==inner1) return false; // inner1 contains inner2 current = ((GPNode)current).parent; } return true; } /** Returns true if inner1 can feasibly be swapped into inner2's position. */ boolean verifyPoints(GPInitializer initializer, GPNode inner1, GPNode inner2) { // first check to see if inner1 is swap-compatible with inner2 // on a type basis if (!inner1.swapCompatibleWith(initializer, inner2)) return false; // next check to see if inner1 can fit in inner2's spot if (inner1.depth()+inner2.atDepth() > maxDepth) return false; // checks done! return true; } public int produce(final int min, final int max, final int start, final int subpopulation, final Individual[] inds, final EvolutionState state, final int thread) { // grab n individuals from our source and stick 'em right into inds. // we'll modify them from there int n = sources[0].produce(min,max,start,subpopulation,inds,state,thread); // should we bother? if (!state.random[thread].nextBoolean(likelihood)) return reproduce(n, start, subpopulation, inds, state, thread, false); // DON'T produce children from source -- we already did GPInitializer initializer = ((GPInitializer)state.initializer); for(int q=start;q= i.trees.length)) // uh oh state.output.fatal("Internal Crossover Pipeline 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"); if (tree2!=TREE_UNFIXED && (tree2<0 || tree2 >= i.trees.length)) // uh oh state.output.fatal("Internal Crossover Pipeline 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;x 1) t1 = state.random[thread].nextInt(i.trees.length); else t1 = 0; else t1 = tree1; if (tree2==TREE_UNFIXED) if (i.trees.length > 1) t2 = state.random[thread].nextInt(i.trees.length); else t2 = 0; else t2 = tree2; } while (i.trees[t1].constraints(initializer) != i.trees[t2].constraints(initializer)); } else { t1 = tree1; t2 = tree2; // make sure the constraints are okay if (i.trees[t1].constraints(initializer) != i.trees[t2].constraints(initializer)) // uh oh state.output.fatal("GP Crossover Pipeline's two tree choices are both specified by the user -- but their GPTreeConstraints are not the same"); } // prepare the nodeselectors nodeselect0.reset(); nodeselect1.reset(); // pick some nodes GPNode p1=null; GPNode p2=null; boolean res = false; for(int x=0;x

Ads help maintain this website.