org.jgap.gp.function.SubProgram.java Source code

Java tutorial

Introduction

Here is the source code for org.jgap.gp.function.SubProgram.java

Source

/*
 * This file is part of JGAP.
 *
 * JGAP offers a dual license model containing the LGPL as well as the MPL.
 *
 * For licensing information please see the file license.txt included with JGAP
 * or have a look at the top of class org.jgap.Chromosome which representatively
 * includes the JGAP license policy applicable for any file delivered with JGAP.
 */
package org.jgap.gp.function;

import org.apache.commons.lang.builder.*;
import org.jgap.*;
import org.jgap.gp.*;
import org.jgap.gp.impl.*;
import org.jgap.util.*;

/**
 * A connector for independent subprograms (subtrees). Each subtree except the
 * last one must have a memory- or stack-modifying command (such as push or
 * store), otherwise there is no connection between the subtrees (which would
 * be useless bloating).
 *
 * @author Klaus Meffert
 * @since 3.0
 */
public class SubProgram extends CommandGene implements ICloneable, IMutateable {
    /** String containing the CVS revision. Read out via reflection!*/
    private final static String CVS_REVISION = "$Revision: 1.18 $";

    /**
     * Number of subprograms. Redundant, because equal to m_types.length.
     */
    private int m_subtrees;

    /**
     * Minimum arity allowed during mutation of arity.
     */
    private int m_minArity;

    /**
     * Maximum arity allowed during mutation of arity.
     */
    private int m_maxArity;

    /**
     * Return types of the subprograms to excecute.
     */
    private Class[] m_types;

    private boolean m_mutateable;

    private int m_mode;

    public SubProgram(final GPConfiguration a_conf, Class[] a_types) throws InvalidConfigurationException {
        this(a_conf, a_types, 0, null);
    }

    /**
     * Collage constructor: Create a sub program that has a_arity elements
     * of the same type a_types.
     *
     * @param a_conf the configuration to use
     * @param a_arity number of children in the collage
     * @param a_types uniform type of all children
     * @throws org.jgap.InvalidConfigurationException
     *
     * @author Klaus Meffert
     * @since 3.4
     */
    public SubProgram(final GPConfiguration a_conf, int a_arity, Class a_types)
            throws InvalidConfigurationException {
        this(a_conf, a_arity, a_types, false);
    }

    /**
     * Collage constructor: Create a sub program that has a_arity elements
     * of the same type a_types.
     *
     * @param a_conf the configuration to use
     * @param a_arity number of children in the collage
     * @param a_types uniform type of all children
     * @param a_mutateable true: allow mutation of the sub program, i.e., the
     * number of children (=arity) may be varied automatically during evolution
     * @throws org.jgap.InvalidConfigurationException
     *
     * @author Klaus Meffert
     * @since 3.4
     */
    public SubProgram(final GPConfiguration a_conf, int a_arity, Class a_types, boolean a_mutateable)
            throws InvalidConfigurationException {
        this(a_conf, a_arity, a_types, a_arity, a_arity + 5, a_mutateable);
    }

    public SubProgram(final GPConfiguration a_conf, int a_arity, Class a_types, int a_minArity, int a_maxArity,
            boolean a_mutateable) throws InvalidConfigurationException {
        super(a_conf, a_arity, a_types, 0, null);
        if (a_arity < 1) {
            throw new IllegalArgumentException("Arity must be >= 1");
        }
        if (a_minArity > a_arity) {
            throw new IllegalArgumentException("Arity must not be smaller than" + " min. arity");
        }
        if (a_maxArity < a_arity) {
            throw new IllegalArgumentException("Arity must not be bigger than" + " max. arity");
        }
        m_mode = 2;
        m_types = new Class[a_arity];
        for (int i = 0; i < a_arity; i++) {
            m_types[i] = a_types;
        }
        m_subtrees = a_arity;
        m_mutateable = a_mutateable;
        m_minArity = a_minArity;
        m_maxArity = a_maxArity;
    }

