Package ec.gp

# Class ERC

java.lang.Object
ec.gp.GPNode
ec.gp.ERC

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

Direct Known Subclasses:
  `Terminal`

public abstract class ERC extends GPNode
ERC is an abstract GPNode which implements Ephemeral Random Constants, as described in Koza I. An ERC is a node which, when first instantiated, gets set to some random constant value which it always returns from then on, even after being crossed over into other individuals. In order to implement an ERC, you need to override several methods below.

## Impementing an ERC

A basic no-frills ERC needs to have the following things:

- The data holding the ERC (perhaps a float or a couple of floats)
- An implementation of the eval method which returns the appropriate data when the node is evaluated.
- Possibly an implementation of the clone method to copy that data properly. If your ERC data is just a simple or immutable type (like an int or a string), you don't need write a clone() method; the default one works fine. But if your data is an array or other mutable object, you'll need to override the clone() method to copy the array.
- An implementation of the resetNode method to randomize the data once cloned from the prototype. This essentially "initializes" your ERC.
- An implementation of the encode method which presents the ERC as a String. If you don't plan on writing individuals out to files in a fashion that enables them to be read back in again later, but only care to print out individuals for statistics purposes, you can implement this to just write `"" + value`, where value is your data.
- An implementation of the nodeEquals method to return true if the other node is also an ERC of the same type, and it has the same ERC data as yourself.

A more advanced ERC will need some of the following gizmos:

- If you have ERCs of different class types (for example, a vector ERC and a floating-point scalar ERC), you will wish to distinguish them when they're printed to files. To do this, override the name method to return different strings for each of them (perhaps "vec" versus "").
- If you want to write your ERCs to files such that they can be read back in again, you'll need to override the encode method to write using the `ec.util.Code` class. Further, you'll need to override the decode method to read in the individual using the `ec.util.Code` and `ec.util.DecodeReturn` classes. The default version -- which is wrong -- returns `false`. When you do this, you'll probably also want to override the toStringForHumans() method to return a simple string form of the ERC: perhaps just a number or a vector like "invalid input: '<'7.24, 9.23>". This is because by default toStringForHumans() calls toString(), which in turn calls encode, which you have just overidden to be more computer-ish.
- ERCs can be mutated using a custom mutator pipeline, for example the ec.gp.breed.MutateERCPipeline. If you expect to mutate your ERCs, you may wish to override the mutateERC method to do something more subtle than its default setting (which just randomizes the ERC again, by calling resetNode).
- The default nodeHashCode implementation is poor and slow (it creates a string using encode() and then hashes the sting). You might create a better (and probably simpler) hash code function.
- If you're going to use facilities such as the Island Model or the distributed evaluator, you'll need to implement the writeNode and readNode methods to read/write the node to DataInput/DataOutput. The default implementations just throw errors.
- If you need to set up your ERC class from the parameter file, do so in the setup method.

See the ec.app.regression.func.RegERC class for an example of a simple but "fuly-implemented" ERC. A slightly more complicated example can be found in ec.app.lawnmower.func.LawnERC.

See Also:
  - Serialized Form

