ec.gp.push.Terminal Maven / Gradle / Ivy
Show all versions of ecj Show documentation
package ec.gp.push;
import ec.gp.*;
import ec.*;
import ec.util.*;
/*
* Terminal.java
*
* Created: Fri Feb 15 23:00:04 EST 2013
* By: Sean Luke
*/
/**
Terminal is the leaf node in Push trees and is used to represent Push
instructions of all types.
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:
- Built-in Push instructions like float.* or integer.swap
- Floating-point ERCs (defined by "float.erc")
- Integer ERCs (defined by "integer.erc")
- Custom Push instructions
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
*/
public class Terminal extends ERC
{
public static final String P_INSTRUCTION = "in";
public static final String P_NUM_INSTRUCTIONS = "size";
public static final String P_FUNC = "func";
public static final String P_FLOAT = "erc.float";
public static final String P_INTEGER = "erc.int";
public static final String P_MIN = "min";
public static final String P_MAX = "max";
public static final int FLOAT_ERC = 0; // ultimately this needs to be a special kind of class
public static final int INTEGER_ERC = 1; // ultimately this needs to be a special kind of class
public static final String[] ERC_NAMES = { "float.erc", "integer.erc" };
public static double minFloatERC = -10.0; // inclusive
public static double maxFloatERC = 10.0; // inclusive
public static int minIntegerERC = -10;
public static int maxIntegerERC = 10;
/** Names of all the Push instructions I can be set to. This includes names for custom PushInstructions. */
public String[] instructions;
/** A list of custom PushInstructions I can be set to. */
public PushInstruction[] customInstructions;
/** For each PushInstruction, a pointer into instructions which gives the name of that instruction.
Note that some instructions in instructions are built-in Push instructions and will have nothing
pointing to them. */
public int[] indices; // point to locations in instructions
/** The current name of the Push Terminal I am set to. */
String value;
public String name() { return "IN"; }
public int expectedChildren() { return 0; }
public String toStringForHumans() { return value; }
public Parameter defaultBase()
{
return PushDefaults.base().push(P_INSTRUCTION);
}
public void setup(final EvolutionState state, final Parameter base)
{
super.setup(state, base);
Parameter def = defaultBase();
// Load my standard instructions
int len = state.parameters.getInt(base.push(P_INSTRUCTION).push(P_NUM_INSTRUCTIONS), def.push(P_NUM_INSTRUCTIONS), 1);
if (len < 1)
state.output.fatal("Number of instructions must be >= 1", base.push(P_INSTRUCTION).push(P_NUM_INSTRUCTIONS), def.push(P_NUM_INSTRUCTIONS));
instructions = new String[len];
PushInstruction[] insts = new PushInstruction[len];
for(int i =0; i < len; i++)
{
instructions[i] = state.parameters.getString(base.push(P_INSTRUCTION).push("" + i), def.push("" + i));
if (instructions[i] == null)
state.output.fatal("Terminal number " + i + " is missing.", base.push(P_INSTRUCTION).push("" + i), def.push("" + i));
// load Instruction if there is one
Parameter bb = base.push(P_INSTRUCTION).push("" + i).push(P_FUNC);
Parameter dd = def.push("" + i).push(P_FUNC);
if (state.parameters.exists(bb, dd)) // got one
{
String s = state.parameters.getString(bb, dd);
state.output.message("Adding Instruction " + instructions[i] + " --> " + s);
PushInstruction inst = (PushInstruction)(state.parameters.getInstanceForParameter(bb, dd, PushInstruction.class));
if (inst == null) // uh oh
state.output.fatal("Terminal number " + i + ", named " + instructions[i] + ", has an invalid function class: " + s);
// load that sucker
insts[i] = inst;
}
}
// compress instruction list
int count = 0;
for(int i =0 ;i < len; i++)
if (insts[i] != null)
count++;
customInstructions = new PushInstruction[count];
indices = new int[count];
count = 0;
for(int i=0; i