diff options
Diffstat (limited to 'src/jcgp/modules')
-rw-r--r-- | src/jcgp/modules/Module.java | 15 | ||||
-rw-r--r-- | src/jcgp/modules/ea/EvolutionaryAlgorithm.java | 13 | ||||
-rw-r--r-- | src/jcgp/modules/ea/StandardEA.java | 50 | ||||
-rw-r--r-- | src/jcgp/modules/fitness/FitnessFunction.java | 9 | ||||
-rw-r--r-- | src/jcgp/modules/fitness/TestCase.java | 42 | ||||
-rw-r--r-- | src/jcgp/modules/fitness/TruthTableEvaluator.java | 30 | ||||
-rw-r--r-- | src/jcgp/modules/function/Arithmetic.java | 123 | ||||
-rw-r--r-- | src/jcgp/modules/function/BitwiseLogic.java | 178 | ||||
-rw-r--r-- | src/jcgp/modules/function/BooleanLogic.java | 178 | ||||
-rw-r--r-- | src/jcgp/modules/function/Function.java | 12 | ||||
-rw-r--r-- | src/jcgp/modules/function/FunctionSet.java | 39 | ||||
-rw-r--r-- | src/jcgp/modules/mutator/Mutator.java | 9 | ||||
-rw-r--r-- | src/jcgp/modules/mutator/StandardMutator.java | 31 |
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())); + } + } + } + } +} |