- ## Field Summary

  ### Fields inherited from class ec.gp.GPNode

  `argposition, children, CHILDREN_UNKNOWN, constraints, GPNODEPRINTTAB, MAXPRINTBYTES, NODESEARCH_ALL, NODESEARCH_NONTERMINALS, NODESEARCH_TERMINALS, P_NODE, P_NODECONSTRAINTS, parent`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `ERC()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `boolean`
  `decode(DecodeReturn dret)`
  Decodes data into the ERC from dret.
  `abstract String`
  `encode()`
  Encodes data from the ERC, using ec.util.Code.
  `int`
  `expectedChildren()`
  Usually ERCs don't have children, and this default implementation makes certain of it.
  `void`
  `mutateERC(EvolutionState state, int thread)`
  Mutates the node's "value".
  `String`
  `name()`
  Returns the lowercase "name" of this ERC function class, some simple, short name which distinguishes this class from other ERC function classes you're using.
  `abstract boolean`
  `nodeEquals(GPNode node)`
  Implement this to do ERC-to-ERC comparisons.
  `int`
  `nodeHashCode()`
  Implement this to hash ERCs, along with other nodes, in such a way that two "equal" ERCs will usually hash to the same value.
  `void`
  `readNode(EvolutionState state, DataInput dataInput)`
  To successfully read from a DataOutput, you must override this to read your specific ERC data in.
  `GPNode`
  `readNode(DecodeReturn dret)`
  Reads the node symbol, advancing the DecodeReturn to the first character in the string beyond the node symbol, and returns a new, empty GPNode of the appropriate class representing that symbol, else null if the node symbol is not of the correct type for your GPNode class.
  `abstract void`
  `resetNode(EvolutionState state, int thread)`
  Remember to override this to randomize your ERC after it has been cloned.
  `String`
  `toString()`
  This defaults to simply name() + "[" + encode() + "]".
  `String`
  `toStringForHumans()`
  You might want to override this to return a special human-readable version of the erc value; otherwise this defaults to toString(); This should be something that resembles a LISP atom.
  `void`
  `writeNode(EvolutionState state, DataOutput dataOutput)`
  To successfully write to a DataOutput, you must override this to write your specific ERC data out.

  ### Methods inherited from class ec.gp.GPNode

  `atDepth, checkConstraints, clone, cloneReplacing, cloneReplacing, cloneReplacing, cloneReplacingAtomic, cloneReplacingAtomic, cloneReplacingNoSubclone, constraints, contains, defaultBase, depth, errorInfo, eval, iterator, iterator, iterator, lightClone, makeCTree, makeGraphvizSubtree, makeGraphvizTree, makeLatexTree, makeLispTree, makeLispTree, nodeEquivalentTo, nodeInPosition, nodeInPosition, numNodes, numNodes, parentType, pathLength, printNode, printNode, printNode, printNodeForHumans, printNodeForHumans, printRootedTree, printRootedTree, printRootedTree, printRootedTreeForHumans, printRootedTreeForHumans, readRootedTree, readRootedTree, replaceWith, rootedTreeEquals, rootedTreeHashCode, rootParent, setup, swapCompatibleWith, toStringForError, writeRootedTree`

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

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

- ## Constructor Details

  - ### ERC

    public ERC()

- ## Method Details

  - ### name

    public String name()
    Returns the lowercase "name" of this ERC function class, some simple, short name which distinguishes this class from other ERC function classes you're using. If you have more than one ERC function, you need to distinguish them here. By default the value is "ERC", which works fine for a single ERC function in the function set. Whatever the name is, it should generally only have letters, numbers, or hyphens or underscores in it. No whitespace or other characters.
    Overrides:
      `name` in class `GPNode`

  - ### expectedChildren

    public int expectedChildren()
    Usually ERCs don't have children, and this default implementation makes certain of it. But if you want to override this, you're welcome to.
    Overrides:
      `expectedChildren` in class `GPNode`

  - ### resetNode

    public abstract void resetNode(EvolutionState state, int thread)
    Remember to override this to randomize your ERC after it has been cloned. The prototype will not ever receive this method call.
    Overrides:
      `resetNode` in class `GPNode`

  - ### nodeEquals

    public abstract boolean nodeEquals(GPNode node)
    Implement this to do ERC-to-ERC comparisons.
    Overrides:
      `nodeEquals` in class `GPNode`

  - ### nodeHashCode

    public int nodeHashCode()
    Implement this to hash ERCs, along with other nodes, in such a way that two "equal" ERCs will usually hash to the same value. The default value, which may not be very good, is a combination of the class hash code and the hash code of the string returned by encode(). You might make a better hash value.
    Overrides:
      `nodeHashCode` in class `GPNode`

  - ### toStringForHumans

    public String toStringForHumans()
    You might want to override this to return a special human-readable version of the erc value; otherwise this defaults to toString(); This should be something that resembles a LISP atom. If a simple number or other object won't suffice, you might use something that begins with name() + [ + ... + ]
    Overrides:
      `toStringForHumans` in class `GPNode`

  - ### toString

    public String toString()
    This defaults to simply name() + "[" + encode() + "]". You probably shouldn't deviate from this.
    Specified by:
      `toString` in class `GPNode`

  - ### encode

    public abstract String encode()
    Encodes data from the ERC, using ec.util.Code.

  - ### decode

    public boolean decode(DecodeReturn dret)
    Decodes data into the ERC from dret. Return true if you sucessfully decoded, false if you didn't. Don't increment dret.pos's value beyond exactly what was needed to decode your ERC. If you fail to decode, you should make sure that the position and data in the dret are exactly as they were originally.

  - ### mutateERC

    public void mutateERC(EvolutionState state, int thread)
    Mutates the node's "value". This is called by mutating operators which specifically mutate the "value" of ERCs, as opposed to replacing them with whole new ERCs. The default form of this function simply calls resetNode(state,thread), but you might want to modify this to do a specialized form of mutation, applying gaussian noise for example.

  - ### writeNode

    public void writeNode(EvolutionState state, DataOutput dataOutput) throws IOException
    To successfully write to a DataOutput, you must override this to write your specific ERC data out. The default implementation issues a fatal error.
    Overrides:
      `writeNode` in class `GPNode`
    Throws:
      `IOException`

  - ### readNode

    public void readNode(EvolutionState state, DataInput dataInput) throws IOException
    To successfully read from a DataOutput, you must override this to read your specific ERC data in. The default implementation issues a fatal error.
    Overrides:
      `readNode` in class `GPNode`
    Throws:
      `IOException`

  - ### readNode

    public GPNode readNode(DecodeReturn dret)
    Description copied from class: `GPNode`
    Reads the node symbol, advancing the DecodeReturn to the first character in the string beyond the node symbol, and returns a new, empty GPNode of the appropriate class representing that symbol, else null if the node symbol is not of the correct type for your GPNode class. You may assume that initial whitespace has been eliminated. Generally should be case-SENSITIVE, unlike in Lisp. The default version usually works for "simple" function names, that is, not ERCs or other stuff where you have to encode the symbol.
    Overrides:
      `readNode` in class `GPNode`