From 6419b69faeb4736db1ccb50cfa5a030f9aa818aa Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Thu, 13 Feb 2014 22:41:26 +0000 Subject: Added methods in Chromosome to compare active and all nodes. Associated tests also written. --- src/jcgp/population/Chromosome.java | 63 +++++++++++++++++++++++++++------ src/jcgp/population/Connection.java | 4 --- src/jcgp/population/Input.java | 9 ----- src/jcgp/population/MutableElement.java | 18 ++++++++++ src/jcgp/population/Node.java | 60 ++++++++++++++++++++++++------- src/jcgp/population/Output.java | 30 ++++++++++++++-- 6 files changed, 146 insertions(+), 38 deletions(-) (limited to 'src/jcgp/population') diff --git a/src/jcgp/population/Chromosome.java b/src/jcgp/population/Chromosome.java index 08ff9b9..f61b780 100644 --- a/src/jcgp/population/Chromosome.java +++ b/src/jcgp/population/Chromosome.java @@ -11,8 +11,8 @@ public class Chromosome { private Input[] inputs; private Node[][] nodes; private Output[] outputs; - - private ArrayList activeNodes; + + private ArrayList activeNodes; private int fitness = 0; private boolean recomputeActiveNodes = true; @@ -117,7 +117,7 @@ public class Chromosome { 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++) { @@ -153,6 +153,11 @@ public class Chromosome { fitness = newFitness; } + /** + * + * @param values + * @throws ParameterMismatchException + */ 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) { @@ -232,31 +237,67 @@ public class Chromosome { 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. + * This method computes a list of active connections (if necessary) and returns it. * * @return */ - public ArrayList getActiveNodes() { + public ArrayList getActiveNodes() { + computeActiveNodes(); + return activeNodes; + } + + private void computeActiveNodes() { // lazy recomputation has been triggered, do it if (recomputeActiveNodes) { recomputeActiveNodes = false; - activeNodes = new ArrayList(); - + activeNodes = new ArrayList(); + for (Output output : outputs) { output.getActiveNodes(activeNodes); } - } - return activeNodes; + } + public boolean compareTo(Chromosome chromosome) { + for (int r = 0; r < Parameters.getRows(); r++) { + for (int c = 0; c < Parameters.getColumns(); c++) { + if (!(nodes[r][c].copyOf(chromosome.getNode(r, c)))) { + return false; + } + } + } + + for (int o = 0; o < Parameters.getOutputs(); o++) { + if (!(outputs[o].copyOf(chromosome.getOutput(o)))) { + return false; + } + } + + return true; + } + + public boolean compareActiveTo(Chromosome chromosome) { + // update list if it is out of date + computeActiveNodes(); + + if (activeNodes.size() == chromosome.getActiveNodes().size()) { + for (int i = 0; i < activeNodes.size(); i++) { + if (!(activeNodes.get(i).copyOf(chromosome.getActiveNodes().get(i)))){ + return false; + } + } + return true; + } + return false; + } } diff --git a/src/jcgp/population/Connection.java b/src/jcgp/population/Connection.java index 12e92d6..3312de3 100644 --- a/src/jcgp/population/Connection.java +++ b/src/jcgp/population/Connection.java @@ -1,11 +1,7 @@ package jcgp.population; -import java.util.ArrayList; - public interface Connection { public int getValue(); - public void getActive(ArrayList activeNodes); - } diff --git a/src/jcgp/population/Input.java b/src/jcgp/population/Input.java index f3199b8..ee008ce 100644 --- a/src/jcgp/population/Input.java +++ b/src/jcgp/population/Input.java @@ -1,7 +1,5 @@ package jcgp.population; -import java.util.ArrayList; - public class Input implements Connection { private int value = 0, index; @@ -23,11 +21,4 @@ public class Input implements Connection { return index; } - @Override - public void getActive(ArrayList activeNodes) { - if (!activeNodes.contains(this)) { - activeNodes.add(this); - } - } - } diff --git a/src/jcgp/population/MutableElement.java b/src/jcgp/population/MutableElement.java index 5eae4ef..114a4ab 100644 --- a/src/jcgp/population/MutableElement.java +++ b/src/jcgp/population/MutableElement.java @@ -3,5 +3,23 @@ package jcgp.population; public interface MutableElement { public void setConnection(Connection newConnection); + + /** + * This method returns true if and only if:
+ * - the elements being compared are not the same instance;
+ * - the connections of the compared elements are not the same instance;
+ * - the elements have the same function (in the case of Node);
+ * - the grid position of the elements themselves are the same;
+ * - the grid position of all equivalent connections are the same;

+ * + * 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;
+ * + * @param m + * @return + */ + boolean copyOf(MutableElement m); } diff --git a/src/jcgp/population/Node.java b/src/jcgp/population/Node.java index c09532c..b2e29df 100644 --- a/src/jcgp/population/Node.java +++ b/src/jcgp/population/Node.java @@ -1,6 +1,7 @@ package jcgp.population; import java.util.ArrayList; +import java.util.Arrays; import jcgp.Parameters; import jcgp.Utilities; @@ -8,7 +9,7 @@ import jcgp.function.Function; public class Node implements MutableElement, Connection { - + private Function function; private Connection[] connections; private int column, row; @@ -18,28 +19,29 @@ public class Node implements MutableElement, Connection { this.chromosome = chromosome; this.column = column; this.row = row; + this.connections = new Connection[Parameters.getMaxArity()]; } - + @Override public int getValue() { - return function.run(connections); + return function.run(Arrays.copyOfRange(connections, 0, function.getArity())); } - + public void setFunction(Function newFunction) { function = newFunction; chromosome.recomputeActiveNodes(); } - + @Override public void setConnection(Connection newConnection) { connections[Utilities.getRandomInt(connections.length)] = newConnection; chromosome.recomputeActiveNodes(); } - + public void initialise(Function newFunction, Connection ... newConnections) throws InsufficientConnectionsException { - + function = newFunction; - + if (newConnections.length >= Parameters.getMaxArity()) { connections = newConnections; } else { @@ -48,7 +50,6 @@ public class Node implements MutableElement, Connection { } public int getColumn() { - return column; } @@ -64,13 +65,48 @@ public class Node implements MutableElement, Connection { return connections[index]; } - @Override - public void getActive(ArrayList activeNodes) { + public void getActive(ArrayList activeNodes) { if (!activeNodes.contains(this)) { activeNodes.add(this); } for (int i = 0; i < function.getArity(); i++) { - connections[i].getActive(activeNodes); + if (connections[i] instanceof Node) { + ((Node) connections[i]).getActive(activeNodes); + } + + } + } + + @Override + public boolean copyOf(MutableElement m) { + if (this != m) { + if (m instanceof Node) { + Node n = (Node) m; + if (function == 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()) { + 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()) { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + return true; + } + } + } } + return false; } } diff --git a/src/jcgp/population/Output.java b/src/jcgp/population/Output.java index 0171d7b..f0bcbbf 100644 --- a/src/jcgp/population/Output.java +++ b/src/jcgp/population/Output.java @@ -31,7 +31,33 @@ public class Output implements MutableElement { return source; } - public void getActiveNodes(ArrayList activeNodes) { - source.getActive(activeNodes); + public void getActiveNodes(ArrayList activeNodes) { + if (source instanceof Node) { + ((Node) source).getActive(activeNodes); + } + } + + @Override + public boolean copyOf(MutableElement m) { + if (this != m) { + 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()) { + 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()) { + return true; + } + } + } + } + } + } + return false; } } -- cgit v1.2.3