aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/jcgp/modules')
-rw-r--r--src/jcgp/modules/Module.java15
-rw-r--r--src/jcgp/modules/ea/EvolutionaryAlgorithm.java13
-rw-r--r--src/jcgp/modules/ea/StandardEA.java50
-rw-r--r--src/jcgp/modules/fitness/FitnessFunction.java9
-rw-r--r--src/jcgp/modules/fitness/TestCase.java42
-rw-r--r--src/jcgp/modules/fitness/TruthTableEvaluator.java30
-rw-r--r--src/jcgp/modules/function/Arithmetic.java123
-rw-r--r--src/jcgp/modules/function/BitwiseLogic.java178
-rw-r--r--src/jcgp/modules/function/BooleanLogic.java178
-rw-r--r--src/jcgp/modules/function/Function.java12
-rw-r--r--src/jcgp/modules/function/FunctionSet.java39
-rw-r--r--src/jcgp/modules/mutator/Mutator.java9
-rw-r--r--src/jcgp/modules/mutator/StandardMutator.java31
13 files changed, 729 insertions, 0 deletions
diff --git a/src/jcgp/modules/Module.java b/src/jcgp/modules/Module.java
new file mode 100644
index 0000000..a0da50a
--- /dev/null
+++ b/src/jcgp/modules/Module.java
@@ -0,0 +1,15 @@
+package jcgp.modules;
+
+import jcgp.parameters.Parameter;
+import jcgp.parameters.Parameters;
+
+public abstract class Module {
+
+ /**
+ * Register a new parameter
+ */
+ protected final void registerParameter(String key, Parameter value) {
+ Parameters.add(key, value);
+ };
+
+}
diff --git a/src/jcgp/modules/ea/EvolutionaryAlgorithm.java b/src/jcgp/modules/ea/EvolutionaryAlgorithm.java
new file mode 100644
index 0000000..8de8c87
--- /dev/null
+++ b/src/jcgp/modules/ea/EvolutionaryAlgorithm.java
@@ -0,0 +1,13 @@
+package jcgp.modules.ea;
+
+import jcgp.modules.mutator.Mutator;
+import jcgp.population.Chromosome;
+import jcgp.population.Population;
+
+public interface EvolutionaryAlgorithm {
+
+ public abstract void evolve(Population population, Mutator mutator);
+
+ public abstract Chromosome getFittestChromosome();
+
+}
diff --git a/src/jcgp/modules/ea/StandardEA.java b/src/jcgp/modules/ea/StandardEA.java
new file mode 100644
index 0000000..2db8776
--- /dev/null
+++ b/src/jcgp/modules/ea/StandardEA.java
@@ -0,0 +1,50 @@
+package jcgp.modules.ea;
+
+import jcgp.modules.mutator.Mutator;
+import jcgp.parameters.Parameters;
+import jcgp.parameters.IntegerParameter;
+import jcgp.parameters.BooleanParameter;
+import jcgp.population.Chromosome;
+import jcgp.population.Population;
+
+/**
+ * (1 + λ) EA.
+ *
+ *
+ * @author Eduardo Pedroni
+ *
+ */
+public class StandardEA implements EvolutionaryAlgorithm {
+
+ private Chromosome fittestChromosome;
+
+ @Override
+ public void evolve(Population population, Mutator mutator) {
+ // select fittest chromosome
+ int fittest = 0;
+
+ for (int i = 1; i < ((IntegerParameter) Parameters.get("population")).getValue(); i++) {
+ if (population.getChromosome(i).getFitness() >= population.getChromosome(fittest).getFitness()) {
+ fittest = i;
+ }
+ }
+ fittestChromosome = population.getChromosome(fittest);
+ population.setBestIndividual(fittest);
+ if (((BooleanParameter) Parameters.get("debug")).getValue()) {
+ System.out.println("Best fitness: " + fittestChromosome.getFitness());
+ }
+ // create copies of fittest chromosome, mutate them
+ Chromosome fc = population.getChromosome(fittest);
+ for (int i = 0; i < ((IntegerParameter) Parameters.get("population")).getValue(); i++) {
+ if (i != fittest) {
+ population.getChromosome(i).copyConnections(fc);
+ mutator.mutate(population.getChromosome(i));
+ }
+ }
+ }
+
+ @Override
+ public Chromosome getFittestChromosome() {
+ return fittestChromosome;
+ }
+}
diff --git a/src/jcgp/modules/fitness/FitnessFunction.java b/src/jcgp/modules/fitness/FitnessFunction.java
new file mode 100644
index 0000000..8ed1b56
--- /dev/null
+++ b/src/jcgp/modules/fitness/FitnessFunction.java
@@ -0,0 +1,9 @@
+package jcgp.modules.fitness;
+
+import jcgp.population.Population;
+
+public interface FitnessFunction {
+
+ public void evaluate(Population population);
+
+}
diff --git a/src/jcgp/modules/fitness/TestCase.java b/src/jcgp/modules/fitness/TestCase.java
new file mode 100644
index 0000000..0cb09f1
--- /dev/null
+++ b/src/jcgp/modules/fitness/TestCase.java
@@ -0,0 +1,42 @@
+package jcgp.modules.fitness;
+
+import jcgp.exceptions.ParameterMismatchException;
+import jcgp.parameters.Parameters;
+
+public class TestCase {
+
+ private Object[] inputs;
+ private Object[] outputs;
+
+ public TestCase(Object[] inputs, Object[] outputs) throws ParameterMismatchException {
+ if (inputs.length == Parameters.getInputs()) {
+ this.inputs = inputs;
+ } else {
+ throw new ParameterMismatchException();
+ }
+
+ if (outputs.length == Parameters.getOutputs()) {
+ this.outputs = outputs;
+ } else {
+ throw new ParameterMismatchException();
+ }
+
+ }
+
+ public Object getInput(int index) {
+ return inputs[index];
+ }
+
+ public Object getOutput(int index) {
+ return outputs[index];
+ }
+
+ public Object[] getInputs() {
+ return inputs;
+ }
+
+ public Object[] getOutputs() {
+ return outputs;
+ }
+
+}
diff --git a/src/jcgp/modules/fitness/TruthTableEvaluator.java b/src/jcgp/modules/fitness/TruthTableEvaluator.java
new file mode 100644
index 0000000..a69de96
--- /dev/null
+++ b/src/jcgp/modules/fitness/TruthTableEvaluator.java
@@ -0,0 +1,30 @@
+package jcgp.modules.fitness;
+
+import jcgp.TruthTable;
+import jcgp.parameters.Parameters;
+import jcgp.population.Population;
+
+public class TruthTableEvaluator implements FitnessFunction {
+
+ @Override
+ public void evaluate(Population population) {
+ // for every chromosome in the population
+ for (int i = 0; i < Parameters.getPopulationSize(); i++) {
+ int fitness = 0;
+ // for every test case
+ for (int t = 0; t < TruthTable.getTestCaseCount(); t++) {
+ population.getChromosome(i).setInputs(TruthTable.getTestCase(t).getInputs());
+ // check every output
+ for (int o = 0; o < Parameters.getOutputs(); o++) {
+ if (population.getChromosome(i).getOutput(o).calculate() == TruthTable.getTestCase(t).getOutput(o)) {
+ fitness++;
+ }
+ }
+ }
+ population.getChromosome(i).setFitness(fitness);
+ if (Parameters.getDebug()) {
+ System.out.println("active nodes: " + population.getChromosome(i).getActiveNodes().size());
+ }
+ }
+ }
+}
diff --git a/src/jcgp/modules/function/Arithmetic.java b/src/jcgp/modules/function/Arithmetic.java
new file mode 100644
index 0000000..73debd2
--- /dev/null
+++ b/src/jcgp/modules/function/Arithmetic.java
@@ -0,0 +1,123 @@
+package jcgp.modules.function;
+
+import jcgp.exceptions.InvalidArgumentsException;
+import jcgp.parameters.Parameters;
+import jcgp.population.Connection;
+
+public class Arithmetic {
+
+ public static class Addition extends Function {
+
+ private int arity = 2;
+
+ @Override
+ public Integer run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Integer arg1 = ((Integer) connections[0].getValue());
+ Integer arg2 = ((Integer) connections[1].getValue());
+ Integer result = arg1 + arg2;
+
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " + " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Subtraction extends Function {
+
+ private int arity = 2;
+
+ @Override
+ public Integer run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Integer arg1 = ((Integer) connections[0].getValue());
+ Integer arg2 = ((Integer) connections[1].getValue());
+ Integer result = arg1 - arg2;
+
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " - " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Multiplication extends Function {
+
+ private int arity = 2;
+
+ @Override
+ public Integer run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Integer arg1 = ((Integer) connections[0].getValue());
+ Integer arg2 = ((Integer) connections[1].getValue());
+ Integer result = arg1 * arg2;
+
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " * " + arg2 + " = " + result);
+ }
+
+
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Division extends Function {
+
+ private int arity = 2;
+
+ @Override
+ public Integer run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("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;
+ }
+
+
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " / " + arg2 + " = " + result);
+ }
+
+
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+}
diff --git a/src/jcgp/modules/function/BitwiseLogic.java b/src/jcgp/modules/function/BitwiseLogic.java
new file mode 100644
index 0000000..a260715
--- /dev/null
+++ b/src/jcgp/modules/function/BitwiseLogic.java
@@ -0,0 +1,178 @@
+package jcgp.modules.function;
+
+import jcgp.exceptions.InvalidArgumentsException;
+import jcgp.parameters.Parameters;
+import jcgp.population.Connection;
+
+public class BitwiseLogic {
+
+ public static class And extends Function {
+ private int arity = 2;
+
+ @Override
+ public Object run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ int arg1 = ((int) connections[0].getValue());
+ int arg2 = ((int) connections[1].getValue());
+ int result = arg1 & arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " AND " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Or extends Function {
+ private int arity = 2;
+
+ @Override
+ public Object run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ int arg1 = ((int) connections[0].getValue());
+ int arg2 = ((int) connections[1].getValue());
+ int result = arg1 | arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " OR " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Not extends Function {
+ private int arity = 1;
+
+ @Override
+ public Object run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ int arg1 = ((int) connections[0].getValue());
+ int result = ~arg1;
+ if (Parameters.getDebug()) {
+ System.out.println("NOT " + arg1 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Xor extends Function {
+ private int arity = 2;
+
+ @Override
+ public Object run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ int arg1 = ((int) connections[0].getValue());
+ int arg2 = ((int) connections[1].getValue());
+ int result = arg1 ^ arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " XOR " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Nand extends Function {
+ private int arity = 2;
+
+ @Override
+ public Object run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ int arg1 = ((int) connections[0].getValue());
+ int arg2 = ((int) connections[1].getValue());
+ int result = arg1 & arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " NAND " + arg2 + " = " + ~result);
+ }
+ return ~result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Nor extends Function {
+ private int arity = 2;
+
+ @Override
+ public Object run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ int arg1 = ((int) connections[0].getValue());
+ int arg2 = ((int) connections[1].getValue());
+ int result = arg1 | arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " NOR " + arg2 + " = " + ~result);
+ }
+ return ~result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Xnor extends Function {
+ private int arity = 2;
+
+ @Override
+ public Object run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ int arg1 = ((int) connections[0].getValue());
+ int arg2 = ((int) connections[1].getValue());
+ int result = arg1 ^ arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " XNOR " + arg2 + " = " + ~result);
+ }
+ return ~result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+
+
+}
diff --git a/src/jcgp/modules/function/BooleanLogic.java b/src/jcgp/modules/function/BooleanLogic.java
new file mode 100644
index 0000000..887e0e6
--- /dev/null
+++ b/src/jcgp/modules/function/BooleanLogic.java
@@ -0,0 +1,178 @@
+package jcgp.modules.function;
+
+import jcgp.exceptions.InvalidArgumentsException;
+import jcgp.parameters.Parameters;
+import jcgp.population.Connection;
+
+public class BooleanLogic {
+
+ public static class And extends Function {
+ private int arity = 2;
+
+ @Override
+ public Boolean run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Boolean arg1 = ((Boolean) connections[0].getValue());
+ Boolean arg2 = ((Boolean) connections[1].getValue());
+ Boolean result = arg1 && arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " AND " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Or extends Function {
+ private int arity = 2;
+
+ @Override
+ public Boolean run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Boolean arg1 = ((Boolean) connections[0].getValue());
+ Boolean arg2 = ((Boolean) connections[1].getValue());
+ Boolean result = arg1 || arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " OR " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Not extends Function {
+ private int arity = 1;
+
+ @Override
+ public Boolean run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Boolean arg1 = ((Boolean) connections[0].getValue());
+ Boolean result = !arg1;
+ if (Parameters.getDebug()) {
+ System.out.println("NOT " + arg1 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Xor extends Function {
+ private int arity = 2;
+
+ @Override
+ public Boolean run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Boolean arg1 = ((Boolean) connections[0].getValue());
+ Boolean arg2 = ((Boolean) connections[1].getValue());
+ Boolean result = arg1 ^ arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " XOR " + arg2 + " = " + result);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Nand extends Function {
+ private int arity = 2;
+
+ @Override
+ public Boolean run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Boolean arg1 = ((Boolean) connections[0].getValue());
+ Boolean arg2 = ((Boolean) connections[1].getValue());
+ Boolean result = arg1 && arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " NAND " + arg2 + " = " + !result);
+ }
+ return !result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Nor extends Function {
+ private int arity = 2;
+
+ @Override
+ public Boolean run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Boolean arg1 = ((Boolean) connections[0].getValue());
+ Boolean arg2 = ((Boolean) connections[1].getValue());
+ Boolean result = arg1 || arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " NOR " + arg2 + " = " + !result);
+ }
+ return !result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+ public static class Xnor extends Function {
+ private int arity = 2;
+
+ @Override
+ public Boolean run(Connection... connections) {
+ if (connections.length < arity) {
+ throw new InvalidArgumentsException("Not enough connections were given.");
+ } else {
+ Boolean arg1 = ((Boolean) connections[0].getValue());
+ Boolean arg2 = ((Boolean) connections[1].getValue());
+ Boolean result = arg1 ^ arg2;
+ if (Parameters.getDebug()) {
+ System.out.println(arg1 + " XNOR " + arg2 + " = " + !result);
+ }
+ return !result;
+ }
+ }
+
+ @Override
+ public int getArity() {
+ return arity;
+ }
+ }
+
+
+
+}
diff --git a/src/jcgp/modules/function/Function.java b/src/jcgp/modules/function/Function.java
new file mode 100644
index 0000000..3314c2f
--- /dev/null
+++ b/src/jcgp/modules/function/Function.java
@@ -0,0 +1,12 @@
+package jcgp.modules.function;
+
+import jcgp.exceptions.InvalidArgumentsException;
+import jcgp.population.Connection;
+
+public abstract class Function {
+
+ public abstract Object run(Connection ... connections) throws InvalidArgumentsException;
+
+ public abstract int getArity();
+
+}
diff --git a/src/jcgp/modules/function/FunctionSet.java b/src/jcgp/modules/function/FunctionSet.java
new file mode 100644
index 0000000..8a2190a
--- /dev/null
+++ b/src/jcgp/modules/function/FunctionSet.java
@@ -0,0 +1,39 @@
+package jcgp.modules.function;
+
+/**
+ *
+ * TODO: if function set flexibility is desired (i.e. add more functions as the program runs)
+ * an add function method should be created
+ * this would lead to concurrency problems, so tread lightly!
+ *
+ *
+ * @author Eduardo Pedroni
+ *
+ */
+public class FunctionSet {
+ private Function[] functionList;
+ private int maxArity = 0;
+
+ public FunctionSet(Function ... functions) {
+ functionList = functions;
+
+ for (Function function : functionList) {
+ if (function.getArity() > maxArity) {
+ maxArity = function.getArity();
+ }
+ }
+
+ }
+
+ public int getFunctionCount() {
+ return functionList.length;
+ }
+
+ public Function getFunction(int index) {
+ return functionList[index];
+ }
+
+ public int getMaxArity(){
+ return maxArity;
+ }
+ } \ No newline at end of file
diff --git a/src/jcgp/modules/mutator/Mutator.java b/src/jcgp/modules/mutator/Mutator.java
new file mode 100644
index 0000000..10df8cd
--- /dev/null
+++ b/src/jcgp/modules/mutator/Mutator.java
@@ -0,0 +1,9 @@
+package jcgp.modules.mutator;
+
+import jcgp.population.Chromosome;
+
+public interface Mutator {
+
+ void mutate(Chromosome chromosome);
+
+}
diff --git a/src/jcgp/modules/mutator/StandardMutator.java b/src/jcgp/modules/mutator/StandardMutator.java
new file mode 100644
index 0000000..17bd0be
--- /dev/null
+++ b/src/jcgp/modules/mutator/StandardMutator.java
@@ -0,0 +1,31 @@
+package jcgp.modules.mutator;
+
+import jcgp.Utilities;
+import jcgp.parameters.Parameters;
+import jcgp.population.Chromosome;
+import jcgp.population.MutableElement;
+import jcgp.population.Node;
+import jcgp.population.Output;
+
+public class StandardMutator implements Mutator {
+
+ @Override
+ public void mutate(Chromosome chromosome) {
+ int mutations = (int) (Parameters.getMutationRate() * (((double) Parameters.getNodeCount() + Parameters.getOutputs()) / 100));
+
+ for (int i = 0; i < mutations; i++) {
+ MutableElement m = chromosome.getRandomMutableElement();
+
+ if (m instanceof Output) {
+ m.setConnection(chromosome.getRandomConnection());
+ } else if (m instanceof Node) {
+ int geneType = Utilities.getRandomInt(1 + Parameters.getMaxArity());
+ if (geneType < 1) {
+ ((Node) m).setFunction(Utilities.getRandomFunction());
+ } else {
+ m.setConnection(chromosome.getRandomConnection(((Node) m).getColumn()));
+ }
+ }
+ }
+ }
+}