diff options
Diffstat (limited to 'src/jcgp/backend')
-rw-r--r-- | src/jcgp/backend/function/BitwiseLogic.java | 337 | ||||
-rw-r--r-- | src/jcgp/backend/function/DoubleArithmetic.java | 589 | ||||
-rw-r--r-- | src/jcgp/backend/function/FunctionSet.java | 1 | ||||
-rw-r--r-- | src/jcgp/backend/function/IntegerArithmetic.java | 122 | ||||
-rw-r--r-- | src/jcgp/backend/modules/problem/SymbolicRegression.java | 12 | ||||
-rw-r--r-- | src/jcgp/backend/parser/ChromosomeParser.java | 131 | ||||
-rw-r--r-- | src/jcgp/backend/parser/FunctionParser.java | 58 | ||||
-rw-r--r-- | src/jcgp/backend/parser/ParameterParser.java | 76 | ||||
-rw-r--r-- | src/jcgp/backend/parser/TestCaseParser.java | 13 | ||||
-rw-r--r-- | src/jcgp/backend/population/Population.java | 1 | ||||
-rw-r--r-- | src/jcgp/backend/resources/ModifiableResources.java | 14 | ||||
-rw-r--r-- | src/jcgp/backend/resources/Resources.java | 18 | ||||
-rw-r--r-- | src/jcgp/backend/tests/ChromosomeTests.java | 4 | ||||
-rw-r--r-- | src/jcgp/backend/tests/NodeTests.java | 8 | ||||
-rw-r--r-- | src/jcgp/backend/tests/OutputTests.java | 4 | ||||
-rw-r--r-- | src/jcgp/backend/tests/PopulationTests.java | 4 |
16 files changed, 1171 insertions, 221 deletions
diff --git a/src/jcgp/backend/function/BitwiseLogic.java b/src/jcgp/backend/function/BitwiseLogic.java index 5d47ff7..14f4488 100644 --- a/src/jcgp/backend/function/BitwiseLogic.java +++ b/src/jcgp/backend/function/BitwiseLogic.java @@ -1,6 +1,5 @@ package jcgp.backend.function; -import jcgp.backend.exceptions.InvalidArgumentsException; import jcgp.backend.population.Connection; public class BitwiseLogic extends FunctionSet { @@ -8,26 +7,155 @@ public class BitwiseLogic extends FunctionSet { public BitwiseLogic() { name = "32-bit Logic"; functionList = new Function[]{ + new ConstantZero(), + new ConstantOne(), + new WireA(), + new WireB(), + new NotA(), + new NotB(), new And(), - new Or(), - new Not(), - new Xor(), - new Nand(), + new AndNotA(), + new AndNotB(), new Nor(), - new Xnor()}; + new Xor(), + new Xnor(), + new Or(), + new OrNotA(), + new OrNotB(), + new Nand()}; + + // TODO muxes enableAll(); } + + public static class ConstantZero extends Function { + @Override + public Long run(Connection... connections) { + return new Long(0); + } + + @Override + public int getArity() { + return 0; + } + + @Override + public String getName() { + return "0"; + } + } + + public static class ConstantOne extends Function { + @Override + public Long run(Connection... connections) { + return new Long(Long.MAX_VALUE); + } + + @Override + public int getArity() { + return 0; + } + + @Override + public String getName() { + return "1"; + } + } + + public static class WireA extends Function { + @Override + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + return ((Long) connections[0].getValue()).longValue(); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Wire A"; + } + } + + public static class WireB extends Function { + @Override + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + return ((Long) connections[1].getValue()).longValue(); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Wire B"; + } + } + + public static class NotA extends Function { + @Override + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + return ~((Long) connections[0].getValue()).longValue(); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Not A"; + } + } + + public static class NotB extends Function { + @Override + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + return ~((Long) connections[1].getValue()).longValue(); + } + } + + @Override + public int getArity() { + return 2; + } + @Override + public String getName() { + return "Not B"; + } + } + public static class And extends Function { @Override - public Object run(Connection... connections) { - if (connections.length < 2) { - throw new InvalidArgumentsException("Not enough connections were given."); + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); } else { - int arg1 = ((int) connections[0].getValue()); - int arg2 = ((int) connections[1].getValue()); - int result = arg1 & arg2; + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 & arg2; return result; } @@ -40,20 +168,20 @@ public class BitwiseLogic extends FunctionSet { @Override public String getName() { - return "AND"; + return "And"; } } - public static class Or extends Function { + public static class AndNotA extends Function { @Override - public Object run(Connection... connections) { - if (connections.length < 2) { - throw new InvalidArgumentsException("Not enough connections were given."); + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); } else { - int arg1 = ((int) connections[0].getValue()); - int arg2 = ((int) connections[1].getValue()); - int result = arg1 | arg2; - + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = ~arg1 & arg2; + return result; } } @@ -65,43 +193,69 @@ public class BitwiseLogic extends FunctionSet { @Override public String getName() { - return "OR"; + return "And !A"; } } - - public static class Not extends Function { + + public static class AndNotB extends Function { @Override - public Object run(Connection... connections) { - if (connections.length < 1) { - throw new InvalidArgumentsException("Not enough connections were given."); + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); } else { - int arg1 = ((int) connections[0].getValue()); - int result = ~arg1; - + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 & ~arg2; + return result; } } @Override public int getArity() { - return 1; + return 2; } @Override public String getName() { - return "NOT"; + return "And !B"; } } + + public static class Nor extends Function { + @Override + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 | arg2; + return ~result; + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Nor"; + } + } + public static class Xor extends Function { @Override - public Object run(Connection... connections) { - if (connections.length < 2) { - throw new InvalidArgumentsException("Not enough connections were given."); + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); } else { - int arg1 = ((int) connections[0].getValue()); - int arg2 = ((int) connections[1].getValue()); - int result = arg1 ^ arg2; + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 ^ arg2; return result; } @@ -114,19 +268,19 @@ public class BitwiseLogic extends FunctionSet { @Override public String getName() { - return "XOR"; + return "Xor"; } } - - public static class Nand extends Function { + + public static class Xnor extends Function { @Override - public Object run(Connection... connections) { - if (connections.length < 2) { - throw new InvalidArgumentsException("Not enough connections were given."); + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); } else { - int arg1 = ((int) connections[0].getValue()); - int arg2 = ((int) connections[1].getValue()); - int result = arg1 & arg2; + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 ^ arg2; return ~result; } @@ -139,21 +293,71 @@ public class BitwiseLogic extends FunctionSet { @Override public String getName() { - return "NAND"; + return "Xnor"; } } + + public static class Or extends Function { + @Override + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 | arg2; - public static class Nor extends Function { + return result; + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Or"; + } + } + + public static class OrNotA extends Function { @Override - public Object run(Connection... connections) { - if (connections.length < 2) { - throw new InvalidArgumentsException("Not enough connections were given."); + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); } else { - int arg1 = ((int) connections[0].getValue()); - int arg2 = ((int) connections[1].getValue()); - int result = arg1 | arg2; + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = ~arg1 | arg2; - return ~result; + return result; + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Or !A"; + } + } + + public static class OrNotB extends Function { + @Override + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 | ~arg2; + + return result; } } @@ -164,19 +368,19 @@ public class BitwiseLogic extends FunctionSet { @Override public String getName() { - return "NOR"; + return "Or !B"; } } - public static class Xnor extends Function { + public static class Nand extends Function { @Override - public Object run(Connection... connections) { - if (connections.length < 2) { - throw new InvalidArgumentsException("Not enough connections were given."); + public Long run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); } else { - int arg1 = ((int) connections[0].getValue()); - int arg2 = ((int) connections[1].getValue()); - int result = arg1 ^ arg2; + Long arg1 = ((Long) connections[0].getValue()); + Long arg2 = ((Long) connections[1].getValue()); + Long result = arg1 & arg2; return ~result; } @@ -189,10 +393,7 @@ public class BitwiseLogic extends FunctionSet { @Override public String getName() { - return "XNOR"; + return "Nand"; } } - - - } diff --git a/src/jcgp/backend/function/DoubleArithmetic.java b/src/jcgp/backend/function/DoubleArithmetic.java new file mode 100644 index 0000000..ce4826f --- /dev/null +++ b/src/jcgp/backend/function/DoubleArithmetic.java @@ -0,0 +1,589 @@ +package jcgp.backend.function; + +import jcgp.backend.population.Connection; + +public class DoubleArithmetic extends FunctionSet { + + public final static double DIVISION_LIMIT = 0.0001; + + public DoubleArithmetic() { + name = "Double Arithmetic"; + functionList = new Function[]{ + new Absolute(), + new SquareRoot(), + new Reciprocal(), + new Sine(), + new Cosine(), + new Tangent(), + new Exponential(), + new HyperbolicSine(), + new HyperbolicCosine(), + new HyperbolicTangent(), + new NaturalLog(), + new LogBaseTen(), + new SineAB(), + new CosineAB(), + new Hypotenuse(), + new Power(), + new Addition(), + new Subtraction(), + new Multiplication(), + new Division()}; + + enableAll(); + } + + /** + * Absolute returns the positive value of input 0. + * + * @see Math.abs() + */ + public static class Absolute extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.abs(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Absolute"; + } + } + + /** + * Protected square root function, returns the square root of the absolute + * value of input 0. + * + * @see Math.abs(), Math.sqrt() + */ + public static class SquareRoot extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.sqrt(Math.abs(in0)); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Square root"; + } + } + + /** + * Protected reciprocal function, returns (1 / input 0). If input 0 is less than + * {@link DoubleArithmetic.}DIVISION_LIMIT, this returns it unchanged. + * + */ + public static class Reciprocal extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return in0 < DIVISION_LIMIT ? in0 : (1 / in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Reciprocal"; + } + } + + /** + * Sine function, in radians. + * + * @see Math.sin() + */ + public static class Sine extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.sin(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Sin"; + } + } + + /** + * Cosine function, in radians. + * + * @see Math.cos() + */ + public static class Cosine extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.cos(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Cos"; + } + } + + /** + * Protected tangent function, in radians. Returns the tangent of input 0. + * If input 0 is less than {@link DoubleArithmetic.}DIVISION_LIMIT, + * this returns it unchanged. + * + * @see Math.tan() + */ + public static class Tangent extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return in0 < DIVISION_LIMIT ? in0 : Math.tan(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Tan"; + } + } + + /** + * Exponential function. Returns the exponential of input 0. + * + * @see Math.exp() + */ + public static class Exponential extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.exp(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Exp"; + } + } + + /** + * Returns the hyperbolic sine of input 0. + * + * @see Math.sinh() + */ + public static class HyperbolicSine extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.sinh(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Sinh"; + } + } + + /** + * Returns the hyperbolic cosine of input 0. + * + * @see Math.cosh() + */ + public static class HyperbolicCosine extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.cosh(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Cosh"; + } + } + + /** + * Returns the hyperbolic tangent of input 0. + * + * @see Math.tanh() + */ + public static class HyperbolicTangent extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return Math.tanh(in0); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Tanh"; + } + } + + /** + * Protected natural log function. Returns the natural log of the absolute + * value of input 0. If input 0 is less than {@link DoubleArithmetic.}DIVISION_LIMIT, + * this returns it unchanged. + * + * @see Math.log(), Math.abs() + */ + public static class NaturalLog extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return in0 < DIVISION_LIMIT ? in0 : Math.log(Math.abs(in0)); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Ln"; + } + } + + /** + * Protected log base 10 function. Returns the log to base 10 the absolute + * value of input 0. If input 0 is less than {@link DoubleArithmetic.}DIVISION_LIMIT, + * this returns it unchanged. + * + * @see Math.log10(), Math.abs() + */ + public static class LogBaseTen extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + return in0 < DIVISION_LIMIT ? in0 : Math.log10(Math.abs(in0)); + } + } + + @Override + public int getArity() { + return 1; + } + + @Override + public String getName() { + return "Log"; + } + } + + /** + * Sine of sum. Returns the sine of the sum of inputs 0 and 1. + * + * @see Math.sin() + */ + public static class SineAB extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + return Math.sin(in0 + in1); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Sin(a+b)"; + } + } + + /** + * Cosine of sum. Returns the cosine of the sum of inputs 0 and 1. + * + * @see Math.cos() + */ + public static class CosineAB extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + return Math.cos(in0 + in1); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Cos(a+b)"; + } + } + + /** + * Hypotenuse function. Returns the square root of input 0 squared + * plus input 1 squared. + * + * @see Math.hypot() + */ + public static class Hypotenuse extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + return Math.hypot(in0, in1); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Hypotenuse"; + } + } + + /** + * Power function. Returns the absolute value of input 0 to the power of input 1. + * + * @see Math.abs(), Math.pow + */ + public static class Power extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + return Math.pow(Math.abs(in0), in1); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Power"; + } + } + + /** + * Addition returns the sum of inputs 0 and 1. + * + */ + public static class Addition extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + return in0 + in1; + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Addition"; + } + } + + /** + * Subtraction returns the difference between inputs 0 and 1. + * + */ + public static class Subtraction extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + return in0 - in1; + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Subtraction"; + } + } + + /** + * Multiplication returns the product of inputs 0 and 1. + * + */ + public static class Multiplication extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + return in0 * in1; + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Multiplication"; + } + } + + /** + * Protected division, returns the quotient of input 0 (the dividend) and input 1 (the divisor). + * If the divisor is less than {@link DoubleArithmetic.}DIVISION_LIMIT, this returns the it unchanged. + * + */ + public static class Division extends Function { + @Override + public Double run(Connection... connections) { + if (connections.length < getArity()) { + throw new IllegalArgumentException(getName() + " received " + connections.length + " connections but arity is " + getArity() + "."); + } else { + Double in0 = ((Double) connections[0].getValue()); + Double in1 = ((Double) connections[1].getValue()); + + return in1 < DIVISION_LIMIT ? in0 : (in0 / in1); + } + } + + @Override + public int getArity() { + return 2; + } + + @Override + public String getName() { + return "Division"; + } + } +} diff --git a/src/jcgp/backend/function/FunctionSet.java b/src/jcgp/backend/function/FunctionSet.java index 78801fc..1712b51 100644 --- a/src/jcgp/backend/function/FunctionSet.java +++ b/src/jcgp/backend/function/FunctionSet.java @@ -51,6 +51,7 @@ public abstract class FunctionSet { int function = iterator.next(); if (function == index) { iterator.remove(); + break; } } } else { diff --git a/src/jcgp/backend/function/IntegerArithmetic.java b/src/jcgp/backend/function/IntegerArithmetic.java deleted file mode 100644 index 9bb02b5..0000000 --- a/src/jcgp/backend/function/IntegerArithmetic.java +++ /dev/null @@ -1,122 +0,0 @@ -package jcgp.backend.function; - -import jcgp.backend.population.Connection; - -public class IntegerArithmetic extends FunctionSet { - - public IntegerArithmetic() { - name = "Integer Arithmetic"; - functionList = new Function[]{ - new Addition(), - new Subtraction(), - new Multiplication(), - new Division()}; - - enableAll(); - } - - public static class Addition extends Function { - @Override - public Integer run(Connection... connections) { - if (connections.length < 2) { - throw new IllegalArgumentException("Not enough connections were given."); - } else { - Integer arg1 = ((Integer) connections[0].getValue()); - Integer arg2 = ((Integer) connections[1].getValue()); - Integer result = arg1 + arg2; - - return result; - } - } - - @Override - public int getArity() { - return 2; - } - - @Override - public String getName() { - return "Addition"; - } - } - - public static class Subtraction extends Function { - @Override - public Integer run(Connection... connections) { - if (connections.length < 2) { - throw new IllegalArgumentException("Not enough connections were given."); - } else { - Integer arg1 = ((Integer) connections[0].getValue()); - Integer arg2 = ((Integer) connections[1].getValue()); - Integer result = arg1 - arg2; - - return result; - } - } - - @Override - public int getArity() { - return 2; - } - - @Override - public String getName() { - return "Subtraction"; - } - } - - public static class Multiplication extends Function { - @Override - public Integer run(Connection... connections) { - if (connections.length < 2) { - throw new IllegalArgumentException("Not enough connections were given."); - } else { - Integer arg1 = ((Integer) connections[0].getValue()); - Integer arg2 = ((Integer) connections[1].getValue()); - Integer result = arg1 * arg2; - return result; - } - } - - @Override - public int getArity() { - return 2; - } - - @Override - public String getName() { - return "Multiplication"; - } - } - - public static class Division extends Function { - @Override - public Integer run(Connection... connections) { - if (connections.length < 2) { - throw new IllegalArgumentException("Not enough connections were given."); - } else { - Integer arg1 = ((Integer) connections[0].getValue()); - Integer arg2 = ((Integer) connections[1].getValue()); - Integer result; - if (arg2 == 0) { - result = 0; - } else { - result = arg1 / arg2; - } - - return result; - } - } - - @Override - public int getArity() { - return 2; - } - - @Override - public String getName() { - return "Division"; - } - } - -} diff --git a/src/jcgp/backend/modules/problem/SymbolicRegression.java b/src/jcgp/backend/modules/problem/SymbolicRegression.java index c92d183..46b8e09 100644 --- a/src/jcgp/backend/modules/problem/SymbolicRegression.java +++ b/src/jcgp/backend/modules/problem/SymbolicRegression.java @@ -2,18 +2,18 @@ package jcgp.backend.modules.problem; import java.util.ArrayList; -import jcgp.backend.function.IntegerArithmetic; +import jcgp.backend.function.DoubleArithmetic; import jcgp.backend.resources.Resources; -public class SymbolicRegression extends TestCaseProblem<Integer> { +public class SymbolicRegression extends TestCaseProblem<Double> { public SymbolicRegression(Resources resources) { super(resources); - functionSet = new IntegerArithmetic(); + functionSet = new DoubleArithmetic(); - ArrayList<TestCase<Integer>> tc = new ArrayList<TestCase<Integer>>(); - tc.add(new TestCase<Integer>(new Integer[]{1, 2, 3}, new Integer[]{-4, 5, 6})); - tc.add(new TestCase<Integer>(new Integer[]{3, 2, 5}, new Integer[]{2, 5, 9})); + ArrayList<TestCase<Double>> tc = new ArrayList<TestCase<Double>>(); + tc.add(new TestCase<Double>(new Double[]{1.0, 2.0, 3.0}, new Double[]{-4.0, 5.0, 6.0})); + tc.add(new TestCase<Double>(new Double[]{3.0, 2.0, 5.0}, new Double[]{2.0, 5.0, 9.0})); setTestCases(tc); } diff --git a/src/jcgp/backend/parser/ChromosomeParser.java b/src/jcgp/backend/parser/ChromosomeParser.java new file mode 100644 index 0000000..74f638c --- /dev/null +++ b/src/jcgp/backend/parser/ChromosomeParser.java @@ -0,0 +1,131 @@ +package jcgp.backend.parser; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.Scanner; + +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Node; +import jcgp.backend.resources.Resources; + +/** + * This class includes a method for parsing .chr files and another + * for writing .chr files from given chromosomes. + * + * @author Eduardo Pedroni + * + */ +public class ChromosomeParser { + + /** + * Use this method to parse .chr files into a given chromosome. + * <br><br> + * This is not fully defensive as it doesn't check for number of inputs, + * doesn't compare rows and columns individually and doesn't account for levels back. It + * is not viable to implement these defensive measures with the chromosome format used + * by CGP. + * + * @param file the .chr file to parse from + * @param chromosome the chromosome to configure + * @param resources the experiment resources + */ + public static void parse(File file, Chromosome chromosome, Resources resources) { + /* + * Count the nodes to make sure the size of the .chr file matches the experiment parameters. + * + * We do this by using the scanner to get the node and output portions of the file as they + * are separated by 3 tab characters. Every number is replaced by a single known character, + * and the length of the string with the new characters is compared with that of a string + * where the new known character has been removed, yielding the total number of values. + * + */ + FileReader fr; + try { + fr = new FileReader(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return; + } + Scanner in = new Scanner(fr); + in.useDelimiter("\\t\\t\\t"); + String geneString = in.next().replaceAll("[0-9]+", "g"); + String outString = in.next().replaceAll("[0-9]+", "o"); + int geneCount = geneString.length() - geneString.replace("g", "").length(); + int outCount = outString.length() - outString.replace("o", "").length(); + in.close(); + + + // if the acquired values match the current parameters, apply them to the chromosome + if ((geneCount == resources.nodes() * (resources.arity() + 1)) + && outCount == resources.outputs()) { + // prepare a new scanner + try { + fr = new FileReader(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return; + } + in = new Scanner(fr); + + int gene; + Connection newConnection; + Node changingNode; + // for all nodes, columns first + for (int c = 0; c < resources.columns(); c ++) { + for (int r = 0; r < resources.rows(); r ++) { + // store the changing node + changingNode = chromosome.getNode(r, c); + + // for every connection + for (int i = 0; i < resources.arity(); i ++) { + // get connection number from the .chr file + gene = in.nextInt(); + if (gene < resources.inputs()) { + // connection was an input + newConnection = chromosome.getInput(gene); + } else { + // connection was another node, calculate which from its number + newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(), + (gene - resources.inputs()) / resources.rows()); + } + changingNode.setConnection(i, newConnection); + } + + // set the function, straight indexing should work - this is not entirely + // safe, but it is not viable to check for functionset compatibility + changingNode.setFunction(resources.getFunction(in.nextInt())); + } + } + + // outputs + for (int o = 0; o < resources.outputs(); o ++) { + gene = in.nextInt(); + if (gene < resources.inputs()) { + // connection was an input + newConnection = chromosome.getInput(gene); + } else { + // connection was another node, calculate which from its number + newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(), + (gene - resources.inputs()) / resources.rows()); + } + chromosome.getOutput(o).setConnection(0, newConnection); + } + in.close(); + } + } + + /** + * Writes a chromosome into the specified .chr file. + * + * + * + * @param file + * @param chromosome + */ + public static void save(File file, Chromosome chromosome) { + + } + +} diff --git a/src/jcgp/backend/parser/FunctionParser.java b/src/jcgp/backend/parser/FunctionParser.java new file mode 100644 index 0000000..64a095c --- /dev/null +++ b/src/jcgp/backend/parser/FunctionParser.java @@ -0,0 +1,58 @@ +package jcgp.backend.parser; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.Scanner; + +import jcgp.backend.function.FunctionSet; +import jcgp.backend.modules.problem.Problem; + +public class FunctionParser { + +private FunctionSet functionSet; + + private FunctionParser(Problem problem) { + this.functionSet = problem.getFunctionSet(); + } + + public static void parseFunctions(File file, Problem problem) { + FunctionParser pp = new FunctionParser(problem); + + FileReader fr; + try { + fr = new FileReader(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return; + } + + Scanner in = new Scanner(fr); + + while (in.hasNextLine()) { + String line = in.nextLine(); + if (line.substring(line.length() - 1).matches("[0-9]")) { + pp.parseAndSet(line.split("[^0-9]+")); + } + } + + in.close(); + } + + private void parseAndSet(String[] splitString) { +// System.out.println("new line"); +// for (int i= 0; i < splitString.length; i++) { +// System.out.println(i + ": " + splitString[i]); +// } + int functionIndex = Integer.parseInt(splitString[splitString.length - 1]); + System.out.println("index: " + functionIndex); + if (Integer.parseInt(splitString[0]) != 0) { + System.out.println("enabling: " + functionSet.getFunction(functionIndex).getName()); + functionSet.enableFunction(functionIndex); + } else { + System.out.println("disabling: " + functionSet.getFunction(functionIndex).getName()); + functionSet.disableFunction(functionIndex); + } + + } +} diff --git a/src/jcgp/backend/parser/ParameterParser.java b/src/jcgp/backend/parser/ParameterParser.java new file mode 100644 index 0000000..473b632 --- /dev/null +++ b/src/jcgp/backend/parser/ParameterParser.java @@ -0,0 +1,76 @@ +package jcgp.backend.parser; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.Scanner; +import jcgp.backend.resources.ModifiableResources; + +public class ParameterParser { + + private ModifiableResources resources; + + private ParameterParser(ModifiableResources resources) { + this.resources = resources; + } + + public static void parseParameters(File file, ModifiableResources resources) { + ParameterParser pp = new ParameterParser(resources); + + FileReader fr; + try { + fr = new FileReader(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return; + } + + Scanner in = new Scanner(fr); + + while (in.hasNextLine()) { + pp.parseAndSet(in.nextLine().split("( |\t)+")); + } + + in.close(); + } + + private void parseAndSet(String[] splitString) { + switch (splitString[1]) { + + case "population_size": + resources.setPopulationSize(Integer.parseInt(splitString[0])); + break; + + case "num_generations": + resources.setGenerations(Integer.parseInt(splitString[0])); + break; + + case "num_runs_total": + resources.setRuns(Integer.parseInt(splitString[0])); + break; + + case "num_rows": + resources.setRows(Integer.parseInt(splitString[0])); + break; + + case "num_cols": + resources.setColumns(Integer.parseInt(splitString[0])); + break; + + case "levels_back": + resources.setLevelsBack(Integer.parseInt(splitString[0])); + break; + + case "report_interval": + resources.setReportInterval(Integer.parseInt(splitString[0])); + break; + + case "global_seed": + resources.setSeed(Integer.parseInt(splitString[0])); + break; + + default: + break; + } + } +} diff --git a/src/jcgp/backend/parser/TestCaseParser.java b/src/jcgp/backend/parser/TestCaseParser.java new file mode 100644 index 0000000..c997177 --- /dev/null +++ b/src/jcgp/backend/parser/TestCaseParser.java @@ -0,0 +1,13 @@ +package jcgp.backend.parser; + +import java.io.File; + +import jcgp.backend.modules.problem.TestCaseProblem; + +public class TestCaseParser { + + public static void parse(File file, TestCaseProblem<?> problem) { + + } + +} diff --git a/src/jcgp/backend/population/Population.java b/src/jcgp/backend/population/Population.java index a850595..1bbdc54 100644 --- a/src/jcgp/backend/population/Population.java +++ b/src/jcgp/backend/population/Population.java @@ -98,5 +98,4 @@ public class Population { public int getFittestIndex() { return fittest; } - } diff --git a/src/jcgp/backend/resources/ModifiableResources.java b/src/jcgp/backend/resources/ModifiableResources.java index 689f846..3841963 100644 --- a/src/jcgp/backend/resources/ModifiableResources.java +++ b/src/jcgp/backend/resources/ModifiableResources.java @@ -19,6 +19,10 @@ public class ModifiableResources extends Resources { super(); } + public void setValues(String filePath) { + + } + /** * @param rows the rows to set */ @@ -106,8 +110,8 @@ public class ModifiableResources extends Resources { /** * @param report the report to set */ - public void setReport(int report) { - this.report.set(report); + public void setReportInterval(int report) { + this.reportInterval.set(report); } /** @@ -197,10 +201,10 @@ public class ModifiableResources extends Resources { /** * @return the report */ - public IntegerParameter getReportParameter() { - return report; + public IntegerParameter getReportIntervalParameter() { + return reportInterval; } - + public void setFunctionSet(FunctionSet functionSet) { this.functionSet = functionSet; setArity(functionSet.getMaxArity()); diff --git a/src/jcgp/backend/resources/Resources.java b/src/jcgp/backend/resources/Resources.java index c83fa35..0bf1ee1 100644 --- a/src/jcgp/backend/resources/Resources.java +++ b/src/jcgp/backend/resources/Resources.java @@ -21,7 +21,7 @@ import jcgp.backend.resources.parameters.ParameterStatus; public class Resources { protected IntegerParameter rows, columns, inputs, outputs, populationSize, levelsBack, currentGeneration, generations, currentRun, runs, - arity, seed, report; + arity, seed, reportInterval; protected Random numberGenerator = new Random(); protected FunctionSet functionSet; @@ -124,10 +124,10 @@ public class Resources { } /** - * @return the report + * @return the report interval */ - public int report() { - return report.get(); + public int reportInterval() { + return reportInterval.get(); } private void createBaseParameters() { @@ -273,7 +273,7 @@ public class Resources { }); numberGenerator.setSeed(seed.get()); - report = new IntegerParameter(1, "Report", false, false) { + reportInterval = new IntegerParameter(1, "Report interval", false, false) { @Override public void validate(Number newValue) { if (newValue.intValue() > generations.get()) { @@ -325,8 +325,8 @@ public class Resources { * These are affected by parameter report */ public void reportln(String s) { - if (report.get() > 0) { - if (currentGeneration.get() % report.get() == 0) { + if (reportInterval.get() > 0) { + if (currentGeneration.get() % reportInterval.get() == 0) { System.out.println(s); if (console != null) { console.println(s); @@ -336,8 +336,8 @@ public class Resources { } public void report(String s) { - if (report.get() > 0) { - if (currentGeneration.get() % report.get() == 0) { + if (reportInterval.get() > 0) { + if (currentGeneration.get() % reportInterval.get() == 0) { System.out.print(s); if (console != null) { console.print(s); diff --git a/src/jcgp/backend/tests/ChromosomeTests.java b/src/jcgp/backend/tests/ChromosomeTests.java index 07326a7..36278ba 100644 --- a/src/jcgp/backend/tests/ChromosomeTests.java +++ b/src/jcgp/backend/tests/ChromosomeTests.java @@ -2,7 +2,7 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import jcgp.backend.function.IntegerArithmetic; +import jcgp.backend.function.DoubleArithmetic; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Connection; import jcgp.backend.population.Input; @@ -46,7 +46,7 @@ public class ChromosomeTests { @BeforeClass public static void setUpBeforeClass() { resources = new ModifiableResources(); - resources.setFunctionSet(new IntegerArithmetic()); + resources.setFunctionSet(new DoubleArithmetic()); } @Before diff --git a/src/jcgp/backend/tests/NodeTests.java b/src/jcgp/backend/tests/NodeTests.java index 0e08d92..c9f247a 100644 --- a/src/jcgp/backend/tests/NodeTests.java +++ b/src/jcgp/backend/tests/NodeTests.java @@ -3,7 +3,7 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; import jcgp.backend.exceptions.InvalidArgumentsException; import jcgp.backend.function.Function; -import jcgp.backend.function.IntegerArithmetic; +import jcgp.backend.function.DoubleArithmetic; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Connection; import jcgp.backend.population.Node; @@ -41,7 +41,7 @@ public class NodeTests { public static void setUpBeforeClass() { resources = new ModifiableResources(); - resources.setFunctionSet(new IntegerArithmetic()); + resources.setFunctionSet(new DoubleArithmetic()); chromosome = new Chromosome(resources); } @@ -49,7 +49,7 @@ public class NodeTests { public void setUp() throws Exception { node = new Node(chromosome, 0, 0, resources.arity()); // make node with anonymous addition function and hard-coded value connections - node.initialise(new IntegerArithmetic.Addition(), + node.initialise(new DoubleArithmetic.Addition(), new Connection[]{new Connection() { @Override @@ -113,7 +113,7 @@ public class NodeTests { ((int) node.getValue()) == arg1 + arg2); // put in a different function, check the output has changed appropriately - node.setFunction(new IntegerArithmetic.Subtraction()); + node.setFunction(new DoubleArithmetic.Subtraction()); assertTrue("Node did not return expected value (difference of arguments).", ((Integer) node.getValue()) == arg1 - arg2); diff --git a/src/jcgp/backend/tests/OutputTests.java b/src/jcgp/backend/tests/OutputTests.java index a331f2d..95b7fc7 100644 --- a/src/jcgp/backend/tests/OutputTests.java +++ b/src/jcgp/backend/tests/OutputTests.java @@ -1,7 +1,7 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; -import jcgp.backend.function.IntegerArithmetic; +import jcgp.backend.function.DoubleArithmetic; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Connection; import jcgp.backend.population.Output; @@ -35,7 +35,7 @@ public class OutputTests { @BeforeClass public static void setUpBeforeClass() { resources = new ModifiableResources(); - resources.setFunctionSet(new IntegerArithmetic()); + resources.setFunctionSet(new DoubleArithmetic()); chromosome = new Chromosome(resources); } diff --git a/src/jcgp/backend/tests/PopulationTests.java b/src/jcgp/backend/tests/PopulationTests.java index fb8ced4..fca9c4f 100644 --- a/src/jcgp/backend/tests/PopulationTests.java +++ b/src/jcgp/backend/tests/PopulationTests.java @@ -1,7 +1,7 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; -import jcgp.backend.function.IntegerArithmetic; +import jcgp.backend.function.DoubleArithmetic; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Population; import jcgp.backend.resources.ModifiableResources; @@ -32,7 +32,7 @@ public class PopulationTests { @BeforeClass public static void setUpBeforeClass() throws Exception { resources = new ModifiableResources(); - resources.setFunctionSet(new IntegerArithmetic()); + resources.setFunctionSet(new DoubleArithmetic()); } @Before |