aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/function
diff options
context:
space:
mode:
authorEduardo Pedroni <ep625@york.ac.uk>2014-05-01 13:05:27 +0100
committerEduardo Pedroni <ep625@york.ac.uk>2014-05-01 13:05:27 +0100
commit36f4393bcc9e55afa2334baa33e603ce839741a1 (patch)
treed9a1d55d0d3553193a3fc11a92f11515762d202f /src/jcgp/backend/function
parent4c8de2402f2878cde7587c7f3bbf4ffaea86efd4 (diff)
Did more commenting, implemented reflection and statistics
Diffstat (limited to 'src/jcgp/backend/function')
-rw-r--r--src/jcgp/backend/function/DigitalCircuitFunctions.java85
-rw-r--r--src/jcgp/backend/function/Function.java6
-rw-r--r--src/jcgp/backend/function/FunctionSet.java64
-rw-r--r--src/jcgp/backend/function/SymbolicRegressionFunctions.java21
-rw-r--r--src/jcgp/backend/function/TravellingSalesmanFunctions.java19
-rw-r--r--src/jcgp/backend/function/UnsignedInteger.java20
6 files changed, 166 insertions, 49 deletions
diff --git a/src/jcgp/backend/function/DigitalCircuitFunctions.java b/src/jcgp/backend/function/DigitalCircuitFunctions.java
index 31cdf17..0d4ae8e 100644
--- a/src/jcgp/backend/function/DigitalCircuitFunctions.java
+++ b/src/jcgp/backend/function/DigitalCircuitFunctions.java
@@ -1,10 +1,23 @@
package jcgp.backend.function;
+/**
+ * This class contains all digital circuit functions
+ * (defined as unsigned integer functions in the classic
+ * CGP implementation) defined in static nested classes.
+ * <br>
+ * This is the function set used by DigitalCircuitProblem.
+ *
+ * @see DigitalCircuiProblem
+ * @author Eduardo Pedroni
+ *
+ */
public class DigitalCircuitFunctions extends FunctionSet {
+ /**
+ * Creates a new instance of DigitalCircuitFunctions.
+ */
public DigitalCircuitFunctions() {
- name = "32-bit Logic";
- functionList = new Function[]{
+ registerFunctions(
new ConstantZero(),
new ConstantOne(),
new WireA(),
@@ -25,11 +38,12 @@ public class DigitalCircuitFunctions extends FunctionSet {
new Mux2(),
new Mux3(),
new Mux4()
- };
-
- enableAll();
+ );
}
+ /**
+ * Outputs a constant 0, has no inputs.
+ */
public static class ConstantZero extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -47,6 +61,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Outputs a constant 1, has no inputs.
+ */
public static class ConstantOne extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -64,6 +81,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Connects one node to another with no function.
+ */
public static class WireA extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -85,6 +105,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Connects one node to another with no function.
+ */
public static class WireB extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -106,6 +129,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Inverts input, equivalent to inverter logic gate.
+ */
public static class NotA extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -127,6 +153,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Inverts input, equivalent to inverter logic gate.
+ */
public static class NotB extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -148,6 +177,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * ANDs inputs together.
+ */
public static class And extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -173,6 +205,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * ANDs inputs together with one input inverted.
+ */
public static class AndNotA extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -198,6 +233,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * ANDs inputs together with one input inverted.
+ */
public static class AndNotB extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -223,6 +261,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * NORs inputs together.
+ */
public static class Nor extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -248,6 +289,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * XORs inputs together.
+ */
public static class Xor extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -273,6 +317,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * XNORs inputs together.
+ */
public static class Xnor extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -298,6 +345,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * ORs inputs together.
+ */
public static class Or extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -323,6 +373,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * ORs inputs together with one inverted input.
+ */
public static class OrNotA extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -348,6 +401,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * ORs inputs together with one inverted input.
+ */
public static class OrNotB extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -373,6 +429,9 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * NANDs inputs together.
+ */
public static class Nand extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -398,6 +457,10 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Works as a multiplexer. Outputs either one of its two inputs
+ * depending on a third input (select).
+ */
public static class Mux1 extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -424,6 +487,10 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Works as a multiplexer. Outputs either one of its two inputs
+ * depending on a third input (select). Input 0 is inverted.
+ */
public static class Mux2 extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -450,6 +517,10 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Works as a multiplexer. Outputs either one of its two inputs
+ * depending on a third input (select). Input 1 is inverted.
+ */
public static class Mux3 extends Function {
@Override
public UnsignedInteger run(Object... args) {
@@ -476,6 +547,10 @@ public class DigitalCircuitFunctions extends FunctionSet {
}
}
+ /**
+ * Works as a multiplexer. Outputs either one of its two inputs
+ * depending on a third input (select). Both inputs are inverted.
+ */
public static class Mux4 extends Function {
@Override
public UnsignedInteger run(Object... args) {
diff --git a/src/jcgp/backend/function/Function.java b/src/jcgp/backend/function/Function.java
index fdacac0..2e1f3c6 100644
--- a/src/jcgp/backend/function/Function.java
+++ b/src/jcgp/backend/function/Function.java
@@ -7,17 +7,15 @@ package jcgp.backend.function;
* any arbitrary operation on the arguments specified. It must also override
* {@code getArity()} to return the function arity.
*
- *
* @author Eduardo Pedroni
- *
*/
public abstract class Function {
/**
* Executes the function.
*
- * @param args the function arguments
- * @return the function result
+ * @param args the function arguments.
+ * @return the function result.
*/
public abstract Object run(Object... args);
diff --git a/src/jcgp/backend/function/FunctionSet.java b/src/jcgp/backend/function/FunctionSet.java
index 926ed68..052183a 100644
--- a/src/jcgp/backend/function/FunctionSet.java
+++ b/src/jcgp/backend/function/FunctionSet.java
@@ -4,9 +4,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
-
/**
- * FunctionSet encapsulates a group of functions. This is usually done to
+ * FunctionSet encapsulates a group of functions. This is done to
* simplify the implementation of problem types.
* <br><br>
* FunctionSet contains a variety of useful methods for acquiring general
@@ -18,18 +17,16 @@ import java.util.Iterator;
* allowed functions only, providing an easy way to control which functions
* can be used in mutations.
* <br><br>
- * An implementation of FunctionSet must simply set the name field and initialise
- * the functionList array with all of the functions. It is advisable to call
- * {@code enableAll()} to enable all functions once the array is initialised.
- *
+ * An implementation of FunctionSet must simply use its constructor to set
+ * the name field and use {@code registerFunctions()} to add the required
+ * functions.
*
* @author Eduardo Pedroni
*
*/
public abstract class FunctionSet {
- protected Function[] functionList;
- protected ArrayList<Integer> allowedFunctions;
- protected String name;
+ private ArrayList<Function> functionList = new ArrayList<Function>();
+ private ArrayList<Integer> allowedFunctions = new ArrayList<Integer>();
/**
* @return the number of currently allowed functions.
@@ -42,7 +39,7 @@ public abstract class FunctionSet {
* @return the total number of functions, including disabled ones.
*/
public int getTotalFunctionCount() {
- return functionList.length;
+ return functionList.size();
}
/**
@@ -54,7 +51,7 @@ public abstract class FunctionSet {
* @return the allowed function object.
*/
public Function getAllowedFunction(int index) {
- return functionList[allowedFunctions.get(index)];
+ return functionList.get(allowedFunctions.get(index));
}
/**
@@ -67,7 +64,7 @@ public abstract class FunctionSet {
* @return the function object.
*/
public Function getFunction(int index) {
- return functionList[index];
+ return functionList.get(index);
}
/**
@@ -100,7 +97,7 @@ public abstract class FunctionSet {
* list of allowed functions and removes any elements which are equal
* to the specified index.
*/
- if (index < functionList.length) {
+ if (index < functionList.size()) {
for (Iterator<Integer> iterator = allowedFunctions.iterator(); iterator.hasNext();) {
int function = iterator.next();
if (function == index) {
@@ -108,7 +105,7 @@ public abstract class FunctionSet {
}
}
} else {
- throw new ArrayIndexOutOfBoundsException("Function " + index + " does not exist, the set only has " + functionList.length + " functions.");
+ throw new ArrayIndexOutOfBoundsException("Function " + index + " does not exist, the set only has " + functionList.size() + " functions.");
}
}
@@ -126,11 +123,6 @@ public abstract class FunctionSet {
}
}
- @Override
- public String toString() {
- return name;
- }
-
/**
* Checks if a specified function is enabled. If the function
* does not belong in the FunctionSet, this returns false.
@@ -140,7 +132,7 @@ public abstract class FunctionSet {
*/
public boolean isEnabled(Function function) {
for (int i = 0; i < allowedFunctions.size(); i++) {
- if (functionList[allowedFunctions.get(i)] == function) {
+ if (functionList.get(allowedFunctions.get(i)) == function) {
return true;
}
}
@@ -148,12 +140,34 @@ public abstract class FunctionSet {
}
/**
- * Enables all functions.
+ * For internal use in subclass constructors. This method
+ * adds the specified functions and enables them. The same
+ * function cannot be added more than once.
+ *
+ * @param functions the functions to register in the function set.
*/
- public void enableAll() {
- allowedFunctions = new ArrayList<Integer>();
- for (int i = 0; i < functionList.length; i++) {
- allowedFunctions.add(i);
+ protected void registerFunctions(Function... functions) {
+ for (int i = 0; i < functions.length; i++) {
+ if (!alreadyHave(functions[i])) {
+ functionList.add(functions[i]);
+ enableFunction(functionList.size() - 1);
+ }
}
}
+
+ /**
+ * For internal use only, this checks whether a function
+ * is already present in the function set.
+ *
+ * @param function the function to look for.
+ * @return true if the function is already in the function set.
+ */
+ private boolean alreadyHave(Function function) {
+ for (int i = 0; i < functionList.size(); i++) {
+ if (functionList.get(i).getClass() == function.getClass()) {
+ return true;
+ }
+ }
+ return false;
+ }
} \ No newline at end of file
diff --git a/src/jcgp/backend/function/SymbolicRegressionFunctions.java b/src/jcgp/backend/function/SymbolicRegressionFunctions.java
index a35f258..6f72723 100644
--- a/src/jcgp/backend/function/SymbolicRegressionFunctions.java
+++ b/src/jcgp/backend/function/SymbolicRegressionFunctions.java
@@ -1,12 +1,25 @@
package jcgp.backend.function;
+/**
+ * This class contains all symbolic regression functions
+ * (defined as double functions in the classic CGP implementation)
+ * in static nested classes.
+ * <br>
+ * This is the function set used by SymbolicRegressionProblem.
+ *
+ * @see SymbolicRegressionProblem
+ * @author Eduardo Pedroni
+ *
+ */
public class SymbolicRegressionFunctions extends FunctionSet {
public final static double DIVISION_LIMIT = 0.0001;
+ /**
+ * Creates a new instance of SymbolicRegressionFunctions.
+ */
public SymbolicRegressionFunctions() {
- name = "Symbolic regression functions";
- functionList = new Function[] {
+ registerFunctions(
new Absolute(),
new SquareRoot(),
new Reciprocal(),
@@ -26,9 +39,7 @@ public class SymbolicRegressionFunctions extends FunctionSet {
new Addition(),
new Subtraction(),
new Multiplication(),
- new Division()};
-
- enableAll();
+ new Division());
}
/**
diff --git a/src/jcgp/backend/function/TravellingSalesmanFunctions.java b/src/jcgp/backend/function/TravellingSalesmanFunctions.java
index 472b7ad..06b44bb 100644
--- a/src/jcgp/backend/function/TravellingSalesmanFunctions.java
+++ b/src/jcgp/backend/function/TravellingSalesmanFunctions.java
@@ -1,10 +1,21 @@
package jcgp.backend.function;
+/**
+ * This class contains all travelling salesman functions in static nested classes.
+ * <br>
+ * This is the function set used by TravellingSalesmanProblem.
+ *
+ * @see TravellingSalesmanProblem
+ * @author Eduardo Pedroni
+ *
+ */
public class TravellingSalesmanFunctions extends FunctionSet {
+ /**
+ * Creates a new instance of TravellingSalesmanFunctions.
+ */
public TravellingSalesmanFunctions() {
- name = "Travelling salesman functions";
- functionList = new Function[]{
+ registerFunctions(
new SquareRoot(),
new Square(),
new Cube(),
@@ -16,9 +27,7 @@ public class TravellingSalesmanFunctions extends FunctionSet {
new ScaledAddition(),
new SymmetricSubtraction(),
new Multiplication(),
- new BoundedDivision() };
-
- enableAll();
+ new BoundedDivision());
}
/**
diff --git a/src/jcgp/backend/function/UnsignedInteger.java b/src/jcgp/backend/function/UnsignedInteger.java
index 7feb33f..d23862c 100644
--- a/src/jcgp/backend/function/UnsignedInteger.java
+++ b/src/jcgp/backend/function/UnsignedInteger.java
@@ -14,7 +14,12 @@ package jcgp.backend.function;
* signed and will behave as such for all arithmetic operations.
* Bitwise operations can still be performed as they work at the bit
* level, making this data type particularly suitable for circuit design.
- *
+ * <br><br>
+ * TODO in the unlikely event that unsigned integers are natively
+ * implemented in Java, they should be used instead of this class.
+ * <br><br>
+ * Why are unsigned integers not supported?<br>
+ * http://stackoverflow.com/questions/430346/why-doesnt-java-support-unsigned-ints
*
* @author Eduardo Pedroni
* @see Integer
@@ -27,7 +32,7 @@ public class UnsignedInteger {
/**
* Makes a new instance of UnsignedInteger with a specified value.
*
- * @param i the value with which to initialise
+ * @param i the value with which to initialise.
*/
public UnsignedInteger(int i) {
value = new Integer(i);
@@ -36,7 +41,7 @@ public class UnsignedInteger {
/**
* Makes a new instance of UnsignedInteger with a specified value.
*
- * @param i the value with which to initialise
+ * @param i the value with which to initialise.
*/
public UnsignedInteger(Integer i) {
value = i;
@@ -46,14 +51,14 @@ public class UnsignedInteger {
* Makes a new instance of UnsignedInteger from the string representation
* of an unsigned integer.
*
- * @param i the string with which to initialise
+ * @param i the string with which to initialise.
*/
public UnsignedInteger(String i) {
value = Integer.parseUnsignedInt(i);
}
/**
- * @return the wrapped Integer object
+ * @return the wrapped Integer object.
*/
public Integer get() {
return value;
@@ -61,6 +66,11 @@ public class UnsignedInteger {
@Override
public String toString() {
+ /*
+ * It is important to override this so that
+ * the visual representation of the integer
+ * is unsigned as well.
+ */
return Integer.toUnsignedString(value);
}
}