package jcgp.backend.modules.problem; import jcgp.backend.function.DigitalCircuitFunctions; import jcgp.backend.function.UnsignedInteger; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Population; import jcgp.backend.resources.Resources; /** * Digital circuit problem *

* Using this problem type, digital logic circuits can be evolved. * {@code parseData()} must be used to load the desired circuit * truth table in the standard CGP .plu format. * * @see DigitalCircuitFunctions * @author Eduardo Pedroni * */ public class DigitalCircuitProblem extends TestCaseProblem { /** * Construct a new instance of DigitalCircuitProblem. * * @param resources a reference to the experiment's resources. */ public DigitalCircuitProblem(Resources resources) { super(resources); setFunctionSet(new DigitalCircuitFunctions()); setName("Digital circuit"); setFileExtension(".plu"); } @Override public void evaluate(Population population, Resources resources) { // for every chromosome in the population for (int i = 0; i < resources.populationSize(); i++) { // assume an initial fitness of 0 int fitness = 0; // iterate over every test case for (int t = 0; t < testCases.size(); t++) { population.getChromosome(i).setInputs((Object[]) testCases.get(t).getInputs()); // check each output for (int o = 0; o < resources.outputs(); o++) { Integer output = ((UnsignedInteger) population.getChromosome(i).getOutput(o).calculate()).get(); Integer matches = ~(output ^ testCases.get(t).getOutput(o).get()); // check only the relevant bits int bits = (int) Math.pow(2.0, (double) resources.inputs()); for (int b = 0; b < bits; b++) { if (((matches >>> b) & 1) == 1) { fitness++; } } } } // assign the resulting fitness to the respective individual population.getChromosome(i).setFitness(fitness); } // sort population population.sortAscending(); } @Override protected double getMaxFitness() { // calculate the fitness by looking at inputs, not number of test cases double maxFitness = Math.pow(2.0, (double) resources.inputs()) * resources.outputs(); return maxFitness; } @Override public TestCase parseTestCase(String[] inputs, String[] outputs) { // cast the test case values to UnsignedInteger UnsignedInteger[] inputCases = new UnsignedInteger[inputs.length]; UnsignedInteger[] outputCases = new UnsignedInteger[outputs.length]; for (int i = 0; i < inputCases.length; i++) { inputCases[i] = new UnsignedInteger(inputs[i]); } for (int o = 0; o < outputCases.length; o++) { outputCases[o] = new UnsignedInteger(outputs[o]); } return new TestCase(inputCases, outputCases); } @Override public boolean isPerfectSolution(Chromosome fittest) { // higher fitness is better return fittest.getFitness() >= maxFitness.get(); } @Override public boolean isImprovement(Chromosome fittest) { // higher fitness is better if (fittest.getFitness() > bestFitness.get()) { bestFitness.set(fittest.getFitness()); return true; } else { return false; } } }