diff options
Diffstat (limited to 'src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java')
-rw-r--r-- | src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java b/src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java new file mode 100644 index 0000000..52df0f2 --- /dev/null +++ b/src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java @@ -0,0 +1,124 @@ +package jcgp.backend.modules.problem; + +import jcgp.backend.function.DoubleArithmetic; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Population; +import jcgp.backend.resources.Resources; +import jcgp.backend.resources.parameters.BooleanParameter; +import jcgp.backend.resources.parameters.DoubleParameter; +import jcgp.backend.resources.parameters.Parameter; +import jcgp.backend.resources.parameters.ParameterStatus; + +public class SymbolicRegressionProblem extends TestCaseProblem<Double> { + + private DoubleParameter errorThreshold, perfectionThreshold; + private BooleanParameter hitsBasedFitness; + + public SymbolicRegressionProblem(Resources resources) { + super(resources); + functionSet = new DoubleArithmetic(); + errorThreshold = new DoubleParameter(0.01, "Error threshold") { + @Override + public void validate(Number newValue) { + if (newValue.doubleValue() < 0) { + status = ParameterStatus.INVALID; + status.setDetails("Error threshold must be a positive value."); + } else if (newValue.doubleValue() == 0) { + status = ParameterStatus.WARNING; + status.setDetails("An error threshold of 0 is very rigorous and difficult to achieve."); + } else { + status = ParameterStatus.VALID; + } + } + }; + perfectionThreshold = new DoubleParameter(0.000001, "Perfection threshold") { + @Override + public void validate(Number newValue) { + if (newValue.doubleValue() < 0) { + status = ParameterStatus.INVALID; + status.setDetails("Perfection threshold must be a positive value."); + } else if (newValue.doubleValue() == 0) { + status = ParameterStatus.WARNING; + status.setDetails("A perfection threshold of 0 is very rigorous and difficult to achieve."); + } else { + status = ParameterStatus.VALID; + } + } + }; + hitsBasedFitness = new BooleanParameter(true, "Hits-based fitness") { + @Override + public void validate(Boolean newValue) { + // blank + } + }; + } + + @Override + public void evaluate(Population population, Resources resources) { + // set fittest to 0, change it whenever a fitter one is found + population.setFittest(0); + + // for every chromosome in the population + for (int i = 0; i < resources.populationSize(); i++) { + // assume an initial fitness of 0 + double fitness = 0; + // for each test case + for (int t = 0; t < testCases.size(); t++) { + population.getChromosome(i).setInputs((Object[]) testCases.get(t).getInputs()); + // check each output + for (int o = 0; o < resources.outputs(); o++) { + Double cgpValue = (Double) population.getChromosome(i).getOutput(o).calculate(); + Double dataValue = testCases.get(t).getOutput(o); + if (hitsBasedFitness.get()) { + if (Math.abs(cgpValue - dataValue) <= errorThreshold.get()) { + fitness++; + } + } else { + fitness += 1 - Math.abs(cgpValue - dataValue); + } + + } + } + // assign the resulting fitness to the respective individual + population.getChromosome(i).setFitness(fitness); + if (fitness >= population.getFittest().getFitness()) { + population.setFittest(i); + } + } + } + + + @Override + public String toString() { + return "Symbolic regression"; + } + + @Override + public void addTestCase(String[] inputs, String[] outputs) { + Double[] inputCases = new Double[inputs.length]; + Double[] outputCases = new Double[outputs.length]; + for (int i = 0; i < inputCases.length; i++) { + inputCases[i] = Double.parseDouble(inputs[i]); + } + for (int o = 0; o < outputCases.length; o++) { + outputCases[o] = Double.parseDouble(outputs[o]); + } + + addTestCase(new TestCase<Double>(inputCases, outputCases)); + } + + @Override + public boolean isPerfectSolution(Chromosome fittest) { + return fittest.getFitness() >= maxFitness.get() - perfectionThreshold.get(); + } + + @Override + public Parameter<?>[] getLocalParameters() { + return new Parameter[]{maxFitness, errorThreshold, perfectionThreshold, hitsBasedFitness}; + } + + @Override + public String getFileExtension() { + return ".dat"; + } +} |