Class GPNode
- All Implemented Interfaces:
GPNodeParent,Prototype,Setup,Serializable,Cloneable
- Direct Known Subclasses:
ADF,ADFArgument,ERC,Nonterminal
GPNodes contain a number of important items:
- A constraints object which defines the name of the node, its arity, and its type constraints. This object is shared with all GPNodes of the same function name/arity/returntype/childtypes.
- A parent. This is either another GPNode, or (if this node is the root) a GPTree.
- Zero or more children, which are GPNodes.
- An argument position in its parent.
In addition to serialization for checkpointing, GPNodes may read and write themselves to streams in three ways.
- writeNode(...,DataOutput)/readNode(...,DataInput) This method transmits or receives a GPNode in binary. It is the most efficient approach to sending GPNodes over networks, etc. The default versions of writeNode/readNode both generate errors. GPNode subclasses should override them to provide more functionality, particularly if you're planning on using ECJ in a distributed fashion. Both of these functions are called by GPNode's readRootedTree/writeRootedTree respectively, which handle the reading/printing of the trees as a whole.
- printNode(...,PrintWriter)/readNode(...,LineNumberReader) This approach transmits or receives a GPNode in text encoded such that the GPNode is largely readable by humans but can be read back in 100% by ECJ as well. To do this, these methods will typically encode numbers using the ec.util.Code class. These methods are mostly used to write out populations to files for inspection, slight modification, then reading back in later on. Both of these functions are called by GPNode's readRootedTree/writeRootedTree respectively, which handle the reading/printing of the trees as a whole. Notably readRootedNode will try to determine what kind of node is next, then call readNode on the prototype for that node to generate the node. printNode by default calls toString() and prints the result, though subclasses often override this to provide additional functionality (notably ERCs).
- printNodeForHumans(...,PrintWriter) This approach prints a GPNode in a fashion intended for human consumption only. printNodeForHumans by default calls toStringForHumans() (which by default calls toString()) and prints the result. printNodeForHumans is called by printRootedTreeForHumans, which handles printing of the entire GPNode tree.
Parameters
| base.nc String |
(name of the node constraints for the GPNode) |
Default Base
gp.node
- See Also:
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionintatDepth()Returns the depth at which I appear in the tree, which is a value >= 0.voidcheckConstraints(EvolutionState state, int tree, GPIndividual typicalIndividual, Parameter individualBase) You ought to override this method to check to make sure that the constraints are valid as best you can tell.clone()Deep-clones the tree rooted at this node, and returns the entire copied tree.final GPNodeDeep-clones the tree rooted at this node, and returns the entire copied tree.final GPNodecloneReplacing(GPNode[] newSubtrees, GPNode[] oldSubtrees) Deep-clones the tree rooted at this node, and returns the entire copied tree.final GPNodecloneReplacing(GPNode newSubtree, GPNode oldSubtree) Deep-clones the tree rooted at this node, and returns the entire copied tree.final GPNodecloneReplacingAtomic(GPNode[] newNodes, GPNode[] oldNodes) Clones a new subtree, but with each node in oldNodes[] respectively (which may or may not be in the subtree) replaced with the equivalent nodes in newNodes[] (and not clones).final GPNodecloneReplacingAtomic(GPNode newNode, GPNode oldNode) Clones a new subtree, but with the single node oldNode (which may or may not be in the subtree) replaced with a newNode (not a clone of newNode).final GPNodecloneReplacingNoSubclone(GPNode newSubtree, GPNode oldSubtree) Deep-clones the tree rooted at this node, and returns the entire copied tree.final GPNodeConstraintsconstraints(GPInitializer initializer) booleanReturns true if the subtree rooted at this node contains subnode.The default base for GPNodes -- defined even though GPNode is abstract so you don't have to in subclasses.intdepth()Returns the depth of the tree, which is a value >= 1.A convenience function for identifying a GPNode in an error messageabstract voideval(EvolutionState state, int thread, GPData input, ADFStack stack, GPIndividual individual, Problem problem) Evaluates the node with the given thread, state, individual, problem, and stack.intReturns the number of children this node expects to have.iterator()Returns an iterator over all the GPNodes in the subtree rooted by this GPNode.iterator(int nodesearch) Returns an iterator over all the GPNodes in the subtree rooted by this GPNode, filtered by the provided nodesearch option (either NODSEARCH_TERMINALS, NODESEARCH_NONTERMINALS, or NODESEARCH_ALL)Returns an iterator over all the GPNodes in the subtree rooted by this GPNode, filtered by the provided GPNodeGatherer.makeCTree(boolean parentMadeParens, boolean printTerminalsAsVariables, boolean useOperatorForm) Producess a String consisting of the tree in pseudo-C form, given that the parent already will wrap the expression in parentheses (or not).protected StringmakeGraphvizSubtree(String prefix) Produces the inner code for a graphviz subtree.Produces the Graphviz code for a Graphviz tree of the subtree rooted at this node.Produces the LaTeX code for a LaTeX tree of the subtree rooted at this node, using the epic and fancybox packages, as described in sections 10.5.2 (page 307) and 10.1.3 (page 278) of The LaTeX Companion, respectively.Produces a tree for human consumption in Lisp form similar to that generated by printTreeForHumans().name()Returns a Lisp-like atom for the node and any nodes of the same class.booleannodeEquals(GPNode node) Returns true if I am the "genetically" identical to this node, and our children arrays are the same length, though we may have different parents and children.booleannodeEquivalentTo(GPNode node) Returns true if I and the provided node are the same kind of node -- that is, we could have both been cloned() and reset() from the same prototype node.intReturns a hashcode usually associated with all nodes that are equal to you (using nodeEquals(...)).nodeInPosition(int p, int nodesearch) Returns the p'th node, constrained by nodesearch, in the subtree for which this GPNode is root.nodeInPosition(int p, GPNodeGatherer g) Returns the p'th node, constrained by nodesearch, in the subtree for which this GPNode is root.intnumNodes(int nodesearch) Returns the number of nodes, constrained by nodesearch, in the subtree for which this GPNode is root.intReturns the number of nodes, constrained by g.test(...) in the subtree for which this GPNode is root.final GPTypeparentType(GPInitializer initializer) Returns the argument type of the slot that I fit into in my parent.intpathLength(int nodesearch) Returns the path length of the tree, which is the sum of all paths from all nodes to the root.intprintNode(EvolutionState state, int log) Prints out a COMPUTER-readable and Lisp-like atom for the node, which is also suitable for readNode to read, and returns the number of bytes in the string that you sent to the log (use print(), not println()).intprintNode(EvolutionState state, int log, int verbosity) Prints out a COMPUTER-readable and Lisp-like atom for the node, which is also suitable for readNode to read, and returns the number of bytes in the string that you sent to the log (use print(), not println()).intprintNode(EvolutionState state, PrintWriter writer) Prints out a COMPUTER-readable and Lisp-like atom for the node, which is also suitable for readNode to read, and returns the number of bytes in the string that you sent to the log (use print(), not println()).intprintNodeForHumans(EvolutionState state, int log) Prints out a human-readable and Lisp-like atom for the node, and returns the number of bytes in the string that you sent to the log (use print(), not println()).intprintNodeForHumans(EvolutionState state, int log, int verbosity) Prints out a human-readable and Lisp-like atom for the node, and returns the number of bytes in the string that you sent to the log (use print(), not println()).intprintRootedTree(EvolutionState state, int log, int printbytes) Prints out the tree on a single line, with no ending \n, in a fashion that can be read in later by computer.intprintRootedTree(EvolutionState state, int log, int verbosity, int printbytes) Prints out the tree on a single line, with no ending \n, in a fashion that can be read in later by computer.intprintRootedTree(EvolutionState state, PrintWriter writer, int printbytes) Prints out the tree on a single line, with no ending \n, in a fashion that can be read in later by computer.intprintRootedTreeForHumans(EvolutionState state, int log, int tablevel, int printbytes) Prints out the tree in a readable Lisp-like multi-line fashion.intprintRootedTreeForHumans(EvolutionState state, int log, int verbosity, int tablevel, int printbytes) Prints out the tree in a readable Lisp-like multi-line fashion.voidreadNode(EvolutionState state, DataInput dataInput) Override this to read any additional node-specific information from dataInput besides: the number of arguments, the specific node class, the children, and the parent.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.static GPNodereadRootedTree(int linenumber, DecodeReturn dret, GPType expectedType, GPFunctionSet set, GPNodeParent parent, int argposition, EvolutionState state) Reads the node and its children from the form printed out by printRootedTree.static GPNodereadRootedTree(EvolutionState state, DataInput dataInput, GPType expectedType, GPFunctionSet set, GPNodeParent parent, int argposition) final voidreplaceWith(GPNode newNode) Replaces the node with another node in its position in the tree.voidresetNode(EvolutionState state, int thread) Starts a node in a new life immediately after it has been cloned.booleanrootedTreeEquals(GPNode node) Returns true if the two rooted trees are "genetically" equal, though they may have different parents.intReturns a hashcode associated with all the nodes in the tree.Returns the root ancestor of this node.voidsetup(EvolutionState state, Parameter base) Sets up a prototypical GPNode with those features all nodes of that prototype share, and nothing more.final booleanswapCompatibleWith(GPInitializer initializer, GPNode node) Returns true if I can swap into node's position.abstract StringtoString()Returns a Lisp-like atom for the node which can be read in again by computer.Returns a description of the node that can make it easy to identify in error messages (by default, at least its name and the tree it's found in).Returns a Lisp-like atom for the node which is intended for human consumption, and not to be read in again.voidwriteNode(EvolutionState state, DataOutput dataOutput) Override this to write any additional node-specific information to dataOutput besides: the number of arguments, the specific node class, the children, and the parent.voidwriteRootedTree(EvolutionState state, GPType expectedType, GPFunctionSet set, DataOutput dataOutput)
-
Field Details
-
P_NODE
- See Also:
-
P_NODECONSTRAINTS
- See Also:
-
GPNODEPRINTTAB
- See Also:
-
MAXPRINTBYTES
public static final int MAXPRINTBYTES- See Also:
-
NODESEARCH_ALL
public static final int NODESEARCH_ALL- See Also:
-
NODESEARCH_TERMINALS
public static final int NODESEARCH_TERMINALS- See Also:
-
NODESEARCH_NONTERMINALS
public static final int NODESEARCH_NONTERMINALS- See Also:
-
CHILDREN_UNKNOWN
public static final int CHILDREN_UNKNOWN- See Also:
-
parent
The GPNode's parent. 4 bytes. :-( But it really helps simplify breeding. -
children
-
argposition
public byte argpositionThe argument position of the child in its parent. This is a byte to save space (GPNode is the critical object space-wise) -- besides, how often do you have 256 children? You can change this to a short or int easily if you absolutely need to. It's possible to eliminate even this and have the child find itself in its parent, but that's an O(children[]) operation, and probably not inlinable, so I figure a byte is okay. -
constraints
public byte constraintsThe GPNode's constraints. This is a byte to save space -- how often do you have 256 different GPNodeConstraints? Well, I guess it's not infeasible. You can increase this to an int without much trouble. You typically shouldn't access the constraints through this variable -- use the constraints(state) method instead.
-
-
Constructor Details
-
GPNode
public GPNode()
-
-
Method Details
-
constraints
-
defaultBase
The default base for GPNodes -- defined even though GPNode is abstract so you don't have to in subclasses.- Specified by:
defaultBasein interfacePrototype
-
checkConstraints
public void checkConstraints(EvolutionState state, int tree, GPIndividual typicalIndividual, Parameter individualBase) You ought to override this method to check to make sure that the constraints are valid as best you can tell. Things you might check for:- children.length is correct
- certain arguments in constraints.childtypes are swap-compatible with each other
- constraints.returntype is swap-compatible with appropriate arguments in constraints.childtypes
-
expectedChildren
public int expectedChildren()Returns the number of children this node expects to have. This method is only called by the default implementation of checkConstraints(...), and by default it returns CHILDREN_UNKNOWN. You can override this method to return a value >= 0, which will be checked for in the default checkConstraints(...), or you can leave this method alone and override checkConstraints(...) to check for more complex constraints as you see fit. -
setup
Sets up a prototypical GPNode with those features all nodes of that prototype share, and nothing more. So no filled-in children, no argposition, no parent. Yet. This must be called after the GPTypes and GPNodeConstraints have been set up. Presently they're set up in GPInitializer, which gets called before this does, so we're safe. You should override this if you need to load some special features on a per-function basis. Note that base hangs off of a function set, so this method may get called for different instances in the same GPNode class if they're being set up as prototypes for different GPFunctionSets. If you absolutely need some global base, then you should use something hanging off of GPDefaults.base(). The ultimate caller of this method must guarantee that he will eventually call state.output.exitIfErrors(), so you can freely use state.output.error instead of state.output.fatal(), which will help a lot. -
parentType
Returns the argument type of the slot that I fit into in my parent. If I'm the root, returns the treetype of the GPTree. -
swapCompatibleWith
Returns true if I can swap into node's position. -
numNodes
Returns the number of nodes, constrained by g.test(...) in the subtree for which this GPNode is root. This might be sped up by caching the value. O(n). -
numNodes
public int numNodes(int nodesearch) Returns the number of nodes, constrained by nodesearch, in the subtree for which this GPNode is root. This might be sped up by cacheing the value somehow. O(n). -
depth
public int depth()Returns the depth of the tree, which is a value >= 1. O(n). -
pathLength
public int pathLength(int nodesearch) Returns the path length of the tree, which is the sum of all paths from all nodes to the root. O(n). -
atDepth
public int atDepth()Returns the depth at which I appear in the tree, which is a value >= 0. O(ln n) avg. -
iterator
Returns an iterator over all the GPNodes in the subtree rooted by this GPNode, filtered by the provided GPNodeGatherer. -
iterator
Returns an iterator over all the GPNodes in the subtree rooted by this GPNode, filtered by the provided nodesearch option (either NODSEARCH_TERMINALS, NODESEARCH_NONTERMINALS, or NODESEARCH_ALL) -
iterator
Returns an iterator over all the GPNodes in the subtree rooted by this GPNode. -
nodeInPosition
Returns the p'th node, constrained by nodesearch, in the subtree for which this GPNode is root. Use numNodes(nodesearch) to determine the total number. g.test(...) is used as the constraining predicate. p ranges from 0 to this number minus 1. O(n). The resultant node is returned in g. -
nodeInPosition
Returns the p'th node, constrained by nodesearch, in the subtree for which this GPNode is root. Use numNodes(nodesearch) to determine the total number. g.test(...) is used as the constraining predicate. p ranges from 0 to this number minus 1. O(n). The resultant node is returned in g. -
rootParent
Returns the root ancestor of this node. O(ln n) average case, O(n) worst case. -
contains
Returns true if the subtree rooted at this node contains subnode. O(n). -
resetNode
Starts a node in a new life immediately after it has been cloned. The default version of this function does nothing. The purpose of this function is to give ERCs a chance to set themselves to a new random value after they've been cloned from the prototype. You should not assume that the node is properly connected to other nodes in the tree at the point this method is called. -
errorInfo
A convenience function for identifying a GPNode in an error message -
lightClone
-
clone
Deep-clones the tree rooted at this node, and returns the entire copied tree. The result has everything set except for the root node's parent and argposition. This method is identical to cloneReplacing for historical reasons, except that it returns the object as an Object, not a GPNode. -
cloneReplacing
Deep-clones the tree rooted at this node, and returns the entire copied tree. The result has everything set except for the root node's parent and argposition. This method is identical to cloneReplacing for historical reasons, except that it returns the object as a GPNode, not an Object. -
cloneReplacing
Deep-clones the tree rooted at this node, and returns the entire copied tree. If the node oldSubtree is located somewhere in this tree, then its subtree is replaced with a deep-cloned copy of newSubtree. The result has everything set except for the root node's parent and argposition. -
cloneReplacingNoSubclone
Deep-clones the tree rooted at this node, and returns the entire copied tree. If the node oldSubtree is located somewhere in this tree, then its subtree is replaced with newSubtree (not a copy of newSubtree). The result has everything set except for the root node's parent and argposition. -
cloneReplacing
Deep-clones the tree rooted at this node, and returns the entire copied tree. If a node in oldSubtrees is located somewhere in this tree, then its subtree is replaced with a deep-cloned copy of the subtree rooted at its equivalent number in newSubtrees. The result has everything set except for the root node's parent and argposition. -
cloneReplacingAtomic
Clones a new subtree, but with the single node oldNode (which may or may not be in the subtree) replaced with a newNode (not a clone of newNode). These nodes should be type-compatible both in argument and return types, and should have the same number of arguments obviously. This function will not check for this, and if they are not the result is undefined. -
cloneReplacingAtomic
Clones a new subtree, but with each node in oldNodes[] respectively (which may or may not be in the subtree) replaced with the equivalent nodes in newNodes[] (and not clones). The length of oldNodes[] and newNodes[] should be the same of course. These nodes should be type-compatible both in argument and return types, and should have the same number of arguments obviously. This function will not check for this, and if they are not the result is undefined. -
replaceWith
Replaces the node with another node in its position in the tree. newNode should already have been cloned and ready to go. We presume that the other node is type-compatible and of the same arity (these things aren't checked). -
nodeEquivalentTo
Returns true if I and the provided node are the same kind of node -- that is, we could have both been cloned() and reset() from the same prototype node. The default form of this function returns true if I and the node have the same class, the same length children array, and the same constraints. You may wish to override this in certain circumstances. Here's an example of how nodeEquivalentTo(node) differs from nodeEquals(node): two ERCs, both of the same class, but one holding '1.23' and the other holding '2.45', which came from the same prototype node in the same function set. They should NOT be nodeEquals(...) but *should* be nodeEquivalent(...). -
nodeHashCode
public int nodeHashCode()Returns a hashcode usually associated with all nodes that are equal to you (using nodeEquals(...)). The default form of this method returns the hashcode of the node's class. ERCs in particular probably will want to override this method. -
rootedTreeHashCode
public int rootedTreeHashCode()Returns a hashcode associated with all the nodes in the tree. The default version adds the hash of the node plus its child trees, rotated one-off each time, which seems reasonable. -
nodeEquals
Returns true if I am the "genetically" identical to this node, and our children arrays are the same length, though we may have different parents and children. The default form of this method simply calls the much weaker nodeEquivalentTo(node). You may need to override this to perform exact comparisons, if you're an ERC, ADF, or ADM for example. Here's an example of how nodeEquivalentTo(node) differs from nodeEquals(node): two ERCs, both of the same class, but one holding '1.23' and the other holding '2.45', which came from the same prototype node in the same function set. They should NOT be nodeEquals(...) but *should* be nodeEquivalent(...). -
rootedTreeEquals
Returns true if the two rooted trees are "genetically" equal, though they may have different parents. O(n). -
printNodeForHumans
Prints out a human-readable and Lisp-like atom for the node, and returns the number of bytes in the string that you sent to the log (use print(), not println()). The default version gets the atom from toStringForHumans(). -
printNodeForHumans
Prints out a human-readable and Lisp-like atom for the node, and returns the number of bytes in the string that you sent to the log (use print(), not println()). The default version gets the atom from toStringForHumans(). -
printNode
Prints out a COMPUTER-readable and Lisp-like atom for the node, which is also suitable for readNode to read, and returns the number of bytes in the string that you sent to the log (use print(), not println()). The default version gets the atom from toString(). O(1). -
printNode
Prints out a COMPUTER-readable and Lisp-like atom for the node, which is also suitable for readNode to read, and returns the number of bytes in the string that you sent to the log (use print(), not println()). The default version gets the atom from toString(). O(1). -
printNode
Prints out a COMPUTER-readable and Lisp-like atom for the node, which is also suitable for readNode to read, and returns the number of bytes in the string that you sent to the log (use print(), not println()). The default version gets the atom from toString(). O(1). -
name
Returns a Lisp-like atom for the node and any nodes of the same class. This will almost always be identical to the result of toString() (and the default does exactly this), but for ERCs it'll be different: toString will include the encoded constant data, whereas name() will not include this information and will be the same for all ERCs of this type. If two nodes are nodeEquivalentTo(...) each other, then they will have the same name(). If two nodes are nodeEquals(...) each other, then they will have the same toString(). -
toString
Returns a Lisp-like atom for the node which can be read in again by computer. If you need to encode an integer or a float or whatever for some reason (perhaps if it's an ERC), you should use the ec.util.Code library. -
toStringForHumans
Returns a Lisp-like atom for the node which is intended for human consumption, and not to be read in again. The default version just calls toString(). -
toStringForError
Returns a description of the node that can make it easy to identify in error messages (by default, at least its name and the tree it's found in). It's okay if this is a reasonably expensive procedure -- it won't be called a lot. -
makeGraphvizTree
Produces the Graphviz code for a Graphviz tree of the subtree rooted at this node. For this to work, the output of toString() must not contain a double-quote. Note that this isn't particularly efficient and should only be used to generate occasional trees for display, not for storing individuals or sending them over networks. -
makeGraphvizSubtree
Produces the inner code for a graphviz subtree. Called from makeGraphvizTree(). Note that this isn't particularly efficient and should only be used to generate occasional trees for display, not for storing individuals or sending them over networks. -
makeLatexTree
Produces the LaTeX code for a LaTeX tree of the subtree rooted at this node, using the epic and fancybox packages, as described in sections 10.5.2 (page 307) and 10.1.3 (page 278) of The LaTeX Companion, respectively. For this to work, the output of toStringForHumans() must not contain any weird latex characters, notably { or } or % or \, unless you know what you're doing. See the documentation for ec.gp.GPTree for information on how to take this code snippet and insert it into your LaTeX file. Note that this isn't particularly efficient and should only be used to generate occasional trees for display, not for storing individuals or sending them over networks. -
makeCTree
public String makeCTree(boolean parentMadeParens, boolean printTerminalsAsVariables, boolean useOperatorForm) Producess a String consisting of the tree in pseudo-C form, given that the parent already will wrap the expression in parentheses (or not). In pseudo-C form, functions with one child are printed out as a(b), functions with more than two children are printed out as a(b, c, d, ...), and functions with exactly two children are either printed as a(b, c) or in operator form as (b a c) -- for example, (b * c). Whether or not to do this depends on the setting of useOperatorForm. Additionally, terminals will be printed out either in variable form -- a -- or in zero-argument function form -- a() -- depending on the setting of printTerminalsAsVariables. Note that this isn't particularly efficient and should only be used to generate occasional trees for display, not for storing individuals or sending them over networks. -
makeLispTree
Produces a tree for human consumption in Lisp form similar to that generated by printTreeForHumans(). Note that this isn't particularly efficient and should only be used to generate occasional trees for display, not for storing individuals or sending them over networks. -
makeLispTree
-
printRootedTree
Prints out the tree on a single line, with no ending \n, in a fashion that can be read in later by computer. O(n). You should call this method with printbytes == 0. -
printRootedTree
Prints out the tree on a single line, with no ending \n, in a fashion that can be read in later by computer. O(n). You should call this method with printbytes == 0. -
printRootedTree
Prints out the tree on a single line, with no ending \n, in a fashion that can be read in later by computer. O(n). Returns the number of bytes printed. You should call this method with printbytes == 0. -
printRootedTreeForHumans
Prints out the tree in a readable Lisp-like multi-line fashion. O(n). You should call this method with tablevel and printbytes == 0. No ending '\n' is printed. -
printRootedTreeForHumans
public int printRootedTreeForHumans(EvolutionState state, int log, int verbosity, int tablevel, int printbytes) Prints out the tree in a readable Lisp-like multi-line fashion. O(n). You should call this method with tablevel and printbytes == 0. No ending '\n' is printed. -
readNode
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. -
writeRootedTree
public void writeRootedTree(EvolutionState state, GPType expectedType, GPFunctionSet set, DataOutput dataOutput) throws IOException - Throws:
IOException
-
readRootedTree
public static GPNode readRootedTree(EvolutionState state, DataInput dataInput, GPType expectedType, GPFunctionSet set, GPNodeParent parent, int argposition) throws IOException - Throws:
IOException
-
writeNode
Override this to write any additional node-specific information to dataOutput besides: the number of arguments, the specific node class, the children, and the parent. The default version of this method does nothing.- Throws:
IOException
-
readNode
Override this to read any additional node-specific information from dataInput besides: the number of arguments, the specific node class, the children, and the parent. The default version of this method does nothing.- Throws:
IOException
-
readRootedTree
public static GPNode readRootedTree(int linenumber, DecodeReturn dret, GPType expectedType, GPFunctionSet set, GPNodeParent parent, int argposition, EvolutionState state) Reads the node and its children from the form printed out by printRootedTree. -
eval
public abstract void eval(EvolutionState state, int thread, GPData input, ADFStack stack, GPIndividual individual, Problem problem) Evaluates the node with the given thread, state, individual, problem, and stack. Your random number generator will be state.random[thread]. The node should, as appropriate, evaluate child nodes with these same items passed to eval(...).About input: input is special; it is how data is passed between parent and child nodes. If children "receive" data from their parent node when it evaluates them, they should receive this data stored in input. If (more likely) the parent "receives" results from its children, it should pass them an input object, which they'll fill out, then it should check this object for the returned value.
A tree is typically evaluated by dropping a GPData into the root. When the root returns, the resultant input should hold the return value.
In general, you should not be creating new GPDatas. If you think about it, in most conditions (excepting ADFs and ADMs) you can use and reuse input for most communications purposes between parents and children.
So, let's say that your GPNode function implements the boolean AND function, and expects its children to return return boolean values (as it does itself). You've implemented your GPData subclass to be, uh, BooleanData, which looks like
public class BooleanData extends GPData { public boolean result; public GPData copyTo(GPData gpd) { ((BooleanData)gpd).result = result; } }...so, you might implement your eval(...) function as follows:
public void eval(final EvolutionState state, final int thread, final GPData input, final ADFStack stack, final GPIndividual individual, final Problem problem { BooleanData dat = (BooleanData)input; boolean x; // evaluate the first child children[0].eval(state,thread,input,stack,individual,problem); // store away its result x = dat.result; // evaluate the second child children[1].eval(state,thread,input,stack,individual,problem); // return (in input) the result of the two ANDed dat.result = dat.result invalid input: '&'invalid input: '&' x; return; }
-