package ec.app.semanticGP;

import ec.EvolutionState;
import ec.gp.semantic.BooleanSemantics;
import ec.util.Parameter;
import library.semantics.BitSet;
import library.semantics.TestCase;

import java.util.ArrayList;

public class Parity extends BooleanProblem {

	private int evenParity = 0; // 0 for even, 1 for odd-parity
	private int bits = 6;
	
	@Override
	public void setup(EvolutionState state, Parameter base) {
		super.setup(state, base);

		this.bits = state.parameters.getIntWithDefault(base.push("bits"), defaultBase().push("bits"), this.bits);
		this.calculateTestCases();
	}

	private void calculateTestCases() {
		final int upperBound = 1 << this.bits;
		TestCase<Boolean> tc;
		boolean v;

		this.trainingSet = new ArrayList<TestCase<Boolean>>(upperBound);
		BitSet target = new BitSet(upperBound);

		for (int i = 0; i < upperBound; ++i) {
			//								  odd   even  even   odd
			// input | bitCount | & 1 | = 0 | ^ 1 | ^ 0 | &1=0 | &1=1
			// 00000 | 00000    |   0 |   1 |   0 |   1 |    1 |    0
			// 00001 | 00001    |   1 |   0 |   1 |   0 |    0 |    1
			// 00010 | 00001    |   1 |   0 |   1 |   0 |    0 |    1
			// 00011 | 00010    |   0 |   1 |   0 |   1 |    1 |    0
			// 00100 | 00001    |   1 |   0 |   1 |   0 |    0 |    1
			// 00101 | 00010    |   0 |   1 |   0 |   1 |    1 |    0
			// 00110 | 00010    |   0 |   1 |   0 |   1 |    1 |    0
			// 00111 | 00011    |   1 |   0 |   1 |   0 |    0 |    1
			// 11111 | 00101    |   1 |   0 |   1 |   0 |    0 |    1
			v = (Integer.bitCount(i) & 1) == evenParity;
			assert (v == ((Integer.bitCount(i) & 1) == 0 ^ !(evenParity == 0)));
			tc = new TestCase<Boolean>(v, asArray(i, this.bits));
			this.trainingSet.add(tc);
			target.set(i, v);
		}

		this.targetSemantics = new BooleanSemantics(target);
	}

	@Override
	public String getName() {
		return "Parity" + this.bits;
	}
}
