/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); 
    } 
 
}