aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/population/Chromosome.java
diff options
context:
space:
mode:
authorEduardo Pedroni <ep625@york.ac.uk>2014-02-11 16:50:27 +0000
committerEduardo Pedroni <ep625@york.ac.uk>2014-02-11 16:50:27 +0000
commitdd3b6446671f31d716eb07e546c6150b4d080abd (patch)
treeb30c1ac7599bce9a17f1ea621eecc427256e1486 /src/jcgp/population/Chromosome.java
parent3fc4bf4a2ea7c6cff9810b76964dd3c1388c0b3f (diff)
Implemented more tests, refactored chromosome more, added the beginnings of active node detection
Diffstat (limited to 'src/jcgp/population/Chromosome.java')
-rw-r--r--src/jcgp/population/Chromosome.java198
1 files changed, 144 insertions, 54 deletions
diff --git a/src/jcgp/population/Chromosome.java b/src/jcgp/population/Chromosome.java
index 0dc3ff9..1f264f2 100644
--- a/src/jcgp/population/Chromosome.java
+++ b/src/jcgp/population/Chromosome.java
@@ -1,5 +1,7 @@
package jcgp.population;
+import java.util.ArrayList;
+
import jcgp.Parameters;
import jcgp.Utilities;
import jcgp.fitness.ParameterMismatchException;
@@ -9,11 +11,15 @@ public class Chromosome {
private Input[] inputs;
private Node[][] nodes;
private Output[] outputs;
+
+ private ArrayList<Connection> activeNodes;
private int fitness = 0;
+ private boolean recomputeActiveNodes = true;
/**
- * Good citizen.
+ * Initialise a chromosome with the specified parameters. Random valid connections
+ * are created.
*
* @param outputs
* @param columns
@@ -21,61 +27,110 @@ public class Chromosome {
* @param inputs
*
*/
- public Chromosome(int inputCount, int rows, int columns, int outputCount) {
-
- instantiateElements(inputCount, rows, columns, outputCount);
-
+ public Chromosome() {
+ // allocate memory for all elements of the chromosome
+ instantiateElements();
+ // set random connections so that the chromosome can be evaluated
initialiseConnections();
+ }
+ /**
+ * Copy constructor.
+ *
+ * Initialise a new chromosome with the exact same connections as a given instance of Chromosome.
+ *
+ * @param clone the chromosome to be copied
+ */
+ public Chromosome(Chromosome clone) {
+ // allocate memory for all elements of the chromosome
+ instantiateElements();
+ // initialise all connections based on argument
+ copyConnections(clone);
}
/**
- * @param inputCount
- * @param rows
- * @param columns
- * @param outputCount
+ *
*/
- private void instantiateElements(int inputCount, int rows, int columns, int outputCount) {
- inputs = new Input[inputCount];
- for (int i = 0; i < inputCount; i++) {
- inputs[i] = new Input();
+ private void instantiateElements() {
+ inputs = new Input[Parameters.getInputs()];
+ for (int i = 0; i < Parameters.getInputs(); i++) {
+ inputs[i] = new Input(i);
}
// rows first
- 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(r, c);
+ nodes = new Node[Parameters.getRows()][Parameters.getColumns()];
+ for (int r = 0; r < Parameters.getRows(); r++) {
+ for (int c = 0; c < Parameters.getColumns(); c++) {
+ nodes[r][c] = new Node(this, r, c);
}
}
- outputs = new Output[outputCount];
- for (int o = 0; o < outputCount; o++) {
- outputs[o] = new Output(o);
+ outputs = new Output[Parameters.getOutputs()];
+ for (int o = 0; o < Parameters.getOutputs(); o++) {
+ outputs[o] = new Output(this, o);
}
}
+ /**
+ *
+ */
private void initialiseConnections() {
// initialise nodes - [rows][columns]
for (int r = 0; r < nodes.length; r++) {
- for (int c = 0; c < nodes.length; c++) {
+ for (int c = 0; c < nodes[r].length; c++) {
Connection[] connections = new Connection[Parameters.getMaxArity()];
for (int i = 0; i < connections.length; i++) {
- connections[i] = Utilities.getRandomConnection(this, c);
+ connections[i] = getRandomConnection(c);
}
nodes[r][c].initialise(Utilities.getRandomFunction(), connections);
}
}
for (Output output : outputs) {
- output.setConnection(Utilities.getRandomNode(this));
+ output.setConnection(getRandomConnection());
}
}
- public int getActiveNodeCount() {
- return 0;
+ /**
+ * @param clone
+ */
+ private void copyConnections(Chromosome clone) {
+ // copy nodes - [rows][columns]
+ for (int r = 0; r < nodes.length; r++) {
+ for (int c = 0; c < nodes[r].length; c++) {
+ // make array of connections to initialise with
+ Connection[] connections = new Connection[Parameters.getMaxArity()];
+ // populate with connections equivalent to clone
+ Connection copyConnection;
+ for (int i = 0; i < connections.length; i++) {
+ copyConnection = clone.getNode(r, c).getConnections(i);
+ if (copyConnection instanceof Input) {
+ connections[i] = inputs[((Input) copyConnection).getIndex()];
+ } else if (copyConnection instanceof Node) {
+ connections[i] = nodes[((Node) copyConnection).getRow()][((Node) copyConnection).getColumn()];
+ } else {
+ System.out.println("Warning: Connection of subtype " + copyConnection.getClass().toString() + " is not explicitly handled by copy constructor.");
+ }
+ }
+ // initialise with copied arguments
+ nodes[r][c].initialise(clone.getNode(r, c).getFunction(), connections);
+ }
+ }
+
+ // do the same to outputs
+ Connection copyOutput;
+ for (int o = 0; o < outputs.length; o++) {
+ copyOutput = clone.getOutput(o).getSource();
+ if (copyOutput instanceof Input) {
+ outputs[o].setConnection(inputs[((Input) copyOutput).getIndex()]);
+ } else if (copyOutput instanceof Node) {
+ outputs[o].setConnection(nodes[((Node) copyOutput).getRow()][((Node) copyOutput).getColumn()]);
+ } else {
+ // something bad happened
+ System.out.println("Warning: Connection of subtype " + copyOutput.getClass().toString() + " is not explicitly handled by copy constructor.");
+ }
+ }
}
public Node getNode(int row, int column) {
@@ -110,6 +165,11 @@ public class Chromosome {
}
}
+ /**
+ * This method is useful for mutating chromosomes.
+ *
+ * @return a random element that can be mutated - Node or Output
+ */
public MutableElement getRandomMutableElement() {
// choose output or node
int index = Utilities.getRandomInt(outputs.length + Parameters.getNodeCount());
@@ -123,9 +183,9 @@ public class Chromosome {
return nodes[index / Parameters.getColumns()][index % Parameters.getColumns()];
}
}
-
+
/**
- * Returns a random allowed connection respecting levels back.
+ * Returns a random allowed connection respecting levels back.</br>
* This method may always pick inputs, as they can be picked
* regardless of the column.
*
@@ -133,41 +193,71 @@ public class Chromosome {
* @return a random connection
*/
public Connection getRandomConnection(int column) {
-
-
-
- return null;
-
+ // work out the allowed range obeying levels back
+ int allowedColumns = ((column >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : column);
+ int offset = ((column - allowedColumns) * nodes.length) - inputs.length;
+
+ // choose input or allowed node
+ int index = Utilities.getRandomInt(inputs.length + (nodes.length * allowedColumns));
+ if (index < inputs.length) {
+ // input
+ return inputs[index];
+ } else {
+ // node
+ // offset it to address the right columns
+ index += offset;
+ return nodes[index % nodes.length][index / nodes.length];
+ }
}
-
+
/**
- * Returns a random allowed connection.
+ * This method will pick a completely random connection, independently
+ * of levels back, including inputs.
*
- * This method may always pick inputs, as they can be picked
- * regardless of the column.
+ * Useful for setting outputs.
*
- * TODO optimise for less random generations
*
- * @param column the column to use as reference
- * @param levelsBack whether or not to respect levels back
* @return a random connection
*/
- public Connection getRandomConnection(int column, boolean levelsBack) {
-
- if (levelsBack) {
- return getRandomConnection(chromosome, column);
+ public Connection getRandomConnection() {
+ // choose output or node
+ int index = Utilities.getRandomInt(inputs.length + Parameters.getNodeCount());
+
+ if (index < inputs.length) {
+ // outputs
+ return inputs[index];
} else {
- // choose input or node
- int connectionType = Utilities.getRandomInt(inputs.length + (nodes.length * column));
- if (connectionType < inputs.length) {
- // input
- return chromosome.getInput(getRandomInt(Parameters.getInputs()));
- } else {
- // node
- return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(column));
- }
+ // node
+ index -= inputs.length;
+ return nodes[index / Parameters.getColumns()][index % Parameters.getColumns()];
}
-
+ }
+
+ /**
+ * This causes the list of active nodes to be recomputed lazily (once it is actually requested).
+ */
+ public void recomputeActiveNodes() {
+ recomputeActiveNodes = true;
+ }
+
+ /**
+ * This method computes a list of active nodes (if necessary) and returns it.
+ *
+ * @return
+ */
+ public ArrayList<Connection> getActiveNodes() {
+ // lazy recomputation has been triggered, do it
+ if (recomputeActiveNodes) {
+ recomputeActiveNodes = false;
+ activeNodes = new ArrayList<Connection>();
+
+ for (int r = 0; r < nodes.length; r++) {
+ for (int c = 0; c < nodes[r].length; c++) {
+
+ }
+ }
+ }
+ return activeNodes;
}
}