    public SubProgram(final GPConfiguration a_conf, Class[] a_types, boolean a_mutateable)
            throws InvalidConfigurationException {
        this(a_conf, a_types, 0, null, a_mutateable);
    }

    public SubProgram(final GPConfiguration a_conf, Class[] a_types, int a_subReturnType, int[] a_subChildTypes)
            throws InvalidConfigurationException {
        this(a_conf, a_types, a_subReturnType, a_subChildTypes, false);
    }

    public SubProgram(final GPConfiguration a_conf, Class[] a_types, int a_subReturnType, int[] a_subChildTypes,
            boolean a_mutateable) throws InvalidConfigurationException {
        super(a_conf, a_types.length, a_types[a_types.length - 1], a_subReturnType, a_subChildTypes);
        if (a_types.length < 1) {
            throw new IllegalArgumentException("Number of subtrees must be >= 1");
        }
        m_mode = 1;
        m_minArity = a_types.length;
        m_maxArity = m_minArity + 5;
        m_types = a_types;
        m_subtrees = a_types.length;
        m_mutateable = a_mutateable;
    }

    public String toString() {
        String ret = "sub[";
        for (int i = 1; i < m_subtrees; i++) {
            ret += "&" + i + " --> ";
        }
        ret += "&" + m_subtrees + "]";
        return ret;
    }

    /**
     * @return textual name of this command
     *
     * @author Klaus Meffert
     * @since 3.2
     */
    public String getName() {
        return "Sub program";
    }

    public int execute_int(ProgramChromosome c, int n, Object[] args) {
        check(c);
        int value = -1;
        for (int i = 0; i < m_subtrees; i++) {
            if (i < m_subtrees - 1) {
                c.execute_void(n, i, args);
            } else {
                value = c.execute_int(n, i, args); /**@todo evaluate m_types*/
            }
            //      if (i < m_subtrees - 1) {
            //        ( (GPConfiguration) getConfiguration()).storeThruput(i,
            //            new Integer(value));
            //      }
        }
        return value;
    }

    public void execute_void(ProgramChromosome c, int n, Object[] args) {
        check(c);
        for (int i = 0; i < m_subtrees; i++) {
            c.execute_void(n, i, args); /**@todo evaluate m_types*/
        }
    }

    public long execute_long(ProgramChromosome c, int n, Object[] args) {
        check(c);
        long value = -1;
        for (int i = 0; i < m_subtrees; i++) {
            value = c.execute_long(n, i, args);
        }
        return value;
    }

    public float execute_float(ProgramChromosome c, int n, Object[] args) {
        check(c);
        float value = -1;
        for (int i = 0; i < m_subtrees; i++) {
            value = c.execute_float(n, i, args);
        }
        return value;
    }

    public double execute_double(ProgramChromosome c, int n, Object[] args) {
        check(c);
        double value = -1;
        for (int i = 0; i < m_subtrees; i++) {
            value = c.execute_double(n, i, args);
        }
        return value;
    }

    public Object execute_object(ProgramChromosome c, int n, Object[] args) {
        check(c);
        Object value = null;
        for (int i = 0; i < m_subtrees; i++) {
            value = c.execute_object(n, i, args);
        }
        return value;
    }

    public boolean isValid(ProgramChromosome a_program) {
        return true;
    }

    public Class getChildType(IGPProgram a_ind, int a_chromNum) {
        try {
            return m_types[a_chromNum];
        } catch (ArrayIndexOutOfBoundsException aex) {
            return null;
        }
    }

    /**
     * The compareTo-method.
     *
     * @param a_other the other object to compare
     * @return -1, 0, 1
     *
     * @author Klaus Meffert
     * @since 3.0
     */
    public int compareTo(Object a_other) {
        int result = super.compareTo(a_other);
        if (result != 0) {
            return result;
        }
        SubProgram other = (SubProgram) a_other;
        return new CompareToBuilder().append(m_types, other.m_types).toComparison();
    }

