aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp
diff options
context:
space:
mode:
authorEduardo Pedroni <ep625@york.ac.uk>2014-02-10 09:33:54 +0000
committerEduardo Pedroni <ep625@york.ac.uk>2014-02-10 09:33:54 +0000
commit6e7747e5b85f4ca93683ed5166f6e480cc58e6fa (patch)
treee1243f2eb6f743a547b89362e37e516e22f647e8 /src/jcgp
parent0e34bfdb60c28a6118ec93893ddc7ceb6fa50cb5 (diff)
Refactored the resources mechanics, implemented a few of the chromosome tests
Diffstat (limited to 'src/jcgp')
-rw-r--r--src/jcgp/CGP.java362
-rw-r--r--src/jcgp/Parameters.java114
-rw-r--r--src/jcgp/TruthTable.java21
-rw-r--r--src/jcgp/Utilities.java169
-rw-r--r--src/jcgp/ea/StandardMutator.java6
-rw-r--r--src/jcgp/fitness/TestCase.java2
-rw-r--r--src/jcgp/fitness/TruthTableEvaluator.java4
-rw-r--r--src/jcgp/function/Addition.java2
-rw-r--r--src/jcgp/function/Subtraction.java2
-rw-r--r--src/jcgp/population/Chromosome.java26
-rw-r--r--src/jcgp/population/Connection.java2
-rw-r--r--src/jcgp/population/Input.java2
-rw-r--r--src/jcgp/population/MutableElement.java2
-rw-r--r--src/jcgp/population/Node.java18
-rw-r--r--src/jcgp/population/Output.java14
-rw-r--r--src/jcgp/population/Population.java2
-rw-r--r--src/jcgp/tests/ChromosomeTests.java103
-rw-r--r--src/jcgp/tests/Tests.java22
18 files changed, 475 insertions, 398 deletions
diff --git a/src/jcgp/CGP.java b/src/jcgp/CGP.java
index 5111508..6cf5429 100644
--- a/src/jcgp/CGP.java
+++ b/src/jcgp/CGP.java
@@ -1,7 +1,6 @@
package jcgp;
import java.util.Random;
-
import jcgp.ea.EvolutionaryAlgorithm;
import jcgp.ea.Mutator;
import jcgp.ea.StandardEA;
@@ -10,344 +9,12 @@ import jcgp.fitness.FitnessFunction;
import jcgp.fitness.TestCase;
import jcgp.fitness.TruthTableEvaluator;
import jcgp.function.Addition;
-import jcgp.function.Function;
import jcgp.function.FunctionSet;
import jcgp.function.Subtraction;
-import jcgp.population.Chromosome;
-import jcgp.population.Connection;
-import jcgp.population.Input;
-import jcgp.population.MutableElement;
-import jcgp.population.Node;
import jcgp.population.Population;
public final class CGP {
- public static class Parameters {
- private static int rows, columns, inputs, outputs, mutationRate, generations, runs, populationSize, levelsBack, maxArity;
-
- /**
- * @return the number of nodes
- */
- public static int getNodeNumber() {
- return rows * columns;
- }
-
- /**
- * @return the levelsBack
- */
- public static int getLevelsBack() {
- return levelsBack;
- }
-
- /**
- * @param levelsBack the levelsBack to set
- */
- private static void setLevelsBack(int levelsBack) {
- Parameters.levelsBack = levelsBack;
- }
-
- /**
- * @return the populationSize
- */
- public static int getPopulationSize() {
- return populationSize;
- }
-
- /**
- * @param populationSize the populationSize to set
- */
- private static void setPopulationSize(int populationSize) {
- Parameters.populationSize = populationSize;
- }
-
- /**
- * @return the rows
- */
- public static int getRows() {
- return rows;
- }
-
- /**
- * @return the columns
- */
- public static int getColumns() {
- return columns;
- }
-
- /**
- * @return the inputs
- */
- public static int getInputs() {
- return inputs;
- }
-
- /**
- * @return the outputs
- */
- public static int getOutputs() {
- return outputs;
- }
-
- /**
- * @return the mutationRate
- */
- public static int getMutationRate() {
- return mutationRate;
- }
-
- /**
- * @return the generations
- */
- public static int getGenerations() {
- return generations;
- }
-
- /**
- * @return the runs
- */
- public static int getRuns() {
- return runs;
- }
-
- /**
- * @param rows the rows to set
- */
- private static void setRows(int rows) {
- Parameters.rows = rows;
- }
-
- /**
- * @param columns the columns to set
- */
- private static void setColumns(int columns) {
- Parameters.columns = columns;
- }
-
- /**
- * @param inputs the inputs to set
- */
- private static void setInputs(int inputs) {
- Parameters.inputs = inputs;
- }
-
- /**
- * @param outputs the outputs to set
- */
- private static void setOutputs(int outputs) {
- Parameters.outputs = outputs;
- }
-
- /**
- * @param mutationRate the mutationRate to set
- */
- private static void setMutationRate(int mutationRate) {
- Parameters.mutationRate = mutationRate;
- }
-
- /**
- * @param generations the generations to set
- */
- private static void setGenerations(int generations) {
- Parameters.generations = generations;
- }
-
- /**
- * @param runs the runs to set
- */
- private static void setRuns(int runs) {
- Parameters.runs = runs;
- }
-
- /**
- * @return the maxArity
- */
- public static int getMaxArity() {
- return maxArity;
- }
-
- /**
- * @param maxArity the maxArity to set
- */
- private static void setMaxArity(int maxArity) {
- Parameters.maxArity = maxArity;
- }
- }
-
- public abstract static class Utilities {
-
- public static int getRandomInt(int limit){
- return numberGenerator.nextInt(limit);
- }
-
- public static double getRandomDouble(int limit){
- return numberGenerator.nextDouble() * limit;
- }
-
- /**
- * Returns a random allowed connection respecting levels back.
- * This method may always pick inputs, as they can be picked
- * regardless of the column.
- *
- * @param chromosome the chromosome to pick from
- * @param column the column to use as reference
- * @return a random connection
- */
- public static Connection getRandomConnection(Chromosome chromosome, int column){
- // work out the allowed range obeying levels back
- int allowedColumns = ((column >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : column);
- int offset = column - allowedColumns;
-
- // choose input or node
- int connectionType = getRandomInt(Parameters.getInputs() + (Parameters.getRows() * allowedColumns));
- if (connectionType < Parameters.getInputs()) {
- // input
- return chromosome.getInput(getRandomInt(Parameters.getInputs()));
- } else {
- // node
- return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(allowedColumns) + offset);
- }
- }
-
- /**
- * Returns a random allowed connection.
- *
- * This method may always pick inputs, as they can be picked
- * regardless of the column.
- *
- * @param chromosome the chromosome to pick from
- * @param column the column to use as reference
- * @param levelsBack whether or not to respect levels back
- * @return a random connection
- */
- public static Connection getRandomConnection(Chromosome chromosome, int column, boolean levelsBack){
- if (levelsBack) {
- return getRandomConnection(chromosome, column);
- } else {
- // choose input or node
- int connectionType = getRandomInt(Parameters.getInputs() + (Parameters.getRows() * column));
- if (connectionType < Parameters.getInputs()) {
- // input
- return chromosome.getInput(getRandomInt(Parameters.getInputs()));
- } else {
- // node
- return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(column));
- }
- }
- }
-
- /**
- * @param chromosome the chromosome to choose from
- * @return a random input
- */
- public static Input getRandomInput(Chromosome chromosome){
- return chromosome.getInput(getRandomInt(Parameters.getInputs()));
- }
-
- /**
- * Returns a random allowed node respecting levels back.
- *
- * This method will NOT pick inputs.
- *
- * @param chromosome the chromosome to pick from
- * @param column the column to use as reference
- * @return a random node
- */
- public static Node getRandomNode(Chromosome chromosome, int column){
- // work out the allowed range obeying levels back
- int allowedColumns = ((column >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : column);
- int offset = column - allowedColumns;
-
- // pick a random allowed column and row
- int randomColumn = (getRandomInt(allowedColumns) + offset);
- int randomRow = (getRandomInt(Parameters.getRows()));
-
- return chromosome.getNode(randomRow, randomColumn);
- }
-
- /**
- * Returns a random allowed node.
- *
- * This method will NOT pick inputs.
- *
- * @param chromosome the chromosome to pick from
- * @param column the column to use as reference
- * @param levelsBack whether or not to respect levels back
- * @return a random node
- */
- public static Node getRandomNode(Chromosome chromosome, int column, boolean levelsBack){
- if (levelsBack) {
- return getRandomNode(chromosome, column);
- } else {
- // pick any random column before the given column
- int randomColumn = (getRandomInt(column));
- // pick a random rowgetColumns
- int randomRow = (getRandomInt(Parameters.getRows()));
- return chromosome.getNode(randomRow, randomColumn);
- }
- }
-
- /**
- * This method picks a random mutable element from the given chromosome.
- *
- * It will pick outputs or nodes fairly.
- *
- * @param chromosome the chromosome to pick from
- * @return a random mutable element
- */
- public static MutableElement getRandomMutable(Chromosome chromosome){
- // choose output or node
- int connectionType = getRandomInt(Parameters.getOutputs() + Parameters.getNodeNumber());
-
- if (connectionType < Parameters.getOutputs()) {
- // outputs
- return chromosome.getOutput(getRandomInt(Parameters.getOutputs()));
- } else {
- // node
- return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(Parameters.getRows()));
- }
- }
-
- /**
- * pick from any column - use this for setting outputs
- *
- * @param chromosome
- * @return
- */
- public static Node getRandomNode(Chromosome chromosome) {
- return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(Parameters.getColumns()));
- }
-
- public static Function getRandomFunction() {
- return functionSet.getFunction(Utilities.getRandomInt(functionSet.getFunctionCount()));
- }
-
- public static Function getFunction(int index) {
- return functionSet.getFunction(index);
- }
- }
-
- public static class TruthTable {
-
- private static TestCase[] testCases;
-
- private static void setTestCases(TestCase ... testCases) {
- TruthTable.testCases = testCases;
- }
-
- public static TestCase getTestCase(int index) {
- return testCases[index];
- }
-
- public static int getTestCaseCount() {
- return testCases.length;
- }
-
- }
-
- // system-wide resources
- private static FunctionSet functionSet;
- private static Random numberGenerator;
-
// CGP components
private EvolutionaryAlgorithm ea;
private Mutator mutator;
@@ -366,33 +33,30 @@ public final class CGP {
*
*/
private void initialise() {
- // initialise random number generator
- numberGenerator = new Random(1234);
-
// initialise function set
- functionSet = new FunctionSet(new Addition(), new Subtraction());
-
+ FunctionSet functionSet = new FunctionSet(new Addition(), new Subtraction());
+
+ // initialise utilities
+ Utilities.setResources(new Random(1234), functionSet);
+
// initialise parameters
- Parameters.setInputs(3);
Parameters.setColumns(3);
Parameters.setRows(3);
+ Parameters.setInputs(3);
Parameters.setOutputs(3);
- Parameters.setGenerations(10);
- Parameters.setMutationRate(1);
- Parameters.setRuns(5);
- Parameters.setPopulationSize(5);
Parameters.setLevelsBack(1);
-
- // compute and set maximum arity
+ Parameters.setMutationRate(10);
+ Parameters.setTotalGenerations(100);
+ Parameters.setTotalRuns(5);
Parameters.setMaxArity(functionSet.getMaxArity());
+
+ // initialise fitness function and truth table
+ TruthTable.setTestCases(new TestCase(new int[] {2, 5, 4}, new int[] {1, 10, 15}));
+ fitnessFunction = new TruthTableEvaluator();
// initialise EA
ea = new StandardEA();
mutator = new StandardMutator();
-
- // initialise fitness function and truth table
- TruthTable.setTestCases(new TestCase(new int[] {2, 5, 4}, new int[] {1, 10, 15}));
- fitnessFunction = new TruthTableEvaluator();
// initialise population
population = new Population();
diff --git a/src/jcgp/Parameters.java b/src/jcgp/Parameters.java
new file mode 100644
index 0000000..2a417db
--- /dev/null
+++ b/src/jcgp/Parameters.java
@@ -0,0 +1,114 @@
+package jcgp;
+
+public class Parameters {
+
+ private static int rows, columns, inputs, outputs, levelsBack,
+ mutationRate, populationSize, totalGenerations,
+ currentGeneration = 0, totalRuns, currentRun = 0,
+ maxArity;
+
+ public static int getRows() {
+ return rows;
+ }
+
+ public static int getColumns() {
+ return columns;
+ }
+
+ public static int getNodeCount() {
+ return rows * columns;
+ }
+
+ public static int getInputs() {
+ return inputs;
+ }
+
+ public static int getOutputs() {
+ return outputs;
+ }
+
+ public static int getLevelsBack() {
+ return levelsBack;
+ }
+
+ public static int getMutationRate() {
+ return mutationRate;
+ }
+
+ public static int getPopulationSize() {
+ return populationSize;
+ }
+
+ public static int getTotalGenerations() {
+ return totalGenerations;
+ }
+
+ public static int getCurrentGeneration() {
+ return currentGeneration;
+ }
+
+ public static int getTotalRuns() {
+ return totalRuns;
+ }
+
+ public static int getCurrentRun() {
+ return currentRun;
+ }
+
+ public static int getMaxArity() {
+ return maxArity;
+ }
+
+ public static void setRows(int rows) {
+ Parameters.rows = rows;
+ }
+
+ public static void setColumns(int columns) {
+ Parameters.columns = columns;
+ }
+
+ public static void setInputs(int inputs) {
+ Parameters.inputs = inputs;
+ }
+
+ public static void setOutputs(int outputs) {
+ Parameters.outputs = outputs;
+ }
+
+ public static void setLevelsBack(int levelsBack) {
+ Parameters.levelsBack = levelsBack;
+ }
+
+ public static void setMutationRate(int mutationRate) {
+ Parameters.mutationRate = mutationRate;
+ }
+
+ public static void setPopulationSize(int populationSize) {
+ Parameters.populationSize = populationSize;
+ }
+
+ public static void setTotalGenerations(int totalGenerations) {
+ Parameters.totalGenerations = totalGenerations;
+ }
+
+ public static void setCurrentGeneration(int currentGeneration) {
+ Parameters.currentGeneration = currentGeneration;
+ }
+
+ public static void incrementCurrentGeneration() {
+ Parameters.currentGeneration++;
+ }
+
+ public static void setTotalRuns(int totalRuns) {
+ Parameters.totalRuns = totalRuns;
+ }
+
+ public static void setCurrentRun(int currentRun) {
+ Parameters.currentRun = currentRun;
+ }
+
+ public static void setMaxArity(int maxArity) {
+ Parameters.maxArity = maxArity;
+ }
+
+}
diff --git a/src/jcgp/TruthTable.java b/src/jcgp/TruthTable.java
new file mode 100644
index 0000000..72712fc
--- /dev/null
+++ b/src/jcgp/TruthTable.java
@@ -0,0 +1,21 @@
+package jcgp;
+
+import jcgp.fitness.TestCase;
+
+public class TruthTable {
+
+ private static TestCase[] testCases;
+
+ public static void setTestCases(TestCase ... testCases) {
+ TruthTable.testCases = testCases;
+ }
+
+ public static TestCase getTestCase(int index) {
+ return testCases[index];
+ }
+
+ public static int getTestCaseCount() {
+ return testCases.length;
+ }
+
+}
diff --git a/src/jcgp/Utilities.java b/src/jcgp/Utilities.java
new file mode 100644
index 0000000..7de701a
--- /dev/null
+++ b/src/jcgp/Utilities.java
@@ -0,0 +1,169 @@
+package jcgp;
+
+import java.util.Random;
+
+import jcgp.function.Function;
+import jcgp.function.FunctionSet;
+import jcgp.population.*;
+
+public class Utilities {
+
+ private static Random numberGenerator;
+ private static FunctionSet functionSet;
+
+ public static void setResources(Random numberGenerator, FunctionSet functionSet) {
+ Utilities.numberGenerator = numberGenerator;
+ Utilities.functionSet = functionSet;
+ }
+
+ public static int getRandomInt(int limit){
+ return numberGenerator.nextInt(limit);
+ }
+
+ public static double getRandomDouble(int limit){
+ return numberGenerator.nextDouble() * limit;
+ }
+
+ /**
+ * Returns a random allowed connection respecting levels back.
+ * This method may always pick inputs, as they can be picked
+ * regardless of the column.
+ *
+ * @param chromosome the chromosome to pick from
+ * @param column the column to use as reference
+ * @return a random connection
+ */
+ public static Connection getRandomConnection(Chromosome chromosome, int column){
+ // work out the allowed range obeying levels back
+ int allowedColumns = ((column >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : column);
+ int offset = column - allowedColumns;
+
+ // choose input or node
+ int connectionType = getRandomInt(Parameters.getInputs() + (Parameters.getRows() * allowedColumns));
+ if (connectionType < Parameters.getInputs()) {
+ // input
+ return chromosome.getInput(getRandomInt(Parameters.getInputs()));
+ } else {
+ // node
+ return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(allowedColumns) + offset);
+ }
+ }
+
+ /**
+ * Returns a random allowed connection.
+ *
+ * This method may always pick inputs, as they can be picked
+ * regardless of the column.
+ *
+ * @param chromosome the chromosome to pick from
+ * @param column the column to use as reference
+ * @param levelsBack whether or not to respect levels back
+ * @return a random connection
+ */
+ public static Connection getRandomConnection(Chromosome chromosome, int column, boolean levelsBack){
+ if (levelsBack) {
+ return getRandomConnection(chromosome, column);
+ } else {
+ // choose input or node
+ int connectionType = getRandomInt(Parameters.getInputs() + (Parameters.getRows() * column));
+ if (connectionType < Parameters.getInputs()) {
+ // input
+ return chromosome.getInput(getRandomInt(Parameters.getInputs()));
+ } else {
+ // node
+ return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(column));
+ }
+ }
+ }
+
+ /**
+ * @param chromosome the chromosome to choose from
+ * @return a random input
+ */
+ public static Input getRandomInput(Chromosome chromosome){
+ return chromosome.getInput(getRandomInt(Parameters.getInputs()));
+ }
+
+ /**
+ * Returns a random allowed node respecting levels back.
+ *
+ * This method will NOT pick inputs.
+ *
+ * @param chromosome the chromosome to pick from
+ * @param column the column to use as reference
+ * @return a random node
+ */
+ public static Node getRandomNode(Chromosome chromosome, int column){
+ // work out the allowed range obeying levels back
+ int allowedColumns = ((column >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : column);
+ int offset = column - allowedColumns;
+
+ // pick a random allowed column and row
+ int randomColumn = (getRandomInt(allowedColumns) + offset);
+ int randomRow = (getRandomInt(Parameters.getRows()));
+
+ return chromosome.getNode(randomRow, randomColumn);
+ }
+
+ /**
+ * Returns a random allowed node.
+ *
+ * This method will NOT pick inputs.
+ *
+ * @param chromosome the chromosome to pick from
+ * @param column the column to use as reference
+ * @param levelsBack whether or not to respect levels back
+ * @return a random node
+ */
+ public static Node getRandomNode(Chromosome chromosome, int column, boolean levelsBack){
+ if (levelsBack) {
+ return getRandomNode(chromosome, column);
+ } else {
+ // pick any random column before the given column
+ int randomColumn = (getRandomInt(column));
+ // pick a random rowgetColumns
+ int randomRow = (getRandomInt(Parameters.getRows()));
+ return chromosome.getNode(randomRow, randomColumn);
+ }
+ }
+
+ /**
+ * This method picks a random mutable element from the given chromosome.
+ *
+ * It will pick outputs or nodes fairly.
+ *
+ * @param chromosome the chromosome to pick from
+ * @return a random mutable element
+ */
+ public static MutableElement getRandomMutable(Chromosome chromosome){
+ // choose output or node
+ int connectionType = getRandomInt(Parameters.getOutputs() + Parameters.getNodeCount());
+
+ if (connectionType < Parameters.getOutputs()) {
+ // outputs
+ return chromosome.getOutput(getRandomInt(Parameters.getOutputs()));
+ } else {
+ // node
+ return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(Parameters.getRows()));
+ }
+ }
+
+ /**
+ * pick from any column - use this for setting outputs
+ *
+ * @param chromosome
+ * @return
+ */
+ public static Node getRandomNode(Chromosome chromosome) {
+ return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(Parameters.getColumns()));
+ }
+
+ public static Function getRandomFunction() {
+ return functionSet.getFunction(Utilities.getRandomInt(functionSet.getFunctionCount()));
+ }
+
+ public static Function getFunction(int index) {
+ return functionSet.getFunction(index);
+ }
+
+}
diff --git a/src/jcgp/ea/StandardMutator.java b/src/jcgp/ea/StandardMutator.java
index cab5c76..8af3f5c 100644
--- a/src/jcgp/ea/StandardMutator.java
+++ b/src/jcgp/ea/StandardMutator.java
@@ -1,7 +1,7 @@
package jcgp.ea;
-import jcgp.CGP.Parameters;
-import jcgp.CGP.Utilities;
+import jcgp.Parameters;
+import jcgp.Utilities;
import jcgp.population.Chromosome;
import jcgp.population.MutableElement;
import jcgp.population.Node;
@@ -11,7 +11,7 @@ public class StandardMutator implements Mutator {
@Override
public void mutate(Chromosome chromosome) {
- int mutations = (int) (Parameters.getMutationRate() * ((double) Parameters.getNodeNumber() / 100));
+ int mutations = (int) (Parameters.getMutationRate() * ((double) Parameters.getNodeCount() / 100));
for (int i = 0; i < mutations; i++) {
MutableElement m = Utilities.getRandomMutable(chromosome);
diff --git a/src/jcgp/fitness/TestCase.java b/src/jcgp/fitness/TestCase.java
index e2bd5ed..95129c6 100644
--- a/src/jcgp/fitness/TestCase.java
+++ b/src/jcgp/fitness/TestCase.java
@@ -1,6 +1,6 @@
package jcgp.fitness;
-import jcgp.CGP.Parameters;
+import jcgp.Parameters;
public class TestCase {
diff --git a/src/jcgp/fitness/TruthTableEvaluator.java b/src/jcgp/fitness/TruthTableEvaluator.java
index 64ca209..987ea4c 100644
--- a/src/jcgp/fitness/TruthTableEvaluator.java
+++ b/src/jcgp/fitness/TruthTableEvaluator.java
@@ -1,7 +1,7 @@
package jcgp.fitness;
-import jcgp.CGP.Parameters;
-import jcgp.CGP.TruthTable;
+import jcgp.Parameters;
+import jcgp.TruthTable;
import jcgp.population.Chromosome;
import jcgp.population.Population;
diff --git a/src/jcgp/function/Addition.java b/src/jcgp/function/Addition.java
index 8c1e0b5..faf11d5 100644
--- a/src/jcgp/function/Addition.java
+++ b/src/jcgp/function/Addition.java
@@ -7,7 +7,7 @@ public class Addition extends Function {
@Override
public int run(Connection... connections) {
if (connections.length > 0) {
- return connections[0].evaluate() + connections[1].evaluate();
+ return connections[0].getValue() + connections[1].getValue();
} else {
return 0;
}
diff --git a/src/jcgp/function/Subtraction.java b/src/jcgp/function/Subtraction.java
index 169f88c..f8b9c7d 100644
--- a/src/jcgp/function/Subtraction.java
+++ b/src/jcgp/function/Subtraction.java
@@ -7,7 +7,7 @@ public class Subtraction extends Function {
@Override
public int run(Connection... connections) {
if (connections.length > 1) {
- return connections[0].evaluate() - connections[1].evaluate();
+ return connections[0].getValue() - connections[1].getValue();
} else {
return 0;
}
diff --git a/src/jcgp/population/Chromosome.java b/src/jcgp/population/Chromosome.java
index f060e14..328a608 100644
--- a/src/jcgp/population/Chromosome.java
+++ b/src/jcgp/population/Chromosome.java
@@ -1,7 +1,8 @@
package jcgp.population;
-import jcgp.CGP.Parameters;
-import jcgp.CGP.Utilities;
+import jcgp.Parameters;
+import jcgp.Utilities;
+import jcgp.fitness.ParameterMismatchException;
public class Chromosome {
@@ -41,16 +42,16 @@ public class Chromosome {
}
// rows first
- nodes = new Node[Parameters.getRows()][Parameters.getColumns()];
+ nodes = new Node[rows][columns];
for (int r = 0; r < rows; r++) {
//nodes[r] = new Node[Parameters.getColumns()];
for (int c = 0; c < columns; c++) {
- nodes[r][c] = new Node(c);
+ nodes[r][c] = new Node(r, c);
}
}
outputs = new Output[outputCount];
for (int o = 0; o < outputCount; o++) {
- outputs[o] = new Output();
+ outputs[o] = new Output(o);
}
}
@@ -97,16 +98,25 @@ public class Chromosome {
fitness = newFitness;
}
- public void setInputs(int ... values) {
- // if the values provided dont match the specified number of inputs, the user should be warned
+ public void setInputs(int ... values) throws ParameterMismatchException {
+ // if the values provided don't match the specified number of inputs, the user should be warned
if (values.length == inputs.length) {
// set inputs for evaluation
for (int i = 0; i < values.length; i++) {
inputs[i].setValue(values[i]);
}
} else {
- System.out.println("Input mismatch: chromosome has a different number of inputs than the truth table.");
+ throw new ParameterMismatchException();
}
}
+
+ public MutableElement getMutableElement(int row, int column) {
+ if (column < Parameters.getColumns() && column >= 0) {
+ return nodes[row][column];
+ } else if (column == Parameters.getColumns()) {
+ return outputs[row];
+ }
+ return null;
+ }
}
diff --git a/src/jcgp/population/Connection.java b/src/jcgp/population/Connection.java
index fa02a22..4e69e99 100644
--- a/src/jcgp/population/Connection.java
+++ b/src/jcgp/population/Connection.java
@@ -2,5 +2,5 @@ package jcgp.population;
public interface Connection {
- public abstract int evaluate();
+ public abstract int getValue();
}
diff --git a/src/jcgp/population/Input.java b/src/jcgp/population/Input.java
index b9c127f..e00573e 100644
--- a/src/jcgp/population/Input.java
+++ b/src/jcgp/population/Input.java
@@ -9,7 +9,7 @@ public class Input implements Connection {
}
@Override
- public int evaluate() {
+ public int getValue() {
return value;
}
diff --git a/src/jcgp/population/MutableElement.java b/src/jcgp/population/MutableElement.java
index 8ac3724..c21ee0b 100644
--- a/src/jcgp/population/MutableElement.java
+++ b/src/jcgp/population/MutableElement.java
@@ -5,5 +5,7 @@ public interface MutableElement {
public void setConnection(Connection newConnection);
public int getColumn();
+
+ public int getRow();
}
diff --git a/src/jcgp/population/Node.java b/src/jcgp/population/Node.java
index fd0cd47..3dbabb2 100644
--- a/src/jcgp/population/Node.java
+++ b/src/jcgp/population/Node.java
@@ -1,7 +1,7 @@
package jcgp.population;
-import jcgp.CGP.Parameters;
-import jcgp.CGP.Utilities;
+import jcgp.Parameters;
+import jcgp.Utilities;
import jcgp.function.Function;
@@ -9,14 +9,15 @@ public class Node implements MutableElement, Connection {
private Function function;
private Connection[] connections;
- private int column;
+ private int column, row;
- public Node(int col) {
- column = col;
+ public Node(int row, int column) {
+ this.column = column;
+ this.row = row;
}
@Override
- public int evaluate() {
+ public int getValue() {
return function.run(connections);
}
@@ -45,4 +46,9 @@ public class Node implements MutableElement, Connection {
return column;
}
+
+ @Override
+ public int getRow() {
+ return row;
+ }
}
diff --git a/src/jcgp/population/Output.java b/src/jcgp/population/Output.java
index eeae743..ce4f776 100644
--- a/src/jcgp/population/Output.java
+++ b/src/jcgp/population/Output.java
@@ -1,14 +1,19 @@
package jcgp.population;
-import jcgp.CGP.Parameters;
+import jcgp.Parameters;
public class Output implements MutableElement {
private Connection source;
+ private int row;
+
+ public Output(int row) {
+ this.row = row;
+ }
public int calculate() {
- return source.evaluate();
+ return source.getValue();
}
@Override
@@ -22,4 +27,9 @@ public class Output implements MutableElement {
return Parameters.getColumns();
}
+ @Override
+ public int getRow() {
+ return row;
+ }
+
}
diff --git a/src/jcgp/population/Population.java b/src/jcgp/population/Population.java
index c4a0776..b56d992 100644
--- a/src/jcgp/population/Population.java
+++ b/src/jcgp/population/Population.java
@@ -2,7 +2,7 @@ package jcgp.population;
import java.util.Iterator;
-import jcgp.CGP.Parameters;
+import jcgp.Parameters;
public class Population implements Iterable<Chromosome> {
diff --git a/src/jcgp/tests/ChromosomeTests.java b/src/jcgp/tests/ChromosomeTests.java
new file mode 100644
index 0000000..123cbd1
--- /dev/null
+++ b/src/jcgp/tests/ChromosomeTests.java
@@ -0,0 +1,103 @@
+package jcgp.tests;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Random;
+
+import jcgp.Parameters;
+import jcgp.Utilities;
+import jcgp.function.Addition;
+import jcgp.function.FunctionSet;
+import jcgp.function.Subtraction;
+import jcgp.population.Chromosome;
+import jcgp.population.Input;
+import jcgp.population.Node;
+import jcgp.population.Output;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ * Tests which cover the behaviour specified for a chromosome.
+ *
+ * - The chromosome should be able to return a specified node, input or output.
+ * - It should be able to return a MutableElement indexed by row and column,
+ * where column NodeCount returns outputs.
+ * - It should be able to return a Connection indexed by row and column, where
+ * column 0 returns inputs.
+ * - It should contain a freely modifiable fitness value.
+ * - It should be a good citizen - fully initialised upon instantiation.
+ * - It should feature a clone constructor, which creates a deep copy of a
+ * specified Chromosome object.
+ * - It should be able to return the number of active nodes.
+ * - For truth table evaluations, it should be able to have its inputs set.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
+public class ChromosomeTests {
+
+ Chromosome chromosome;
+ int inputCount = 3,
+ rows = 3,
+ columns = 3,
+ outputCount = 3;
+
+ @Before
+ public void setUp() throws Exception {
+ // initialise function set
+ FunctionSet functionSet = new FunctionSet(new Addition(), new Subtraction());
+
+ // initialise utilities
+ Utilities.setResources(new Random(1234), functionSet);
+
+ // initialise parameters
+ Parameters.setColumns(columns);
+ Parameters.setRows(rows);
+ Parameters.setInputs(inputCount);
+ Parameters.setOutputs(outputCount);
+ Parameters.setLevelsBack(1);
+ Parameters.setMutationRate(10);
+ Parameters.setTotalGenerations(100);
+ Parameters.setTotalRuns(5);
+ Parameters.setMaxArity(functionSet.getMaxArity());
+
+ chromosome = new Chromosome(inputCount, rows, columns, outputCount);
+
+ }
+
+ @Test
+ public void test() {
+ // pick arbitrary node, assume that if one node is right, all nodes are right
+ boolean nodeReturn = chromosome.getNode(1, 2).getColumn() == 2
+ && chromosome.getNode(1, 2).getRow() == 1
+ && chromosome.getNode(1, 2) instanceof Node;
+ assertTrue("Incorrect node returned.", nodeReturn);
+
+ // set input values, check that acquired values are correct
+ chromosome.setInputs(4, 5, 6);
+ boolean inputReturn = chromosome.getInput(0).getValue() == 4 && chromosome.getInput(0) instanceof Input
+ && chromosome.getInput(1).getValue() == 5 && chromosome.getInput(0) instanceof Input
+ && chromosome.getInput(2).getValue() == 6 && chromosome.getInput(0) instanceof Input;
+ assertTrue("Incorrect inputs returned.", inputReturn);
+
+ // connect outputs to inputs, check that calculated outputs return input values
+ for (int i = 0; i < outputCount; i++) {
+ chromosome.getOutput(i).setConnection(chromosome.getInput(0));
+ }
+ boolean outputReturn = chromosome.getOutput(0).calculate() == 4 && chromosome.getOutput(0) instanceof Output
+ && chromosome.getOutput(1).calculate() == 4 && chromosome.getOutput(0) instanceof Output
+ && chromosome.getOutput(2).calculate() == 4 && chromosome.getOutput(0) instanceof Output;
+ assertTrue("Incorrect output returned.", outputReturn);
+
+ // get a mutable element, that that it is a Mutable
+ boolean mutableReturn = chromosome.getMutable() instanceof Output;
+
+ // set a fitness value, check if returned value is the same
+ chromosome.setFitness(10);
+ assertTrue("Incorrect fitness returned.", chromosome.getFitness() == 10);
+
+ }
+
+}
diff --git a/src/jcgp/tests/Tests.java b/src/jcgp/tests/Tests.java
deleted file mode 100644
index 8fbf0be..0000000
--- a/src/jcgp/tests/Tests.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package jcgp.tests;
-
-import static org.junit.Assert.fail;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class Tests {
-
- @Before
- public void setUp() throws Exception {
-
-
- }
-
- @Test
- public void test() {
- fail("Not yet implemented");
-
- }
-
-}