diff options
Diffstat (limited to 'src/jcgp/backend/modules/problem')
5 files changed, 252 insertions, 94 deletions
diff --git a/src/jcgp/backend/modules/problem/DigitalCircuit.java b/src/jcgp/backend/modules/problem/DigitalCircuit.java deleted file mode 100644 index d94197d..0000000 --- a/src/jcgp/backend/modules/problem/DigitalCircuit.java +++ /dev/null @@ -1,25 +0,0 @@ -package jcgp.backend.modules.problem; - -import java.util.ArrayList; - -import jcgp.backend.function.BitwiseLogic; -import jcgp.backend.resources.Resources; - -public class DigitalCircuit extends TestCaseProblem<Integer> { - - public DigitalCircuit(Resources resources) { - super(resources); - functionSet = new BitwiseLogic(); - - ArrayList<TestCase<Integer>> tc = new ArrayList<TestCase<Integer>>(); - tc.add(new TestCase<Integer>(new Integer[]{1, 2, 3}, new Integer[]{-4, 5, 6})); - - setTestCases(tc); - } - - @Override - public String toString() { - return "Digital circuit"; - } - -} diff --git a/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java b/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java new file mode 100644 index 0000000..e92989e --- /dev/null +++ b/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java @@ -0,0 +1,85 @@ +package jcgp.backend.modules.problem; + +import jcgp.backend.function.BitwiseLogic; +import jcgp.backend.function.UnsignedInteger; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Population; +import jcgp.backend.resources.Resources; + +public class DigitalCircuitProblem extends TestCaseProblem<UnsignedInteger> { + + public DigitalCircuitProblem(Resources resources) { + super(resources); + functionSet = new BitwiseLogic(); + } + + @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 + int fitness = 0; + + // iterate over every 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++) { + Integer output = ((UnsignedInteger) population.getChromosome(i).getOutput(o).calculate()).get(); + Integer matches = ~(output ^ testCases.get(t).getOutput(o).get()); + // check only the relevant bits + int bits = (int) Math.pow(2.0, (double) resources.inputs()); + for (int b = 0; b < bits; b++) { + if (((matches >>> b) & 1) == 1) { + fitness++; + } + } + } + } + + // assign the resulting fitness to the respective individual + population.getChromosome(i).setFitness(fitness); + if (fitness >= population.getFittest().getFitness()) { + population.setFittest(i); + } + } + } + + @Override + protected int getMaxFitness() { + int maxFitness = (int) Math.pow(2.0, (double) resources.inputs()) * resources.outputs(); + return maxFitness; + } + + @Override + public String toString() { + return "Digital circuit"; + } + + @Override + public void addTestCase(String[] inputs, String[] outputs) { + UnsignedInteger[] inputCases = new UnsignedInteger[inputs.length]; + UnsignedInteger[] outputCases = new UnsignedInteger[outputs.length]; + for (int i = 0; i < inputCases.length; i++) { + inputCases[i] = new UnsignedInteger(inputs[i]); + } + for (int o = 0; o < outputCases.length; o++) { + outputCases[o] = new UnsignedInteger(outputs[o]); + } + + addTestCase(new TestCase<UnsignedInteger>(inputCases, outputCases)); + } + + @Override + public boolean isPerfectSolution(Chromosome fittest) { + return fittest.getFitness() >= maxFitness.get(); + } + + @Override + public String getFileExtension() { + return ".plu"; + } +} diff --git a/src/jcgp/backend/modules/problem/SymbolicRegression.java b/src/jcgp/backend/modules/problem/SymbolicRegression.java deleted file mode 100644 index 46b8e09..0000000 --- a/src/jcgp/backend/modules/problem/SymbolicRegression.java +++ /dev/null @@ -1,26 +0,0 @@ -package jcgp.backend.modules.problem; - -import java.util.ArrayList; - -import jcgp.backend.function.DoubleArithmetic; -import jcgp.backend.resources.Resources; - -public class SymbolicRegression extends TestCaseProblem<Double> { - - public SymbolicRegression(Resources resources) { - super(resources); - functionSet = new DoubleArithmetic(); - - ArrayList<TestCase<Double>> tc = new ArrayList<TestCase<Double>>(); - tc.add(new TestCase<Double>(new Double[]{1.0, 2.0, 3.0}, new Double[]{-4.0, 5.0, 6.0})); - tc.add(new TestCase<Double>(new Double[]{3.0, 2.0, 5.0}, new Double[]{2.0, 5.0, 9.0})); - - setTestCases(tc); - } - - @Override - public String toString() { - return "Symbolic regression"; - } - -} 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"; + } +} diff --git a/src/jcgp/backend/modules/problem/TestCaseProblem.java b/src/jcgp/backend/modules/problem/TestCaseProblem.java index ee72860..ff13c2e 100644 --- a/src/jcgp/backend/modules/problem/TestCaseProblem.java +++ b/src/jcgp/backend/modules/problem/TestCaseProblem.java @@ -1,11 +1,11 @@ package jcgp.backend.modules.problem; +import java.io.File; import java.util.List; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import jcgp.backend.population.Chromosome; -import jcgp.backend.population.Population; +import jcgp.backend.parser.TestCaseParser; import jcgp.backend.resources.Resources; import jcgp.backend.resources.parameters.IntegerParameter; import jcgp.backend.resources.parameters.Parameter; @@ -48,15 +48,16 @@ public abstract class TestCaseProblem<U extends Object> extends Problem { } } - private ObservableList<TestCase<U>> testCases; - private IntegerParameter maxFitness; - private final int inputCount, outputCount; + protected ObservableList<TestCase<U>> testCases; + protected IntegerParameter maxFitness; + protected Resources resources; + + protected TestCaseParser parser; public TestCaseProblem(Resources resources) { super(); - inputCount = resources.inputs(); - outputCount = resources.outputs(); + this.resources = resources; maxFitness = new IntegerParameter(0, "Max fitness", true, false) { @Override @@ -65,34 +66,26 @@ public abstract class TestCaseProblem<U extends Object> extends Problem { } }; testCases = FXCollections.observableArrayList(); + + parser = new TestCaseParser(this); } - - @Override - public void evaluate(Population population, Resources resources) { - // set fittest to 0, change it whenever a fitter one is found - population.setFittest(0); + public TestCaseProblem(Resources resources, File testCase) { + super(); - // for every chromosome in the population - for (int i = 0; i < resources.populationSize(); i++) { - // assume an initial fitness of 0 - int fitness = 0; - // for each test case - for (int t = 0; t < testCases.size(); t++) { - population.getChromosome(i).setInputs(testCases.get(t).getInputs()); - // check each output - for (int o = 0; o < resources.outputs(); o++) { - if (population.getChromosome(i).getOutput(o).calculate() == testCases.get(t).getOutput(o)) { - fitness++; - } - } - } - // assign the resulting fitness to the respective individual - population.getChromosome(i).setFitness(fitness); - if (fitness >= population.getFittest().getFitness()) { - population.setFittest(i); + this.resources = resources; + + maxFitness = new IntegerParameter(0, "Max fitness", true, false) { + @Override + public void validate(Number newValue) { + // blank } - } + }; + testCases = FXCollections.observableArrayList(); + + parser = new TestCaseParser(this); + + parser.parse(testCase); } @Override @@ -100,12 +93,7 @@ public abstract class TestCaseProblem<U extends Object> extends Problem { return new Parameter[]{maxFitness}; } - @Override - public boolean isPerfectSolution(Chromosome fittest) { - return fittest.getFitness() >= maxFitness.get(); - } - - private int getMaxFitness() { + protected int getMaxFitness() { int fitness = 0; for (TestCase<U> tc : testCases) { @@ -125,13 +113,15 @@ public abstract class TestCaseProblem<U extends Object> extends Problem { return testCases; } + public abstract void addTestCase(String[] inputs, String[] outputs); + public void addTestCase(TestCase<U> testCase) { - if (testCase.getInputs().length != inputCount) { + if (testCase.getInputs().length != resources.inputs()) { throw new IllegalArgumentException("Received test case with " + testCase.getInputs().length + - "inputs but need exactly " + inputCount); - } else if (testCase.getOutputs().length != outputCount) { + " inputs but need exactly " + resources.inputs()); + } else if (testCase.getOutputs().length != resources.outputs()) { throw new IllegalArgumentException("Received test case with " + testCase.getOutputs().length + - "outputs but need exactly " + outputCount); + " outputs but need exactly " + resources.outputs()); } else { this.testCases.add(testCase); maxFitness.set(getMaxFitness()); @@ -144,12 +134,22 @@ public abstract class TestCaseProblem<U extends Object> extends Problem { } public int getInputCount() { - return inputCount; + return resources.inputs(); } public int getOutputCount() { - return outputCount; + return resources.outputs(); + } + + public void parse(File file) { + parser.parse(file); } + + public void clearTestCases() { + testCases.clear(); + } + + public abstract String getFileExtension(); } |