All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ec.gp.push.Terminal Maven / Gradle / Ivy

Go to download

ECJ, A Java-based Evolutionary Computation Research System. ECJ is a research EC system written in Java. It was designed to be highly flexible, with nearly all classes (and all of their settings) dynamically determined at runtime by a user-provided parameter file. All structures in the system are arranged to be easily modifiable. Even so, the system was designed with an eye toward efficiency. ECJ is developed at George Mason University's ECLab Evolutionary Computation Laboratory. The software has nothing to do with its initials' namesake, Evolutionary Computation Journal. ECJ's sister project is MASON, a multi-agent simulation system which dovetails with ECJ nicely.

The newest version!
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:

  1. Built-in Push instructions like float.* or integer.swap
  2. Floating-point ERCs (defined by "float.erc")
  3. Integer ERCs (defined by "integer.erc")
  4. 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 maxFloatERC) // uh oh state.output.fatal("" + ERC_NAMES[FLOAT_ERC] + " min value is greater than max value.\nMin: " + minFloatERC +"\nMax: " + maxFloatERC); b = base.push(P_INTEGER).push(P_MIN); d = PushDefaults.base().push(P_INTEGER).push(P_MIN); // load integer ERC bounds if (!state.parameters.exists(b, d)) state.output.warning("No " + ERC_NAMES[INTEGER_ERC] + " min value provided, using " + minIntegerERC, b, d); else { double min = state.parameters.getDoubleWithDefault(b, d, NaN); if ((min != min) || (min != (int)min)) // it's NaN or invalid state.output.fatal("Malformed " + ERC_NAMES[INTEGER_ERC] + " min value", b, d); minIntegerERC = (int)min; } b = base.push(P_INTEGER).push(P_MAX); d = PushDefaults.base().push(P_INTEGER).push(P_MAX); if (!state.parameters.exists(b, d)) state.output.warning("No " + ERC_NAMES[INTEGER_ERC] + " max value provided, using " + maxIntegerERC, b, d); else { double max = state.parameters.getDoubleWithDefault(b, d, NaN); if ((max != max) || (max != (int)max)) // it's NaN or invalid state.output.fatal("Malformed " + ERC_NAMES[INTEGER_ERC] + " max value", b, d); else maxIntegerERC = (int)max; } if (minIntegerERC > maxIntegerERC) // uh oh state.output.fatal("" + ERC_NAMES[INTEGER_ERC] + " min value is greater than max value.\nMin: " + minIntegerERC +"\nMax: " + maxIntegerERC); } public boolean nodeEquals(GPNode other) { if (other == null) return false; if (!(other instanceof Terminal)) return false; Terminal o = (Terminal) other; return (o.value == value); } public String encode() { return Code.encode(value); } public boolean decode(final DecodeReturn dret) { Code.decode(dret); if (dret.type == DecodeReturn.T_STRING) { value = dret.s; // verify for(int i = 0; i < instructions.length; i++) if (instructions[i].equals(value)) return true; } // otherwise, uh oh return false; } public void resetNode(EvolutionState state, int thread) { int i = state.random[thread].nextInt(instructions.length); if (instructions[i].endsWith("erc")) // it's an erc { // we'll assume we don't have a lot of ercs for(int j = 0 ; j < ERC_NAMES.length; j++) { if (instructions[i].equals(ERC_NAMES[j])) { switch(j) { case FLOAT_ERC: value = "" + (state.random[thread].nextDouble(true, true) * (maxFloatERC - minFloatERC) + minFloatERC); break; case INTEGER_ERC: value = "" + (state.random[thread].nextInt(maxIntegerERC - minIntegerERC + 1) + minIntegerERC); break; default: state.output.fatal("The following PUSH ERC is unknown: " + instructions[i]); break; } break; // break from for-loop } } } else // it's an instruction { value = instructions[i]; } } public void eval(final EvolutionState state, final int thread, final GPData input, final ADFStack stack, final GPIndividual individual, final Problem problem) { // do nothing } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy