Package ec.gp.ge

# Class GESpecies

java.lang.Object
ec.Species
ec.vector.VectorSpecies
ec.vector.IntegerVectorSpecies
ec.gp.ge.GESpecies

All Implemented Interfaces:
  `Prototype`, `Setup`, `Serializable`, `Cloneable`

public class GESpecies extends IntegerVectorSpecies

GESpecies generates GPIndividuals from GEIndividuals through the application of a grammar parse graph computed by the GrammarParser.

GESpecies uses a GrammarParser to do its dirty work. This parser's job is to take a grammar (in the form of a BufferedReader) and convert it to a tree of GrammarNodes which define the parse graph of the grammar. The GESpecies then interprets his parse graph according to the values in the GEIndividual to produce the equivalent GPIndividual, which is then evaluated.

To do this, GESpecies relies on a subsidiary GPSpecies which defines the GPIndividual and various GPFunctionSets from which to build the parser. This is a grand hack -- the GPSpecies does not know it's being used this way, and so we must provide various dummy parameters to keep the GPSpecies happy even though they'll never be used.

If you are daring, you can replace the GrammarParser with one of your own to customize the parse structure and grammar.

ECJ's Default GE Grammar GE traditionally can use any grammar, and builds parse graphs from that. For simplicity, and in order to remain as compatable as possible with ECJ's existing GP facilities (and GP tradition), ECJ only uses a single Lisp-like grammar which generates standard ECJ trees. This doesn't lose much in generality as the grammar is quite genral.

The grammar assumes that expansion points are enclosed in <> and functions are enclosed in (). For example:

`# This is a comment <prog> ::= <op>
<op> ::= (if-food-ahead <op> <op>)
<op> ::= (progn2 <op> <op>)
<op> ::= (progn3 <op> <op> <op>)
<op> ::= (left) | (right) | (move)
`

alternatively the grammar could also be writen in the following format:

`<prog> ::= <op>
<op> ::= (if-food-ahead <op> <op>) | (progn2 <op> <op>) | (progn3 <op> <op> <op>) | (left) | (right) | (move)
`

Note that you can use several lines to define the same grammar rule: for example, `<op>` was defined by several lines when it could have consisted of several elements separated by vertical pipes ( `|` ). Either way is fine, or a combination of both.

GPNodes are included in the grammar by using their name. This includes ERCs, ADFs, ADMs, and ADFArguments, which should all work just fine. For example, since most ERC GPNodes are simply named "ERC", if you have only one ERC GPNode in your function set, you can just use `(ERC)` in your grammar.

Once the gammar file has been created and setup has been run trees can the be created using the genome (chromosome) of a GEIndividual. A genome of an individual is an array of random integers each of which are one int long. These numbers are used when a decision point (a rule having more that one choice) is reached within the grammar. Once a particular gene (index) in the genome has been used it will not be used again (this may change) when creating the tree.

For example:
number of chromosomes used = 0
genome = {23, 654, 86}
the current rule we are considering is <op>.
%lt;op> can map into one of the following: (if-food-ahead <op> <op>) | (progn2 <op> <op>) | (progn3 <op> <op> <op>) | (left) | (right) | (move)
Since the rule <op> has more than one choice that it can map to, we must consult the genome to decide which choice to take. In this case the number of chromosomes used is 0 so genome[0] is used and number of chromosomes used is incremented. Since values in the genome can be negitive values they are offset by 128 (max negitive of a int) giving us a value from 0-255. A modulus is performed on this resulting number by the number of choices present for the given rule. In the above example since we are using genome[0] the resulting operation would look like: 23+128=151, number of choices for <op> = 6, 151%6=1 so we use choices[1] which is: (progn2 <op> <op>). If all the genes in a genome are used and the tree is still incompete an invalid tree error is returned.

Each node in the tree is a GPNode and trees are constructed depth first.

Parameters

base.`file` String | (the file is where the rules of the gammar are stored)
base.`gp-species` classname, inherits and != ec.gp.GPSpecies | (the GPSpecies subservient to the GESpecies)
base.`parser` classname, inherits and != ge.GrammarParser | (the GrammarParser used by the GESpecies)

Default Base
ge.GESpecies

