/*
 This is a proprietary part of jHepWork package.
 License: the Creative Commons Attribution-Share Alike License; either version 3.0 of the License, 
 or any later version.
 http://creativecommons.org/licenses/by-sa/3.0/
 

Permission to use, copy and modify this software and its documentation for NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgment to the author, Dr Sergei Chekanov appears in all copies and associated documentation or publications.

Redistributions of the source code, or parts of the source codes, must retain the copyright notice, this list of conditions and the following disclaimer (all at the top of each source code) and requires the written permission of Sergei Chekanov

Redistribution in binary form of all or parts of a class must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution and requires the written permission of Sergei Chekanov

Details about license agreement or commercial use are: http://jwork.org/jhepwork/license.php */ package jhpro.sregression; import jhplot.gui.*; /* * * Symbolic Regression. * Perform symboBased on in JGAP. * * This program is based on the JGAP example MathProblem.java * (by Klaus Meffert) with some more generality. * * This program was written by Hakan Kjellerstrand and S.Chekanov * Also, see my JGAP page http://www.hakank.org/jgap/ */ import java.util.*; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import org.apache.commons.lang.ArrayUtils; import org.jgap.*; import org.jgap.gp.*; import org.jgap.gp.function.*; import org.jgap.gp.impl.*; import org.jgap.gp.terminal.*; import org.jgap.symbolic.*; import org.jgap.util.*; import jhplot.gui.HelpBrowser; import jhplot.PND; /** * Perform symbolic regression. It reads a configuration file and makes * evaluation using JGAP. * * @author S.Chekanov * */ public class SymRegression { // private transient Logger LOGGER = // Logger.getLogger(SymbolicRegression.class); /* * protected variables which may be changed by configuration file */ // number of variables to use (output variable is excluded) protected static int numInputVariables; // the variables to use (of size numInputVariables) protected static Variable[] variables; // variable name protected static String[] variableNames; // index of the output variable protected static Integer outputVariable; // default last protected int[] ignoreVariables; // TODO // constants protected static ArrayList constants = new ArrayList(); // size of data protected static int numRows; // the data (as Double) // Note: the last row is the output variable per default protected static double[][] data; // If we have found a perfect solution. protected boolean foundPerfect = false; // standard GP parameters protected int minInitDepth = 2; protected int maxInitDepth = 4; protected int populationSize = 1000; protected int maxCrossoverDepth = 8; protected int programCreationMaxTries = 5; protected int numEvolutions = 1800; protected static boolean verboseOutput = true; protected static int maxNodes = 21; protected double functionProb = 0.9d; protected float reproductionProb = 0.1f; // float protected float mutationProb = 0.1f; // float protected float crossoverProb = 0.9f; // float protected float dynamizeArityProb = 0.08f; // float protected double newChromsPercent = 0.3d; protected int tournamentSelectorSize = 0; protected boolean noCommandGeneCloning = true; protected boolean strictProgramCreation = false; protected boolean useProgramCache = true; // lower/upper ranges for the Terminal protected static double lowerRange = -10.0d; protected static double upperRange = -10.0d; // Should the terminal be a whole numbers (integers as double) or not? protected static boolean terminalWholeNumbers = true; protected String returnType = "DoubleClass"; // not used yet protected String presentation = ""; // Using ADF protected static int adfArity = 0; protected static String adfType = "double"; protected static boolean useADF = false; // list of functions (as strings) protected static String[] functions = { "Multiply", "Divide", "Add", "Subtract" }; // list of functions for ADF protected static String[] adfFunctions = { "Multiply3", "Divide", "Add3", "Subtract" }; // if the values are too small we may want to scale // the error protected static double scaleError = -1.0d; // timing protected long startTime; protected long endTime; protected String bestSolution = ""; // if >= 0.0d, then stop if the fitness is below or equal // this value protected double stopCriteriaFitness = -1.0d; // shows the whole population (sorted by fitness) // in all generations. Mainly for debugging purposes. protected boolean showPopulation = false; // show similiar solutions with the same fitness // as the overall best program protected boolean showSimiliar = false; // 2010-02-27 // how to sort the similiar solutions. // Valid options: // - occurrence (descending, default) // - length (asccending) protected String similiarSortMethod = "occurrence"; // shows progression as generation number protected boolean showProgression = false; // show results for all generations protected boolean showAllGenerations = false; // show all the results for the fittest program protected static boolean showResults = false; protected int resultPrecision = 5; // take a sample of the data set (if > 0.0) protected double samplePCT = 0.0d; // hits criteria: if >= 0.0d then collect and show // number of fitness values (errors) that is equal // or below this value. protected static double hitsCriteria = -1.0d; // withheld a percentage for validation of the // of the fittest program protected double validationPCT = 0.0d; protected double[][] validationSet; // for testing some values protected double[][] testData; // for ModuloReplaceD: replacement for 0 protected static int modReplace = 0; // 2010-02-27 // make time series based on a single sequence protected boolean makeTimeSeries = false; // 2010-02-27 // make time series based on a single sequence // and adding the index of the instance protected boolean makeTimeSeriesWithIndex = false; private GPProblem problem; private GPGenotype gp; private GPConfiguration config; private ArrayList configstring; // make a sequence of (ix, number)static based on a single sequence // protected boolean makeIndexSeq = false; // 2010-02-22 // Error method. // Valid options: // totalError (default) // minError // meanError // medianError // maxError // // Note that hitsCriteria > -1 overrides errorMethod // protected static String errorMethod = "totalError"; // 2010-02-26: If we don't want to have any Terminals protected static boolean noTerminals = false; // 2010-03-01: Penalty if the number of nodes in a program // is less than minimum required. protected static int minNodes = -1; // The penalty for less nodes (may be application dependent) protected static double minNodesPenalty = 0.0d; // 2010-03-02: Penalty if the variables are not different protected static boolean alldifferentVariables = false; protected static double alldifferentVariablesPenalty = 0.0d; private ArrayList theData; private ArrayList theValidationSet; // contains user defined testdata private ArrayList theTestData; /** * Initialise symbolic regression calculation without any configuration. */ public SymRegression() { configstring = new ArrayList(); theData = new ArrayList(); theValidationSet = new ArrayList(); theTestData = new ArrayList(); } /** * Initialize symbolic regression from an input configuration file. The file * must contain data appended after configuration. settings. The file can be * URL location. Use the method "run". * * @param inputfile * input configuration file. If the name starts from URL (http: * or ftp:), we read this file from URL. */ public SymRegression(String inputfile) { configstring = new ArrayList(); theData = new ArrayList(); theValidationSet = new ArrayList(); theTestData = new ArrayList(); readFile(inputfile); Configuration.reset(); processIni(); } /** * Initialise symbolic calculations programically. * * @param data * in form PND * @param configuration * . A list where strings representing conguration settings. Each * parameter setting seprated by new line. */ public SymRegression(ArrayList xdata, ArrayList configuration) { configstring = new ArrayList(); theData = xdata; theValidationSet = new ArrayList(); theTestData = new ArrayList(); for (int j = 0; j < configuration.size(); j++) { collectConfigValues(j + 1, configuration.get(j)); } makeRest(); Configuration.reset(); processIni(); } /** * Initialise symbolic calculations programically. * * @param data * input data * @param configuration * list of configuration values */ public SymRegression(PND xdata, ArrayList configuration) { configstring = new ArrayList(); theData = xdata.getArrayList(); theValidationSet = new ArrayList(); theTestData = new ArrayList(); for (int j = 0; j < configuration.size(); j++) { collectConfigValues(j + 1, configuration.get(j)); } makeRest(); Configuration.reset(); processIni(); } /** * Initialise symbolic calculations programically. * * @param data * input data * @param configuration * array of strings with configuration values */ public SymRegression(PND xdata, String[] configuration) { configstring = new ArrayList(); theData = xdata.getArrayList(); theValidationSet = new ArrayList(); theTestData = new ArrayList(); for (int j = 0; j < configuration.length; j++) { collectConfigValues(j + 1, configuration[j]); } makeRest(); Configuration.reset(); processIni(); } /** * Initialize calculations from input values. * @param xdata input data * @param valid validation data * @param test test data * @param configuration array with configuration values. */ public SymRegression(PND xdata, PND valid, PND test, String[] configuration) { configstring = new ArrayList(); theData = xdata.getArrayList(); theValidationSet = valid.getArrayList(); theTestData =test.getArrayList(); ; for (int j = 0; j < configuration.length; j++) { collectConfigValues(j + 1, configuration[j]); } makeRest(); Configuration.reset(); processIni(); } /** * Process initialisation. */ private void processIni() { // Present the problem // ------------------- System.out.println("Presentation: " + presentation); if (outputVariable == null) { outputVariable = numInputVariables; } if (variableNames == null) { variableNames = new String[numInputVariables + 1]; for (int i = 0; i < numInputVariables + 1; i++) { variableNames[i] = "V" + (i + 1); } } System.out.println("output_variable: " + variableNames[outputVariable] + " (index: " + outputVariable + ")"); // Setup the algorithm's parameters. // --------------------------------- config = null; try { config = new GPConfiguration(); } catch (InvalidConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } // We use a delta fitness evaluator because we compute a defect rate, // not // a point score! // ---------------------------------------------------------------------- config.setGPFitnessEvaluator(new DeltaGPFitnessEvaluator()); config.setMaxInitDepth(maxInitDepth); try { config.setPopulationSize(populationSize); } catch (InvalidConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } // experimental // config.setUseProgramCache(true); // Default selectionMethod is is TournamentSelector(3) if (tournamentSelectorSize > 0) { config.setSelectionMethod(new TournamentSelector( tournamentSelectorSize)); } /** * The maximum depth of an individual resulting from crossover. */ config.setMaxCrossoverDepth(maxCrossoverDepth); try { config.setFitnessFunction(new FormulaFitnessFunction()); } catch (InvalidConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } // Experimental // config.setNodeValidator(new SRNodeValidator()); /** * @param a_strict * true: throw an error during evolution in case a situation * is detected where no function or terminal of a required * type is declared in the GPConfiguration; false: don't * throw an error but try a completely different combination * of functions and terminals */ config.setStrictProgramCreation(strictProgramCreation); /** * Decide whether to clone command genes when creating a new GP program * in ProgramChromosome. */ config.setNoCommandGeneCloning(noCommandGeneCloning); config.setUseProgramCache(useProgramCache); /** * In crossover: If random number (0..1) < this value, then choose a * function otherwise a terminal. */ config.setFunctionProb(functionProb); /** * The probability that a reproduction operation is chosen during * evolution. Must be between 0.0d and 1.0d. crossoverProb + * reproductionProb must equal 1.0d. */ config.setReproductionProb(reproductionProb); config.setCrossoverProb(crossoverProb); /** * The probability that a node is mutated during growing a program. */ config.setMutationProb(mutationProb); /** * The probability that the arity of a node is changed during growing a * program. */ config.setDynamizeArityProb(dynamizeArityProb); /** * Percentage of the population that will be filled with new individuals * during evolution. Must be between 0.0d and 1.0d. */ config.setNewChromsPercent(newChromsPercent); /** * The minimum depth of an individual when the world is created. */ config.setMinInitDepth(minInitDepth); /** * If m_strictProgramCreation is false: Maximum number of tries to * construct a valid program. */ config.setProgramCreationMaxTries(programCreationMaxTries); } /** * Run symbolic regression. */ public void run() { problem = null; gp = null; try { problem = new SymProblem(config); // Create the genotype of the problem, i.e., define the GP commands // and // terminals that can be used, and constrain the structure of the GP // program. gp = problem.create(); // gp.setVerboseOutput(true); gp.setVerboseOutput(false); } catch (InvalidConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } startTime = System.currentTimeMillis(); System.out.println("Creating initial population"); // System.out.println("Mem free: " + // SystemKit.niceMemory(SystemKit.getTotalMemoryMB()) + " MB"); IGPProgram fittest = null; double bestFit = -1.0d; String bestProgram = ""; int bestGen = 0; HashMap similiar = null; if (showSimiliar) { similiar = new HashMap(); } int numEvolutions2 = numEvolutions; if (stopCriteriaFitness >= 0.0d) { // basically forever numEvolutions2 = Integer.MAX_VALUE; } int gen = 0; for (gen = 0; gen < numEvolutions2; gen++) { gp.evolve(); // evolve one generation gp.calcFitness(); GPPopulation pop = gp.getGPPopulation(); IGPProgram thisFittest = pop.determineFittestProgram(); ProgramChromosome chrom = thisFittest.getChromosome(0); String program = chrom.toStringNorm(0); double fitness = thisFittest.getFitnessValue(); if (showSimiliar || showPopulation || showAllGenerations) { if (showPopulation || showAllGenerations) { System.out.println("Generation " + gen); } pop.sortByFitness(); for (IGPProgram p : pop.getGPPrograms()) { double fit = p.getFitnessValue(); if (showSimiliar && fit <= bestFit) { String prog = p.toStringNorm(0); if (!similiar.containsKey(prog)) { similiar.put(prog, 1); } else { similiar.put(prog, similiar.get(prog) + 1); } } if (showPopulation) { String prg = p.toStringNorm(0); int sz = p.size(); System.out.println("\tprogram: " + prg + " fitness: " + fit); } } } // // Yes, I have to think more about this.... // Right now a program is printed if it has // better fitness value than the former best solution. // if (gen % 25 == 0) { // myOutputSolution(fittest, gen); // } if (bestFit < 0.0d || fitness < bestFit || showAllGenerations) { if (bestFit < 0.0d || fitness < bestFit) { bestGen = gen; bestFit = fitness; bestProgram = program; fittest = thisFittest; if (showSimiliar) { // reset the hash similiar.clear(); // = new HashMap(); similiar.put(thisFittest.toStringNorm(0), 1); } } myOutputSolution(fittest, gen); // Ensure that the best solution is in the population. // gp.addFittestProgram(thisFittest); } else { /* * if (gen % 25 == 0 && gen != numEvolutions) { * System.out.println("Generation " + gen + * " (This is a keep alive message.)"); // * myOutputSolution(fittest, gen); } */ if (showProgression) { String genStr = "" + (gen - 1); for (int i = 0; i <= genStr.length(); i++) { System.out.print("\b"); } System.out.print("" + gen); } } if (stopCriteriaFitness >= 0 && fitness <= stopCriteriaFitness) { System.out.print("\nFitness stopping criteria (" + stopCriteriaFitness + ") reached with fitness " + fitness + " at generation " + gen + "\n"); break; } } // Print the best solution so far to the console. // ---------------------------------------------- // gp.outputSolution(gp.getAllTimeBest()); System.out.println("\nAll time best (from generation " + bestGen + ")"); myOutputSolution(fittest, gen); // Create a graphical tree of the best solution's program and write // it to a PNG file. // ---------------------------------------------------------------- // problem.showTree(gp.getAllTimeBest(), "mathproblem_best.png"); endTime = System.currentTimeMillis(); long elapsedTime = endTime - startTime; String elapsed = String .format("%5.2f", (endTime - startTime) / 1000.0f); System.out.println("\nTotal time " + elapsed + "s"); if (showSimiliar) { System.out.println("\nAll solutions with the best fitness (" + bestFit + "):"); System.out.println("Sort method: " + similiarSortMethod); // 2010-02-27: // sort according to descending number of occurrences or length of // string List sorted = new ArrayList(similiar.keySet()); // must be final in order to be used in compare final HashMap sim = similiar; Collections.sort(sorted, new Comparator() { public int compare(String s1, String s2) { if ("length".equals(similiarSortMethod)) { // descending occurrences return s1.length() - s2.length(); } else { // descending length of programs return sim.get(s2) - sim.get(s1); } } }); for (String p : sorted) { System.out.println(p + " [" + similiar.get(p) + "]"); } System.out.println("It was " + similiar.size() + " different solutions with fitness " + bestFit); } if (testData != null && testData.length > 0) { System.out .println("\nTesting the fittest program with user defined test data: "); int testDataSize = testData.length; for (int i = 0; i < testDataSize; i++) { for (int j = 0; j < testData[i].length; j++) { if (j != outputVariable) { System.out.print(testData[i][j] + " "); } } // System.out.println(); Double testResult = evalData(fittest, testData[i]); System.out.println(" Result: " + testResult); } } // 2010-02-22: Print the result of the validation set if (validationSet != null && validationSet.length > 0) { System.out .println("\nTesting the fittest program with the validation set: "); int validationDataSize = validationSet.length; for (int i = 0; i < validationSet[0].length; i++) { double[] val = new double[validationDataSize]; for (int j = 0; j < validationDataSize; j++) { val[j] = validationSet[j][i]; System.out.print(val[j] + " "); } double testResult = evalData(fittest, val); double diff = Math.abs(testResult - val[outputVariable]); System.out.println(" Result: " + testResult + " should be " + val[outputVariable] + " diff: " + diff); } } } /** * Get configuration values (not data) in form of string "name:value" */ private void collectConfigValues(int lineCount, String str) { str=str.trim(); // Check for parameters on the form // parameter: value(s) // -------------------------------- if (str.contains(":")) { configstring.add(str); String row[] = str.split(":\\s*"); // Now check each parameter if ("return_type".equals(row[0])) { returnType = row[1]; } else if ("presentation".equals(row[0])) { presentation = row[1]; } else if ("num_input_variables".equals(row[0])) { numInputVariables = Integer.parseInt(row[1]); } else if ("num_rows".equals(row[0])) { System.out .println("num_rows is not used anymore; it is calculated by the program."); // numRows = Integer.parseInt(row[1]); } else if ("terminal_range".equals(row[0])) { String[] ranges = row[1].split("\\s+"); lowerRange = Double.parseDouble(ranges[0]); upperRange = Double.parseDouble(ranges[1]); } else if ("terminal_wholenumbers".equals(row[0])) { terminalWholeNumbers = Boolean.parseBoolean(row[1]); } else if ("max_init_depth".equals(row[0])) { maxInitDepth = Integer.parseInt(row[1]); } else if ("min_init_depth".equals(row[0])) { minInitDepth = Integer.parseInt(row[1]); } else if ("program_creation_max_tries".equals(row[0])) { programCreationMaxTries = Integer.parseInt(row[1]); } else if ("population_size".equals(row[0])) { populationSize = Integer.parseInt(row[1]); } else if ("max_crossover_depth".equals(row[0])) { maxCrossoverDepth = Integer.parseInt(row[1]); } else if ("function_prob".equals(row[0])) { functionProb = Double.parseDouble(row[1]); } else if ("reproduction_prob".equals(row[0])) { reproductionProb = Float.parseFloat(row[1]); } else if ("mutation_prob".equals(row[0])) { mutationProb = Float.parseFloat(row[1]); } else if ("crossover_prob".equals(row[0])) { crossoverProb = Float.parseFloat(row[1]); } else if ("dynamize_arity_prob".equals(row[0])) { dynamizeArityProb = Float.parseFloat(row[1]); } else if ("new_chroms_percent".equals(row[0])) { newChromsPercent = Double.parseDouble(row[1]); } else if ("num_evolutions".equals(row[0])) { numEvolutions = Integer.parseInt(row[1]); } else if ("max_nodes".equals(row[0])) { maxNodes = Integer.parseInt(row[1]); } else if ("functions".equals(row[0])) { functions = row[1].split("[\\s,]+"); } else if ("adf_functions".equals(row[0])) { adfFunctions = row[1].split("[\\s,]+"); } else if ("variable_names".equals(row[0])) { variableNames = row[1].split("[\\s,]+"); } else if ("output_variable".equals(row[0])) { outputVariable = Integer.parseInt(row[1]); } else if ("ignore_variables".equals(row[0])) { String[] ignoreVariablesS = row[1].split("[\\s,]+"); ignoreVariables = new int[ignoreVariablesS.length]; // TODO: make it a HashMap instead for (int i = 0; i < ignoreVariablesS.length; i++) { ignoreVariables[i] = Integer.parseInt(ignoreVariablesS[i]); } } else if ("constant".equals(row[0])) { Double constant = Double.parseDouble(row[1]); constants.add(constant); } else if ("adf_arity".equals(row[0])) { adfArity = Integer.parseInt(row[1]); System.out.println("ADF arity " + adfArity); if (adfArity > 0) { useADF = true; } } else if ("adf_type".equals(row[0])) { adfType = row[1]; } else if ("tournament_selector_size".equals(row[0])) { tournamentSelectorSize = Integer.parseInt(row[1]); } else if ("scale_error".equals(row[0])) { scaleError = Double.parseDouble(row[1]); } else if ("stop_criteria_fitness".equals(row[0])) { stopCriteriaFitness = Double.parseDouble(row[1]); } else if ("show_population".equals(row[0])) { showPopulation = Boolean.parseBoolean(row[1]); } else if ("show_similiar".equals(row[0]) || "show_similar".equals(row[0])) { // 2010-02-27:added alternative spelling showSimiliar = Boolean.parseBoolean(row[1]); } else if ("similiar_sort_method".equals(row[0]) || "similar_sort_method".equals(row[0])) { // 2010-02-27 similiarSortMethod = row[1]; if (!("length".equals(similiarSortMethod) || "occurrence" .equals(similiarSortMethod))) { System.out.println("Unknown similiar_sort_method: " + similiarSortMethod); return; // System.exit(1); } } else if ("show_progression".equals(row[0])) { showProgression = Boolean.parseBoolean(row[1]); } else if ("sample_pct".equals(row[0])) { samplePCT = Float.parseFloat(row[1]); } else if ("validation_pct".equals(row[0])) { validationPCT = Float.parseFloat(row[1]); } else if ("hits_criteria".equals(row[0])) { hitsCriteria = Double.parseDouble(row[1]); errorMethod = "hitsCriteria"; } else if ("show_all_generations".equals(row[0])) { showAllGenerations = Boolean.parseBoolean(row[1]); } else if ("strict_program_creation".equals(row[0])) { strictProgramCreation = Boolean.parseBoolean(row[1]); } else if ("no_command_gene_cloning".equals(row[0])) { noCommandGeneCloning = Boolean.parseBoolean(row[1]); } else if ("use_program_cache".equals(row[0])) { useProgramCache = Boolean.parseBoolean(row[1]); } else if ("mod_replace".equals(row[0])) { // this is quite experimental modReplace = Integer.parseInt(row[1]); } else if ("show_results".equals(row[0])) { showResults = Boolean.parseBoolean(row[1]); } else if ("result_precision".equals(row[0])) { resultPrecision = Integer.parseInt(row[1]); } else if ("error_method".equals(row[0])) { errorMethod = row[1]; if (!("maxError".equals(errorMethod) || "minError".equals(errorMethod) || "medianError".equals(errorMethod) || "meanError".equals(errorMethod) || "totalError" .equals(errorMethod))) { System.out.println("Unknown errorMethod: " + errorMethod); return; } } else if ("no_terminals".equals(row[0])) { // Added 2010-02-26 noTerminals = Boolean.parseBoolean(row[1]); } else if ("make_time_series".equals(row[0])) { makeTimeSeries = Boolean.parseBoolean(row[1]); } else if ("make_time_series_with_index".equals(row[0])) { makeTimeSeriesWithIndex = Boolean.parseBoolean(row[1]); } else if ("min_nodes".equals(row[0])) { // 2010-03-01: Added this and min_nodes_penalty String[] opt = row[1].split("[\\s,]+"); minNodes = Integer.parseInt(opt[0]); if (minNodes > maxNodes) { System.out.println("minNodes (" + minNodes + ") > maxNodes (" + maxNodes + ") which is weird. Cannot continue. "); return; } minNodesPenalty = Integer.parseInt(opt[1]); } else if ("alldifferent_variables".equals(row[0])) { // added 2010-03-02 String[] opt = row[1].split("[\\s,]+"); alldifferentVariables = Boolean.parseBoolean(opt[0]); alldifferentVariablesPenalty = Double.parseDouble(opt[1]); // } else if ("make_index_seq".equals(row[0])) { // makeIndexSeq = Boolean.parseBoolean(row[1]); } else { System.out.println("Unknown keyword: " + row[0] + " on line " + lineCount); return; } } } /** * Read input configuration file. The file can be from URL. * * @param file * configuration file to read. It can be URL if starts with * "http:" or "ftp:". */ public void readFile(String file) { file = file.trim(); BufferedReader inr = null; if (file.startsWith("http:") || file.startsWith("ftp:")) { try { URL url = new URL(file); URLConnection urlConn = url.openConnection(); InputStreamReader inStream = new InputStreamReader( urlConn.getInputStream()); inr = new BufferedReader(inStream); } catch (MalformedURLException e) { System.err.println("Please check the URL:" + e.toString()); return; } catch (IOException e1) { System.err.println("Can't read from the Internet: " + e1.toString()); return; } } else { // normal file try { inr = new BufferedReader(new FileReader(file)); } catch (IOException e1) { System.err.println("Can't read : " + e1.toString()); return; } } // end reader try { // start processing String str; int lineCount = 0; boolean gotData = false; // // read the lines // while ((str = inr.readLine()) != null) { lineCount++; str = str.trim(); // ignore empty lines or comments, i.e. lines starting with // either # or % // ---------------------------------------------------------------------- if (str.startsWith("#") || str.startsWith("%") || str.length() == 0) { continue; } if ("data".equals(str)) { gotData = true; continue; } if (gotData) { // Read the data rows // ------------------ String[] dataRowStr = str.split("[\\s,]+"); int len = dataRowStr.length; double[] dataRow = new double[len]; boolean isTestData = false; for (int i = 0; i < len; i++) { if ("?".equals(dataRowStr[i])) { isTestData = true; dataRow[i] = -1.0d; // dummy value } else { dataRow[i] = Double.parseDouble(dataRowStr[i]); } } // check if this row should be in the data // or maybe in the validation set. // A data point may not be in the both data // set and validation set. boolean inData = true; if (isTestData) { inData = false; theTestData.add(dataRow); } // Get sample to use // Keep all the rows where nextFloat is <= samplePCT if (!isTestData && samplePCT > 0.0d) { Random randomGenerator = new Random(); float rand = randomGenerator.nextFloat(); if (rand > samplePCT) { inData = false; } } // make validation set if (!isTestData && validationPCT > 0.0d) { Random randomGenerator = new Random(); float rand = randomGenerator.nextFloat(); if (rand < validationPCT) { inData = false; theValidationSet.add(dataRow); } } // put in the data set if (inData) { theData.add(dataRow); } } else { collectConfigValues(lineCount, str); // collect non-data // staff } } // end while inr.close(); // 2010-02-27: if makeTimeSeries is set we // makes a timeseries of the first data row. // It is undocumented what will happen with more than one // data rows. // // The lag is the number of input variables + 1. // makeRest(); } catch (IOException e1) { System.err.println("Cannot process the file " + e1.toString()); return; } // end exepion } // end readFile /** * Make the rest of the initialisation. */ private void makeRest(){ // 2010-02-27: if makeTimeSeries is set we // makes a timeseries of the first data row. // It is undocumented what will happen with more than one // data rows. // // The lag is the number of input variables + 1. // if (makeTimeSeries || makeTimeSeriesWithIndex) { // last we substitute theData with this ArrayList theDataNew = new ArrayList(); double[] dat = theData.get(0); int numElements = dat.length; System.out.println("Making timeseries, #elements: " + numElements); int cols = numInputVariables + 1; if (makeTimeSeriesWithIndex) { cols++; } for (int i = 0; i < numElements - cols; i++) { double[] tmp = new double[cols]; int jStart = 0; if (makeTimeSeriesWithIndex) { System.out.print(i + 1 + " "); tmp[0] = (double) i + 1; jStart = 1; } for (int j = jStart; j < cols; j++) { System.out.print(dat[i + j] + " "); tmp[j] = dat[i + j]; } System.out.println(); theDataNew.add(tmp); } theData = theDataNew; } // // Now we know everything to be known. // Construct the matrix from the file. // ----------------------------------- int r = theData.size(); int c = theData.get(0).length; int numIgnore = 0; if (ignoreVariables != null) { // TODO: ignoreVariables should be a HashMap numIgnore = ignoreVariables.length; // c = c - numIgnore; } double[][] dataTmp = new double[r][c]; // TODO: ignore the variables in ignoreVariables for (int i = 0; i < r; i++) { double[] this_row = theData.get(i); for (int j = 0; j < c; j++) { dataTmp[i][j] = this_row[j]; } } // Since we calculate the error on the variable we // must transpose the data matrix // ----------------------------------------------- data = transposeMatrix(dataTmp); numRows = data[0].length; System.out.println("It was " + numRows + " data rows"); // // Do the same thing with the validation data // // TODO: This should really be a separate method if (validationPCT > 0.0d && theValidationSet != null && theValidationSet.size() > 0) { int r_v = theValidationSet.size(); int c_v = theValidationSet.get(0).length; double[][] dataTmp_v = new double[r_v][c_v]; // TODO: ignore the variables in ignoreVariables for (int i = 0; i < r_v; i++) { double[] this_row = (double[]) theValidationSet.get(i); for (int j = 0; j < c_v; j++) { dataTmp_v[i][j] = this_row[j]; } } validationSet = transposeMatrix(dataTmp_v); System.out.println("It was " + validationSet[0].length + " data rows in the validation data set"); } // // Do the same thing with the test data // if (theTestData.size() > 0) { int r_v = theTestData.size(); int c_v = theTestData.get(0).length; double[][] dataTmp_v = new double[r_v][c_v]; // TODO: ignore the variables in ignoreVariables for (int i = 0; i < r_v; i++) { double[] this_row = theTestData.get(i); for (int j = 0; j < c_v; j++) { dataTmp_v[i][j] = this_row[j]; } } // testData = transposeMatrix(dataTmp_v); testData = dataTmp_v; System.out.println("It was " + testData.length + " data rows in the user defined data set"); } } /** * Transpose matrix * * @param dataTmp * @return */ protected double[][] transposeMatrix(double[][] dataTmp) { int r = dataTmp.length; int c = dataTmp[0].length; double[][] t = new double[c][r]; for (int i = 0; i < r; ++i) { for (int j = 0; j < c; ++j) { t[j][i] = dataTmp[i][j]; } } return t; } // end transposeMatrix /* * makeCommands: makes the CommandGene array given the function listed in * the configurations file * ------------------------------------------------------------ */ static CommandGene[] makeCommands(GPConfiguration conf, String[] functions, Double lowerRange, Double upperRange, String type) { ArrayList commandsList = new ArrayList(); int len = functions.length; boolean isADF = "ADF".equals(type); try { for (int i = 0; i < len; i++) { // // Note: all functions may not be applicable... // if ("Multiply".equals(functions[i])) { commandsList .add(new Multiply(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Multiply(conf, CommandGene.BooleanClass)); } } else if ("Multiply3".equals(functions[i])) { commandsList.add(new Multiply3(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Multiply3(conf, CommandGene.BooleanClass)); } } else if ("Add".equals(functions[i])) { commandsList.add(new Add(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList .add(new Add(conf, CommandGene.BooleanClass)); } } else if ("Divide".equals(functions[i])) { commandsList.add(new Divide(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Divide(conf, CommandGene.BooleanClass)); } } else if ("DivideIntD".equals(functions[i])) { commandsList.add(new DivideIntD(conf, CommandGene.DoubleClass)); } else if ("DivideProtected".equals(functions[i])) { commandsList.add(new DivideProtected(conf, CommandGene.DoubleClass)); } else if ("Add3".equals(functions[i])) { commandsList.add(new Add3(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Add3(conf, CommandGene.BooleanClass)); } } else if ("Add4".equals(functions[i])) { commandsList.add(new Add4(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Add4(conf, CommandGene.BooleanClass)); } } else if ("Subtract".equals(functions[i])) { commandsList .add(new Subtract(conf, CommandGene.DoubleClass)); if (useADF && "boolean".equals(adfType)) { commandsList.add(new Subtract(conf, CommandGene.BooleanClass)); } } else if ("Sine".equals(functions[i])) { commandsList.add(new Sine(conf, CommandGene.DoubleClass)); } else if ("ArcSine".equals(functions[i])) { commandsList .add(new ArcSine(conf, CommandGene.DoubleClass)); } else if ("Tangent".equals(functions[i])) { commandsList .add(new Tangent(conf, CommandGene.DoubleClass)); } else if ("ArcTangent".equals(functions[i])) { commandsList.add(new ArcTangent(conf, CommandGene.DoubleClass)); } else if ("Cosine".equals(functions[i])) { commandsList.add(new Cosine(conf, CommandGene.DoubleClass)); } else if ("ArcCosine".equals(functions[i])) { commandsList.add(new ArcCosine(conf, CommandGene.DoubleClass)); } else if ("Exp".equals(functions[i])) { commandsList.add(new Exp(conf, CommandGene.DoubleClass)); } else if ("Log".equals(functions[i])) { commandsList.add(new Log(conf, CommandGene.DoubleClass)); } else if ("Abs".equals(functions[i])) { commandsList.add(new Abs(conf, CommandGene.DoubleClass)); } else if ("Pow".equals(functions[i])) { commandsList.add(new Pow(conf, CommandGene.DoubleClass)); } else if ("Round".equals(functions[i])) { commandsList.add(new Round(conf, CommandGene.DoubleClass)); } else if ("RoundD".equals(functions[i])) { commandsList.add(new RoundD(conf, CommandGene.DoubleClass)); } else if ("Ceil".equals(functions[i])) { commandsList.add(new Ceil(conf, CommandGene.DoubleClass)); } else if ("Floor".equals(functions[i])) { commandsList.add(new Floor(conf, CommandGene.DoubleClass)); } else if ("Modulo".equals(functions[i])) { commandsList.add(new Modulo(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Modulo(conf, CommandGene.BooleanClass)); } } else if ("ModuloD".equals(functions[i])) { commandsList .add(new ModuloD(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new ModuloD(conf, CommandGene.BooleanClass)); } } else if ("ModuloReplaceD".equals(functions[i])) { // this is quite experimental commandsList.add(new ModuloReplaceD(conf, CommandGene.DoubleClass, modReplace)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new ModuloReplaceD(conf, CommandGene.BooleanClass, modReplace)); } } else if ("Max".equals(functions[i])) { commandsList.add(new Max(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList .add(new Max(conf, CommandGene.BooleanClass)); } } else if ("Min".equals(functions[i])) { commandsList.add(new Min(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList .add(new Min(conf, CommandGene.BooleanClass)); } } else if ("Sqrt".equals(functions[i])) { // Note: This uses my Sqrt.java file commandsList.add(new Sqrt(conf, CommandGene.DoubleClass)); } else if ("Square".equals(functions[i])) { // Note: This uses my Square.java file commandsList.add(new Square(conf, CommandGene.DoubleClass)); } else if ("Cube".equals(functions[i])) { // Note: This uses my Cube.java file commandsList.add(new Cube(conf, CommandGene.DoubleClass)); } else if ("Logistic".equals(functions[i])) { // Note: This uses my Logistic.java file commandsList .add(new Logistic(conf, CommandGene.DoubleClass)); } else if ("Gaussian".equals(functions[i])) { // Note: This uses my Gaussian.java file commandsList .add(new Gaussian(conf, CommandGene.DoubleClass)); } else if ("Sigmoid".equals(functions[i])) { // Note: This uses my Sigmoid.java file commandsList .add(new Sigmoid(conf, CommandGene.DoubleClass)); } else if ("Gamma".equals(functions[i])) { // Note: This uses my Gamma.java file commandsList.add(new Gamma(conf, CommandGene.DoubleClass)); } else if ("Step".equals(functions[i])) { // Note: This uses my Step.java file commandsList.add(new Step(conf, CommandGene.DoubleClass)); } else if ("Sign".equals(functions[i])) { // Note: This uses my Sign.java file commandsList.add(new Sign(conf, CommandGene.DoubleClass)); } else if ("Hill".equals(functions[i])) { // Note: This uses my Hill.java file commandsList.add(new Hill(conf, CommandGene.DoubleClass)); } else if ("LesserThan".equals(functions[i])) { commandsList.add(new LesserThan(conf, CommandGene.BooleanClass)); } else if ("LesserThanD".equals(functions[i])) { commandsList.add(new LesserThanD(conf, CommandGene.DoubleClass)); } else if ("LesserThanOrEqualD".equals(functions[i])) { commandsList.add(new LesserThanOrEqualD(conf, CommandGene.DoubleClass)); } else if ("GreaterThan".equals(functions[i])) { commandsList.add(new GreaterThan(conf, CommandGene.BooleanClass)); } else if ("GreaterThanD".equals(functions[i])) { commandsList.add(new GreaterThanD(conf, CommandGene.DoubleClass)); } else if ("GreaterThanOrEqualD".equals(functions[i])) { commandsList.add(new GreaterThanOrEqualD(conf, CommandGene.DoubleClass)); } else if ("DifferentD".equals(functions[i])) { commandsList.add(new DifferentD(conf, CommandGene.DoubleClass)); } else if ("If".equals(functions[i])) { // Note: This is just If on DoubleClass, not a proper // Boolean commandsList.add(new If(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList .add(new If(conf, CommandGene.BooleanClass)); } } else if ("IfElse".equals(functions[i])) { commandsList.add(new IfElse(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new IfElse(conf, CommandGene.BooleanClass)); } } else if ("IfElseD".equals(functions[i])) { commandsList .add(new IfElseD(conf, CommandGene.DoubleClass)); } else if ("IfLessThanOrEqualD".equals(functions[i])) { // if a < b then c else d commandsList.add(new IfLessThanOrEqualD(conf, CommandGene.DoubleClass)); } else if ("IfLessThanOrEqualZeroD".equals(functions[i])) { // 2010-02-22: Added IfLessThanOrEqualZeroD // if a < 0 then b else c commandsList.add(new IfLessThanOrEqualZeroD(conf, CommandGene.DoubleClass)); } else if ("IfDyn".equals(functions[i])) { // Well, this don't work as expected... // System.out.println("IfDyn is not supported yet"); commandsList.add(new IfDyn(conf, CommandGene.DoubleClass, 1, 1, 5)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new IfDyn(conf, CommandGene.DoubleClass, 1, 1, 5)); } // } else if ("IfDynD".equals(functions[i])) { // // Using IfDynD.java // commandsList.add(new IfDynD(conf, // CommandGene.DoubleClass,3,1,3)); } else if ("Loop".equals(functions[i])) { // experimental commandsList .add(new Loop(conf, CommandGene.DoubleClass, 3)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Loop(conf, CommandGene.BooleanClass, 3)); } } else if ("LoopD".equals(functions[i])) { // experimental commandsList.add(new LoopD(conf, CommandGene.DoubleClass, numInputVariables)); } else if ("Equals".equals(functions[i])) { // commandsList.add(new Equals(conf, // CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Equals(conf, CommandGene.BooleanClass)); } } else if ("EqualsD".equals(functions[i])) { commandsList .add(new EqualsD(conf, CommandGene.DoubleClass)); } else if ("ForXLoop".equals(functions[i])) { // experimental commandsList.add(new ForXLoop(conf, CommandGene.IntegerClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new ForXLoop(conf, CommandGene.BooleanClass)); } else if (useADF && "integer".equals(adfType)) { commandsList.add(new ForXLoop(conf, CommandGene.IntegerClass)); } } else if ("ForLoop".equals(functions[i])) { // experimental commandsList.add(new ForLoop(conf, CommandGene.DoubleClass, 1, numInputVariables)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new ForLoop(conf, CommandGene.BooleanClass, 10)); } else if (isADF && "integer".equals(adfType)) { commandsList.add(new ForLoop(conf, CommandGene.IntegerClass, 10)); } } else if ("ForLoopD".equals(functions[i])) { // added 2010-03-01 // ForLoopD.java commandsList.add(new ForLoopD(conf, CommandGene.DoubleClass, numInputVariables * 2)); } else if ("Increment".equals(functions[i])) { commandsList.add(new Increment(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new Increment(conf, CommandGene.BooleanClass)); } } else if ("Argument".equals(functions[i])) { // experimental /* * commandsList.add(new Argument(conf, 1, * CommandGene.DoubleClass)); if ("boolean".equals(adfType)) * { commandsList.add(new Argument(conf, 1, * CommandGene.BooleanClass)); } */ } else if ("StoreTerminal".equals(functions[i])) { // experimental commandsList.add(new StoreTerminal(conf, "dmem0", CommandGene.DoubleClass)); commandsList.add(new StoreTerminal(conf, "dmem1", CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList.add(new StoreTerminal(conf, "bmem0", CommandGene.DoubleClass)); commandsList.add(new StoreTerminal(conf, "bmem1", CommandGene.DoubleClass)); } } else if ("Pop".equals(functions[i])) { // experimental // commandsList.add(new Pop(conf, CommandGene.DoubleClass)); if (isADF && "boolean".equals(adfType)) { commandsList .add(new Pop(conf, CommandGene.BooleanClass)); } } else if ("Push".equals(functions[i])) { // experimental commandsList.add(new Push(conf, CommandGene.DoubleClass)); } else if ("And".equals(functions[i])) { commandsList.add(new And(conf)); } else if ("Or".equals(functions[i])) { commandsList.add(new Or(conf)); } else if ("Xor".equals(functions[i])) { commandsList.add(new Xor(conf)); } else if ("Not".equals(functions[i])) { commandsList.add(new Not(conf)); } else if ("AndD".equals(functions[i])) { commandsList.add(new AndD(conf)); } else if ("OrD".equals(functions[i])) { commandsList.add(new OrD(conf)); } else if ("XorD".equals(functions[i])) { commandsList.add(new XorD(conf)); } else if ("NotD".equals(functions[i])) { commandsList.add(new NotD(conf)); // } else if ("Replace".equals(functions[i])) { // commandsList.add(new Replace(conf)); } else if ("Id".equals(functions[i])) { // experimental commandsList.add(new Id(conf)); } else if ("SubProgram".equals(functions[i])) { // experimental if (isADF && "boolean".equals(adfType)) { commandsList.add(new SubProgram(conf, new Class[] { CommandGene.BooleanClass, CommandGene.BooleanClass })); commandsList.add(new SubProgram(conf, new Class[] { CommandGene.BooleanClass, CommandGene.BooleanClass, CommandGene.BooleanClass })); } commandsList .add(new SubProgram(conf, new Class[] { CommandGene.DoubleClass, CommandGene.DoubleClass })); commandsList.add(new SubProgram(conf, new Class[] { CommandGene.DoubleClass, CommandGene.DoubleClass, CommandGene.DoubleClass })); } else if ("Tupel".equals(functions[i])) { // experimental if (isADF && "boolean".equals(adfType)) { commandsList.add(new Tupel(conf, new Class[] { CommandGene.BooleanClass, CommandGene.BooleanClass })); } } else { System.out.println("Unkown function: " + functions[i]); System.exit(1); } } if (!noTerminals) { commandsList.add(new Terminal(conf, CommandGene.DoubleClass, lowerRange, upperRange, terminalWholeNumbers)); // commandsList.add(new Terminal(conf, CommandGene.BooleanClass, // lowerRange, upperRange, terminalWholeNumbers)); } // ADF // Just add the ADF to the "normal" command list (i.e. not to the // ADF list) if (useADF && !"ADF".equals(type)) { commandsList.add(new ADF(conf, 1, adfArity)); // for (int i = 0; i <= adfArity; i++) { // commandsList.add(new ADF(conf, i, adfArity)); // } } if (constants != null) { for (int i = 0; i < constants.size(); i++) { double constant = (double) constants.get(i); commandsList.add(new Constant(conf, CommandGene.DoubleClass, constant)); } } } catch (Exception e) { System.out.println(e); } CommandGene[] commands = new CommandGene[commandsList.size()]; commandsList.toArray(commands); return commands; } /** * Outputs the best solution until now at standard output. * * This is stolen (and somewhat edited) from GPGenotype.outputSolution which * used log4j. * * @param a_best * the fittest ProgramChromosome * * @author Hakan Kjellerstrand (originally by Klaus Meffert) */ private void myOutputSolution(IGPProgram a_best, int gen) { String freeMB = SystemKit.niceMemory(SystemKit.getFreeMemoryMB()); long now = System.currentTimeMillis(); String elapsedNow = String.format("%5.2f", (now - startTime) / 1000.0f); if (showProgression) { System.out.println(); } System.out.println("\nEvolving generation " + (gen) + "/" + numEvolutions + "(time from start: " + elapsedNow + "s)"); if (a_best == null) { System.out.println("No best solution (null)"); return; } double bestValue = a_best.getFitnessValue(); if (Double.isInfinite(bestValue)) { System.out.println("No best solution (infinite)"); return; } System.out.print("Best solution fitness: " + NumberKit.niceDecimalNumber(bestValue, 2) + " (error method: " + errorMethod + ")"); if (validationPCT > 0.0d && validationSet != null) { // validate this program against the validation set double validationFitness = validateData(a_best); System.out.print(" (validation fitness: " + validationFitness + ")"); } System.out.println(); bestSolution = a_best.toStringNorm(0); System.out.println("Best solution: " + bestSolution); String depths = ""; int size = a_best.size(); for (int i = 0; i < size; i++) { if (i > 0) { depths += " / "; } depths += a_best.getChromosome(i).getDepth(0); } if (size == 1) { System.out.print("Depth of chrom: " + depths); } else { System.out.print("Depths of chroms: " + depths); } ProgramChromosome chrom = a_best.getChromosome(0); int numFunctions = chrom.numFunctions(); int numTerminals = chrom.numTerminals(); int numTerms = numFunctions + numTerminals; System.out.println(". Number of functions+terminals: " + numTerms + " (" + numFunctions + " functions, " + numTerminals + " terminals)"); ApplicationData appData = (ApplicationData) a_best.getApplicationData(); System.out.println("Correlation coefficient: " + appData.getCorrelation()); // 2010-02-22: Print out the different error variants System.out.println("minError: " + appData.getMinError() + " meanError: " + appData.getMeanError() + " medianError: " + appData.getMedianError() + " maxError: " + appData.getMaxError() + " totalError: " + appData.getTotalError()); if (hitsCriteria >= 0.0d) { int numHits = appData.getNumHits(); String hitsPct = String.format("%5.2f", numHits / (double) numRows); System.out.println("Number of hits (<= " + hitsCriteria + "): " + numHits + " (of " + numRows + " = " + hitsPct + ")"); } if (showResults) { double[] results = appData.getResults(); if (results != null) { System.out.println("Results for this program:"); double sumAbsDiff = 0.0d; double sumDiff = 0.0d; String formatStr = "%5." + resultPrecision + "f"; int thisNumHits = 0; for (int i = 0; i < results.length; i++) { double d = data[outputVariable][i]; double r = results[i]; double diff = d - r; double absDiff = Math.abs(diff); String hitsStr = ""; if (hitsCriteria >= 0.0d && absDiff > hitsCriteria) { hitsStr = " > " + hitsCriteria + "!"; } else { thisNumHits++; } System.out.println("(" + i + ") " + d + ": " + String.format(formatStr, r) + " (diff: " + String.format(formatStr, diff) + ")" + hitsStr); sumDiff += diff; sumAbsDiff += absDiff; } String numHitsStr = hitsCriteria >= 0 ? " #hits: " + thisNumHits + " (of " + numRows : ""; System.out.println("total diff: " + sumAbsDiff + " (no abs diff: " + sumDiff + numHitsStr + ")\n"); } } } /** * Due to lazyness this is borrowed from Weka's weka/core/Utils.java, * slightly edited. [Copyright (C) 1999-2004 University of Waikato, * Hamilton, New Zealand] * * Weka is a great machine learning/data mining system: * http://www.cs.waikato.ac.nz/~ml/weka/index.html * * * Returns the correlation coefficient of two double vectors. * * @param data2 * Double vector 1 * @param y2 * double vector 2 * @param n * the length of two double vectors * @return the correlation coefficient */ protected final static double correlation(double[] data2, double y2[], int n) { int i; double av1 = 0.0, av2 = 0.0, y11 = 0.0, y22 = 0.0, y12 = 0.0, c; if (n <= 1) { return 1.0; } for (i = 0; i < n; i++) { av1 += data2[i]; av2 += y2[i]; } av1 /= (double) n; av2 /= (double) n; for (i = 0; i < n; i++) { y11 += (data2[i] - av1) * (data2[i] - av1); y22 += (y2[i] - av2) * (y2[i] - av2); y12 += (data2[i] - av1) * (y2[i] - av2); } if (y11 * y22 == 0.0) { c = 1.0; } else { c = y12 / Math.sqrt(Math.abs(y11 * y22)); } return c; } // check fitness for an individual, typically the fittest program // in the population // 2010-02-22: error is according to the error method protected double validateData(final IGPProgram ind) { double error = 0.0d; double[] errors = new double[validationSet[0].length]; Object[] noargs = new Object[0]; if (validationSet != null && validationSet.length > 0) { for (int j = 0; j < validationSet[0].length; j++) { int variableIndex = 0; for (int i = 0; i < numInputVariables + 1; i++) { if (i != outputVariable) { variables[variableIndex].set(validationSet[i][j]); variableIndex++; } } try { double result = ind.execute_double(0, noargs); double err = Math.abs(result - validationSet[outputVariable][j]); errors[j] = err; error += err; if (Double.isInfinite(error) || Double.isNaN(error)) { return Double.MAX_VALUE; } } catch (ArithmeticException ex) { System.out.println(ind); throw ex; } } } double[] err = calcAllErrors(error, errors); return err[0]; } // 2010-02-22: Calculate the different error alternatives protected static double[] calcAllErrors(double error, double[] errors) { double totalError = error; double[] minMaxErrors = getMinMax(errors); double minError = minMaxErrors[0]; double maxError = minMaxErrors[1]; double medianError = minMaxErrors[2]; double meanError = error / errors.length; // default is totalError if ("meanError".equals(errorMethod)) { error = meanError; } else if ("minError".equals(errorMethod)) { error = minError; } else if ("maxError".equals(errorMethod)) { error = maxError; } else if ("medianError".equals(errorMethod)) { error = medianError; } double[] err = { error, totalError, minError, maxError, meanError, medianError }; return err; } /** * Evaluate data of this program. * * @param ind * @param data * input data. * @return */ protected double evalData(final IGPProgram ind, double[] data) { Double result = 0.0d; // Double error = 0.0d; Object[] noargs = new Object[0]; int variableIndex = 0; for (int i = 0; i < numInputVariables + 1; i++) { if (i != outputVariable) { variables[variableIndex].set(data[i]); variableIndex++; } } try { result = ind.execute_double(0, noargs); // error = Math.abs(result - data[outputVariable]); } catch (ArithmeticException ex) { System.out.println(ind); throw ex; } return result; } protected static double[] getMinMax(double[] arr) { double min = Double.MAX_VALUE; double max = Double.MIN_VALUE; int len = arr.length; for (int i = 0; i < len; i++) { if (arr[i] < min) { min = arr[i]; } if (arr[i] > max) { max = arr[i]; } } double median = Double.MIN_VALUE; int len2 = (int) len / 2; if (len == 1) { median = arr[0]; } else if (len == 2) { median = (arr[0] + arr[1]) / 2; } else if (len % 2 == 1) { median = arr[len2]; } else { median = (arr[len2] + arr[len2 + 1]) / 2; } return new double[] { min, max, median }; } /** * Create a tree with best solution in form os a graphic file. The extension * is "png" * * @param imagename * image name. It is a PNG file. The extension should be png */ public void createTree(String imagename) { try { problem.showTree(gp.getAllTimeBest(), imagename); } catch (InvalidConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Get the best solution as a string * * @return represents a best solution */ public String getBestSolution() { return bestSolution; } /** * Return configuration file * * @return */ public GPConfiguration getConfig() { return config; } /** * Return problem. * * @return */ public GPProblem getProblem() { return problem; } /** * Return input data * * @return */ public ArrayList getData() { return theData; } /** * Return test data as double array * * @return */ public ArrayList getTestData() { return theTestData; } /** * Return validation data as double array * * @return */ public ArrayList getValidationData() { return theValidationSet; } /** * Return validation data as PND * * @return */ public PND getValidationPND() { PND pn = new PND("Validation data"); for (int j = 0; j < theValidationSet.size(); j++) { double[] d = (double[]) theValidationSet.get(j); pn.add(d); } return pn; } /** * Return test data as PND * * @return */ public PND getTestPND() { PND pn = new PND("Test data"); for (int j = 0; j < theTestData.size(); j++) { double[] d = (double[]) theTestData.get(j); pn.add(d); } return pn; } /** * Return data in form PND object * * @return */ public PND getDataPND() { PND pn = new PND("Data"); for (int j = 0; j < theData.size(); j++) { double[] d = (double[]) theData.get(j); pn.add(d); } return pn; } /** * Get configuration string passed to this program. * @return congig string. */ public ArrayList getConfigArray(){ return configstring; } /** * Show online documentation. */ public void doc() { String a = this.getClass().getName(); a = a.replace(".", "/") + ".html"; new HelpBrowser(HelpBrowser.JHPLOT_HTTP + a); } }

Ads help maintain this website.