package jhpro.sregression;

import java.util.HashMap;

import org.jgap.gp.CommandGene;
import org.jgap.gp.GPFitnessFunction;
import org.jgap.gp.IGPProgram;
import org.jgap.gp.impl.ProgramChromosome;

/**
 * Fitness function for evaluating the produced fomulas, represented as GP
 * programs. The fitness is computed by calculating the result (Y) of the
 * function/formula for integer inputs (X's). The sum of the differences
 * between expected Y and actual Y is the fitness, the lower the better (as
 * it is a defect rate here).
 */
public class FormulaFitnessFunction
    extends GPFitnessFunction {
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	protected double evaluate(final IGPProgram a_subject) {
        return computeRawFitness(a_subject);
    }
    
    public double computeRawFitness(final IGPProgram ind) {
        double error = 0.0d;
        Object[] noargs = new Object[0];

        // 2010-03-01: Allow "penalty"
        // If we have requirements of size etc we will
        // penalty programs with smaller size.

        // normally we don't penalty anything
        double penalty = 0.0;

        ProgramChromosome chrom = ind.getChromosome(0);
        int numTerms =  chrom.numFunctions()  + chrom.numTerminals();

        // penalty if the terms are less than minNodes
        if (SymRegression.minNodes >= 0) {
            if (numTerms < SymRegression.minNodes) {
                penalty += Math.abs(numTerms - SymRegression.minNodes)*SymRegression.minNodesPenalty; 
            }
        }

        // added 2010-03-20
        // for alldifferent type of constraints
        // (Note: This could surely be done more efficient.)
        if (SymRegression.alldifferentVariables) {
            CommandGene[] functions = chrom.getFunctions();
            HashMap countVariables = new HashMap();
            for (int i = 0; i < functions.length; i++) {
                CommandGene func = functions[i];
                
                if (func != null) {
                    int arity = func.getArity(ind);
                    String funcStr = func.toString();
                    if (arity == 0) {
                        Class returnType = func.getReturnType();
                        int subReturnType = func.getSubReturnType();
                        
                        // It is a terminal
                        if (!countVariables.containsKey(funcStr)) {
                            countVariables.put(funcStr, 1);
                        } else {
                            // this variable is already seen so we
                            // punish this program
                            penalty += SymRegression.alldifferentVariablesPenalty;
                            countVariables.put(funcStr, countVariables.get(funcStr)+1);
                        }
                    }
                }
            }
        }

        // Evaluate function for the input numbers
        // ---------------------------------------
        int thisNumHits = 0;
        double[] results  =  new double[SymRegression.numRows];
        double[] errors   = new double[SymRegression.numRows];
        for (int j = 0; j < SymRegression.numRows; j++) {

            // Provide the variable X with the input number.
            // See method create(), declaration of "nodeSets" for where X is
            // defined.
            // -------------------------------------------------------------

            // set all the input variables
            int variableIndex = 0;
            for(int i = 0; i < SymRegression.numInputVariables+1; i++) {
                if (i != SymRegression.outputVariable) {
                    SymRegression.variables[variableIndex].set(SymRegression.data[i][j]);
                    variableIndex++;
                }
            }
            try {

                double result = ind.execute_double(0, noargs);
                results[j] = result;

                // Sum up the error between actual and expected result 
                // to get a defect rate.
                // ---------------------------------------------------

                // original:
                double res = SymRegression.data[SymRegression.outputVariable][j];
                double diff = Math.abs(result - res) + penalty;
                // diff = Math.sqrt(Math.abs(result*result - res*res)); 

                errors[j] = diff;
                
                // double r = data[outputVariable][j];


                if (SymRegression.hitsCriteria >= 0.0) {
                    // count the number of non hits
                    if (Double.isInfinite(result) || Double.isNaN(result) || Double.isInfinite(diff) || Double.isNaN(diff) || diff > SymRegression.hitsCriteria) {
                        error += 1.0 + penalty;
                    }
                } else {
                    error += diff;
                }

                if (diff <= SymRegression.hitsCriteria) {
                    thisNumHits++;
                }

                // If the error is too high, stop evaluation and return 
                // worst error possible.
                // ----------------------------------------------------
                if (Double.isInfinite(error) || Double.isNaN(error)) {
                    return Double.MAX_VALUE;
                }
            } catch (ArithmeticException ex) {
                // This should not happen, some illegal operation was 
                // executed.
                // ----------------------------------------------------
                System.out.println(ind);
                throw ex;
            }
        }

        // 2010-02-22: Calculate different types of errors
        double[] errs = SymRegression.calcAllErrors(error, errors);
        if (SymRegression.hitsCriteria < 0) {
            error = errs[0];
        }
        double totalError  = errs[1]; 
        double minError    = errs[2];
        double maxError    = errs[3];
        double meanError   = errs[4];
        double medianError = errs[5];

        double correlation = SymRegression.correlation(SymRegression.data[SymRegression.outputVariable], results, results.length);
        ApplicationData appData;
        if (SymRegression.showResults) {
            appData = new ApplicationData(error, correlation, thisNumHits, minError, maxError, meanError, medianError, totalError, results);
        } else {
            appData = new ApplicationData(error, correlation, thisNumHits, minError, maxError, meanError, medianError, totalError);
        }
        ind.setApplicationData(appData);

        if (SymRegression.scaleError > 0.0d) {

            return error*SymRegression.scaleError;

        } else {

            return error;

        }

    }
}
 

Ads help maintain this website.