/home/ooechs/Ecj2Java/src/ac/essex/ooechs/ecj/ecj2java/nodes/ParseableERC.java
|
package ac.essex.ooechs.ecj.ecj2java.nodes;
import ec.gp.*;
import ec.EvolutionState;
import ec.Problem;
import ec.util.Code;
import ec.util.DecodeReturn;
import java.io.DataInput;
import java.io.IOException;
import java.io.DataOutput;
// If you have downloaded ECJ2Java, you'll need to change this
// to your own DoubleData class that you use. There is an example
// of such a class in ac.essex.ooechs.ecj.ecj2java.example.data
//import ac.essex.ooechs.ecj.commons.data.DoubleData;
import ac.essex.ooechs.ecj.ecj2java.example.data.DoubleData;
/**
* <p>
* ParseableERC is an adapter class that serves two functions:
* <ol>
* <li>It allows ECJ2Java to write the ERC into pure java</li>
* <li>It makes ERCs easier to code</li>
* </ol>
* </p>
*
* <p>
* It adapts a number of unpleasant methods in the ERC class that don't
* need to be altered often (if at all).
* </p>
*
* <p>
* It implements the functionality required by ParseableNode which allows
* the node to be converted into pure java.
* </p>
*
* <p>
* Implementation is easy - just take your existing ERC and extend
* ParseableERC instead of ERC. The only required methods are setNumber()
* and name().
* </p>
*
* <p/>
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version,
* provided that any use properly credits the author.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details at http://www.gnu.org
* </p>
*
* @author Olly Oechsle, University of Essex, Date: 06-Sep-2006
* @version 1.0
*/
public abstract class ParseableERC extends ERC implements ParseableNode {
protected int type = ParseableNode.ERC;
protected double value;
/**
* Set the value of the ERC here
*/
public abstract double setNumber(final EvolutionState state, final int thread);
/**
* Mutates the node's "value". This is called by mutating operators
* which specifically <i>mutate</i> 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.
*/
public void mutateERC(final EvolutionState state, final int thread) {
// move the value within +- 25% of its original position
value *= 1 + ((Math.random() * 0.5) - 0.25);
}
/**
* The name of the class that ECK uses.
*/
public abstract String name();
public ParseableNode getChild(int index) {
return (ParseableNode) children[index];
}
public int getType() {
return type;
}
public String getValue() {
return String.valueOf(value);
}
public void setValue(double value) {
this.value = value;
}
public int countChildren() { return 0; }
String variableName;
/**
* When the java writer uses this node, it may use a variable name to describe it.
*/
public String getVariableName() {
return variableName;
}
/**
* Attaches a variable name to this node, used by JavaWriter
*/
public void setVariableName(String name) {
this.variableName = name;
}
public String getJavaCode() {
switch (getObjectType()) {
case DOUBLE:
return String.valueOf(value);
case BOOLEAN:
return value == 1 ? "true" : "false";
case INT:
return String.valueOf((int) value);
default:
// should not get here
System.err.println("Missing type in ParseableERC, getJavaCode: " + getObjectType() + ", " + getClass());
return getValue();
}
}
public String getLineComment() {
return null;
}
public void setType(int type) {
this.type = type;
}
// ECJ ERC stuff below
// This is all pretty much boilerplate code and you'll rarely need to look at it,
// much less repeat it in every ERC class you write!
public void resetNode(final EvolutionState state, final int thread) {
value = setNumber(state, thread);
}
public boolean nodeEquals(final GPNode node) {
// check first to see if we're the same kind of ERC --
// won't work for subclasses; in that case you'll need
// to change this to isAssignableTo(...)
if (this.getClass() != node.getClass()) return false;
// now check to see if the ERCs hold the same value
return (((ParseableERC) node).value == value);
}
public void readNode(final EvolutionState state, final DataInput dataInput) throws IOException {
value = dataInput.readDouble();
}
public void writeNode(final EvolutionState state, final DataOutput dataOutput) throws IOException {
dataOutput.writeDouble(value);
}
public String encode() {
return Code.encode(value);
}
public boolean decode(DecodeReturn dret) {
// store the position and the string in case they
// get modified by Code.java
int pos = dret.pos;
String data = dret.data;
// decode
Code.decode(dret);
if (dret.type != DecodeReturn.T_DOUBLE) // uh oh!
{
// restore the position and the string; it was an error
dret.data = data;
dret.pos = pos;
return false;
}
// store the data
value = dret.d;
return true;
}
public String toStringForHumans() {
return "" + value;
}
public void eval(final EvolutionState state, final int thread, final GPData input, final ADFStack stack, final GPIndividual individual, final Problem problem) {
DoubleData rd = ((DoubleData) (input));
rd.x = value;
}
public int nodeHashCode() {
// a reasonable hash code
return this.getClass().hashCode() + Float.floatToIntBits((float) value);
}
}