public class Terminal extends ERC
ECJ implements Push's s-expressions as trees of nonterminals and terminals. The nonterminals are all dummy instances of the Nonterminal class. Terminals are all instances of the Terminal class.
The nonterminals and terminals aren't actually evaluated. Instead, the tree is printed out as a lisp s-expression and sent to the Push interpreter.
Terminals are implemented as ERCs which hold the actual Push instruction or atom as a string ('value'). There are four kinds of instructions at present:
You specify your instructions like this:
push.op.size = 7
push.op.0 = float.erc
push.op.1 = float.+
# This is a custom instruction
push.op.2 = float.print
push.op.2.func = ec.gp.push.example.MyPushInstruction
push.op.3 = float.%
push.op.4 = float.-
push.op.5 = float.dup
push.op.6 = float.swap
For the (at present) two kinds of ERCs, you can specify a minimum
and a maximum value. Here are the defaults:
push.op.float.min = -10
push.op.float.max = 10
push.op.int.min = -10
push.op.int.max = 10
The full list of Psh instructions is:
integer.+
integer.-
integer./
integer.\%
integer.*
integer.pow
integer.log
integer.=
integer.>
integer.*lt;
integer.min
integer.max
integer.abs
integer.neg
integer.ln
integer.fromfloat
integer.fromboolean
integer.rand
float.+
float.-
float./
float.\%
float.*
float.pow
float.log
float.=
float.>
float.<
float.min
float.max
float.sin
float.cos
float.tan
float.exp
float.abs
float.neg
float.ln
float.frominteger
float.fromboolean
float.rand
boolean.=
boolean.not
boolean.and
boolean.or
boolean.xor
boolean.frominteger
boolean.fromfloat
boolean.rand
true
false
code.quote
code.fromboolean
code.frominteger
code.fromfloat
code.noop
code.do*times
code.do*count
code.do*range
code.=
code.if
code.rand
exec.k
exec.s
exec.y
exec.noop
exec.do*times
exec.do*count
exec.do*range
exec.=
exec.if
exec.rand
input.index
input.inall
input.inallrev
input.stackdepth
frame.push
frame.pop
Parameters
base.op.size int >= 1 |
(Number of instructions in Push's internal "instruction set") |
base.op.i String |
(Name of instruction i) |
base.op.i.func classname, inherits and != ec.gp.push.PushInstruction |
(PushInstruction corresponding to instruction i, if it is a custom instruction) |
base.op.float.min float |
(Minimum value for a Push floating-point ERC) |
base.op.float.max float |
(Maximum value for a Push floating-point ERC) |
base.op.int.min int |
(Minimum value for a Push integer ERC) |
base.op.int.max int |
(Maximum value for a Push integer ERC) |
Default Base
gp.push
Modifier and Type | Field and Description |
---|---|
PushInstruction[] |
customInstructions
A list of custom PushInstructions I can be set to.
|
static java.lang.String[] |
ERC_NAMES |
static int |
FLOAT_ERC |
int[] |
indices
For each PushInstruction, a pointer into instructions which gives the name of that instruction.
|
java.lang.String[] |
instructions
Names of all the Push instructions I can be set to.
|
static int |
INTEGER_ERC |
static double |
maxFloatERC |
static int |
maxIntegerERC |
static double |
minFloatERC |
static int |
minIntegerERC |
static java.lang.String |
P_FLOAT |
static java.lang.String |
P_FUNC |
static java.lang.String |
P_INSTRUCTION |
static java.lang.String |
P_INTEGER |
static java.lang.String |
P_MAX |
static java.lang.String |
P_MIN |
static java.lang.String |
P_NUM_INSTRUCTIONS |
argposition, children, CHILDREN_UNKNOWN, constraints, GPNODEPRINTTAB, MAXPRINTBYTES, NODESEARCH_ALL, NODESEARCH_NONTERMINALS, NODESEARCH_TERMINALS, P_NODE, P_NODECONSTRAINTS, parent
Constructor and Description |
---|
Terminal() |
Modifier and Type | Method and Description |
---|---|
boolean |
decode(DecodeReturn dret)
Decodes data into the ERC from dret.
|
Parameter |
defaultBase()
The default base for GPNodes -- defined even though
GPNode is abstract so you don't have to in subclasses.
|
java.lang.String |
encode()
Encodes data from the ERC, using ec.util.Code.
|
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.
|
int |
expectedChildren()
Usually ERCs don't have children, and this default implementation makes certain of it.
|
java.lang.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.
|
boolean |
nodeEquals(GPNode other)
Implement this to do ERC-to-ERC comparisons.
|
void |
resetNode(EvolutionState state,
int thread)
Remember to override this to randomize your ERC after it has been cloned.
|
void |
setup(EvolutionState state,
Parameter base)
Sets up a prototypical GPNode with those features all nodes of that
prototype share, and nothing more.
|
java.lang.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.
|
mutateERC, nodeHashCode, readNode, readNode, toString, writeNode
atDepth, checkConstraints, clone, cloneReplacing, cloneReplacing, cloneReplacing, cloneReplacingAtomic, cloneReplacingAtomic, cloneReplacingNoSubclone, constraints, contains, depth, errorInfo, 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, swapCompatibleWith, toStringForError, writeRootedTree
public static final java.lang.String P_INSTRUCTION
public static final java.lang.String P_NUM_INSTRUCTIONS
public static final java.lang.String P_FUNC
public static final java.lang.String P_FLOAT
public static final java.lang.String P_INTEGER
public static final java.lang.String P_MIN
public static final java.lang.String P_MAX
public static final int FLOAT_ERC
public static final int INTEGER_ERC
public static final java.lang.String[] ERC_NAMES
public static double minFloatERC
public static double maxFloatERC
public static int minIntegerERC
public static int maxIntegerERC
public java.lang.String[] instructions
public PushInstruction[] customInstructions
public int[] indices
public java.lang.String name()
ERC
public int expectedChildren()
ERC
expectedChildren
in class ERC
public java.lang.String toStringForHumans()
ERC
toStringForHumans
in class ERC
public Parameter defaultBase()
GPNode
defaultBase
in interface Prototype
defaultBase
in class GPNode
public void setup(EvolutionState state, Parameter base)
GPNode
public boolean nodeEquals(GPNode other)
ERC
nodeEquals
in class ERC
public java.lang.String encode()
ERC
public boolean decode(DecodeReturn dret)
ERC
public void resetNode(EvolutionState state, int thread)
ERC
public void eval(EvolutionState state, int thread, GPData input, ADFStack stack, GPIndividual individual, Problem problem)
GPNode
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 && x;
return;
}