/// <summary> /// Returns the number of elements consumed from the GEIndividual array to produce /// the tree, else returns -1 if an error occurs, specifically if all elements were /// consumed and the tree had still not been completed. /// If you pass in a non-null HashMap for ERCmappings, then ERCmappings will be loaded with key->ERCvalue /// pairs of ERC mappings used in this map. /// </summary> public int Consumed(IEvolutionState state, GEIndividual ind, int threadnum) { // create a dummy individual var newind = ((GPIndividual)GPSpecies.I_Prototype).LightClone(); // do the mapping and return the number consumed return(MakeTrees(state, ind, newind.Trees, threadnum, null)); }
/** * This is an ugly hack to simulate the "Sensible Initialization", * First we create a GPIndividual, then reverse-map it to GEIndividuals, * We do not need to call IntegerVectorSpecies.newIndividual() since it is overriden * by the GPSpecies.newIndividual(); * * Moreover, as in the case for non-identical representations (i,e, GP-GE island * models etc,), the grammar rules, tree constraints, ERC's etc, are supposed to be * identical across all islands, so we are using the same "gpspecies" inside this class. * * However, the identicality of the GPTree particulars like grammar, constraints, ADFs, * ERC's may not be universally true. */ public override Individual NewIndividual(IEvolutionState state, int thread) { GEIndividual gei = null; if (InitScheme != null && InitScheme.Equals("sensible")) { GPIndividual gpi = (GPIndividual)GPSpecies.NewIndividual(state, thread); gei = ReverseMap(state, gpi, thread); } else { gei = (GEIndividual)base.NewIndividual(state, thread); gei.Species = this; } return(gei); }
/** * Reverse of the original map() function, takes a GPIndividual and returns * a corresponding GEIndividual; The GPIndividual may contain more than one trees, * and such cases are handled accordingly, see the 3rd bullet below -- * * NOTE: * This reverse mapping is only valid for S-expression trees ; * * This procedure supports ERC for the current population (not for population * /subpopulation from other islands); However, that could be done by merging * all ERCBanks from all the sub-populations but that is not done yet ; * * Support for the ADF's are done as follows -- suppose in one GPIndividual, * there are N trees -- T1, T2, ,,, Tn and each of them follows n different * grammars G1, G2, ,,, Gn respectively; now if they are reverse-mapped to * int arrays, there will be n int arrays A1[], A2[], ,,, An[]; and suppose * the i-th tree Ti is reverse mapped to int array Ai[] and morevoer Ai[] is * the longest among all the arrays (Bj[]s); so Bi[] is sufficient to build * all ADF trees Tjs. */ public GEIndividual ReverseMap(IEvolutionState state, GPIndividual ind, int threadnum) { // create a dummy individual GEIndividual newind = (GEIndividual)I_Prototype.Clone(); // The longest int will be able to contain all ADF trees. int longestIntLength = -1; int[] longestInt = null; // Now go through all the ADF trees. for (int treeIndex = 0; treeIndex < ind.Trees.Length; treeIndex++) { // Flatten the Lisp tree ArrayList flatSexp = (ArrayList)FlattenSexp(state, threadnum, ind.Trees[treeIndex]); // Now convert the flatten list into an array of ints // no. of trees == no. of grammars int[] genomeVals = ParseSexp(flatSexp, GrammarParser[treeIndex]); // store the longest int array if (genomeVals.Length >= longestIntLength) { longestIntLength = genomeVals.Length; longestInt = new int[genomeVals.Length]; Array.Copy(genomeVals, 0, longestInt, 0, genomeVals.Length); } genomeVals = null; } // assign the longest int to the individual's genome newind.genome = longestInt; // update the GPIndividual's fitness information newind.Fitness = ind.Fitness; newind.Evaluated = false; // Set the species to me ? not sure. newind.Species = this; // return it return(newind); }
/// <summary> /// Returns a dummy GPIndividual with a single tree which was built by mapping /// over the elements of the given GEIndividual. Null is returned if an error occurs, /// specifically, if all elements were consumed and the tree had still not been completed. /// </summary> public GPIndividual Map(IEvolutionState state, GEIndividual ind, int threadnum, IDictionary <int, GPNode> ercMapsForFancyPrint) { // create a dummy individual var newind = ((GPIndividual)GPSpecies.I_Prototype).LightClone(); // Do NOT initialize its trees // Set the fitness to the ByteVectorIndividual's fitness newind.Fitness = ind.Fitness; newind.Evaluated = false; // Set the species to me newind.Species = GPSpecies; // do the mapping if (MakeTrees(state, ind, newind.Trees, threadnum, ercMapsForFancyPrint) < 0) // error { return(null); } return(newind); }
/// <summary> /// Creates all of an individual's trees /// </summary> /// <param name="state">Evolution state</param> /// <param name="ind">ind the GEIndividual</param> /// <param name="trees">array of trees for the individual</param> /// <param name="threadnum">thread number</param> /// <param name="ercMapsForFancyPrint"></param> /// <returns>Number of chromosomes consumed</returns> public int MakeTrees(IEvolutionState state, GEIndividual ind, GPTree[] trees, int threadnum, IDictionary <int, GPNode> ercMapsForFancyPrint) { int[] genome = ind.genome; var position = 0; // We start with one pass, then repeatedly double the genome length and // try again until it's big enough. This is simple but very costly in terms of // memory so our maximum pass size is MAXIMUM_PASSES, which should be small enough // to allow for even pretty long genomes. for (int i = 1; i <= Passes; i *= 2) // note i starts at 1 { position = MakeTrees(state, genome, trees, threadnum, ercMapsForFancyPrint); if (position < 0 && i < Passes) // gotta try again { // this is a total hack int[] old = genome; genome = new int[old.Length * 2]; Array.Copy(old, 0, genome, 0, old.Length); Array.Copy(old, 0, genome, old.Length, old.Length); // duplicate } } return(Math.Min(position, ind.genome.Length)); }