aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/epar3.plu5
-rw-r--r--src/jcgp/JCGP.java17
-rw-r--r--src/jcgp/backend/function/BitwiseLogic.java124
-rw-r--r--src/jcgp/backend/function/BooleanLogic.java199
-rw-r--r--src/jcgp/backend/function/UnsignedInteger.java66
-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
-rw-r--r--src/jcgp/backend/parser/ChromosomeParser.java2
-rw-r--r--src/jcgp/backend/parser/FunctionParser.java7
-rw-r--r--src/jcgp/backend/parser/ParameterParser.java1
-rw-r--r--src/jcgp/backend/parser/TestCaseParser.java79
-rw-r--r--src/jcgp/backend/population/Chromosome.java6
-rw-r--r--src/jcgp/backend/resources/Resources.java4
-rw-r--r--src/jcgp/backend/tests/NodeTests.java2
-rw-r--r--src/jcgp/gui/population/GUIInput.java22
-rw-r--r--src/jcgp/gui/population/GUINode.java2
-rw-r--r--src/jcgp/gui/population/GUIOutput.java2
-rw-r--r--src/jcgp/gui/settings/SettingsPane.java76
-rw-r--r--src/jcgp/gui/settings/parameters/GUIDoubleParameter.java41
-rw-r--r--src/jcgp/gui/settings/parameters/GUIIntegerParameter.java32
-rw-r--r--src/jcgp/gui/settings/parameters/GUIParameter.java12
-rw-r--r--src/jcgp/gui/settings/testcase/TestCaseTable.java18
-rw-r--r--src/mult2.plu5
-rw-r--r--src/quintic-polynomial.dat26
28 files changed, 634 insertions, 477 deletions
diff --git a/src/epar3.plu b/src/epar3.plu
new file mode 100644
index 0000000..b554b66
--- /dev/null
+++ b/src/epar3.plu
@@ -0,0 +1,5 @@
+.i 3
+.o 1
+.p 1
+240 204 170 105
+.e \ No newline at end of file
diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java
index 1e847fb..f949944 100644
--- a/src/jcgp/JCGP.java
+++ b/src/jcgp/JCGP.java
@@ -7,9 +7,9 @@ import jcgp.backend.modules.es.MuPlusLambda;
import jcgp.backend.modules.es.TournamentSelection;
import jcgp.backend.modules.mutator.Mutator;
import jcgp.backend.modules.mutator.PointMutator;
-import jcgp.backend.modules.problem.DigitalCircuit;
+import jcgp.backend.modules.problem.DigitalCircuitProblem;
import jcgp.backend.modules.problem.Problem;
-import jcgp.backend.modules.problem.SymbolicRegression;
+import jcgp.backend.modules.problem.SymbolicRegressionProblem;
import jcgp.backend.modules.problem.TestCaseProblem;
import jcgp.backend.parser.ChromosomeParser;
import jcgp.backend.parser.FunctionParser;
@@ -60,8 +60,8 @@ public class JCGP {
// problem types
private Problem[] problems = new Problem[] {
- new SymbolicRegression(resources),
- new DigitalCircuit(resources) };
+ new SymbolicRegressionProblem(resources),
+ new DigitalCircuitProblem(resources) };
private Problem problem;
/*
@@ -84,7 +84,7 @@ public class JCGP {
jcgp.loadParameters(new File(args[0]));
if (jcgp.getProblem() instanceof TestCaseProblem) {
- TestCaseParser.parse(new File(args[2]), (TestCaseProblem<?>) jcgp.getProblem());
+ ((TestCaseProblem<?>) jcgp.getProblem()).parse(new File(args[2]));
}
jcgp.start();
@@ -230,7 +230,8 @@ public class JCGP {
private void reportGeneration() {
if (resources.reportInterval() > 0) {
if (resources.currentGeneration() % resources.reportInterval() == 0) {
- resources.println("[CGP] Generation: " + resources.currentGeneration());
+ resources.println("[CGP] Generation: " + resources.currentGeneration() + ", fittest chromosome ("
+ + population.getFittestIndex() + ") has fitness: " + population.getFittest().getFitness());
}
}
}
@@ -260,7 +261,9 @@ public class JCGP {
public void loadTestCases(File file) {
if (problem instanceof TestCaseProblem) {
- TestCaseParser.parse(file, (TestCaseProblem<?>) problem);
+ TestCaseParser.parseParameters(file, resources);
+ reset();
+ ((TestCaseProblem<?>) problem).parse(file);
}
}
diff --git a/src/jcgp/backend/function/BitwiseLogic.java b/src/jcgp/backend/function/BitwiseLogic.java
index 14f4488..a4c2737 100644
--- a/src/jcgp/backend/function/BitwiseLogic.java
+++ b/src/jcgp/backend/function/BitwiseLogic.java
@@ -31,8 +31,8 @@ public class BitwiseLogic extends FunctionSet {
public static class ConstantZero extends Function {
@Override
- public Long run(Connection... connections) {
- return new Long(0);
+ public UnsignedInteger run(Connection... connections) {
+ return new UnsignedInteger(0);
}
@Override
@@ -48,8 +48,8 @@ public class BitwiseLogic extends FunctionSet {
public static class ConstantOne extends Function {
@Override
- public Long run(Connection... connections) {
- return new Long(Long.MAX_VALUE);
+ public UnsignedInteger run(Connection... connections) {
+ return new UnsignedInteger(0xFFFF);
}
@Override
@@ -65,11 +65,11 @@ public class BitwiseLogic extends FunctionSet {
public static class WireA extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- return ((Long) connections[0].getValue()).longValue();
+ return ((UnsignedInteger) connections[0].getValue());
}
}
@@ -86,11 +86,11 @@ public class BitwiseLogic extends FunctionSet {
public static class WireB extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- return ((Long) connections[1].getValue()).longValue();
+ return ((UnsignedInteger) connections[1].getValue());
}
}
@@ -107,11 +107,11 @@ public class BitwiseLogic extends FunctionSet {
public static class NotA extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- return ~((Long) connections[0].getValue()).longValue();
+ return new UnsignedInteger(~((UnsignedInteger) connections[0].getValue()).get());
}
}
@@ -128,11 +128,11 @@ public class BitwiseLogic extends FunctionSet {
public static class NotB extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- return ~((Long) connections[1].getValue()).longValue();
+ return new UnsignedInteger(~((UnsignedInteger) connections[1].getValue()).get());
}
}
@@ -149,15 +149,15 @@ public class BitwiseLogic extends FunctionSet {
public static class And extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 & arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() & arg2.get();
- return result;
+ return new UnsignedInteger(result);
}
}
@@ -174,15 +174,15 @@ public class BitwiseLogic extends FunctionSet {
public static class AndNotA extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = ~arg1 & arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = ~(arg1.get()) & arg2.get();
- return result;
+ return new UnsignedInteger(result);
}
}
@@ -199,15 +199,15 @@ public class BitwiseLogic extends FunctionSet {
public static class AndNotB extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 & ~arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() & ~(arg2.get());
- return result;
+ return new UnsignedInteger(result);
}
}
@@ -224,15 +224,15 @@ public class BitwiseLogic extends FunctionSet {
public static class Nor extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 | arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() | arg2.get();
- return ~result;
+ return new UnsignedInteger(~result);
}
}
@@ -249,15 +249,15 @@ public class BitwiseLogic extends FunctionSet {
public static class Xor extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 ^ arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() ^ arg2.get();
- return result;
+ return new UnsignedInteger(result);
}
}
@@ -274,15 +274,15 @@ public class BitwiseLogic extends FunctionSet {
public static class Xnor extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 ^ arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() ^ arg2.get();
- return ~result;
+ return new UnsignedInteger(~result);
}
}
@@ -299,15 +299,15 @@ public class BitwiseLogic extends FunctionSet {
public static class Or extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 | arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() | arg2.get();
- return result;
+ return new UnsignedInteger(result);
}
}
@@ -324,15 +324,15 @@ public class BitwiseLogic extends FunctionSet {
public static class OrNotA extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = ~arg1 | arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = ~arg1.get() | arg2.get();
- return result;
+ return new UnsignedInteger(result);
}
}
@@ -349,15 +349,15 @@ public class BitwiseLogic extends FunctionSet {
public static class OrNotB extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 | ~arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() | ~arg2.get();
- return result;
+ return new UnsignedInteger(result);
}
}
@@ -374,15 +374,15 @@ public class BitwiseLogic extends FunctionSet {
public static class Nand extends Function {
@Override
- public Long run(Connection... connections) {
+ public UnsignedInteger run(Connection... connections) {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- Long arg1 = ((Long) connections[0].getValue());
- Long arg2 = ((Long) connections[1].getValue());
- Long result = arg1 & arg2;
+ UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = arg1.get() & arg2.get();
- return ~result;
+ return new UnsignedInteger(~result);
}
}
diff --git a/src/jcgp/backend/function/BooleanLogic.java b/src/jcgp/backend/function/BooleanLogic.java
deleted file mode 100644
index 9e7d1ff..0000000
--- a/src/jcgp/backend/function/BooleanLogic.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package jcgp.backend.function;
-
-
-import jcgp.backend.exceptions.InvalidArgumentsException;
-import jcgp.backend.population.Connection;
-
-public class BooleanLogic extends FunctionSet {
-
- public BooleanLogic() {
- name = "1-bit Logic";
- functionList = new Function[]{
- new And(),
- new Or(),
- new Not(),
- new Xor(),
- new Nand(),
- new Nor(),
- new Xnor()};
-
- enableAll();
- }
-
- public static class And extends Function {
- @Override
- public Boolean run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
- } else {
- Boolean arg1 = ((Boolean) connections[0].getValue());
- Boolean arg2 = ((Boolean) connections[1].getValue());
- Boolean result = arg1 && arg2;
-
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "AND";
- }
- }
-
- public static class Or extends Function {
- @Override
- public Boolean run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
- } else {
- Boolean arg1 = ((Boolean) connections[0].getValue());
- Boolean arg2 = ((Boolean) connections[1].getValue());
- Boolean result = arg1 || arg2;
-
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "OR";
- }
- }
-
- public static class Not extends Function {
- @Override
- public Boolean run(Connection... connections) {
- if (connections.length < 1) {
- throw new InvalidArgumentsException("Not enough connections were given.");
- } else {
- Boolean arg1 = ((Boolean) connections[0].getValue());
- Boolean result = !arg1;
-
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 1;
- }
-
- @Override
- public String getName() {
- return "NOT";
- }
- }
-
- public static class Xor extends Function {
- @Override
- public Boolean run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
- } else {
- Boolean arg1 = ((Boolean) connections[0].getValue());
- Boolean arg2 = ((Boolean) connections[1].getValue());
- Boolean result = arg1 ^ arg2;
-
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "XOR";
- }
- }
-
- public static class Nand extends Function {
- @Override
- public Boolean run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
- } else {
- Boolean arg1 = ((Boolean) connections[0].getValue());
- Boolean arg2 = ((Boolean) connections[1].getValue());
- Boolean result = arg1 && arg2;
-
- return !result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "NAND";
- }
- }
-
- public static class Nor extends Function {
- @Override
- public Boolean run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
- } else {
- Boolean arg1 = ((Boolean) connections[0].getValue());
- Boolean arg2 = ((Boolean) connections[1].getValue());
- Boolean result = arg1 || arg2;
-
- return !result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "NOR";
- }
- }
-
- public static class Xnor extends Function {
- @Override
- public Boolean run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
- } else {
- Boolean arg1 = ((Boolean) connections[0].getValue());
- Boolean arg2 = ((Boolean) connections[1].getValue());
- Boolean result = arg1 ^ arg2;
-
- return !result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "XNOR";
- }
- }
-
-
-
-}
diff --git a/src/jcgp/backend/function/UnsignedInteger.java b/src/jcgp/backend/function/UnsignedInteger.java
new file mode 100644
index 0000000..7feb33f
--- /dev/null
+++ b/src/jcgp/backend/function/UnsignedInteger.java
@@ -0,0 +1,66 @@
+package jcgp.backend.function;
+
+/**
+ * Integer wrapper type for unsigned integer values.
+ * <br><br>
+ * Java offers no support for unsigned types save from
+ * unsigned conversion methods. This class uses those methods
+ * to simulate the unsigned int data type, useful for circuit
+ * truth table encodings.
+ * <br><br>
+ * When a string representation of an unsigned integer is parsed
+ * using Integer.parseUnsignedInt(), an Integer is created using
+ * all 32 bits for unsigned magnitude. The integer however is still
+ * signed and will behave as such for all arithmetic operations.
+ * Bitwise operations can still be performed as they work at the bit
+ * level, making this data type particularly suitable for circuit design.
+ *
+ *
+ * @author Eduardo Pedroni
+ * @see Integer
+ *
+ */
+public class UnsignedInteger {
+
+ private Integer value;
+
+ /**
+ * Makes a new instance of UnsignedInteger with a specified value.
+ *
+ * @param i the value with which to initialise
+ */
+ public UnsignedInteger(int i) {
+ value = new Integer(i);
+ }
+
+ /**
+ * Makes a new instance of UnsignedInteger with a specified value.
+ *
+ * @param i the value with which to initialise
+ */
+ public UnsignedInteger(Integer i) {
+ value = i;
+ }
+
+ /**
+ * Makes a new instance of UnsignedInteger from the string representation
+ * of an unsigned integer.
+ *
+ * @param i the string with which to initialise
+ */
+ public UnsignedInteger(String i) {
+ value = Integer.parseUnsignedInt(i);
+ }
+
+ /**
+ * @return the wrapped Integer object
+ */
+ public Integer get() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toUnsignedString(value);
+ }
+}
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();
}
diff --git a/src/jcgp/backend/parser/ChromosomeParser.java b/src/jcgp/backend/parser/ChromosomeParser.java
index 74f638c..d5af1bd 100644
--- a/src/jcgp/backend/parser/ChromosomeParser.java
+++ b/src/jcgp/backend/parser/ChromosomeParser.java
@@ -17,7 +17,7 @@ import jcgp.backend.resources.Resources;
* @author Eduardo Pedroni
*
*/
-public class ChromosomeParser {
+public abstract class ChromosomeParser {
/**
* Use this method to parse .chr files into a given chromosome.
diff --git a/src/jcgp/backend/parser/FunctionParser.java b/src/jcgp/backend/parser/FunctionParser.java
index 64a095c..ab94899 100644
--- a/src/jcgp/backend/parser/FunctionParser.java
+++ b/src/jcgp/backend/parser/FunctionParser.java
@@ -40,17 +40,10 @@ private FunctionSet functionSet;
}
private void parseAndSet(String[] splitString) {
-// System.out.println("new line");
-// for (int i= 0; i < splitString.length; i++) {
-// System.out.println(i + ": " + splitString[i]);
-// }
int functionIndex = Integer.parseInt(splitString[splitString.length - 1]);
- System.out.println("index: " + functionIndex);
if (Integer.parseInt(splitString[0]) != 0) {
- System.out.println("enabling: " + functionSet.getFunction(functionIndex).getName());
functionSet.enableFunction(functionIndex);
} else {
- System.out.println("disabling: " + functionSet.getFunction(functionIndex).getName());
functionSet.disableFunction(functionIndex);
}
diff --git a/src/jcgp/backend/parser/ParameterParser.java b/src/jcgp/backend/parser/ParameterParser.java
index 473b632..f96ebf9 100644
--- a/src/jcgp/backend/parser/ParameterParser.java
+++ b/src/jcgp/backend/parser/ParameterParser.java
@@ -4,6 +4,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
+
import jcgp.backend.resources.ModifiableResources;
public class ParameterParser {
diff --git a/src/jcgp/backend/parser/TestCaseParser.java b/src/jcgp/backend/parser/TestCaseParser.java
index c997177..d47d663 100644
--- a/src/jcgp/backend/parser/TestCaseParser.java
+++ b/src/jcgp/backend/parser/TestCaseParser.java
@@ -1,13 +1,90 @@
package jcgp.backend.parser;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.Scanner;
import jcgp.backend.modules.problem.TestCaseProblem;
+import jcgp.backend.resources.ModifiableResources;
public class TestCaseParser {
- public static void parse(File file, TestCaseProblem<?> problem) {
+ private TestCaseProblem<?> problem;
+
+ public TestCaseParser(TestCaseProblem<?> problem) {
+ this.problem = problem;
+ }
+
+ public void parse(File file) {
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Scanner in = new Scanner(fr);
+ boolean readingTestCases = false;
+ int inputs = 0, outputs = 0;
+
+ problem.clearTestCases();
+
+ while (in.hasNextLine()) {
+ String nextLine = in.nextLine();
+
+ if (nextLine.startsWith(".i")) {
+ String[] split = nextLine.split(" +");
+ inputs = Integer.parseInt(split[1]);
+ } else if (nextLine.startsWith(".o")) {
+ String[] split = nextLine.split(" +");
+ outputs = Integer.parseInt(split[1]);
+ } else if (nextLine.startsWith(".p") || nextLine.startsWith(".t")) {
+ readingTestCases = true;
+ } else if (nextLine.startsWith(".e")) {
+ readingTestCases = false;
+ // set test cases? not safe probably
+ } else if (readingTestCases) {
+ String[] split = nextLine.split("( |\t)+");
+ String[] inputCases = new String[inputs];
+ String[] outputCases = new String[outputs];
+ for (int i = 0; i < inputs; i++) {
+ inputCases[i] = split[i];
+ }
+ for (int o = 0; o < outputs; o++) {
+ outputCases[o] = split[o + inputs];
+ }
+
+ problem.addTestCase(inputCases, outputCases);
+ }
+ }
+ in.close();
}
+ public static void parseParameters(File file, ModifiableResources resources) {
+
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Scanner in = new Scanner(fr);
+
+ while (in.hasNextLine()) {
+ String nextLine = in.nextLine();
+ if (nextLine.startsWith(".i")) {
+ String[] split = nextLine.split(" +");
+ resources.setInputs(Integer.parseInt(split[1]));
+ } else if (nextLine.startsWith(".o")) {
+ String[] split = nextLine.split(" +");
+ resources.setOutputs(Integer.parseInt(split[1]));
+ }
+ }
+ in.close();
+ }
}
diff --git a/src/jcgp/backend/population/Chromosome.java b/src/jcgp/backend/population/Chromosome.java
index 71e19ec..f8830fa 100644
--- a/src/jcgp/backend/population/Chromosome.java
+++ b/src/jcgp/backend/population/Chromosome.java
@@ -15,7 +15,7 @@ public class Chromosome {
private ArrayList<Node> activeNodes;
- private int fitness = 0;
+ private double fitness = 0;
private boolean recomputeActiveNodes = true;
/**
@@ -154,11 +154,11 @@ public class Chromosome {
return inputs[index];
}
- public int getFitness() {
+ public double getFitness() {
return fitness;
}
- public void setFitness(int newFitness) {
+ public void setFitness(double newFitness) {
fitness = newFitness;
}
diff --git a/src/jcgp/backend/resources/Resources.java b/src/jcgp/backend/resources/Resources.java
index 0bf1ee1..151d536 100644
--- a/src/jcgp/backend/resources/Resources.java
+++ b/src/jcgp/backend/resources/Resources.java
@@ -155,7 +155,7 @@ public class Resources {
}
};
- inputs = new IntegerParameter(3, "Inputs", false, true) {
+ inputs = new IntegerParameter(3, "Inputs", true, false) {
@Override
public void validate(Number newValue) {
if (newValue.intValue() <= 0) {
@@ -167,7 +167,7 @@ public class Resources {
}
};
- outputs = new IntegerParameter(3, "Outputs", false, true) {
+ outputs = new IntegerParameter(3, "Outputs", true, false) {
@Override
public void validate(Number newValue) {
if (newValue.intValue() <= 0) {
diff --git a/src/jcgp/backend/tests/NodeTests.java b/src/jcgp/backend/tests/NodeTests.java
index c9f247a..4054661 100644
--- a/src/jcgp/backend/tests/NodeTests.java
+++ b/src/jcgp/backend/tests/NodeTests.java
@@ -2,8 +2,8 @@ package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
import jcgp.backend.exceptions.InvalidArgumentsException;
-import jcgp.backend.function.Function;
import jcgp.backend.function.DoubleArithmetic;
+import jcgp.backend.function.Function;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Node;
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index 6a783db..065c125 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -7,7 +7,6 @@ import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Input;
-import jcgp.backend.population.Output;
import jcgp.gui.GUI;
public class GUIInput extends GUIGene {
@@ -40,20 +39,12 @@ public class GUIInput extends GUIGene {
// the drag has entered this node, react appropriately
// this happens even if we are the source of the drag
((GUIGene) event.getGestureSource()).setConnectionLine((GUIGene) event.getSource());
-
- if (event.getGestureSource() instanceof GUINode) {
- Connection source = ((GUINode) event.getGestureSource()).getChangingConnection();
- if (input == source) {
- setState(GUIGeneState.NO_CHANGE_TARGET);
- return;
- }
- } else if (event.getGestureSource() instanceof GUIOutput) {
- Output source = ((GUIOutput) event.getGestureSource()).getGene();
- if (((GUIGene) event.getSource()).getGene() == source.getSource()) {
- ((GUIGene) event.getSource()).setState(GUIGeneState.NO_CHANGE_TARGET);
- }
+ Connection source = ((GUIGene) event.getGestureSource()).getChangingConnection();
+ if (input == source) {
+ setState(GUIGeneState.NO_CHANGE_TARGET);
+ } else {
+ setState(GUIGeneState.TARGET);
}
- setState(GUIGeneState.TARGET);
}
});
@@ -170,7 +161,6 @@ public class GUIInput extends GUIGene {
break;
default:
break;
-
}
}
@@ -241,7 +231,7 @@ public class GUIInput extends GUIGene {
@Override
public void updateText() {
if (parent.isEvaluating()) {
- text.setText("I: " + input.getIndex() + "\nValue: " + value.toString());
+ text.setText("I: " + input.getIndex() + "\n" + value.toString());
} else {
text.setText("I: " + input.getIndex());
}
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index 2b953c0..f50edd3 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -454,7 +454,7 @@ public class GUINode extends GUIGene {
public void updateText() {
if (parent.isEvaluating()) {
- text.setText(node.getFunction().getName() + "\nValue: " + value.toString());
+ text.setText(node.getFunction().getName() + "\n" + value.toString());
} else {
text.setText(node.getFunction().getName());
}
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index 89c12b3..79159b9 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -321,7 +321,7 @@ public class GUIOutput extends GUIGene {
@Override
public void updateText() {
if (parent.isEvaluating()) {
- text.setText("O: " + output.getIndex() + "\nValue: " + value.toString());
+ text.setText("O: " + output.getIndex() + "\n" + value.toString());
} else {
text.setText("O: " + output.getIndex());
}
diff --git a/src/jcgp/gui/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java
index 4e8c342..4050a89 100644
--- a/src/jcgp/gui/settings/SettingsPane.java
+++ b/src/jcgp/gui/settings/SettingsPane.java
@@ -6,7 +6,6 @@ import java.util.ArrayList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
-import javafx.scene.Group;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
@@ -125,8 +124,7 @@ public class SettingsPane extends AnchorPane {
eaCBox.getSelectionModel().select(jcgp.getEvolutionaryStrategy());
eaCBox.prefWidthProperty().bind(mainContainer.widthProperty());
- final VBox eaParameters = new VBox();
- eaParameters.setSpacing(2);
+ final VBox eaParameters = new VBox(2);
if (jcgp.getEvolutionaryStrategy().getLocalParameters() != null) {
refreshParameters(jcgp.getEvolutionaryStrategy().getLocalParameters(), eaParameters);
@@ -158,8 +156,7 @@ public class SettingsPane extends AnchorPane {
mutatorCBox.getSelectionModel().select(jcgp.getMutator());
mutatorCBox.prefWidthProperty().bind(mainContainer.widthProperty());
- final VBox mutatorParameters = new VBox();
- mutatorParameters.setSpacing(2);
+ final VBox mutatorParameters = new VBox(2);
if (jcgp.getEvolutionaryStrategy().getLocalParameters() != null) {
refreshParameters(jcgp.getMutator().getLocalParameters(), mutatorParameters);
}
@@ -190,23 +187,27 @@ public class SettingsPane extends AnchorPane {
problemCBox.getSelectionModel().select(jcgp.getProblem());
problemCBox.prefWidthProperty().bind(mainContainer.widthProperty());
- final VBox problemParameters = new VBox();
- problemParameters.setSpacing(2);
+ final VBox problemParameters = new VBox(2);
problemParameters.setPadding(new Insets(0, 0, 4, 0));
if (jcgp.getProblem().getLocalParameters() != null) {
refreshParameters(jcgp.getProblem().getLocalParameters(), problemParameters);
}
- final Group showTestCaseContainer = new Group();
+ final HBox testCaseControlContainer = new HBox(2);
+
final Button showTestCaseButton = makeTestCaseButton();
+ final Button loadTestCaseButton = makeLoadTestCaseButton();
+ HBox.setHgrow(showTestCaseButton, Priority.ALWAYS);
+ showTestCaseButton.setMaxWidth(Double.MAX_VALUE);
+ HBox.setHgrow(loadTestCaseButton, Priority.ALWAYS);
+ loadTestCaseButton.setMaxWidth(Double.MAX_VALUE);
+
if (jcgp.getProblem() instanceof TestCaseProblem<?>) {
- showTestCaseContainer.getChildren().add(showTestCaseButton);
-
- testCaseTable = new TestCaseTable((TestCaseProblem<Object>) jcgp.getProblem(), gui);
+ testCaseControlContainer.getChildren().addAll(showTestCaseButton, loadTestCaseButton);
+ remakeTestCaseTable();
}
- nodeFunctions = new VBox();
- nodeFunctions.setSpacing(2);
+ nodeFunctions = new VBox(2);
nodeFunctions.setPadding(new Insets(0, 0, 4, 0));
refreshFunctions();
@@ -220,20 +221,40 @@ public class SettingsPane extends AnchorPane {
testCaseTable.close();
gui.setEvaluating(false);
refreshFunctions();
- showTestCaseContainer.getChildren().clear();
+ testCaseControlContainer.getChildren().clear();
if (jcgp.getProblem() instanceof TestCaseProblem) {
- showTestCaseContainer.getChildren().add(showTestCaseButton);
- testCaseTable = new TestCaseTable((TestCaseProblem<Object>) jcgp.getProblem(), gui);
+ testCaseControlContainer.getChildren().addAll(showTestCaseButton, loadTestCaseButton);
+ remakeTestCaseTable();
}
gui.reset();
}
});
- problemPane.getChildren().addAll(header, problemCBox, problemParameters, nodeFunctions, showTestCaseContainer);
+ problemPane.getChildren().addAll(header, problemCBox, problemParameters, nodeFunctions, testCaseControlContainer);
mainContainer.getChildren().add(problemPane);
}
+ private Button makeLoadTestCaseButton() {
+ Button b = new Button("Load test cases");
+ b.setOnAction(new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent event) {
+ FileChooser fc = new FileChooser();
+ fc.setTitle("Open test case file...");
+ fc.getExtensionFilters().add(new ExtensionFilter("CGP " + gui.getExperiment().getProblem() + " files", "*" + ((TestCaseProblem<?>) gui.getExperiment().getProblem()).getFileExtension()));
+ fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*"));
+ File chrFile = fc.showOpenDialog(gui.getStage());
+ if (chrFile != null) {
+ gui.getExperiment().loadTestCases(chrFile);
+ remakeTestCaseTable();
+ gui.reDraw();
+ }
+ }
+ });
+ return b;
+ }
+
private Button makeTestCaseButton() {
Button b = new Button("Show test cases");
b.setOnAction(new EventHandler<ActionEvent>() {
@@ -295,9 +316,9 @@ public class SettingsPane extends AnchorPane {
File parFile = fc.showOpenDialog(gui.getStage());
if (parFile != null) {
gui.getExperiment().loadParameters(parFile);
+ gui.reDraw();
+ refreshFunctions();
}
- gui.reDraw();
- refreshFunctions();
}
});
@@ -311,14 +332,14 @@ public class SettingsPane extends AnchorPane {
File chrFile = fc.showOpenDialog(gui.getStage());
if (chrFile != null) {
gui.getExperiment().loadChromosome(chrFile);
+ gui.reDraw();
}
- gui.reDraw();
}
});
saveChromosome.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
- //gui.step();
+
}
});
@@ -458,10 +479,21 @@ public class SettingsPane extends AnchorPane {
loadChromosome.setDisable(running);
saveChromosome.setDisable(running);
-
testCaseTable.getTable().setDisable(running);
}
+ private void remakeTestCaseTable() {
+ boolean wasShowing = false;
+ if (testCaseTable != null) {
+ wasShowing = testCaseTable.isShowing();
+ testCaseTable.close();
+ }
+ testCaseTable = new TestCaseTable((TestCaseProblem<Object>) gui.getExperiment().getProblem(), gui);
+ if (wasShowing) {
+ testCaseTable.show();
+ }
+ }
+
public TestCaseTable getTestCaseTable() {
return testCaseTable;
}
diff --git a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
index 29648ca..9a6ec4a 100644
--- a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
@@ -1,12 +1,12 @@
package jcgp.gui.settings.parameters;
+import java.text.DecimalFormat;
+
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
-import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Control;
import javafx.scene.control.TextField;
-import javafx.scene.input.KeyEvent;
import jcgp.backend.resources.parameters.Parameter;
import jcgp.backend.resources.parameters.ParameterStatus;
import jcgp.gui.settings.SettingsPane;
@@ -23,6 +23,7 @@ import jcgp.gui.settings.SettingsPane;
public class GUIDoubleParameter extends GUIParameter<Number> {
private TextField textField;
+ private DecimalFormat decimalFormat;
/**
* This default-visibility constructor is intended for use
@@ -31,6 +32,8 @@ public class GUIDoubleParameter extends GUIParameter<Number> {
*/
GUIDoubleParameter(Parameter<Number> parameter, SettingsPane sp) {
super(parameter, sp);
+ decimalFormat = new DecimalFormat();
+ decimalFormat.setMaximumFractionDigits(10);
}
@Override
@@ -38,23 +41,12 @@ public class GUIDoubleParameter extends GUIParameter<Number> {
textField = new TextField(String.valueOf(parameter.get()));
textField.setStyle(VALID_PARAMETER_STYLE);
textField.setAlignment(Pos.CENTER_RIGHT);
-
+ textField.prefWidthProperty().bind(widthProperty().divide(2));
return textField;
}
@Override
protected void setControlListeners() {
- /* filter keypresses and ignore anything that is not a number
- * and any decimal point beyond the first ones */
- textField.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
- @Override
- public void handle( KeyEvent t ) {
- char ch = t.getCharacter().toCharArray()[t.getCharacter().toCharArray().length - 1];
- if (!((ch >= '0' && ch <= '9') || (ch == '.' && !textField.getText().contains(".")))) {
- t.consume();
- }
- }
- });
/* pass the TextField value back to the parameter whenever it gets
* modified, provided it is not empty and the experiment isn't running */
textField.textProperty().addListener(new ChangeListener<String>() {
@@ -62,11 +54,17 @@ public class GUIDoubleParameter extends GUIParameter<Number> {
public void changed(
ObservableValue<? extends String> observable,
String oldValue, String newValue) {
- if (!newValue.isEmpty() && !settingsPane.isExperimentRunning()) {
- parameter.set(Double.parseDouble(newValue));
- settingsPane.revalidateParameters();
+ if (!settingsPane.isExperimentRunning()) {
+ if (newValue.matches("([0-9]*[.]*[0-9]*)")) {
+ if (!newValue.isEmpty()) {
+ double value = Double.parseDouble(newValue);
+ parameter.set(value);
+ settingsPane.revalidateParameters();
+ }
+ } else {
+ refreshValue();
+ }
}
-
}
});
/* if the TextField loses focus and is empty, set it to the current
@@ -76,8 +74,8 @@ public class GUIDoubleParameter extends GUIParameter<Number> {
public void changed(
ObservableValue<? extends Boolean> observable,
Boolean oldValue, Boolean newValue) {
- if (!newValue && textField.getText().isEmpty()) {
- textField.setText(String.valueOf(parameter.get()));
+ if (!newValue) {
+ refreshValue();
}
}
});
@@ -102,6 +100,7 @@ public class GUIDoubleParameter extends GUIParameter<Number> {
@Override
public void refreshValue() {
- textField.setText(String.valueOf((parameter).get()));
+ System.out.println("setting text to: " + parameter.get().doubleValue());
+ textField.setText(decimalFormat.format(parameter.get().doubleValue()));
}
}
diff --git a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
index da2c11f..ee266f3 100644
--- a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
@@ -2,11 +2,9 @@ package jcgp.gui.settings.parameters;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
-import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Control;
import javafx.scene.control.TextField;
-import javafx.scene.input.KeyEvent;
import jcgp.backend.resources.parameters.Parameter;
import jcgp.backend.resources.parameters.ParameterStatus;
import jcgp.gui.settings.SettingsPane;
@@ -38,22 +36,13 @@ public class GUIIntegerParameter extends GUIParameter<Number> {
textField = new TextField(String.valueOf(parameter.get()));
textField.setStyle(VALID_PARAMETER_STYLE);
textField.setAlignment(Pos.CENTER_RIGHT);
+ textField.prefWidthProperty().bind(widthProperty().divide(2));
return textField;
}
@Override
protected void setControlListeners() {
- /* filter keypresses and ignore anything that is not a number */
- textField.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
- @Override
- public void handle( KeyEvent t ) {
- char ch = t.getCharacter().toCharArray()[t.getCharacter().toCharArray().length - 1];
- if (!(ch >= '0' && ch <= '9')) {
- t.consume();
- }
- }
- });
/* pass the TextField value back to the parameter whenever it gets
* modified, provided it is not empty and the experiment isn't running */
textField.textProperty().addListener(new ChangeListener<String>() {
@@ -61,9 +50,16 @@ public class GUIIntegerParameter extends GUIParameter<Number> {
public void changed(
ObservableValue<? extends String> observable,
String oldValue, String newValue) {
- if (!newValue.isEmpty() && !settingsPane.isExperimentRunning()) {
- parameter.set(Double.parseDouble(newValue));
- settingsPane.revalidateParameters();
+ if (!settingsPane.isExperimentRunning()) {
+ if (newValue.matches("[0-9]*")) {
+ if (!newValue.isEmpty()) {
+ int value = Integer.parseInt(newValue);
+ parameter.set(value);
+ settingsPane.revalidateParameters();
+ }
+ } else {
+ refreshValue();
+ }
}
}
});
@@ -74,8 +70,8 @@ public class GUIIntegerParameter extends GUIParameter<Number> {
public void changed(
ObservableValue<? extends Boolean> observable,
Boolean oldValue, Boolean newValue) {
- if (!newValue && textField.getText().isEmpty()) {
- textField.setText(String.valueOf(parameter.get()));
+ if (!newValue) {
+ refreshValue();
}
}
});
@@ -101,6 +97,6 @@ public class GUIIntegerParameter extends GUIParameter<Number> {
@Override
public void refreshValue() {
- textField.setText(String.valueOf((parameter).get()));
+ textField.setText(String.valueOf(parameter.get()));
}
}
diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java
index 159e709..7dd7231 100644
--- a/src/jcgp/gui/settings/parameters/GUIParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIParameter.java
@@ -7,10 +7,9 @@ import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.control.Control;
+import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.text.Text;
import jcgp.backend.resources.parameters.BooleanParameter;
import jcgp.backend.resources.parameters.DoubleParameter;
import jcgp.backend.resources.parameters.IntegerParameter;
@@ -46,7 +45,7 @@ public abstract class GUIParameter<T> extends HBox {
public static final String WARNING_PARAMETER_STYLE = "-fx-background-color: " + GUI.NEUTRAL_SELECTION_COLOUR;
public static final String VALID_PARAMETER_STYLE = "-fx-background-color: " + GUI.NEUTRAL_COLOUR;
- private Text name;
+ private Label name;
private Control valueControl;
protected SettingsPane settingsPane;
@@ -80,9 +79,9 @@ public abstract class GUIParameter<T> extends HBox {
setAlignment(Pos.CENTER_LEFT);
setSpacing(5);
- name = new Text(parameter.getName());
+ name = new Label(parameter.getName());
// set text width to half of the total width of the GUIParameter
- name.wrappingWidthProperty().bind(widthProperty().divide(2));
+ name.prefWidthProperty().bind(widthProperty().divide(2));
// the tooltip is the hover-over label containing status information, when appropriate
tooltip = new Tooltip();
@@ -90,7 +89,6 @@ public abstract class GUIParameter<T> extends HBox {
tooltip.setSkin(null);
valueControl = makeControl();
- setHgrow(valueControl, Priority.ALWAYS);
// if the parameter is a monitor, it should be permanently disabled
valueControl.setDisable(parameter.isMonitor());
@@ -177,7 +175,7 @@ public abstract class GUIParameter<T> extends HBox {
*/
public void validate() {
parameter.validate(parameter.get());
- refreshValue();
+ //refreshValue();
setValidityStyle();
}
diff --git a/src/jcgp/gui/settings/testcase/TestCaseTable.java b/src/jcgp/gui/settings/testcase/TestCaseTable.java
index b84f9ab..d7b2e2b 100644
--- a/src/jcgp/gui/settings/testcase/TestCaseTable.java
+++ b/src/jcgp/gui/settings/testcase/TestCaseTable.java
@@ -19,7 +19,6 @@ import jcgp.backend.modules.problem.TestCaseProblem.TestCase;
import jcgp.gui.GUI;
/**
- * Dont forget to override toString()!
*
*
* @author Eduardo Pedroni
@@ -29,17 +28,17 @@ public class TestCaseTable extends Stage {
private TableView<TestCase<Object>> table;
- public TestCaseTable(final TestCaseProblem<Object> problem, final GUI gui) {
+ public TestCaseTable(final TestCaseProblem<Object> testCaseProblem, final GUI gui) {
super();
table = new TableView<TestCase<Object>>();
- ObservableList<TestCase<Object>> testCaseList = problem.getTestCases();
+ ObservableList<TestCase<Object>> testCaseList = testCaseProblem.getTestCases();
- ArrayList<TableColumn<TestCase<Object>, String>> inputs = new ArrayList<TableColumn<TestCase<Object>, String>>(problem.getInputCount());
- ArrayList<TableColumn<TestCase<Object>, String>> outputs = new ArrayList<TableColumn<TestCase<Object>, String>>(problem.getOutputCount());
+ ArrayList<TableColumn<TestCase<Object>, String>> inputs = new ArrayList<TableColumn<TestCase<Object>, String>>(testCaseProblem.getInputCount());
+ ArrayList<TableColumn<TestCase<Object>, String>> outputs = new ArrayList<TableColumn<TestCase<Object>, String>>(testCaseProblem.getOutputCount());
TableColumn<TestCase<Object>, String> tc;
- for (int i = 0; i < problem.getInputCount(); i++) {
+ for (int i = 0; i < testCaseProblem.getInputCount(); i++) {
tc = new TableColumn<TestCase<Object>, String>("I: " + i);
inputs.add(tc);
final int index = i;
@@ -50,10 +49,10 @@ public class TestCaseTable extends Stage {
}
});
tc.setSortable(false);
- tc.prefWidthProperty().bind(table.widthProperty().divide(problem.getInputCount() + problem.getOutputCount()));
+ tc.prefWidthProperty().bind(table.widthProperty().divide(testCaseProblem.getInputCount() + testCaseProblem.getOutputCount()));
}
- for (int o = 0; o < problem.getOutputCount(); o++) {
+ for (int o = 0; o < testCaseProblem.getOutputCount(); o++) {
tc = new TableColumn<TestCase<Object>, String>("O: " + o);
outputs.add(tc);
final int index = o;
@@ -64,7 +63,7 @@ public class TestCaseTable extends Stage {
}
});
tc.setSortable(false);
- tc.prefWidthProperty().bind(table.widthProperty().divide(problem.getInputCount() + problem.getOutputCount()));
+ tc.prefWidthProperty().bind(table.widthProperty().divide(testCaseProblem.getInputCount() + testCaseProblem.getOutputCount()));
}
table.getColumns().addAll(inputs);
@@ -84,6 +83,7 @@ public class TestCaseTable extends Stage {
@Override
public void handle(WindowEvent event) {
gui.hideGeneValues();
+ table.getSelectionModel().select(null);
}
});
diff --git a/src/mult2.plu b/src/mult2.plu
new file mode 100644
index 0000000..e629d28
--- /dev/null
+++ b/src/mult2.plu
@@ -0,0 +1,5 @@
+.i 4
+.o 4
+.p 1
+65280 61680 52428 43690 32768 19456 27328 41120
+.e \ No newline at end of file
diff --git a/src/quintic-polynomial.dat b/src/quintic-polynomial.dat
new file mode 100644
index 0000000..347b95a
--- /dev/null
+++ b/src/quintic-polynomial.dat
@@ -0,0 +1,26 @@
+.i 1
+.o 1
+.t 21
+-1.0 0.0
+-0.9 -0.03249
+-0.8 -0.10368
+-0.7 -0.18207
+-0.6 -0.24576
+-0.5 -0.28125
+-0.4 -0.28224
+-0.3 -0.24843
+-0.2 -0.18432
+-0.1 -0.09801
+0.0 0.0
+0.1 0.09801
+0.2 0.18432
+0.3 0.24843
+0.4 0.28224
+0.5 0.28125
+0.6 0.24576
+0.7 0.18207
+0.8 0.10368
+0.9 0.03249
+1.0 0.0
+.e
+