See Also:
  - Serialized Form

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final int`
  `BIG_TREE_ERROR`
  `HashMap`
  `ERCBank`
  All the ERCs created so far, the ERCs are mapped as, "key --> list of ERC nodes", where the key = (genome[i] - minGene[i]); The ERCBank is "static", beacause we need one identical copy for all the individuals; Moreover, this copy may be sent to other sub-populations as well.
  `GPSpecies`
  `gpspecies`
  The GPSpecies subsidiary to GESpecies.
  `GrammarRuleNode[]`
  `grammar`
  The parsed grammars.
  `GrammarParser[]`
  `grammarParser`
  Parser for each grammar -- khaled
  `String`
  `initScheme`
  `static final String`
  `P_FILE`
  `static final String`
  `P_GESPECIES`
  `static final String`
  `P_GPSPECIES`
  `static final String`
  `P_INITSCHEME`
  `static final String`
  `P_PARSER`
  `static final String`
  `P_PASSES`
  `GrammarParser`
  `parser_prototype`
  The prototypical parser used to parse the grammars.
  `int`
  `passes`
  The number of passes permitted through the genome if we're wrapping.

  ### Fields inherited from class ec.vector.IntegerVectorSpecies

  `C_RANDOM_WALK_MUTATION, C_RESET_MUTATION, maxGene, minGene, mutationIsBounded, mutationType, P_MAXGENE, P_MINGENE, P_MUTATION_BOUNDED, P_MUTATIONTYPE, P_NUM_SEGMENTS, P_RANDOM_WALK_PROBABILITY, P_SEGMENT, P_SEGMENT_END, P_SEGMENT_START, P_SEGMENT_TYPE, randomWalkProbability, V_RANDOM_WALK_MUTATION, V_RESET_MUTATION`

  ### Fields inherited from class ec.vector.VectorSpecies

  `C_ANY_POINT, C_GEOMETRIC, C_INTERMED_RECOMB, C_LINE_RECOMB, C_NONE, C_ONE_POINT, C_ONE_POINT_NO_NOP, C_SIMULATED_BINARY, C_TWO_POINT, C_TWO_POINT_NO_NOP, C_UNIFORM, chunksize, crossoverDistributionIndex, crossoverProbability, crossoverType, duplicateRetries, dynamicInitialSize, genomeIncreaseProbability, genomeResizeAlgorithm, genomeSize, lineDistance, maxInitialSize, minInitialSize, mutationProbability, P_CHUNKSIZE, P_CROSSOVER_DISTRIBUTION_INDEX, P_CROSSOVERPROB, P_CROSSOVERTYPE, P_DUPLICATE_RETRIES, P_GENOMESIZE, P_GEOMETRIC_PROBABILITY, P_LINEDISTANCE, P_MUTATIONPROB, P_UNIFORM_MAX, P_UNIFORM_MIN, P_VECTORSPECIES, V_ANY_POINT, V_GEOMETRIC, V_INTERMED_RECOMB, V_LINE_RECOMB, V_ONE_POINT, V_ONE_POINT_NO_NOP, V_SIMULATED_BINARY, V_TWO_POINT, V_TWO_POINT_NO_NOP, V_UNIFORM`

  ### Fields inherited from class ec.Species

  `f_prototype, i_prototype, P_FITNESS, P_INDIVIDUAL, P_PIPE, pipe_prototype`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `GESpecies()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `Object`
  `clone()`
  Creates a new individual cloned from a prototype, and suitable to begin use in its own evolutionary context.
  `int`
  `consumed(EvolutionState state, GEIndividual ind, int threadnum)`
  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.
  `Parameter`
  `defaultBase()`
  Returns the default base for this prototype.
  `List`
  `flattenSexp(EvolutionState state, int threadnum, GPTree tree)`
  Flattens an S-expression
  `List`
  `gatherNodeString(EvolutionState state, int threadnum, GPNode node, int index)`
  Used by the above function
  `String`
  `getKeyFromNode(EvolutionState state, int threadnum, GPNode node, int index)`
  `int`
  `makeTree(EvolutionState state, int[] genome, GPTree tree, int position, int treeNum, int threadnum, HashMap ercMapsForFancyPrint)`
  makeTree, edits the tree that its given by adding a root (and all subtrees attached)
  `int`
  `makeTrees(EvolutionState state, int[] genome, GPTree[] trees, int threadnum, HashMap ercMapsForFancyPrint)`
  `int`
  `makeTrees(EvolutionState state, GEIndividual ind, GPTree[] trees, int threadnum, HashMap ercMapsForFancyPrint)`
  creates all of an individual's trees
  `GPIndividual`
  `map(EvolutionState state, GEIndividual ind, int threadnum, HashMap ercMapsForFancyPrint)`
  Returns a dummy GPIndividual with a single tree which was built by mapping over the elements of the given GEIndividual.
  `Individual`
  `newIndividual(EvolutionState state, int thread)`
  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.
  `GPNode`
  `obtainERC(EvolutionState state, int genomeVal, int threadnum, GPNode node, HashMap ercMapsForFancyPrint)`
  Loads an ERC from the ERCBank given the value in the genome.
  `int[]`
  `parseSexp(ArrayList flatSexp, GrammarParser gp)`
  The LL(1) parsing algorithm to parse the lisp tree, the lisp tree is actually fed as a flattened list, the parsing code uses the "exact" (and as-is) procedure described in the dragon book.
  `GEIndividual`
  `reverseMap(EvolutionState state, GPIndividual ind, int threadnum)`
  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.
  `void`
  `setup(EvolutionState state, Parameter base)`
  The default version of setup(...) loads requested pipelines and calls setup(...) on them and normalizes their probabilities.

  ### Methods inherited from class ec.vector.IntegerVectorSpecies

  `inNumericalTypeRange, inNumericalTypeRange, loadParametersForGene, maxGene, minGene, mutationIsBounded, mutationType, randomWalkProbability`

  ### Methods inherited from class ec.vector.VectorSpecies

  `contains, contains, contains, contains, duplicateRetries, fill, fill, fill, fill, initializeGenomeSegmentsByEndIndices, initializeGenomeSegmentsByStartIndices, mutationProbability, setupGenome`

  ### Methods inherited from class ec.Species

  `buildMisc, newIndividual, newIndividual, updateIndividual, updateSubpopulation`

  ### Methods inherited from class java.lang.Object

  `equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### P_GESPECIES

    public static final String P_GESPECIES
    See Also:
      - Constant Field Values

  - ### P_FILE

    public static final String P_FILE
    See Also:
      - Constant Field Values

  - ### P_GPSPECIES

    public static final String P_GPSPECIES
    See Also:
      - Constant Field Values

  - ### P_PARSER

    public static final String P_PARSER
    See Also:
      - Constant Field Values

  - ### P_PASSES

    public static final String P_PASSES
    See Also:
      - Constant Field Values

  - ### P_INITSCHEME

    public static final String P_INITSCHEME
    See Also:
      - Constant Field Values

  - ### BIG_TREE_ERROR

    public static final int BIG_TREE_ERROR
    See Also:
      - Constant Field Values

  - ### gpspecies

    public GPSpecies gpspecies
    The GPSpecies subsidiary to GESpecies.

  - ### ERCBank

    public HashMap ERCBank
    All the ERCs created so far, the ERCs are mapped as, "key --> list of ERC nodes", where the key = (genome[i] - minGene[i]); The ERCBank is "static", beacause we need one identical copy for all the individuals; Moreover, this copy may be sent to other sub-populations as well.

  - ### grammar

    public GrammarRuleNode[] grammar
    The parsed grammars.

  - ### passes

    public int passes
    The number of passes permitted through the genome if we're wrapping. Must be >= 1.

  - ### initScheme

    public String initScheme

  - ### parser_prototype

    public GrammarParser parser_prototype
    The prototypical parser used to parse the grammars.

  - ### grammarParser

    public GrammarParser[] grammarParser
    Parser for each grammar -- khaled

- ## Constructor Details

  - ### GESpecies

    public GESpecies()

- ## Method Details

  - ### setup

    public void setup(EvolutionState state, Parameter base)
    Description copied from class: `Species`
    The default version of setup(...) loads requested pipelines and calls setup(...) on them and normalizes their probabilities. If your individual prototype might need to know special things about the species (like parameters stored in it), then when you override this setup method, you'll need to set those parameters BEFORE you call super.setup(...), because the setup(...) code in Species sets up the prototype.
    Specified by:
      `setup` in interface `Prototype`
    Specified by:
      `setup` in interface `Setup`
    Overrides:
      `setup` in class `IntegerVectorSpecies`
    See Also:
      - `Prototype.setup(EvolutionState,Parameter)`

  - ### newIndividual

    public Individual newIndividual(EvolutionState state, int thread)
    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.
    Overrides:
      `newIndividual` in class `VectorSpecies`

  - ### makeTrees

    public int makeTrees(EvolutionState state, GEIndividual ind, GPTree[] trees, int threadnum, HashMap ercMapsForFancyPrint)
    creates all of an individual's trees
    Parameters:
      `state` - Evolution state
      `ind` - the GEIndividual
      `trees` - array of trees for the individual
      `threadnum` - tread number
    Returns:
      number of chromosomes consumed

  - ### makeTrees

    public int makeTrees(EvolutionState state, int[] genome, GPTree[] trees, int threadnum, HashMap ercMapsForFancyPrint)

  - ### makeTree

    public int makeTree(EvolutionState state, int[] genome, GPTree tree, int position, int treeNum, int threadnum, HashMap ercMapsForFancyPrint)
    makeTree, edits the tree that its given by adding a root (and all subtrees attached)
    Returns:
      the number of chromosomes used, or an BIG_TREE_ERROR sentinel value.

  - ### obtainERC

    public GPNode obtainERC(EvolutionState state, int genomeVal, int threadnum, GPNode node, HashMap ercMapsForFancyPrint)
    Loads an ERC from the ERCBank given the value in the genome. If there is no such ERC, then one is created and randomized, then added to the bank. The point of this mechanism is to enable ERCs to appear in multiple places in a GPTree.

  - ### clone

    public Object clone()
    Description copied from interface: `Prototype`
    Creates a new individual cloned from a prototype, and suitable to begin use in its own evolutionary context.

    Typically this should be a full "deep" clone. However, you may share certain elements with other objects rather than clone hem, depending on the situation:

    - If you hold objects which are shared with other instances, don't clone them.
    - If you hold objects which must be unique, clone them.
    - If you hold objects which were given to you as a gesture of kindness, and aren't owned by you, you probably shouldn't clone them.
    - DON'T attempt to clone: Singletons, Cliques, or Populations, or Subpopulation.
    - Arrays are not cloned automatically; you may need to clone an array if you're not sharing it with other instances. Arrays have the nice feature of being copyable by calling clone() on them.

    Implementations.

    - If no ancestor of yours implements clone(), and you have no need to do clone deeply, and you are abstract, then you should not declare clone().
    - If no ancestor of yours implements clone(), and you have no need to do clone deeply, and you are not abstract, then you should implement it as follows:

      ``

           public Object clone()
               {
               try
                   {
                   return super.clone();
                   }
               catch ((CloneNotSupportedException e)
                   { throw new InternalError(); } // never happens
               }

    - If no ancestor of yours implements clone(), but you need to deep-clone some things, then you should implement it as follows:

      ``

           public Object clone()
               {
               try
                   {
                   MyObject myobj = (MyObject) (super.clone());

                   // put your deep-cloning code here...
                   }
               catch ((CloneNotSupportedException e)
                   { throw new InternalError(); } // never happens
               return myobj;
               }

    - If an ancestor has implemented clone(), and you also need to deep clone some things, then you should implement it as follows:

      ``

           public Object clone()
               {
               MyObject myobj = (MyObject) (super.clone());

               // put your deep-cloning code here...

               return myobj;
               }

    Specified by:
      `clone` in interface `Prototype`
    Overrides:
      `clone` in class `Species`

  - ### defaultBase

    public Parameter defaultBase()
    Description copied from interface: `Prototype`
    Returns the default base for this prototype. This should generally be implemented by building off of the static base() method on the DefaultsForm object for the prototype's package. This should be callable during setup(...).
    Specified by:
      `defaultBase` in interface `Prototype`
    Overrides:
      `defaultBase` in class `VectorSpecies`

  - ### consumed

    public int consumed(EvolutionState state, GEIndividual ind, int threadnum)
    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.

  - ### map

    public GPIndividual map(EvolutionState state, GEIndividual ind, int threadnum, HashMap ercMapsForFancyPrint)
    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. If you pass in a non-null HashMap for ercMapsForFancyPrint, then ercMapsForFancyPrint will be loaded with key->ERCvalue pairs of ERC mappings used in this map.

  - ### flattenSexp

    public List flattenSexp(EvolutionState state, int threadnum, GPTree tree)
    Flattens an S-expression

  - ### gatherNodeString

    public List gatherNodeString(EvolutionState state, int threadnum, GPNode node, int index)
    Used by the above function

  - ### getKeyFromNode

    public String getKeyFromNode(EvolutionState state, int threadnum, GPNode node, int index)

  - ### parseSexp

    public int[] parseSexp(ArrayList flatSexp, GrammarParser gp)
    The LL(1) parsing algorithm to parse the lisp tree, the lisp tree is actually fed as a flattened list, the parsing code uses the "exact" (and as-is) procedure described in the dragon book.

  - ### reverseMap

    public GEIndividual reverseMap(EvolutionState state, GPIndividual ind, int threadnum)
    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.