From 0c288cc1952809294c8d70d86b9f41b04878ac2e Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Sun, 23 Mar 2014 18:05:13 +0000 Subject: Majorly refactored, node grid is fully implemented. About to attempt active path locking. --- src/jcgp/population/Chromosome.java | 85 +++++++++++++++++++-------------- src/jcgp/population/Gene.java | 5 ++ src/jcgp/population/Input.java | 2 +- src/jcgp/population/MutableElement.java | 15 ++++-- src/jcgp/population/Node.java | 75 +++++++++++++++++------------ src/jcgp/population/Output.java | 31 +++++++----- src/jcgp/population/Population.java | 27 ++++++----- 7 files changed, 146 insertions(+), 94 deletions(-) create mode 100644 src/jcgp/population/Gene.java (limited to 'src/jcgp/population') diff --git a/src/jcgp/population/Chromosome.java b/src/jcgp/population/Chromosome.java index 1f0b312..a7f2ed3 100644 --- a/src/jcgp/population/Chromosome.java +++ b/src/jcgp/population/Chromosome.java @@ -2,11 +2,12 @@ package jcgp.population; import java.util.ArrayList; -import jcgp.Utilities; +import jcgp.CGP.Resources; import jcgp.exceptions.ParameterMismatchException; -import jcgp.parameters.Parameters; public class Chromosome { + + private Resources resources; private Input[] inputs; private Node[][] nodes; @@ -21,13 +22,12 @@ public class Chromosome { * Initialise a chromosome with the specified parameters. Random valid connections * are created. * - * @param outputs - * @param columns - * @param rows - * @param inputs * */ - public Chromosome() { + public Chromosome(Resources resources) { + // store a reference to the parameters + this.resources = resources; + // allocate memory for all elements of the chromosome instantiateElements(); // set random connections so that the chromosome can be evaluated @@ -42,6 +42,9 @@ public class Chromosome { * @param clone the chromosome to be copied */ public Chromosome(Chromosome clone) { + // store a reference to the parameters + this.resources = clone.getParameters(); + // allocate memory for all elements of the chromosome instantiateElements(); // initialise all connections based on argument @@ -52,20 +55,22 @@ public class Chromosome { * */ private void instantiateElements() { - inputs = new Input[((int) Parameters.get("inputs").getValue())]; - for (int i = 0; i < ((int) Parameters.get("inputs").getValue()); i++) { + inputs = new Input[((int) resources.get("inputs"))]; + for (int i = 0; i < ((int) resources.get("inputs")); i++) { inputs[i] = new Input(i); } + int arity = (int) resources.get("arity"); + // rows first - nodes = new Node[((int) Parameters.get("rows").getValue())][((int) Parameters.get("columns").getValue())]; - for (int r = 0; r < ((int) Parameters.get("rows").getValue()); r++) { - for (int c = 0; c < ((int) Parameters.get("columns").getValue()); c++) { - nodes[r][c] = new Node(this, r, c); + nodes = new Node[((int) resources.get("rows"))][((int) resources.get("columns"))]; + for (int r = 0; r < ((int) resources.get("rows")); r++) { + for (int c = 0; c < ((int) resources.get("columns")); c++) { + nodes[r][c] = new Node(this, r, c, arity); } } - outputs = new Output[((int) Parameters.get("outputs").getValue())]; - for (int o = 0; o < ((int) Parameters.get("outputs").getValue()); o++) { + outputs = new Output[((int) resources.get("outputs"))]; + for (int o = 0; o < ((int) resources.get("outputs")); o++) { outputs[o] = new Output(this, o); } } @@ -75,19 +80,21 @@ public class Chromosome { */ private void initialiseConnections() { + int arity = (int) resources.get("arity"); + // initialise nodes - [rows][columns] for (int r = 0; r < nodes.length; r++) { for (int c = 0; c < nodes[r].length; c++) { - Connection[] connections = new Connection[((int) Parameters.get("maxArity").getValue())]; + Connection[] connections = new Connection[arity]; for (int i = 0; i < connections.length; i++) { connections[i] = getRandomConnection(c); } - nodes[r][c].initialise(Utilities.getRandomFunction(), connections); + nodes[r][c].initialise(resources.getRandomFunction(), connections); } } for (Output output : outputs) { - output.setConnection(getRandomConnection()); + output.setConnection(0, getRandomConnection()); } } @@ -96,11 +103,13 @@ public class Chromosome { * @param clone */ public void copyConnections(Chromosome clone) { + int arity = (int) resources.get("arity"); + // 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[((int) Parameters.get("maxArity").getValue())]; + Connection[] connections = new Connection[arity]; // populate with connections equivalent to clone Connection copyConnection; for (int i = 0; i < connections.length; i++) { @@ -123,9 +132,9 @@ public class Chromosome { for (int o = 0; o < outputs.length; o++) { copyOutput = clone.getOutput(o).getSource(); if (copyOutput instanceof Input) { - outputs[o].setConnection(inputs[((Input) copyOutput).getIndex()]); + outputs[o].setConnection(0, inputs[((Input) copyOutput).getIndex()]); } else if (copyOutput instanceof Node) { - outputs[o].setConnection(nodes[((Node) copyOutput).getRow()][((Node) copyOutput).getColumn()]); + outputs[o].setConnection(0, 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."); @@ -177,7 +186,7 @@ public class Chromosome { */ public MutableElement getRandomMutableElement() { // choose output or node - int index = Utilities.getRandomInt(outputs.length + ((int) Parameters.get("rows").getValue()) * ((int) Parameters.get("columns").getValue())); + int index = resources.getRandomInt(outputs.length + ((int) resources.get("rows")) * ((int) resources.get("columns"))); if (index < outputs.length) { // outputs @@ -185,7 +194,7 @@ public class Chromosome { } else { // node index -= outputs.length; - return nodes[index / ((int) Parameters.get("columns").getValue())][index % ((int) Parameters.get("columns").getValue())]; + return nodes[index / ((int) resources.get("columns"))][index % ((int) resources.get("columns"))]; } } @@ -199,11 +208,11 @@ public class Chromosome { */ public Connection getRandomConnection(int column) { // work out the allowed range obeying levels back - int allowedColumns = ((column >= ((int) Parameters.get("levelsBack").getValue())) ? ((int) Parameters.get("levelsBack").getValue()) : column); + int allowedColumns = ((column >= ((int) resources.get("levelsBack"))) ? ((int) resources.get("levelsBack")) : column); int offset = ((column - allowedColumns) * nodes.length) - inputs.length; // choose input or allowed node - int index = Utilities.getRandomInt(inputs.length + (nodes.length * allowedColumns)); + int index = resources.getRandomInt(inputs.length + (nodes.length * allowedColumns)); if (index < inputs.length) { // input return inputs[index]; @@ -226,7 +235,7 @@ public class Chromosome { */ public Connection getRandomConnection() { // choose output or node - int index = Utilities.getRandomInt(inputs.length + ((int) Parameters.get("columns").getValue()) * ((int) Parameters.get("rows").getValue())); + int index = resources.getRandomInt(inputs.length + ((int) resources.get("columns")) * ((int) resources.get("rows"))); if (index < inputs.length) { // outputs @@ -234,7 +243,7 @@ public class Chromosome { } else { // node index -= inputs.length; - return nodes[index / ((int) Parameters.get("columns").getValue())][index % ((int) Parameters.get("columns").getValue())]; + return nodes[index / ((int) resources.get("columns"))][index % ((int) resources.get("columns"))]; } } @@ -269,15 +278,15 @@ public class Chromosome { } public boolean compareTo(Chromosome chromosome) { - for (int r = 0; r < ((int) Parameters.get("rows").getValue()); r++) { - for (int c = 0; c < ((int) Parameters.get("columns").getValue()); c++) { + for (int r = 0; r < ((int) resources.get("rows")); r++) { + for (int c = 0; c < ((int) resources.get("columns")); c++) { if (!(nodes[r][c].copyOf(chromosome.getNode(r, c)))) { return false; } } } - for (int o = 0; o < ((int) Parameters.get("outputs").getValue()); o++) { + for (int o = 0; o < ((int) resources.get("outputs")); o++) { if (!(outputs[o].copyOf(chromosome.getOutput(o)))) { return false; } @@ -302,20 +311,26 @@ public class Chromosome { } public void printNodes() { - for (int r = 0; r < ((int) Parameters.get("rows").getValue()); r++) { + int arity = (int) resources.get("arity"); + + for (int r = 0; r < ((int) resources.get("rows")); r++) { System.out.print("r: " + r + "\t"); - for (int c = 0; c < ((int) Parameters.get("columns").getValue()); c++) { + for (int c = 0; c < ((int) resources.get("columns")); c++) { System.out.print("N: (" + r + ", " + c + ") "); - for (int i = 0; i < ((int) Parameters.get("maxArity").getValue()); i++) { + for (int i = 0; i < arity; i++) { System.out.print("C" + i + ": (" + nodes[r][c].getConnection(i).getDescription() + ") "); } - System.out.print("F: " + nodes[r][c].getFunction().toString() + "\t"); + System.out.print("F: " + nodes[r][c].getFunction().getName() + "\t"); } System.out.print("\n"); } - for (int o = 0; o < ((int) Parameters.get("outputs").getValue()); o++) { + for (int o = 0; o < ((int) resources.get("outputs")); o++) { System.out.print("o: " + o + " (" + outputs[o].getSource().getDescription() + ")\t"); } } + + public Resources getParameters() { + return resources; + } } diff --git a/src/jcgp/population/Gene.java b/src/jcgp/population/Gene.java new file mode 100644 index 0000000..8865a01 --- /dev/null +++ b/src/jcgp/population/Gene.java @@ -0,0 +1,5 @@ +package jcgp.population; + +public abstract class Gene { + +} diff --git a/src/jcgp/population/Input.java b/src/jcgp/population/Input.java index 5c545d6..cfcb3ce 100644 --- a/src/jcgp/population/Input.java +++ b/src/jcgp/population/Input.java @@ -1,6 +1,6 @@ package jcgp.population; -public class Input implements Connection { +public class Input extends Gene implements Connection { private Object value = 0; private int index; diff --git a/src/jcgp/population/MutableElement.java b/src/jcgp/population/MutableElement.java index 114a4ab..12f6bd1 100644 --- a/src/jcgp/population/MutableElement.java +++ b/src/jcgp/population/MutableElement.java @@ -2,8 +2,16 @@ package jcgp.population; public interface MutableElement { - public void setConnection(Connection newConnection); - + /** + * This method sets the indexed connection to the specified new connection. + * Implementing classes may choose to ignore the given index (such as in the + * case of outputs, which only have one connection). + * + * @param index + * @param newConnection + */ + public void setConnection(int index, Connection newConnection); + /** * This method returns true if and only if:
* - the elements being compared are not the same instance;
@@ -15,7 +23,8 @@ public interface MutableElement { * The relationship computed by this method is:
* - symmetric: a.copyOf(b) == b.copyOf(a);
* - not reflexive: a.copyOf(a) returns false;
- * - not transitive: if a.copyOf(b) is true and b.copyOf(c) is true, a.copyOf(c) is not necessarily true;
+ * - not transitive: if a.copyOf(b) is true and b.copyOf(c) is true, a.copyOf(c) is + * not necessarily true since it is possible that a == c.
* * @param m * @return diff --git a/src/jcgp/population/Node.java b/src/jcgp/population/Node.java index 9fafe32..d7013d3 100644 --- a/src/jcgp/population/Node.java +++ b/src/jcgp/population/Node.java @@ -1,51 +1,58 @@ package jcgp.population; import java.util.ArrayList; -import java.util.Arrays; -import jcgp.Utilities; +import javafx.beans.property.SimpleObjectProperty; import jcgp.exceptions.InsufficientConnectionsException; -import jcgp.modules.function.Function; -import jcgp.parameters.Parameters; +import jcgp.function.Function; -public class Node implements MutableElement, Connection { +public class Node extends Gene implements MutableElement, Connection { - private Function function; - private Connection[] connections; + private SimpleObjectProperty function; + private ArrayList> connections; private int column, row; private Chromosome chromosome; - public Node(Chromosome chromosome, int row, int column) { + public Node(Chromosome chromosome, int row, int column, int arity) { + this.function = new SimpleObjectProperty(); this.chromosome = chromosome; this.column = column; this.row = row; - this.connections = new Connection[((int) Parameters.get("maxArity").getValue())]; + this.connections = new ArrayList>(arity); + for (int c = 0; c < arity; c++) { + connections.add(new SimpleObjectProperty()); + } } @Override public Object getValue() { //System.out.print("Calculating node: (" + row + ", " + column + ") > "); - return function.run(Arrays.copyOfRange(connections, 0, function.getArity())); + Connection[] list = new Connection[function.get().getArity()]; + for (int i = 0; i < list.length; i++) { + list[i] = connections.get(i).get(); + } + + return function.get().run(list); } public void setFunction(Function newFunction) { - function = newFunction; + function.set(newFunction); chromosome.recomputeActiveNodes(); } @Override - public void setConnection(Connection newConnection) { - connections[Utilities.getRandomInt(connections.length)] = newConnection; + public void setConnection(int index, Connection newConnection) { + connections.get(index).set(newConnection); chromosome.recomputeActiveNodes(); } public void initialise(Function newFunction, Connection ... newConnections) throws InsufficientConnectionsException { - - function = newFunction; - - if (newConnections.length >= ((int) Parameters.get("maxArity").getValue())) { - connections = newConnections; + function.set(newFunction); + if (newConnections.length >= connections.size()) { + for (int i = 0; i < connections.size(); i++) { + connections.get(i).set(newConnections[i]); + } } else { throw new InsufficientConnectionsException(); } @@ -60,20 +67,28 @@ public class Node implements MutableElement, Connection { } public Function getFunction() { + return function.get(); + } + + public SimpleObjectProperty functionProperty() { return function; } + public ArrayList> connections() { + return connections; + } + public Connection getConnection(int index) { - return connections[index]; + return connections.get(index).get(); } public void getActive(ArrayList activeNodes) { if (!activeNodes.contains(this)) { activeNodes.add(this); } - for (int i = 0; i < function.getArity(); i++) { - if (connections[i] instanceof Node) { - ((Node) connections[i]).getActive(activeNodes); + for (int i = 0; i < function.get().getArity(); i++) { + if (connections.get(i).get() instanceof Node) { + ((Node) connections.get(i).get()).getActive(activeNodes); } } @@ -84,17 +99,17 @@ public class Node implements MutableElement, Connection { if (this != m) { if (m instanceof Node) { Node n = (Node) m; - if (function == n.getFunction()) { + if (function.get() == n.getFunction()) { if (column == n.getColumn() && row == n.getRow()) { - for (int i = 0; i < connections.length; i++) { - if (connections[i] != n.getConnection(i)) { - if (connections[i] instanceof Input && n.getConnection(i) instanceof Input) { - if (((Input) connections[i]).getIndex() != ((Input) n.getConnection(i)).getIndex()) { + for (int i = 0; i < connections.size(); i++) { + if (connections.get(i).get() != n.getConnection(i)) { + if (connections.get(i).get() instanceof Input && n.getConnection(i) instanceof Input) { + if (((Input) connections.get(i).get()).getIndex() != ((Input) n.getConnection(i)).getIndex()) { return false; } - } else if (connections[i] instanceof Node && n.getConnection(i) instanceof Node) { - if (((Node) connections[i]).getRow() != ((Node) n.getConnection(i)).getRow() && - ((Node) connections[i]).getColumn() != ((Node) n.getConnection(i)).getColumn()) { + } else if (connections.get(i).get() instanceof Node && n.getConnection(i) instanceof Node) { + if (((Node) connections.get(i).get()).getRow() != ((Node) n.getConnection(i)).getRow() && + ((Node) connections.get(i).get()).getColumn() != ((Node) n.getConnection(i)).getColumn()) { return false; } } else { diff --git a/src/jcgp/population/Output.java b/src/jcgp/population/Output.java index ccecae0..b7c6128 100644 --- a/src/jcgp/population/Output.java +++ b/src/jcgp/population/Output.java @@ -2,15 +2,18 @@ package jcgp.population; import java.util.ArrayList; -public class Output implements MutableElement { +import javafx.beans.property.SimpleObjectProperty; + +public class Output extends Gene implements MutableElement { - private Connection source; + private SimpleObjectProperty source; private Chromosome chromosome; private int index; public Output(Chromosome chromosome, int index) { this.chromosome = chromosome; this.index = index; + this.source = new SimpleObjectProperty(); } public Object calculate() { @@ -19,8 +22,8 @@ public class Output implements MutableElement { } @Override - public void setConnection(Connection newConnection) { - source = newConnection; + public void setConnection(int index, Connection newConnection) { + source.set(newConnection); chromosome.recomputeActiveNodes(); } @@ -29,12 +32,16 @@ public class Output implements MutableElement { } public Connection getSource() { + return source.get(); + } + + public SimpleObjectProperty sourceProperty() { return source; } public void getActiveNodes(ArrayList activeNodes) { - if (source instanceof Node) { - ((Node) source).getActive(activeNodes); + if (source.get() instanceof Node) { + ((Node) source.get()).getActive(activeNodes); } } @@ -44,14 +51,14 @@ public class Output implements MutableElement { if (m instanceof Output) { Output o = (Output) m; if (index == o.getIndex()) { - if (source != o.getSource()) { - if (source instanceof Input && o.getSource() instanceof Input) { - if (((Input) source).getIndex() == ((Input) o.getSource()).getIndex()) { + if (source.get() != o.getSource()) { + if (source.get() instanceof Input && o.getSource() instanceof Input) { + if (((Input) source.get()).getIndex() == ((Input) o.getSource()).getIndex()) { return true; } - } else if (source instanceof Node && o.getSource() instanceof Node) { - if (((Node) source).getRow() == ((Node) o.getSource()).getRow() && - ((Node) source).getColumn() == ((Node) o.getSource()).getColumn()) { + } else if (source.get() instanceof Node && o.getSource() instanceof Node) { + if (((Node) source.get()).getRow() == ((Node) o.getSource()).getRow() && + ((Node) source.get()).getColumn() == ((Node) o.getSource()).getColumn()) { return true; } } diff --git a/src/jcgp/population/Population.java b/src/jcgp/population/Population.java index 5718515..bc9c9e8 100644 --- a/src/jcgp/population/Population.java +++ b/src/jcgp/population/Population.java @@ -1,14 +1,22 @@ package jcgp.population; -import jcgp.parameters.Parameters; +import jcgp.CGP.Resources; + public class Population { private Chromosome[] chromosomes; - private Chromosome bestIndividual; + private int fittest; + + public Population(Resources parameters) { + chromosomes = new Chromosome[((int) parameters.get("popSize"))]; + for (int c = 0; c < chromosomes.length; c++) { + chromosomes[c] = new Chromosome(parameters); + } + } - public Population(Chromosome parent) { - chromosomes = new Chromosome[((int) Parameters.get("population").getValue())]; + public Population(Chromosome parent, Resources parameters) { + chromosomes = new Chromosome[((int) parameters.get("popSize"))]; // make a clone for safety this.chromosomes[0] = new Chromosome(parent); // generate the rest of the individuals @@ -16,13 +24,6 @@ public class Population { chromosomes[c] = new Chromosome(chromosomes[0]); } } - - public Population() { - chromosomes = new Chromosome[((int) Parameters.get("population").getValue())]; - for (int c = 0; c < chromosomes.length; c++) { - chromosomes[c] = new Chromosome(); - } - } /** * Returns all chromosomes, parents first, then offspring. @@ -35,10 +36,10 @@ public class Population { } public void setBestIndividual(int index) { - bestIndividual = chromosomes[index]; + fittest = index; } public Chromosome getBestIndividual() { - return bestIndividual; + return chromosomes[fittest]; } } -- cgit v1.2.3