    /**
     * The equals-method.
     *
     * @param a_other the other object to compare
     * @return true if the objects are seen as equal
     *
     * @author Klaus Meffert
     * @since 3.0
     */
    public boolean equals(Object a_other) {
        try {
            SubProgram other = (SubProgram) a_other;
            return super.equals(a_other) && new EqualsBuilder().append(m_types, other.m_types).isEquals();
        } catch (ClassCastException cex) {
            return false;
        }
    }

    /**
     * @return deep clone of this instance
     *
     * @author Klaus Meffert
     * @since 3.2
     */
    public Object clone() {
        try {
            //      int[] subChildTypes = getSubChildTypes();
            //      if (subChildTypes != null) {
            //        subChildTypes = (int[]) subChildTypes.clone();
            //      }
            //      SubProgram result = new SubProgram(getGPConfiguration(), m_types,
            //          getSubReturnType(), subChildTypes, m_mutateable);
            //      result.m_subtrees = m_subtrees;
            //      result.m_types = (Class[]) m_types.clone();
            //      return result;
            SubProgram result;
            if (m_mode == 1) {
                // First way of construction.
                // --------------------------
                Class[] types = new Class[m_subtrees];
                for (int i = 0; i < m_subtrees; i++) {
                    types[i] = m_types[m_types.length - 1];
                }
                int[] subChildTypes = getSubChildTypes();
                if (subChildTypes != null) {
                    subChildTypes = (int[]) subChildTypes.clone();
                }
                result = new SubProgram(getGPConfiguration(), types, getSubReturnType(), subChildTypes,
                        m_mutateable);
            } else {
                // Second way of construction.
                // ---------------------------
                result = new SubProgram(getGPConfiguration(), m_subtrees, m_types[0], m_minArity, m_maxArity,
                        m_mutateable);
            }
            return result;
        } catch (Throwable t) {
            throw new CloneException(t);
        }
    }

    public CommandGene applyMutation(int index, double a_percentage) throws InvalidConfigurationException {
        if (!m_mutateable) {
            return this;
        }
        org.jgap.RandomGenerator randomGen = getGPConfiguration().getRandomGenerator();
        double random = randomGen.nextDouble();
        if (random < a_percentage) {
            return applyMutation();
        }
        return this;
    }

    /**@todo use dynamizeArity instead!*/

    /**
     * @return mutated command gene
     * @throws InvalidConfigurationException
     */
    public CommandGene applyMutation() throws InvalidConfigurationException {
        int size = getGPConfiguration().getRandomGenerator().nextInt(m_maxArity + 1 - m_minArity) + m_minArity;
        if (m_types.length == size) {
            return this;
        }
        SubProgram result;
        if (m_mode == 1) {
            // First way of construction.
            // --------------------------
            Class[] types = new Class[size];
            for (int i = 0; i < size; i++) {
                types[i] = m_types[m_types.length - 1];
            }
            int[] subChildTypes = getSubChildTypes();
            if (subChildTypes != null) {
                subChildTypes = (int[]) subChildTypes.clone();
            }
            result = new SubProgram(getGPConfiguration(), types, getSubReturnType(), subChildTypes, m_mutateable);
        } else {
            // Second way of construction.
            // ---------------------------
            result = new SubProgram(getGPConfiguration(), size, m_types[0], m_minArity, m_maxArity, m_mutateable);
        }
        return result;
    }
    /**
     * Adaptation of the arity so that it represents a value within the interval
     * [m_arityMin, m_arityMax].
     *
     * @author Klaus Meffert
     * @since 3.4
     */
    //  public void dynamizeArity() {
    //    int size = getGPConfiguration().getRandomGenerator().nextInt(m_maxArity + 1 -
    //        m_minArity) + m_minArity;
    //    setArity(size);
    //    Class atype = m_types[0];
    //    m_types = new Class[size];
    //    for (int i = 0; i < size; i++) {
    //      m_types[i] = atype;
    //    }
    //    m_subtrees = size;
    //  }
}