From c35a6806df01481c1b169cd0fc47660ea1cc10fb Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Wed, 14 May 2014 01:32:51 +0100 Subject: Refactored Mutable, commented a little bit of the GUI package --- src/jcgp/backend/population/Chromosome.java | 26 +++++++-------- src/jcgp/backend/population/Mutable.java | 22 +++++++------ src/jcgp/backend/population/Node.java | 41 ++++++++++++++++++++--- src/jcgp/backend/population/Output.java | 51 +++++++++++++++++++++-------- 4 files changed, 98 insertions(+), 42 deletions(-) (limited to 'src/jcgp/backend/population') diff --git a/src/jcgp/backend/population/Chromosome.java b/src/jcgp/backend/population/Chromosome.java index 673bb26..e28032c 100644 --- a/src/jcgp/backend/population/Chromosome.java +++ b/src/jcgp/backend/population/Chromosome.java @@ -149,7 +149,7 @@ public class Chromosome implements Comparable { // set random outputs for (Output output : outputs) { - output.setConnection(0, getRandomConnection()); + output.setSource(getRandomConnection()); } } @@ -198,9 +198,9 @@ public class Chromosome implements Comparable { for (int o = 0; o < outputs.length; o++) { copyOutput = clone.getOutput(o).getSource(); if (copyOutput instanceof Input) { - outputs[o].setConnection(0, inputs[((Input) copyOutput).getIndex()]); + outputs[o].setSource(inputs[((Input) copyOutput).getIndex()]); } else if (copyOutput instanceof Node) { - outputs[o].setConnection(0, nodes[((Node) copyOutput).getRow()][((Node) copyOutput).getColumn()]); + outputs[o].setSource(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."); @@ -211,6 +211,16 @@ public class Chromosome implements Comparable { this.fitness = clone.getFitness(); } + /** + * Returns a reference to the indexed input. + * + * @param index the input index. + * @return the input reference. + */ + public Input getInput(int index) { + return inputs[index]; + } + /** * Returns a reference to any node, addressed by row and column. * @@ -232,16 +242,6 @@ public class Chromosome implements Comparable { return outputs[index]; } - /** - * Returns a reference to the indexed input. - * - * @param index the input index. - * @return the input reference. - */ - public Input getInput(int index) { - return inputs[index]; - } - /** * @return the fitness of the chromosome. */ diff --git a/src/jcgp/backend/population/Mutable.java b/src/jcgp/backend/population/Mutable.java index 3ce7065..a5cbe37 100644 --- a/src/jcgp/backend/population/Mutable.java +++ b/src/jcgp/backend/population/Mutable.java @@ -8,8 +8,8 @@ package jcgp.backend.population; *

* This interface provides a way to deal with mutable elements * generically without having to specify whether they are nodes - * or outputs. In this way a random mutable element can be picked and - * dealt with more easily, facilitating mutations. + * or outputs. When mutating a mutable, {@code mutate()} is guaranteed + * to perform a fair mutation. * * @author Eduardo Pedroni * @@ -17,14 +17,16 @@ package jcgp.backend.population; public interface Mutable { /** - * 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 the connection index to set. - * @param newConnection the chromosome element to connect to. + * This method performs an arbitrary mutation on the {@code Mutable}. + *

+ * In the case of nodes, this chooses to mutate a function or connection + * fairly, and carries out the required mutation by using the node's own + * reference to chromosome. + *

+ * In the case of outputs, this simply picks a random connection to serve + * as the source - any connection is allowed. */ - public void setConnection(int index, Connection newConnection); + public void mutate(); /** * Asserts if the specified element is a copy of the elements @@ -48,6 +50,6 @@ public interface Mutable { * @param element the mutable element to compare to. * @return true if {@code element} is a copy of this element. */ - boolean copyOf(Mutable element); + public boolean copyOf(Mutable element); } diff --git a/src/jcgp/backend/population/Node.java b/src/jcgp/backend/population/Node.java index 3bcf3da..7712c50 100644 --- a/src/jcgp/backend/population/Node.java +++ b/src/jcgp/backend/population/Node.java @@ -3,6 +3,7 @@ package jcgp.backend.population; import java.util.ArrayList; import jcgp.backend.function.Function; +import jcgp.backend.resources.Resources; /** * Nodes make up the main part of the chromosome, @@ -16,6 +17,10 @@ import jcgp.backend.function.Function; * (determined by the maximum arity of the function set) * and must be reinstantiated if the experiment arity * changes. + *

+ * When mutating a node, it is easiest to use {@code mutate()}. + * Alternatively, you may also perform a specific mutation using + * {@code setConnection(...)} and {@code setFunction(...)}. * * @author Eduardo Pedroni * @@ -122,6 +127,24 @@ public class Node implements Mutable, Connection { } } } + + /** + * This method sets the indexed connection to the specified new connection. + * If the given connection is null or disrespects levels back, it is discarded + * and no connections are changed. + * + * @param index the connection index to set. + * @param newConnection the {@code Connection} to connect to. + */ + public void setConnection(int index, Connection newConnection) { + // connection must not be null + if (newConnection != null) { + //if () { + connections[index] = newConnection; + chromosome.recomputeActiveNodes(); + //} + } + } @Override public boolean copyOf(Mutable element) { @@ -174,11 +197,19 @@ public class Node implements Mutable, Connection { } @Override - public void setConnection(int index, Connection newConnection) { - // connection must not be null - if (newConnection != null) { - connections[index] = newConnection; - chromosome.recomputeActiveNodes(); + public void mutate() { + Resources resources = chromosome.getResources(); + + // choose to mutate the function or a connection + int geneType = resources.getRandomInt(1 + resources.arity()); + + // if the int is less than 1, mutate function, else mutate connections + if (geneType < 1) { + setFunction(resources.getRandomFunction()); + } else { + // if we decided to mutate connection, subtract 1 from geneType so it fits into the arity range + geneType--; + setConnection(geneType, chromosome.getRandomConnection(column)); } } diff --git a/src/jcgp/backend/population/Output.java b/src/jcgp/backend/population/Output.java index 938741b..a346d4a 100644 --- a/src/jcgp/backend/population/Output.java +++ b/src/jcgp/backend/population/Output.java @@ -8,6 +8,10 @@ import java.util.ArrayList; * returns the value of its single connection, but it * may not be connected to - it terminates a chromosome * active connection path. + *

+ * When mutating an output, it is easiest to use {@code mutate()}. + * Alternatively, you may also perform a specific mutation using + * {@code setSource(...)}. * * @author Eduardo Pedroni * @@ -37,34 +41,47 @@ public class Output implements Mutable { return source.getValue(); } + /** + * @return this output's index. + */ public int getIndex() { return index; } + + /** + * This method sets the output source to the specified connection. + * + * @param newConnection the {@code Connection} to connect to. + */ + public void setSource(Connection newConnection) { + source = newConnection; + // trigger active path recomputation + chromosome.recomputeActiveNodes(); + } + /** + * @return the source of this output's value. + */ public Connection getSource() { return source; } + /** + * Calls {@code getActive(...)} on this output's + * source. This kicks off a recursive process whereby + * all nodes connected to this output are added to the + * specified list of nodes. This is used to create a + * list of all active nodes. + * + * @param activeNodes the list to add all active nodes to. + */ public void getActiveNodes(ArrayList activeNodes) { + // do not add if the source is an input if (source instanceof Node) { ((Node) source).getActive(activeNodes); } } - /** - * When mutating an output, the index parameter - * is simply ignored and the output source is - * set. - * - * @see jcgp.backend.population.Mutable#setConnection(int, jcgp.backend.population.Connection) - */ - @Override - public void setConnection(int index, Connection newConnection) { - source = newConnection; - // trigger active path recomputation - chromosome.recomputeActiveNodes(); - } - @Override public boolean copyOf(Mutable m) { // both cannot be the same instance @@ -93,6 +110,12 @@ public class Output implements Mutable { return false; } + @Override + public void mutate() { + // simply change output to a new, random connection + setSource(chromosome.getRandomConnection()); + } + @Override public String toString() { return "Output " + index; -- cgit v1.2.3