aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/jcgp/backend/modules')
-rw-r--r--src/jcgp/backend/modules/mutator/PointMutator.java17
-rw-r--r--src/jcgp/backend/modules/problem/DigitalCircuit.java25
-rw-r--r--src/jcgp/backend/modules/problem/DigitalCircuitProblem.java85
-rw-r--r--src/jcgp/backend/modules/problem/SymbolicRegression.java26
-rw-r--r--src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java124
-rw-r--r--src/jcgp/backend/modules/problem/TestCaseProblem.java86
6 files changed, 264 insertions, 99 deletions
diff --git a/src/jcgp/backend/modules/mutator/PointMutator.java b/src/jcgp/backend/modules/mutator/PointMutator.java
index ab8efad..44c453a 100644
--- a/src/jcgp/backend/modules/mutator/PointMutator.java
+++ b/src/jcgp/backend/modules/mutator/PointMutator.java
@@ -7,18 +7,21 @@ import jcgp.backend.population.Output;
import jcgp.backend.resources.Resources;
import jcgp.backend.resources.parameters.BooleanParameter;
import jcgp.backend.resources.parameters.DoubleParameter;
+import jcgp.backend.resources.parameters.IntegerParameter;
import jcgp.backend.resources.parameters.Parameter;
import jcgp.backend.resources.parameters.ParameterStatus;
public class PointMutator implements Mutator {
private DoubleParameter mutationRate;
+ private IntegerParameter nodesMutated;
private BooleanParameter report;
public PointMutator(final Resources resources) {
mutationRate = new DoubleParameter(50, "Percent mutation", false, false) {
@Override
public void validate(Number newValue) {
+ nodesMutated.set((int) ((newValue.intValue()) * (((((double) resources.nodes() + resources.outputs()))) / 100)));
if (newValue.doubleValue() <= 0 || newValue.doubleValue() > 100) {
status = ParameterStatus.INVALID;
status.setDetails("Mutation rate must be > 0 and <= 100");
@@ -30,7 +33,12 @@ public class PointMutator implements Mutator {
}
}
};
-
+ nodesMutated = new IntegerParameter(0, "Genes mutated", true, false) {
+ @Override
+ public void validate(Number newValue) {
+ // blank
+ }
+ };
report = new BooleanParameter(false, "Report") {
@Override
public void validate(Boolean newValue) {
@@ -41,9 +49,8 @@ public class PointMutator implements Mutator {
@Override
public void mutate(Chromosome chromosome, Resources resources) {
- int mutations = (int) ((mutationRate.get()) * (((((double) resources.nodes() + resources.outputs()))) / 100));
- if (report.get()) resources.reportln("[Mutator] Number of mutations to be performed: " + mutations);
- for (int i = 0; i < mutations; i++) {
+ if (report.get()) resources.reportln("[Mutator] Number of mutations to be performed: " + nodesMutated.get());
+ for (int i = 0; i < nodesMutated.get(); i++) {
MutableElement m = chromosome.getRandomMutableElement();
if (report.get()) resources.report("[Mutator] Mutation " + i + " selected " + m.toString() + ", ");
@@ -75,7 +82,7 @@ public class PointMutator implements Mutator {
@Override
public Parameter<?>[] getLocalParameters() {
- return new Parameter[] {mutationRate, report};
+ return new Parameter[] {mutationRate, nodesMutated, report};
}
@Override
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();
}