aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/jcgp/JCGP.java61
-rw-r--r--src/jcgp/backend/function/BitwiseLogic.java173
-rw-r--r--src/jcgp/backend/modules/es/TournamentSelection.java10
-rw-r--r--src/jcgp/backend/modules/problem/DigitalCircuitProblem.java4
-rw-r--r--src/jcgp/backend/modules/problem/TestCaseProblem.java43
-rw-r--r--src/jcgp/backend/parsers/ChromosomeParser.java189
-rw-r--r--src/jcgp/backend/parsers/FunctionParser.java53
-rw-r--r--src/jcgp/backend/parsers/ParameterParser.java77
-rw-r--r--src/jcgp/backend/parsers/TestCaseParser.java90
-rw-r--r--src/jcgp/backend/population/Node.java3
-rw-r--r--src/jcgp/backend/resources/ModifiableResources.java3
-rw-r--r--src/jcgp/backend/resources/Resources.java2
-rw-r--r--src/jcgp/gui/settings/parameters/GUIDoubleParameter.java10
-rw-r--r--src/jcgp/gui/settings/parameters/GUIIntegerParameter.java4
-rw-r--r--src/jcgp/gui/settings/parameters/GUIParameter.java2
15 files changed, 610 insertions, 114 deletions
diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java
index 2a6552c..f980c00 100644
--- a/src/jcgp/JCGP.java
+++ b/src/jcgp/JCGP.java
@@ -11,10 +11,10 @@ import jcgp.backend.modules.problem.DigitalCircuitProblem;
import jcgp.backend.modules.problem.Problem;
import jcgp.backend.modules.problem.SymbolicRegressionProblem;
import jcgp.backend.modules.problem.TestCaseProblem;
-import jcgp.backend.parser.ChromosomeParser;
-import jcgp.backend.parser.FunctionParser;
-import jcgp.backend.parser.ParameterParser;
-import jcgp.backend.parser.TestCaseParser;
+import jcgp.backend.parsers.ChromosomeParser;
+import jcgp.backend.parsers.FunctionParser;
+import jcgp.backend.parsers.ParameterParser;
+import jcgp.backend.parsers.TestCaseParser;
import jcgp.backend.population.Population;
import jcgp.backend.resources.Console;
import jcgp.backend.resources.ModifiableResources;
@@ -50,19 +50,19 @@ public class JCGP {
// mutators
private Mutator[] mutators = new Mutator[] {
new PointMutator(resources) };
- private Mutator mutator;
+ private Mutator mutator = mutators[0];
// evolutionary algorithms
private EvolutionaryStrategy[] evolutionaryStrategies = new EvolutionaryStrategy[] {
new MuPlusLambda(resources),
- new TournamentSelection() };
- private EvolutionaryStrategy evolutionaryStrategy;
+ new TournamentSelection(resources) };
+ private EvolutionaryStrategy evolutionaryStrategy = evolutionaryStrategies[0];
// problem types
private Problem[] problems = new Problem[] {
new SymbolicRegressionProblem(resources),
new DigitalCircuitProblem(resources) };
- private Problem problem;
+ private Problem problem = problems[0];
/*
* the population of chromosomes
@@ -84,17 +84,14 @@ public class JCGP {
jcgp.loadParameters(new File(args[0]));
if (jcgp.getProblem() instanceof TestCaseProblem) {
- ((TestCaseProblem<?>) jcgp.getProblem()).parse(new File(args[2]));
+ TestCaseParser.parse(new File(args[2]), (TestCaseProblem<?>) jcgp.getProblem(), jcgp.getResources());
}
jcgp.start();
}
public JCGP() {
- setEvolutionaryStrategy(0);
- setMutator(0);
- setProblem(0);
-
+ resources.setFunctionSet(problem.getFunctionSet());
population = new Population(resources);
}
@@ -159,14 +156,16 @@ public class JCGP {
*/
public void setMutator(int index) {
this.mutator = mutators[index];
+ resources.println("[CGP] Mutator selected: " + mutator.toString());
}
/**
* @param evolutionaryStrategy the evolutionaryAlgorithm to set
*/
- public void setEvolutionaryStrategy(int index) {
+ public void setEvolutionaryStrategy(int index) {
this.evolutionaryStrategy = evolutionaryStrategies[index];
+ resources.println("[CGP] Evolutionary strategy selected: " + evolutionaryStrategy.toString());
}
@@ -179,6 +178,7 @@ public class JCGP {
}
public void nextGeneration() {
+ System.out.println("service: doing next gen");
if (!finished) {
problem.evaluate(population, (Resources) resources);
reportGeneration();
@@ -188,7 +188,6 @@ public class JCGP {
if (problem.isPerfectSolution(population.getFittest())) {
// solution has been found, start next run
resources.println("[CGP] Solution found, generation " + resources.currentGeneration() + ", chromosome " + population.getFittestIndex());
-
if (resources.currentRun() < resources.runs()) {
// there are still runs left
resources.setCurrentRun(resources.currentRun() + 1);
@@ -202,6 +201,8 @@ public class JCGP {
}
} else {
resources.setCurrentGeneration(resources.currentGeneration() + 1);
+ // solution isn't perfect and we still have generations left, evolve more!
+ evolutionaryStrategy.evolve(population, mutator, (Resources) resources);
}
} else {
// the run has ended, check if any more runs must be done
@@ -222,18 +223,11 @@ public class JCGP {
}
}
}
-
- evolutionaryStrategy.evolve(population, mutator, (Resources) resources);
-
}
private void reportGeneration() {
- if (resources.reportInterval() > 0) {
- if (resources.currentGeneration() % resources.reportInterval() == 0) {
- resources.println("[CGP] Generation: " + resources.currentGeneration() + ", fittest chromosome ("
- + population.getFittestIndex() + ") has fitness: " + population.getFittest().getFitness());
- }
- }
+ resources.reportln("[CGP] Generation: " + resources.currentGeneration() + ", fittest chromosome ("
+ + population.getFittestIndex() + ") has fitness: " + population.getFittest().getFitness());
}
public void start() {
@@ -249,13 +243,24 @@ public class JCGP {
population = new Population(resources);
resources.setCurrentGeneration(1);
resources.setCurrentRun(1);
- resources.println("-----------------------------");
- resources.println("New experiment: " + problem.toString());
+ resources.println("*********************************************************");
+ resources.println("[CGP] New experiment: " + problem.toString());
+ resources.println("[CGP] Rows: " + resources.rows());
+ resources.println("[CGP] Columns: " + resources.columns());
+ resources.println("[CGP] Levels back: " + resources.levelsBack());
+ resources.println("[CGP] Population size: " + resources.populationSize());
+ resources.println("[CGP] Total generations: " + resources.generations());
+ resources.println("[CGP] Total runs: " + resources.runs());
+ resources.println("[CGP] Report interval: " + resources.reportInterval());
+ resources.println("[CGP] Seed: " + resources.seed());
+ resources.println("");
+ resources.println("[CGP] Evolutionary strategy: " + evolutionaryStrategy.toString());
+ resources.println("[CGP] Mutator: " + mutator.toString());
}
public void loadParameters(File file) {
ParameterParser.parseParameters(file, resources);
- FunctionParser.parseFunctions(file, problem);
+ FunctionParser.parseFunctions(file, problem, resources);
reset();
}
@@ -263,7 +268,7 @@ public class JCGP {
if (problem instanceof TestCaseProblem) {
TestCaseParser.parseParameters(file, resources);
reset();
- ((TestCaseProblem<?>) problem).parse(file);
+ TestCaseParser.parse(file, (TestCaseProblem<?>) problem, resources);
}
}
diff --git a/src/jcgp/backend/function/BitwiseLogic.java b/src/jcgp/backend/function/BitwiseLogic.java
index a4c2737..2466f36 100644
--- a/src/jcgp/backend/function/BitwiseLogic.java
+++ b/src/jcgp/backend/function/BitwiseLogic.java
@@ -22,9 +22,12 @@ public class BitwiseLogic extends FunctionSet {
new Or(),
new OrNotA(),
new OrNotB(),
- new Nand()};
-
- // TODO muxes
+ new Nand()
+// new Mux1(),
+// new Mux2(),
+// new Mux3(),
+// new Mux4()
+ };
enableAll();
}
@@ -153,9 +156,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() & arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() & in1.get();
return new UnsignedInteger(result);
}
@@ -178,9 +181,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = ~(arg1.get()) & arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = ~(in0.get()) & in1.get();
return new UnsignedInteger(result);
}
@@ -203,9 +206,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() & ~(arg2.get());
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() & ~(in1.get());
return new UnsignedInteger(result);
}
@@ -228,9 +231,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() | arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() | in1.get();
return new UnsignedInteger(~result);
}
@@ -253,9 +256,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() ^ arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() ^ in1.get();
return new UnsignedInteger(result);
}
@@ -278,9 +281,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() ^ arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() ^ in1.get();
return new UnsignedInteger(~result);
}
@@ -303,9 +306,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() | arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() | in1.get();
return new UnsignedInteger(result);
}
@@ -328,9 +331,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = ~arg1.get() | arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = ~in0.get() | in1.get();
return new UnsignedInteger(result);
}
@@ -353,9 +356,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() | ~arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() | ~in1.get();
return new UnsignedInteger(result);
}
@@ -378,9 +381,9 @@ public class BitwiseLogic extends FunctionSet {
if (connections.length < getArity()) {
throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- UnsignedInteger arg1 = ((UnsignedInteger) connections[0].getValue());
- UnsignedInteger arg2 = ((UnsignedInteger) connections[1].getValue());
- Integer result = arg1.get() & arg2.get();
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ Integer result = in0.get() & in1.get();
return new UnsignedInteger(~result);
}
@@ -396,4 +399,108 @@ public class BitwiseLogic extends FunctionSet {
return "Nand";
}
}
+
+ public static class Mux1 extends Function {
+ @Override
+ public UnsignedInteger run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ UnsignedInteger in2 = ((UnsignedInteger) connections[2].getValue());
+ Integer result = ((in0.get() & ~in2.get()) | (in1.get() & in2.get()));
+
+ return new UnsignedInteger(result);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 3;
+ }
+
+ @Override
+ public String getName() {
+ return "Mux1";
+ }
+ }
+
+ public static class Mux2 extends Function {
+ @Override
+ public UnsignedInteger run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ UnsignedInteger in2 = ((UnsignedInteger) connections[2].getValue());
+ Integer result = ((in0.get() & ~in2.get()) | (~in1.get() & in2.get()));
+
+ return new UnsignedInteger(result);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 3;
+ }
+
+ @Override
+ public String getName() {
+ return "Mux2";
+ }
+ }
+
+ public static class Mux3 extends Function {
+ @Override
+ public UnsignedInteger run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ UnsignedInteger in2 = ((UnsignedInteger) connections[2].getValue());
+ Integer result = ((~in0.get() & ~in2.get()) | (in1.get() & in2.get()));
+
+ return new UnsignedInteger(result);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 3;
+ }
+
+ @Override
+ public String getName() {
+ return "Mux3";
+ }
+ }
+
+ public static class Mux4 extends Function {
+ @Override
+ public UnsignedInteger run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ UnsignedInteger in0 = ((UnsignedInteger) connections[0].getValue());
+ UnsignedInteger in1 = ((UnsignedInteger) connections[1].getValue());
+ UnsignedInteger in2 = ((UnsignedInteger) connections[2].getValue());
+ Integer result = ((~in0.get() & ~in2.get()) | (~in1.get() & in2.get()));
+
+ return new UnsignedInteger(result);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 3;
+ }
+
+ @Override
+ public String getName() {
+ return "Mux4";
+ }
+ }
}
diff --git a/src/jcgp/backend/modules/es/TournamentSelection.java b/src/jcgp/backend/modules/es/TournamentSelection.java
index 4070468..7cc9706 100644
--- a/src/jcgp/backend/modules/es/TournamentSelection.java
+++ b/src/jcgp/backend/modules/es/TournamentSelection.java
@@ -8,10 +8,10 @@ import jcgp.backend.resources.parameters.Parameter;
public class TournamentSelection implements EvolutionaryStrategy {
- private IntegerParameter tournament;
+ private IntegerParameter tournamentSize;
- public TournamentSelection() {
- tournament = new IntegerParameter(1, "Tournament size") {
+ public TournamentSelection(Resources resources) {
+ tournamentSize = new IntegerParameter(1, "Tournament size") {
@Override
public void validate(Number newValue) {
// TODO this
@@ -21,13 +21,13 @@ public class TournamentSelection implements EvolutionaryStrategy {
@Override
public Parameter<?>[] getLocalParameters() {
- return new Parameter[] {tournament};
+ return new Parameter[] {tournamentSize};
}
@Override
public void evolve(Population population, Mutator mutator,
Resources parameters) {
- tournament.set(tournament.get() + 1);
+ tournamentSize.set(tournamentSize.get() + 1);
// TODO implement this
}
diff --git a/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java b/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java
index e92989e..3c30e4c 100644
--- a/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java
+++ b/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java
@@ -49,8 +49,8 @@ public class DigitalCircuitProblem extends TestCaseProblem<UnsignedInteger> {
}
@Override
- protected int getMaxFitness() {
- int maxFitness = (int) Math.pow(2.0, (double) resources.inputs()) * resources.outputs();
+ protected double getMaxFitness() {
+ double maxFitness = Math.pow(2.0, (double) resources.inputs()) * resources.outputs();
return maxFitness;
}
diff --git a/src/jcgp/backend/modules/problem/TestCaseProblem.java b/src/jcgp/backend/modules/problem/TestCaseProblem.java
index ff13c2e..d8dd32b 100644
--- a/src/jcgp/backend/modules/problem/TestCaseProblem.java
+++ b/src/jcgp/backend/modules/problem/TestCaseProblem.java
@@ -1,13 +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.parser.TestCaseParser;
import jcgp.backend.resources.Resources;
-import jcgp.backend.resources.parameters.IntegerParameter;
+import jcgp.backend.resources.parameters.DoubleParameter;
import jcgp.backend.resources.parameters.Parameter;
/**
@@ -49,43 +47,21 @@ public abstract class TestCaseProblem<U extends Object> extends Problem {
}
protected ObservableList<TestCase<U>> testCases;
- protected IntegerParameter maxFitness;
+ protected DoubleParameter maxFitness;
protected Resources resources;
- protected TestCaseParser parser;
-
public TestCaseProblem(Resources resources) {
super();
this.resources = resources;
- maxFitness = new IntegerParameter(0, "Max fitness", true, false) {
+ maxFitness = new DoubleParameter(0, "Max fitness", true, false) {
@Override
public void validate(Number newValue) {
// blank
}
};
testCases = FXCollections.observableArrayList();
-
- parser = new TestCaseParser(this);
- }
-
- public TestCaseProblem(Resources resources, File testCase) {
- super();
-
- 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
@@ -93,7 +69,7 @@ public abstract class TestCaseProblem<U extends Object> extends Problem {
return new Parameter[]{maxFitness};
}
- protected int getMaxFitness() {
+ protected double getMaxFitness() {
int fitness = 0;
for (TestCase<U> tc : testCases) {
@@ -115,7 +91,7 @@ public abstract class TestCaseProblem<U extends Object> extends Problem {
public abstract void addTestCase(String[] inputs, String[] outputs);
- public void addTestCase(TestCase<U> testCase) {
+ protected final void addTestCase(TestCase<U> testCase) {
if (testCase.getInputs().length != resources.inputs()) {
throw new IllegalArgumentException("Received test case with " + testCase.getInputs().length +
" inputs but need exactly " + resources.inputs());
@@ -128,11 +104,6 @@ public abstract class TestCaseProblem<U extends Object> extends Problem {
}
}
- public void removeTestCase(TestCase<U> testCase) {
- testCases.remove(testCase);
- maxFitness.set(getMaxFitness());
- }
-
public int getInputCount() {
return resources.inputs();
}
@@ -141,10 +112,6 @@ public abstract class TestCaseProblem<U extends Object> extends Problem {
return resources.outputs();
}
- public void parse(File file) {
- parser.parse(file);
- }
-
public void clearTestCases() {
testCases.clear();
}
diff --git a/src/jcgp/backend/parsers/ChromosomeParser.java b/src/jcgp/backend/parsers/ChromosomeParser.java
new file mode 100644
index 0000000..fe58ff8
--- /dev/null
+++ b/src/jcgp/backend/parsers/ChromosomeParser.java
@@ -0,0 +1,189 @@
+package jcgp.backend.parsers;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.PrintWriter;
+import java.util.Scanner;
+
+import jcgp.backend.population.Chromosome;
+import jcgp.backend.population.Connection;
+import jcgp.backend.population.Input;
+import jcgp.backend.population.Node;
+import jcgp.backend.resources.ModifiableResources;
+
+/**
+ * This class includes a method for parsing .chr files and another
+ * for writing .chr files from given chromosomes.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
+public abstract class ChromosomeParser {
+
+ /**
+ * Use this method to parse .chr files into a given chromosome.
+ * <br><br>
+ * This is not fully defensive as it doesn't check for number of inputs,
+ * doesn't compare rows and columns individually and doesn't account for levels back. It
+ * is not viable to implement these defensive measures with the chromosome format used
+ * by CGP.
+ *
+ * @param file the .chr file to parse from
+ * @param chromosome the chromosome to configure
+ * @param resources the experiment resources
+ */
+ public static void parse(File file, Chromosome chromosome, ModifiableResources resources) {
+ /*
+ * Count the nodes to make sure the size of the .chr file matches the experiment parameters.
+ *
+ * We do this by using the scanner to get the node and output portions of the file as they
+ * are separated by 3 tab characters. Every number is replaced by a single known character,
+ * and the length of the string with the new characters is compared with that of a string
+ * where the new known character has been removed, yielding the total number of values.
+ *
+ * TODO this is NOT ideal and should be refactored
+ *
+ */
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ return;
+ }
+ Scanner in = new Scanner(fr);
+
+ in.useDelimiter("\\t\\t\\t");
+ String geneString = in.next().replaceAll("[0-9]+", "g");
+ String outString = in.next().replaceAll("[0-9]+", "o");
+ int geneCount = geneString.length() - geneString.replace("g", "").length();
+ int outCount = outString.length() - outString.replace("o", "").length();
+ in.close();
+
+
+ // if the acquired values match the current parameters, apply them to the chromosome
+ if ((geneCount == resources.nodes() * (resources.arity() + 1))
+ && outCount == resources.outputs()) {
+ // prepare a new scanner
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ return;
+ }
+ in = new Scanner(fr);
+
+ resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
+
+ int gene;
+ Connection newConnection;
+ Node changingNode;
+ // for all nodes, columns first
+ for (int c = 0; c < resources.columns(); c++) {
+ for (int r = 0; r < resources.rows(); r++) {
+ // store the changing node
+ changingNode = chromosome.getNode(r, c);
+
+ // for every connection
+ for (int i = 0; i < resources.arity(); i++) {
+ // get connection number from the .chr file
+ gene = in.nextInt();
+ if (gene < resources.inputs()) {
+ // connection was an input
+ newConnection = chromosome.getInput(gene);
+ } else {
+ // connection was another node, calculate which from its number
+ newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(),
+ (gene - resources.inputs()) / resources.rows());
+ }
+ changingNode.setConnection(i, newConnection);
+ }
+
+ // set the function, straight indexing should work - this is not entirely
+ // safe, but it is not viable to check for functionset compatibility
+ changingNode.setFunction(resources.getFunction(in.nextInt()));
+ }
+ }
+
+ // outputs
+ for (int o = 0; o < resources.outputs(); o ++) {
+ gene = in.nextInt();
+ if (gene < resources.inputs()) {
+ // connection was an input
+ newConnection = chromosome.getInput(gene);
+ } else {
+ // connection was another node, calculate which from its number
+ newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(),
+ (gene - resources.inputs()) / resources.rows());
+ }
+ chromosome.getOutput(o).setConnection(0, newConnection);
+ }
+ in.close();
+
+ resources.println("[Parser] File parsed successfully.");
+
+ } else {
+ resources.println("[Parser] Error: the topology of the chromosome in " + file.getName() + " does not match that of the experiment.");
+ }
+ }
+
+ /**
+ * Writes a chromosome into the specified .chr file.
+ * <br><br>
+ * The file is written in the standard .chr format and can
+ * be read by the original CGP implementation.
+ *
+ * @param file the file to write to
+ * @param chromosome the chromosome to save
+ */
+ public static void save(File file, Chromosome chromosome, ModifiableResources resources) {
+ PrintWriter writer;
+ try {
+ writer = new PrintWriter(file);
+ } catch (FileNotFoundException e) {
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ return;
+ }
+
+ resources.println("[Parser] Saving to " + file.getAbsolutePath() + "...");
+
+ // for all nodes, columns first
+ for (int c = 0; c < resources.columns(); c++) {
+ for (int r = 0; r < resources.rows(); r++) {
+ for (int i = 0; i < resources.arity(); i++) {
+ // print the connections, separated by spaces
+ Connection conn = chromosome.getNode(r, c).getConnection(i);
+ if (conn instanceof Input) {
+ writer.print(" " + ((Input) conn).getIndex());
+ } else if (conn instanceof Node) {
+ writer.print(" " + (((((Node) conn).getColumn() + 1) * resources.inputs()) + ((Node) conn).getRow()));
+ } else {
+ resources.println("[Parser] Error: could not handle " + conn.getClass() + " as a subclass of Connection");
+ }
+ }
+ // print the function numbers
+ writer.print(" " + resources.getFunctionIndex(chromosome.getNode(r, c).getFunction()));
+ // node is done, print tab
+ writer.print("\t");
+ }
+ }
+ // nodes are done, print two tabs to separate from output
+ writer.print("\t\t");
+ for (int o = 0; o < resources.outputs(); o ++) {
+ Connection source = chromosome.getOutput(o).getSource();
+ if (source instanceof Input) {
+ writer.print(" " + ((Input) source).getIndex());
+ } else if (source instanceof Node) {
+ writer.print(" " + (((((Node) source).getColumn() + 1) * resources.inputs()) + ((Node) source).getRow()));
+ } else {
+ resources.println("[Parser] Error: could not handle " + source.getClass() + " as a subclass of Connection");
+ }
+ }
+
+ writer.close();
+
+ resources.println("[Parser] Chromosome saved successfully.");
+ }
+
+}
diff --git a/src/jcgp/backend/parsers/FunctionParser.java b/src/jcgp/backend/parsers/FunctionParser.java
new file mode 100644
index 0000000..6d6c73b
--- /dev/null
+++ b/src/jcgp/backend/parsers/FunctionParser.java
@@ -0,0 +1,53 @@
+package jcgp.backend.parsers;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.Scanner;
+
+import jcgp.backend.function.FunctionSet;
+import jcgp.backend.modules.problem.Problem;
+import jcgp.backend.resources.ModifiableResources;
+
+/**
+ * Parses the functions from a .par file.
+ * Functions marked with a 1 will be enabled,
+ * and those marked with 0 are disabled.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
+public abstract class FunctionParser {
+
+ public static void parseFunctions(File file, Problem problem, ModifiableResources resources) {
+
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ return;
+ }
+
+ Scanner in = new Scanner(fr);
+ FunctionSet functionSet = problem.getFunctionSet();
+ resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
+
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if (line.substring(line.length() - 1).matches("[0-9]")) {
+ String[] splitString = line.split("[^0-9]+");
+ int functionIndex = Integer.parseInt(splitString[splitString.length - 1]);
+ if (Integer.parseInt(splitString[0]) != 0 && !functionSet.isEnabled(functionSet.getFunction(functionIndex))) {
+ functionSet.enableFunction(functionIndex);
+ resources.println("[Parser] Enabled function: " + functionSet.getFunction(functionIndex).getName() + ".");
+ } else if (Integer.parseInt(splitString[0]) == 0 && functionSet.isEnabled(functionSet.getFunction(functionIndex))) {
+ functionSet.disableFunction(functionIndex);
+ resources.println("[Parser] Disabled function: " + functionSet.getFunction(functionIndex).getName() + ".");
+ }
+ }
+ }
+ in.close();
+ resources.println("[Parser] Finished parsing functions.");
+ }
+}
diff --git a/src/jcgp/backend/parsers/ParameterParser.java b/src/jcgp/backend/parsers/ParameterParser.java
new file mode 100644
index 0000000..ae72126
--- /dev/null
+++ b/src/jcgp/backend/parsers/ParameterParser.java
@@ -0,0 +1,77 @@
+package jcgp.backend.parsers;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.Scanner;
+
+import jcgp.backend.resources.ModifiableResources;
+
+public abstract class ParameterParser {
+
+ public static void parseParameters(File file, ModifiableResources resources) {
+
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ return;
+ }
+
+ Scanner in = new Scanner(fr);
+ resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
+
+ while (in.hasNextLine()) {
+ String[] splitString = in.nextLine().split("( |\t)+");
+
+ switch (splitString[1]) {
+ case "population_size":
+ resources.setPopulationSize(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Population size is now " + resources.populationSize() + ".");
+ break;
+
+ case "num_generations":
+ resources.setGenerations(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Total generations is now " + resources.generations() + ".");
+ break;
+
+ case "num_runs_total":
+ resources.setRuns(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Total runs is now " + resources.runs() + ".");
+ break;
+
+ case "num_rows":
+ resources.setRows(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Row number is now " + resources.rows() + ".");
+ break;
+
+ case "num_cols":
+ resources.setColumns(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Column number is now " + resources.columns() + ".");
+ break;
+
+ case "levels_back":
+ resources.setLevelsBack(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Levels back is now " + resources.levelsBack() + ".");
+ break;
+
+ case "report_interval":
+ resources.setReportInterval(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Report interval is now " + resources.levelsBack() + ".");
+ break;
+
+ case "global_seed":
+ resources.setSeed(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Seed is now " + resources.seed() + ".");
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ in.close();
+ resources.println("[Parser] Finished parsing parameters.");
+ }
+}
diff --git a/src/jcgp/backend/parsers/TestCaseParser.java b/src/jcgp/backend/parsers/TestCaseParser.java
new file mode 100644
index 0000000..cef018e
--- /dev/null
+++ b/src/jcgp/backend/parsers/TestCaseParser.java
@@ -0,0 +1,90 @@
+package jcgp.backend.parsers;
+
+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 abstract class TestCaseParser {
+
+ public static void parse(File file, TestCaseProblem<?> problem, ModifiableResources resources) {
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ return;
+ }
+ resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
+ Scanner in = new Scanner(fr);
+ boolean readingTestCases = false;
+ int inputs = 0, outputs = 0;
+ int cases = 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;
+ } 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);
+ cases++;
+ }
+ }
+ resources.println("[Parser] Finished, added " + cases + " test cases.");
+ in.close();
+ }
+
+ public static void parseParameters(File file, ModifiableResources resources) {
+
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ return;
+ }
+
+ resources.println("[Parser] Parsing parameters...");
+ 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]));
+ resources.println("[Parser] Number of inputs set to " + resources.inputs());
+ } else if (nextLine.startsWith(".o")) {
+ String[] split = nextLine.split(" +");
+ resources.setOutputs(Integer.parseInt(split[1]));
+ resources.println("[Parser] Number of outputs set to " + resources.outputs());
+ }
+ }
+ in.close();
+
+ resources.println("[Parser] Finished parsing parameters.");
+ }
+}
diff --git a/src/jcgp/backend/population/Node.java b/src/jcgp/backend/population/Node.java
index b716ff8..1ac5b10 100644
--- a/src/jcgp/backend/population/Node.java
+++ b/src/jcgp/backend/population/Node.java
@@ -36,6 +36,9 @@ public class Node extends Gene implements MutableElement, Connection {
connections[index] = newConnection;
chromosome.recomputeActiveNodes();
}
+ } else if (newConnection instanceof Input) {
+ connections[index] = newConnection;
+ chromosome.recomputeActiveNodes();
}
}
diff --git a/src/jcgp/backend/resources/ModifiableResources.java b/src/jcgp/backend/resources/ModifiableResources.java
index 3841963..048e460 100644
--- a/src/jcgp/backend/resources/ModifiableResources.java
+++ b/src/jcgp/backend/resources/ModifiableResources.java
@@ -216,6 +216,7 @@ public class ModifiableResources extends Resources {
/*
* Console functionality
+ * These are not affected by parameter report interval
*/
public void println(String s) {
System.out.println(s);
@@ -223,7 +224,7 @@ public class ModifiableResources extends Resources {
console.println(s);
}
}
-
+
public void print(String s) {
System.out.print(s);
if (console != null) {
diff --git a/src/jcgp/backend/resources/Resources.java b/src/jcgp/backend/resources/Resources.java
index 6eb75cd..e83680f 100644
--- a/src/jcgp/backend/resources/Resources.java
+++ b/src/jcgp/backend/resources/Resources.java
@@ -332,7 +332,7 @@ public class Resources {
/*
* Console functionality
- * These are affected by parameter report
+ * These are affected by parameter report interval
*/
public void reportln(String s) {
if (reportInterval.get() > 0) {
diff --git a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
index 5331364..f177ffa 100644
--- a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
@@ -32,13 +32,13 @@ public class GUIDoubleParameter extends GUIParameter<Number> {
*/
GUIDoubleParameter(Parameter<Number> parameter, SettingsPane sp) {
super(parameter, sp);
- decimalFormat = new DecimalFormat();
- decimalFormat.setMaximumFractionDigits(10);
}
@Override
protected Control makeControl() {
- textField = new TextField(String.valueOf(parameter.get()));
+ decimalFormat = new DecimalFormat();
+ decimalFormat.setMaximumFractionDigits(10);
+ textField = new TextField(decimalFormat.format(parameter.get().doubleValue()));
textField.setStyle(VALID_PARAMETER_STYLE);
textField.setAlignment(Pos.CENTER_RIGHT);
textField.prefWidthProperty().bind(widthProperty().divide(2));
@@ -100,6 +100,8 @@ public class GUIDoubleParameter extends GUIParameter<Number> {
@Override
public void refreshValue() {
- textField.setText(decimalFormat.format(parameter.get().doubleValue()));
+ if (!textField.isFocused()) {
+ 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 ee266f3..e1b0b75 100644
--- a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
@@ -97,6 +97,8 @@ public class GUIIntegerParameter extends GUIParameter<Number> {
@Override
public void refreshValue() {
- textField.setText(String.valueOf(parameter.get()));
+ if (!textField.isFocused()) {
+ 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 c6ac2e6..79762ff 100644
--- a/src/jcgp/gui/settings/parameters/GUIParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIParameter.java
@@ -141,7 +141,7 @@ public abstract class GUIParameter<T> extends HBox {
ObservableValue<? extends Object> observable,
Object oldValue, Object newValue) {
// only do this if the experiment is running
- if (settingsPane.isExperimentRunning()) {
+ if (settingsPane.isExperimentRunning() || !isFocused()) {
/* here's the catch - atomically get the lock state and set it to true
* the lock will only be false again when the runnable is finished executing,
* preventing multiple runnables to concurrently update the same GUIParameter