aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cgp0.chr1
-rw-r--r--src/jcgp/JCGP.java70
-rw-r--r--src/jcgp/backend/function/BitwiseLogic.java337
-rw-r--r--src/jcgp/backend/function/DoubleArithmetic.java589
-rw-r--r--src/jcgp/backend/function/FunctionSet.java1
-rw-r--r--src/jcgp/backend/function/IntegerArithmetic.java122
-rw-r--r--src/jcgp/backend/modules/problem/SymbolicRegression.java12
-rw-r--r--src/jcgp/backend/parser/ChromosomeParser.java131
-rw-r--r--src/jcgp/backend/parser/FunctionParser.java58
-rw-r--r--src/jcgp/backend/parser/ParameterParser.java76
-rw-r--r--src/jcgp/backend/parser/TestCaseParser.java13
-rw-r--r--src/jcgp/backend/population/Population.java1
-rw-r--r--src/jcgp/backend/resources/ModifiableResources.java14
-rw-r--r--src/jcgp/backend/resources/Resources.java18
-rw-r--r--src/jcgp/backend/tests/ChromosomeTests.java4
-rw-r--r--src/jcgp/backend/tests/NodeTests.java8
-rw-r--r--src/jcgp/backend/tests/OutputTests.java4
-rw-r--r--src/jcgp/backend/tests/PopulationTests.java4
-rw-r--r--src/jcgp/gui/GUI.java21
-rw-r--r--src/jcgp/gui/population/PopulationPane.java6
-rw-r--r--src/jcgp/gui/settings/SettingsPane.java59
-rw-r--r--src/jcgp/gui/settings/parameters/GUIParameter.java2
-rw-r--r--src/parameters.par32
23 files changed, 1321 insertions, 262 deletions
diff --git a/src/cgp0.chr b/src/cgp0.chr
new file mode 100644
index 0000000..3157c03
--- /dev/null
+++ b/src/cgp0.chr
@@ -0,0 +1 @@
+ 1 2 7 1 2 6 2 2 7 3 2 7 2 0 7 3 0 7 0 1 7 7 1 10 6 0 7 10 11 7 2 11 7 0 11 6 13 0 7 13 12 10 14 1 7 16 \ No newline at end of file
diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java
index e124dbf..1e847fb 100644
--- a/src/jcgp/JCGP.java
+++ b/src/jcgp/JCGP.java
@@ -1,5 +1,7 @@
package jcgp;
+import java.io.File;
+
import jcgp.backend.modules.es.EvolutionaryStrategy;
import jcgp.backend.modules.es.MuPlusLambda;
import jcgp.backend.modules.es.TournamentSelection;
@@ -8,6 +10,11 @@ import jcgp.backend.modules.mutator.PointMutator;
import jcgp.backend.modules.problem.DigitalCircuit;
import jcgp.backend.modules.problem.Problem;
import jcgp.backend.modules.problem.SymbolicRegression;
+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.population.Population;
import jcgp.backend.resources.Console;
import jcgp.backend.resources.ModifiableResources;
@@ -16,13 +23,13 @@ import jcgp.backend.resources.Resources;
/**
*
* Top-level CGP class. This class is the entry point for a CGP experiment.
- * <p>
+ * <br>
* An instance of JCGP encapsulates the entire experiment. It contains a Resources
* object which can be retrieved via a getter. Modules can be selected using their
* respective setters and function sets can be selected through the resources.
*
* The flow of the experiment is controlled using start() and nextGeneration(). The
- * experiment can be reset with reset(),
+ * experiment can be reset with reset(), TODO comment
*
*
* @author Eduardo Pedroni
@@ -48,7 +55,7 @@ public class JCGP {
// evolutionary algorithms
private EvolutionaryStrategy[] evolutionaryStrategies = new EvolutionaryStrategy[] {
new MuPlusLambda(resources),
- new TournamentSelection()};
+ new TournamentSelection() };
private EvolutionaryStrategy evolutionaryStrategy;
// problem types
@@ -63,6 +70,26 @@ public class JCGP {
private Population population;
private boolean finished = false;
+ /**
+ * TODO comment this!
+ *
+ * @param args
+ */
+ public static void main(String... args) {
+ if (args.length < 1) {
+ System.err.println("JCGP requires at least a .par file.");
+ System.exit(1);
+ }
+ JCGP jcgp = new JCGP();
+ jcgp.loadParameters(new File(args[0]));
+
+ if (jcgp.getProblem() instanceof TestCaseProblem) {
+ TestCaseParser.parse(new File(args[2]), (TestCaseProblem<?>) jcgp.getProblem());
+ }
+
+ jcgp.start();
+ }
+
public JCGP() {
setEvolutionaryStrategy(0);
setMutator(0);
@@ -154,7 +181,7 @@ public class JCGP {
public void nextGeneration() {
if (!finished) {
problem.evaluate(population, (Resources) resources);
- report();
+ reportGeneration();
if (resources.currentGeneration() < resources.generations()) {
// we still have generations left to go
@@ -200,24 +227,20 @@ public class JCGP {
}
- private void report() {
- if (resources.report() > 0) {
- if (resources.currentGeneration() % resources.report() == 0) {
- resources.println("[CGP] Generation: " + resources.currentGeneration() + ", fitness: " + population.getFittest().getFitness());
+ private void reportGeneration() {
+ if (resources.reportInterval() > 0) {
+ if (resources.currentGeneration() % resources.reportInterval() == 0) {
+ resources.println("[CGP] Generation: " + resources.currentGeneration());
}
}
}
public void start() {
if (!finished) {
- while (resources.currentGeneration() <= resources.generations()) {
+ while (!finished) {
nextGeneration();
- if (finished) {
- break;
- }
}
}
-
}
public void reset() {
@@ -228,6 +251,26 @@ public class JCGP {
resources.println("-----------------------------");
resources.println("New experiment: " + problem.toString());
}
+
+ public void loadParameters(File file) {
+ ParameterParser.parseParameters(file, resources);
+ FunctionParser.parseFunctions(file, problem);
+ reset();
+ }
+
+ public void loadTestCases(File file) {
+ if (problem instanceof TestCaseProblem) {
+ TestCaseParser.parse(file, (TestCaseProblem<?>) problem);
+ }
+ }
+
+ public void loadChromosome(File file) {
+ ChromosomeParser.parse(file, population.getChromosome(0), resources);
+ }
+
+ public void saveChromosome(File file, int chromosomeIndex) {
+ ChromosomeParser.save(file, population.getChromosome(chromosomeIndex));
+ }
public boolean isFinished() {
return finished;
@@ -236,5 +279,4 @@ public class JCGP {
public void setConsole(Console console) {
resources.setConsole(console);
}
-
}
diff --git a/src/jcgp/backend/function/BitwiseLogic.java b/src/jcgp/backend/function/BitwiseLogic.java
index 5d47ff7..14f4488 100644
--- a/src/jcgp/backend/function/BitwiseLogic.java
+++ b/src/jcgp/backend/function/BitwiseLogic.java
@@ -1,6 +1,5 @@
package jcgp.backend.function;
-import jcgp.backend.exceptions.InvalidArgumentsException;
import jcgp.backend.population.Connection;
public class BitwiseLogic extends FunctionSet {
@@ -8,26 +7,155 @@ public class BitwiseLogic extends FunctionSet {
public BitwiseLogic() {
name = "32-bit Logic";
functionList = new Function[]{
+ new ConstantZero(),
+ new ConstantOne(),
+ new WireA(),
+ new WireB(),
+ new NotA(),
+ new NotB(),
new And(),
- new Or(),
- new Not(),
- new Xor(),
- new Nand(),
+ new AndNotA(),
+ new AndNotB(),
new Nor(),
- new Xnor()};
+ new Xor(),
+ new Xnor(),
+ new Or(),
+ new OrNotA(),
+ new OrNotB(),
+ new Nand()};
+
+ // TODO muxes
enableAll();
}
+
+ public static class ConstantZero extends Function {
+ @Override
+ public Long run(Connection... connections) {
+ return new Long(0);
+ }
+
+ @Override
+ public int getArity() {
+ return 0;
+ }
+
+ @Override
+ public String getName() {
+ return "0";
+ }
+ }
+
+ public static class ConstantOne extends Function {
+ @Override
+ public Long run(Connection... connections) {
+ return new Long(Long.MAX_VALUE);
+ }
+
+ @Override
+ public int getArity() {
+ return 0;
+ }
+
+ @Override
+ public String getName() {
+ return "1";
+ }
+ }
+
+ public static class WireA extends Function {
+ @Override
+ public Long 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();
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Wire A";
+ }
+ }
+
+ public static class WireB extends Function {
+ @Override
+ public Long 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();
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Wire B";
+ }
+ }
+
+ public static class NotA extends Function {
+ @Override
+ public Long 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();
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Not A";
+ }
+ }
+
+ public static class NotB extends Function {
+ @Override
+ public Long 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();
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+ @Override
+ public String getName() {
+ return "Not B";
+ }
+ }
+
public static class And extends Function {
@Override
- public Object run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
+ public Long run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- int arg1 = ((int) connections[0].getValue());
- int arg2 = ((int) connections[1].getValue());
- int result = arg1 & arg2;
+ Long arg1 = ((Long) connections[0].getValue());
+ Long arg2 = ((Long) connections[1].getValue());
+ Long result = arg1 & arg2;
return result;
}
@@ -40,20 +168,20 @@ public class BitwiseLogic extends FunctionSet {
@Override
public String getName() {
- return "AND";
+ return "And";
}
}
- public static class Or extends Function {
+ public static class AndNotA extends Function {
@Override
- public Object run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
+ public Long run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- int arg1 = ((int) connections[0].getValue());
- int arg2 = ((int) connections[1].getValue());
- int result = arg1 | arg2;
-
+ Long arg1 = ((Long) connections[0].getValue());
+ Long arg2 = ((Long) connections[1].getValue());
+ Long result = ~arg1 & arg2;
+
return result;
}
}
@@ -65,43 +193,69 @@ public class BitwiseLogic extends FunctionSet {
@Override
public String getName() {
- return "OR";
+ return "And !A";
}
}
-
- public static class Not extends Function {
+
+ public static class AndNotB extends Function {
@Override
- public Object run(Connection... connections) {
- if (connections.length < 1) {
- throw new InvalidArgumentsException("Not enough connections were given.");
+ public Long run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- int arg1 = ((int) connections[0].getValue());
- int result = ~arg1;
-
+ Long arg1 = ((Long) connections[0].getValue());
+ Long arg2 = ((Long) connections[1].getValue());
+ Long result = arg1 & ~arg2;
+
return result;
}
}
@Override
public int getArity() {
- return 1;
+ return 2;
}
@Override
public String getName() {
- return "NOT";
+ return "And !B";
}
}
+
+ public static class Nor extends Function {
+ @Override
+ public Long 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;
+ return ~result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Nor";
+ }
+ }
+
public static class Xor extends Function {
@Override
- public Object run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
+ public Long run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- int arg1 = ((int) connections[0].getValue());
- int arg2 = ((int) connections[1].getValue());
- int result = arg1 ^ arg2;
+ Long arg1 = ((Long) connections[0].getValue());
+ Long arg2 = ((Long) connections[1].getValue());
+ Long result = arg1 ^ arg2;
return result;
}
@@ -114,19 +268,19 @@ public class BitwiseLogic extends FunctionSet {
@Override
public String getName() {
- return "XOR";
+ return "Xor";
}
}
-
- public static class Nand extends Function {
+
+ public static class Xnor extends Function {
@Override
- public Object run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
+ public Long run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- int arg1 = ((int) connections[0].getValue());
- int arg2 = ((int) connections[1].getValue());
- int result = arg1 & arg2;
+ Long arg1 = ((Long) connections[0].getValue());
+ Long arg2 = ((Long) connections[1].getValue());
+ Long result = arg1 ^ arg2;
return ~result;
}
@@ -139,21 +293,71 @@ public class BitwiseLogic extends FunctionSet {
@Override
public String getName() {
- return "NAND";
+ return "Xnor";
}
}
+
+ public static class Or extends Function {
+ @Override
+ public Long 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;
- public static class Nor extends Function {
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Or";
+ }
+ }
+
+ public static class OrNotA extends Function {
@Override
- public Object run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
+ public Long run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- int arg1 = ((int) connections[0].getValue());
- int arg2 = ((int) connections[1].getValue());
- int result = arg1 | arg2;
+ Long arg1 = ((Long) connections[0].getValue());
+ Long arg2 = ((Long) connections[1].getValue());
+ Long result = ~arg1 | arg2;
- return ~result;
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Or !A";
+ }
+ }
+
+ public static class OrNotB extends Function {
+ @Override
+ public Long 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;
+
+ return result;
}
}
@@ -164,19 +368,19 @@ public class BitwiseLogic extends FunctionSet {
@Override
public String getName() {
- return "NOR";
+ return "Or !B";
}
}
- public static class Xnor extends Function {
+ public static class Nand extends Function {
@Override
- public Object run(Connection... connections) {
- if (connections.length < 2) {
- throw new InvalidArgumentsException("Not enough connections were given.");
+ public Long run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
} else {
- int arg1 = ((int) connections[0].getValue());
- int arg2 = ((int) connections[1].getValue());
- int result = arg1 ^ arg2;
+ Long arg1 = ((Long) connections[0].getValue());
+ Long arg2 = ((Long) connections[1].getValue());
+ Long result = arg1 & arg2;
return ~result;
}
@@ -189,10 +393,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public String getName() {
- return "XNOR";
+ return "Nand";
}
}
-
-
-
}
diff --git a/src/jcgp/backend/function/DoubleArithmetic.java b/src/jcgp/backend/function/DoubleArithmetic.java
new file mode 100644
index 0000000..ce4826f
--- /dev/null
+++ b/src/jcgp/backend/function/DoubleArithmetic.java
@@ -0,0 +1,589 @@
+package jcgp.backend.function;
+
+import jcgp.backend.population.Connection;
+
+public class DoubleArithmetic extends FunctionSet {
+
+ public final static double DIVISION_LIMIT = 0.0001;
+
+ public DoubleArithmetic() {
+ name = "Double Arithmetic";
+ functionList = new Function[]{
+ new Absolute(),
+ new SquareRoot(),
+ new Reciprocal(),
+ new Sine(),
+ new Cosine(),
+ new Tangent(),
+ new Exponential(),
+ new HyperbolicSine(),
+ new HyperbolicCosine(),
+ new HyperbolicTangent(),
+ new NaturalLog(),
+ new LogBaseTen(),
+ new SineAB(),
+ new CosineAB(),
+ new Hypotenuse(),
+ new Power(),
+ new Addition(),
+ new Subtraction(),
+ new Multiplication(),
+ new Division()};
+
+ enableAll();
+ }
+
+ /**
+ * Absolute returns the positive value of input 0.
+ *
+ * @see Math.abs()
+ */
+ public static class Absolute extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.abs(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Absolute";
+ }
+ }
+
+ /**
+ * Protected square root function, returns the square root of the absolute
+ * value of input 0.
+ *
+ * @see Math.abs(), Math.sqrt()
+ */
+ public static class SquareRoot extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.sqrt(Math.abs(in0));
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Square root";
+ }
+ }
+
+ /**
+ * Protected reciprocal function, returns (1 / input 0). If input 0 is less than
+ * {@link DoubleArithmetic.}DIVISION_LIMIT, this returns it unchanged.
+ *
+ */
+ public static class Reciprocal extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return in0 < DIVISION_LIMIT ? in0 : (1 / in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Reciprocal";
+ }
+ }
+
+ /**
+ * Sine function, in radians.
+ *
+ * @see Math.sin()
+ */
+ public static class Sine extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.sin(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Sin";
+ }
+ }
+
+ /**
+ * Cosine function, in radians.
+ *
+ * @see Math.cos()
+ */
+ public static class Cosine extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.cos(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Cos";
+ }
+ }
+
+ /**
+ * Protected tangent function, in radians. Returns the tangent of input 0.
+ * If input 0 is less than {@link DoubleArithmetic.}DIVISION_LIMIT,
+ * this returns it unchanged.
+ *
+ * @see Math.tan()
+ */
+ public static class Tangent extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return in0 < DIVISION_LIMIT ? in0 : Math.tan(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Tan";
+ }
+ }
+
+ /**
+ * Exponential function. Returns the exponential of input 0.
+ *
+ * @see Math.exp()
+ */
+ public static class Exponential extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.exp(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Exp";
+ }
+ }
+
+ /**
+ * Returns the hyperbolic sine of input 0.
+ *
+ * @see Math.sinh()
+ */
+ public static class HyperbolicSine extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.sinh(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Sinh";
+ }
+ }
+
+ /**
+ * Returns the hyperbolic cosine of input 0.
+ *
+ * @see Math.cosh()
+ */
+ public static class HyperbolicCosine extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.cosh(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Cosh";
+ }
+ }
+
+ /**
+ * Returns the hyperbolic tangent of input 0.
+ *
+ * @see Math.tanh()
+ */
+ public static class HyperbolicTangent extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return Math.tanh(in0);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Tanh";
+ }
+ }
+
+ /**
+ * Protected natural log function. Returns the natural log of the absolute
+ * value of input 0. If input 0 is less than {@link DoubleArithmetic.}DIVISION_LIMIT,
+ * this returns it unchanged.
+ *
+ * @see Math.log(), Math.abs()
+ */
+ public static class NaturalLog extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return in0 < DIVISION_LIMIT ? in0 : Math.log(Math.abs(in0));
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Ln";
+ }
+ }
+
+ /**
+ * Protected log base 10 function. Returns the log to base 10 the absolute
+ * value of input 0. If input 0 is less than {@link DoubleArithmetic.}DIVISION_LIMIT,
+ * this returns it unchanged.
+ *
+ * @see Math.log10(), Math.abs()
+ */
+ public static class LogBaseTen extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ return in0 < DIVISION_LIMIT ? in0 : Math.log10(Math.abs(in0));
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Log";
+ }
+ }
+
+ /**
+ * Sine of sum. Returns the sine of the sum of inputs 0 and 1.
+ *
+ * @see Math.sin()
+ */
+ public static class SineAB extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+ return Math.sin(in0 + in1);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Sin(a+b)";
+ }
+ }
+
+ /**
+ * Cosine of sum. Returns the cosine of the sum of inputs 0 and 1.
+ *
+ * @see Math.cos()
+ */
+ public static class CosineAB extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+ return Math.cos(in0 + in1);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Cos(a+b)";
+ }
+ }
+
+ /**
+ * Hypotenuse function. Returns the square root of input 0 squared
+ * plus input 1 squared.
+ *
+ * @see Math.hypot()
+ */
+ public static class Hypotenuse extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+ return Math.hypot(in0, in1);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Hypotenuse";
+ }
+ }
+
+ /**
+ * Power function. Returns the absolute value of input 0 to the power of input 1.
+ *
+ * @see Math.abs(), Math.pow
+ */
+ public static class Power extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+ return Math.pow(Math.abs(in0), in1);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Power";
+ }
+ }
+
+ /**
+ * Addition returns the sum of inputs 0 and 1.
+ *
+ */
+ public static class Addition extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+ return in0 + in1;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Addition";
+ }
+ }
+
+ /**
+ * Subtraction returns the difference between inputs 0 and 1.
+ *
+ */
+ public static class Subtraction extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+ return in0 - in1;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Subtraction";
+ }
+ }
+
+ /**
+ * Multiplication returns the product of inputs 0 and 1.
+ *
+ */
+ public static class Multiplication extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+ return in0 * in1;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Multiplication";
+ }
+ }
+
+ /**
+ * Protected division, returns the quotient of input 0 (the dividend) and input 1 (the divisor).
+ * If the divisor is less than {@link DoubleArithmetic.}DIVISION_LIMIT, this returns the it unchanged.
+ *
+ */
+ public static class Division extends Function {
+ @Override
+ public Double run(Connection... connections) {
+ if (connections.length < getArity()) {
+ throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + ".");
+ } else {
+ Double in0 = ((Double) connections[0].getValue());
+ Double in1 = ((Double) connections[1].getValue());
+
+ return in1 < DIVISION_LIMIT ? in0 : (in0 / in1);
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ return "Division";
+ }
+ }
+}
diff --git a/src/jcgp/backend/function/FunctionSet.java b/src/jcgp/backend/function/FunctionSet.java
index 78801fc..1712b51 100644
--- a/src/jcgp/backend/function/FunctionSet.java
+++ b/src/jcgp/backend/function/FunctionSet.java
@@ -51,6 +51,7 @@ public abstract class FunctionSet {
int function = iterator.next();
if (function == index) {
iterator.remove();
+ break;
}
}
} else {
diff --git a/src/jcgp/backend/function/IntegerArithmetic.java b/src/jcgp/backend/function/IntegerArithmetic.java
deleted file mode 100644
index 9bb02b5..0000000
--- a/src/jcgp/backend/function/IntegerArithmetic.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package jcgp.backend.function;
-
-import jcgp.backend.population.Connection;
-
-public class IntegerArithmetic extends FunctionSet {
-
- public IntegerArithmetic() {
- name = "Integer Arithmetic";
- functionList = new Function[]{
- new Addition(),
- new Subtraction(),
- new Multiplication(),
- new Division()};
-
- enableAll();
- }
-
- public static class Addition extends Function {
- @Override
- public Integer run(Connection... connections) {
- if (connections.length < 2) {
- throw new IllegalArgumentException("Not enough connections were given.");
- } else {
- Integer arg1 = ((Integer) connections[0].getValue());
- Integer arg2 = ((Integer) connections[1].getValue());
- Integer result = arg1 + arg2;
-
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "Addition";
- }
- }
-
- public static class Subtraction extends Function {
- @Override
- public Integer run(Connection... connections) {
- if (connections.length < 2) {
- throw new IllegalArgumentException("Not enough connections were given.");
- } else {
- Integer arg1 = ((Integer) connections[0].getValue());
- Integer arg2 = ((Integer) connections[1].getValue());
- Integer result = arg1 - arg2;
-
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "Subtraction";
- }
- }
-
- public static class Multiplication extends Function {
- @Override
- public Integer run(Connection... connections) {
- if (connections.length < 2) {
- throw new IllegalArgumentException("Not enough connections were given.");
- } else {
- Integer arg1 = ((Integer) connections[0].getValue());
- Integer arg2 = ((Integer) connections[1].getValue());
- Integer result = arg1 * arg2;
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "Multiplication";
- }
- }
-
- public static class Division extends Function {
- @Override
- public Integer run(Connection... connections) {
- if (connections.length < 2) {
- throw new IllegalArgumentException("Not enough connections were given.");
- } else {
- Integer arg1 = ((Integer) connections[0].getValue());
- Integer arg2 = ((Integer) connections[1].getValue());
- Integer result;
- if (arg2 == 0) {
- result = 0;
- } else {
- result = arg1 / arg2;
- }
-
- return result;
- }
- }
-
- @Override
- public int getArity() {
- return 2;
- }
-
- @Override
- public String getName() {
- return "Division";
- }
- }
-
-}
diff --git a/src/jcgp/backend/modules/problem/SymbolicRegression.java b/src/jcgp/backend/modules/problem/SymbolicRegression.java
index c92d183..46b8e09 100644
--- a/src/jcgp/backend/modules/problem/SymbolicRegression.java
+++ b/src/jcgp/backend/modules/problem/SymbolicRegression.java
@@ -2,18 +2,18 @@ package jcgp.backend.modules.problem;
import java.util.ArrayList;
-import jcgp.backend.function.IntegerArithmetic;
+import jcgp.backend.function.DoubleArithmetic;
import jcgp.backend.resources.Resources;
-public class SymbolicRegression extends TestCaseProblem<Integer> {
+public class SymbolicRegression extends TestCaseProblem<Double> {
public SymbolicRegression(Resources resources) {
super(resources);
- functionSet = new IntegerArithmetic();
+ functionSet = new DoubleArithmetic();
- ArrayList<TestCase<Integer>> tc = new ArrayList<TestCase<Integer>>();
- tc.add(new TestCase<Integer>(new Integer[]{1, 2, 3}, new Integer[]{-4, 5, 6}));
- tc.add(new TestCase<Integer>(new Integer[]{3, 2, 5}, new Integer[]{2, 5, 9}));
+ 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);
}
diff --git a/src/jcgp/backend/parser/ChromosomeParser.java b/src/jcgp/backend/parser/ChromosomeParser.java
new file mode 100644
index 0000000..74f638c
--- /dev/null
+++ b/src/jcgp/backend/parser/ChromosomeParser.java
@@ -0,0 +1,131 @@
+package jcgp.backend.parser;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.Scanner;
+
+import jcgp.backend.population.Chromosome;
+import jcgp.backend.population.Connection;
+import jcgp.backend.population.Node;
+import jcgp.backend.resources.Resources;
+
+/**
+ * This class includes a method for parsing .chr files and another
+ * for writing .chr files from given chromosomes.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
+public 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, Resources 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.
+ *
+ */
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ 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) {
+ e.printStackTrace();
+ return;
+ }
+ in = new Scanner(fr);
+
+ 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();
+ }
+ }
+
+ /**
+ * Writes a chromosome into the specified .chr file.
+ *
+ *
+ *
+ * @param file
+ * @param chromosome
+ */
+ public static void save(File file, Chromosome chromosome) {
+
+ }
+
+}
diff --git a/src/jcgp/backend/parser/FunctionParser.java b/src/jcgp/backend/parser/FunctionParser.java
new file mode 100644
index 0000000..64a095c
--- /dev/null
+++ b/src/jcgp/backend/parser/FunctionParser.java
@@ -0,0 +1,58 @@
+package jcgp.backend.parser;
+
+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;
+
+public class FunctionParser {
+
+private FunctionSet functionSet;
+
+ private FunctionParser(Problem problem) {
+ this.functionSet = problem.getFunctionSet();
+ }
+
+ public static void parseFunctions(File file, Problem problem) {
+ FunctionParser pp = new FunctionParser(problem);
+
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Scanner in = new Scanner(fr);
+
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if (line.substring(line.length() - 1).matches("[0-9]")) {
+ pp.parseAndSet(line.split("[^0-9]+"));
+ }
+ }
+
+ in.close();
+ }
+
+ 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
new file mode 100644
index 0000000..473b632
--- /dev/null
+++ b/src/jcgp/backend/parser/ParameterParser.java
@@ -0,0 +1,76 @@
+package jcgp.backend.parser;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.Scanner;
+import jcgp.backend.resources.ModifiableResources;
+
+public class ParameterParser {
+
+ private ModifiableResources resources;
+
+ private ParameterParser(ModifiableResources resources) {
+ this.resources = resources;
+ }
+
+ public static void parseParameters(File file, ModifiableResources resources) {
+ ParameterParser pp = new ParameterParser(resources);
+
+ FileReader fr;
+ try {
+ fr = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Scanner in = new Scanner(fr);
+
+ while (in.hasNextLine()) {
+ pp.parseAndSet(in.nextLine().split("( |\t)+"));
+ }
+
+ in.close();
+ }
+
+ private void parseAndSet(String[] splitString) {
+ switch (splitString[1]) {
+
+ case "population_size":
+ resources.setPopulationSize(Integer.parseInt(splitString[0]));
+ break;
+
+ case "num_generations":
+ resources.setGenerations(Integer.parseInt(splitString[0]));
+ break;
+
+ case "num_runs_total":
+ resources.setRuns(Integer.parseInt(splitString[0]));
+ break;
+
+ case "num_rows":
+ resources.setRows(Integer.parseInt(splitString[0]));
+ break;
+
+ case "num_cols":
+ resources.setColumns(Integer.parseInt(splitString[0]));
+ break;
+
+ case "levels_back":
+ resources.setLevelsBack(Integer.parseInt(splitString[0]));
+ break;
+
+ case "report_interval":
+ resources.setReportInterval(Integer.parseInt(splitString[0]));
+ break;
+
+ case "global_seed":
+ resources.setSeed(Integer.parseInt(splitString[0]));
+ break;
+
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/jcgp/backend/parser/TestCaseParser.java b/src/jcgp/backend/parser/TestCaseParser.java
new file mode 100644
index 0000000..c997177
--- /dev/null
+++ b/src/jcgp/backend/parser/TestCaseParser.java
@@ -0,0 +1,13 @@
+package jcgp.backend.parser;
+
+import java.io.File;
+
+import jcgp.backend.modules.problem.TestCaseProblem;
+
+public class TestCaseParser {
+
+ public static void parse(File file, TestCaseProblem<?> problem) {
+
+ }
+
+}
diff --git a/src/jcgp/backend/population/Population.java b/src/jcgp/backend/population/Population.java
index a850595..1bbdc54 100644
--- a/src/jcgp/backend/population/Population.java
+++ b/src/jcgp/backend/population/Population.java
@@ -98,5 +98,4 @@ public class Population {
public int getFittestIndex() {
return fittest;
}
-
}
diff --git a/src/jcgp/backend/resources/ModifiableResources.java b/src/jcgp/backend/resources/ModifiableResources.java
index 689f846..3841963 100644
--- a/src/jcgp/backend/resources/ModifiableResources.java
+++ b/src/jcgp/backend/resources/ModifiableResources.java
@@ -19,6 +19,10 @@ public class ModifiableResources extends Resources {
super();
}
+ public void setValues(String filePath) {
+
+ }
+
/**
* @param rows the rows to set
*/
@@ -106,8 +110,8 @@ public class ModifiableResources extends Resources {
/**
* @param report the report to set
*/
- public void setReport(int report) {
- this.report.set(report);
+ public void setReportInterval(int report) {
+ this.reportInterval.set(report);
}
/**
@@ -197,10 +201,10 @@ public class ModifiableResources extends Resources {
/**
* @return the report
*/
- public IntegerParameter getReportParameter() {
- return report;
+ public IntegerParameter getReportIntervalParameter() {
+ return reportInterval;
}
-
+
public void setFunctionSet(FunctionSet functionSet) {
this.functionSet = functionSet;
setArity(functionSet.getMaxArity());
diff --git a/src/jcgp/backend/resources/Resources.java b/src/jcgp/backend/resources/Resources.java
index c83fa35..0bf1ee1 100644
--- a/src/jcgp/backend/resources/Resources.java
+++ b/src/jcgp/backend/resources/Resources.java
@@ -21,7 +21,7 @@ import jcgp.backend.resources.parameters.ParameterStatus;
public class Resources {
protected IntegerParameter rows, columns, inputs, outputs, populationSize,
levelsBack, currentGeneration, generations, currentRun, runs,
- arity, seed, report;
+ arity, seed, reportInterval;
protected Random numberGenerator = new Random();
protected FunctionSet functionSet;
@@ -124,10 +124,10 @@ public class Resources {
}
/**
- * @return the report
+ * @return the report interval
*/
- public int report() {
- return report.get();
+ public int reportInterval() {
+ return reportInterval.get();
}
private void createBaseParameters() {
@@ -273,7 +273,7 @@ public class Resources {
});
numberGenerator.setSeed(seed.get());
- report = new IntegerParameter(1, "Report", false, false) {
+ reportInterval = new IntegerParameter(1, "Report interval", false, false) {
@Override
public void validate(Number newValue) {
if (newValue.intValue() > generations.get()) {
@@ -325,8 +325,8 @@ public class Resources {
* These are affected by parameter report
*/
public void reportln(String s) {
- if (report.get() > 0) {
- if (currentGeneration.get() % report.get() == 0) {
+ if (reportInterval.get() > 0) {
+ if (currentGeneration.get() % reportInterval.get() == 0) {
System.out.println(s);
if (console != null) {
console.println(s);
@@ -336,8 +336,8 @@ public class Resources {
}
public void report(String s) {
- if (report.get() > 0) {
- if (currentGeneration.get() % report.get() == 0) {
+ if (reportInterval.get() > 0) {
+ if (currentGeneration.get() % reportInterval.get() == 0) {
System.out.print(s);
if (console != null) {
console.print(s);
diff --git a/src/jcgp/backend/tests/ChromosomeTests.java b/src/jcgp/backend/tests/ChromosomeTests.java
index 07326a7..36278ba 100644
--- a/src/jcgp/backend/tests/ChromosomeTests.java
+++ b/src/jcgp/backend/tests/ChromosomeTests.java
@@ -2,7 +2,7 @@ package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import jcgp.backend.function.IntegerArithmetic;
+import jcgp.backend.function.DoubleArithmetic;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Input;
@@ -46,7 +46,7 @@ public class ChromosomeTests {
@BeforeClass
public static void setUpBeforeClass() {
resources = new ModifiableResources();
- resources.setFunctionSet(new IntegerArithmetic());
+ resources.setFunctionSet(new DoubleArithmetic());
}
@Before
diff --git a/src/jcgp/backend/tests/NodeTests.java b/src/jcgp/backend/tests/NodeTests.java
index 0e08d92..c9f247a 100644
--- a/src/jcgp/backend/tests/NodeTests.java
+++ b/src/jcgp/backend/tests/NodeTests.java
@@ -3,7 +3,7 @@ package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
import jcgp.backend.exceptions.InvalidArgumentsException;
import jcgp.backend.function.Function;
-import jcgp.backend.function.IntegerArithmetic;
+import jcgp.backend.function.DoubleArithmetic;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Node;
@@ -41,7 +41,7 @@ public class NodeTests {
public static void setUpBeforeClass() {
resources = new ModifiableResources();
- resources.setFunctionSet(new IntegerArithmetic());
+ resources.setFunctionSet(new DoubleArithmetic());
chromosome = new Chromosome(resources);
}
@@ -49,7 +49,7 @@ public class NodeTests {
public void setUp() throws Exception {
node = new Node(chromosome, 0, 0, resources.arity());
// make node with anonymous addition function and hard-coded value connections
- node.initialise(new IntegerArithmetic.Addition(),
+ node.initialise(new DoubleArithmetic.Addition(),
new Connection[]{new Connection() {
@Override
@@ -113,7 +113,7 @@ public class NodeTests {
((int) node.getValue()) == arg1 + arg2);
// put in a different function, check the output has changed appropriately
- node.setFunction(new IntegerArithmetic.Subtraction());
+ node.setFunction(new DoubleArithmetic.Subtraction());
assertTrue("Node did not return expected value (difference of arguments).", ((Integer) node.getValue()) == arg1 - arg2);
diff --git a/src/jcgp/backend/tests/OutputTests.java b/src/jcgp/backend/tests/OutputTests.java
index a331f2d..95b7fc7 100644
--- a/src/jcgp/backend/tests/OutputTests.java
+++ b/src/jcgp/backend/tests/OutputTests.java
@@ -1,7 +1,7 @@
package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
-import jcgp.backend.function.IntegerArithmetic;
+import jcgp.backend.function.DoubleArithmetic;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Output;
@@ -35,7 +35,7 @@ public class OutputTests {
@BeforeClass
public static void setUpBeforeClass() {
resources = new ModifiableResources();
- resources.setFunctionSet(new IntegerArithmetic());
+ resources.setFunctionSet(new DoubleArithmetic());
chromosome = new Chromosome(resources);
}
diff --git a/src/jcgp/backend/tests/PopulationTests.java b/src/jcgp/backend/tests/PopulationTests.java
index fb8ced4..fca9c4f 100644
--- a/src/jcgp/backend/tests/PopulationTests.java
+++ b/src/jcgp/backend/tests/PopulationTests.java
@@ -1,7 +1,7 @@
package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
-import jcgp.backend.function.IntegerArithmetic;
+import jcgp.backend.function.DoubleArithmetic;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Population;
import jcgp.backend.resources.ModifiableResources;
@@ -32,7 +32,7 @@ public class PopulationTests {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
resources = new ModifiableResources();
- resources.setFunctionSet(new IntegerArithmetic());
+ resources.setFunctionSet(new DoubleArithmetic());
}
@Before
diff --git a/src/jcgp/gui/GUI.java b/src/jcgp/gui/GUI.java
index e7a4a23..91c72e6 100644
--- a/src/jcgp/gui/GUI.java
+++ b/src/jcgp/gui/GUI.java
@@ -40,6 +40,8 @@ public class GUI extends Application {
private final JCGP jcgp;
+ private Stage stage;
+
private final FunctionSelector functionSelector;
private PopulationPane populationPane;
@@ -108,7 +110,7 @@ public class GUI extends Application {
public void start(Stage primaryStage) throws Exception {
console = new GUIConsole();
jcgp.setConsole(console);
-
+ stage = primaryStage;
/*
* Instantiate the various GUI elements here.
*
@@ -181,15 +183,20 @@ public class GUI extends Application {
public void reset() {
if (!running && settingsPane.areParametersValid()) {
+ setEvaluating(false);
settingsPane.applyParameters();
jcgp.reset();
- populationPane.remakeTabs();
- settingsPane.revalidateParameters();
- settingsPane.updateControls(false, jcgp.isFinished());
- console.flush();
+ reDraw();
}
}
+ public void reDraw() {
+ populationPane.remakeTabs();
+ settingsPane.revalidateParameters();
+ settingsPane.updateControls(false, jcgp.isFinished());
+ console.flush();
+ }
+
private void runningMode(boolean value) {
if (value) {
populationPane.unlockOutputs();
@@ -234,4 +241,8 @@ public class GUI extends Application {
public void setEvaluating(boolean value) {
populationPane.setEvaluating(value);
}
+
+ public Stage getStage() {
+ return stage;
+ }
}
diff --git a/src/jcgp/gui/population/PopulationPane.java b/src/jcgp/gui/population/PopulationPane.java
index 28b0ad9..5fa6067 100644
--- a/src/jcgp/gui/population/PopulationPane.java
+++ b/src/jcgp/gui/population/PopulationPane.java
@@ -38,19 +38,19 @@ public class PopulationPane extends TabPane {
if (evaluating) {
evaluateTestCase(currentTestCase);
}
- for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ for (int i = 0; i < getTabs().size(); i++) {
((ChromosomePane) getTabs().get(i).getContent()).updateGenes();
}
}
public void unlockOutputs() {
- for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ for (int i = 0; i < getTabs().size(); i++) {
((ChromosomePane) getTabs().get(i).getContent()).unlockOutputs();
}
}
public void relockOutputs() {
- for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ for (int i = 0; i < getTabs().size(); i++) {
((ChromosomePane) getTabs().get(i).getContent()).relockOutputs();
}
}
diff --git a/src/jcgp/gui/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java
index 2ab9650..4e8c342 100644
--- a/src/jcgp/gui/settings/SettingsPane.java
+++ b/src/jcgp/gui/settings/SettingsPane.java
@@ -1,5 +1,6 @@
package jcgp.gui.settings;
+import java.io.File;
import java.util.ArrayList;
import javafx.event.ActionEvent;
@@ -16,6 +17,8 @@ import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
+import javafx.stage.FileChooser;
+import javafx.stage.FileChooser.ExtensionFilter;
import jcgp.JCGP;
import jcgp.backend.function.FunctionSet;
import jcgp.backend.modules.es.EvolutionaryStrategy;
@@ -31,6 +34,7 @@ public class SettingsPane extends AnchorPane {
private VBox mainContainer;
private VBox baseParameterPane, eaPane, mutatorPane, problemPane;
+ private VBox nodeFunctions;
private Button runPause = new Button("Run"), step = new Button("Step"), reset = new Button("Reset");
private Button loadParameters = new Button("Load parameters"), loadChromosome = new Button("Load chromosome"), saveChromosome = new Button("Save chromosome");
@@ -103,7 +107,7 @@ public class SettingsPane extends AnchorPane {
parameters.add(gp);
parameters.add(GUIParameter.create(jcgp.getResources().getSeedParameter(), this));
- parameters.add(GUIParameter.create(jcgp.getResources().getReportParameter(), this));
+ parameters.add(GUIParameter.create(jcgp.getResources().getReportIntervalParameter(), this));
baseParameterPane.getChildren().addAll(parameters);
mainContainer.getChildren().add(baseParameterPane);
@@ -201,10 +205,10 @@ public class SettingsPane extends AnchorPane {
testCaseTable = new TestCaseTable((TestCaseProblem<Object>) jcgp.getProblem(), gui);
}
- final VBox nodeFunctions = new VBox();
+ nodeFunctions = new VBox();
nodeFunctions.setSpacing(2);
nodeFunctions.setPadding(new Insets(0, 0, 4, 0));
- refreshFunctions(jcgp.getResources().getFunctionSet(), nodeFunctions, gui);
+ refreshFunctions();
problemCBox.setOnAction(new EventHandler<ActionEvent>() {
@Override
@@ -215,7 +219,7 @@ public class SettingsPane extends AnchorPane {
}
testCaseTable.close();
gui.setEvaluating(false);
- refreshFunctions(jcgp.getProblem().getFunctionSet(), nodeFunctions, gui);
+ refreshFunctions();
showTestCaseContainer.getChildren().clear();
if (jcgp.getProblem() instanceof TestCaseProblem) {
showTestCaseContainer.getChildren().add(showTestCaseButton);
@@ -284,14 +288,31 @@ public class SettingsPane extends AnchorPane {
loadParameters.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
- //gui.runPause();
+ FileChooser fc = new FileChooser();
+ fc.setTitle("Open .par file...");
+ fc.getExtensionFilters().add(new ExtensionFilter("CGP parameter files", "*.par"));
+ fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*"));
+ File parFile = fc.showOpenDialog(gui.getStage());
+ if (parFile != null) {
+ gui.getExperiment().loadParameters(parFile);
+ }
+ gui.reDraw();
+ refreshFunctions();
}
});
loadChromosome.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
- //gui.step();
+ FileChooser fc = new FileChooser();
+ fc.setTitle("Open .chr file...");
+ fc.getExtensionFilters().add(new ExtensionFilter("CGP chromosome files", "*.chr"));
+ fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*"));
+ File chrFile = fc.showOpenDialog(gui.getStage());
+ if (chrFile != null) {
+ gui.getExperiment().loadChromosome(chrFile);
+ }
+ gui.reDraw();
}
});
saveChromosome.setOnAction(new EventHandler<ActionEvent>() {
@@ -331,31 +352,28 @@ public class SettingsPane extends AnchorPane {
/**
* This method handles a problem type change by updating the list of allowed
* node functions.
- *
- * @param functionSet
- * @param container
- * @param gui
*/
- private void refreshFunctions(final FunctionSet functionSet, VBox container, final GUI gui) {
- container.getChildren().clear();
+ private void refreshFunctions() {
+ nodeFunctions.getChildren().clear();
CheckBox cb;
- for (int i = 0; i < functionSet.getTotalFunctionCount(); i++) {
- cb = new CheckBox(functionSet.getFunction(i).getName());
+ final FunctionSet fs = gui.getExperiment().getResources().getFunctionSet();
+ for (int i = 0; i < fs.getTotalFunctionCount(); i++) {
+ cb = new CheckBox(fs.getFunction(i).getName());
cb.setId(String.valueOf(i));
- cb.setSelected(functionSet.isEnabled(functionSet.getFunction(i)));
+ cb.setSelected(fs.isEnabled(fs.getFunction(i)));
final int index = i;
cb.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if (((CheckBox) event.getSource()).isSelected()) {
- functionSet.enableFunction(index);
+ fs.enableFunction(index);
} else {
- functionSet.disableFunction(index);
+ fs.disableFunction(index);
}
gui.updateFunctionSelector();
}
});
- container.getChildren().add(cb);
+ nodeFunctions.getChildren().add(cb);
gui.updateFunctionSelector();
}
@@ -436,6 +454,11 @@ public class SettingsPane extends AnchorPane {
step.setDisable(running || finished);
reset.setDisable(running);
+ loadParameters.setDisable(running);
+ loadChromosome.setDisable(running);
+ saveChromosome.setDisable(running);
+
+
testCaseTable.getTable().setDisable(running);
}
diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java
index a8a8c4a..159e709 100644
--- a/src/jcgp/gui/settings/parameters/GUIParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIParameter.java
@@ -86,7 +86,7 @@ public abstract class GUIParameter<T> extends HBox {
// the tooltip is the hover-over label containing status information, when appropriate
tooltip = new Tooltip();
- tooltip.setStyle("-fx-background-color: white; -fx-border-color: black; .page-corner {-fx-background-color: transparent;}");
+ tooltip.setStyle("-fx-background-color: white; -fx-border-color: black;");
tooltip.setSkin(null);
valueControl = makeControl();
diff --git a/src/parameters.par b/src/parameters.par
new file mode 100644
index 0000000..bf38c11
--- /dev/null
+++ b/src/parameters.par
@@ -0,0 +1,32 @@
+5 population_size
+1.0 per_cent_mutate
+10000 num_generations
+10 num_runs_total
+1 num_rows
+100 num_cols
+100 levels_back
+1 progress_report
+1000 report_interval
+173156789 global_seed
+0 run_from_chrom
+0 shrink_phenotype
+0 1 modulus-0
+0 1 sqrt-1
+0 1 reciprocal-2
+0 1 sin-3
+0 1 cos-4
+0 1 tan-5
+0 1 exp-6
+0 1 sinh-7
+0 1 cosh-8
+0 1 tanh-9
+0 1 nat-log-10
+0 1 logbase10-11
+0 2 sin(a+b)-12
+0 2 cos(a+b)-13
+0 2 hypoteneuse-14
+0 2 power-15
+1 2 addition-16
+1 2 subtraction-17
+1 2 multiplication-18
+1 2 division-19 \ No newline at end of file