package ec.gp.semantic.geometry;

import Jama.Matrix;
import ec.EvolutionState;
import ec.app.semanticGP.func.logic.False;
import ec.app.semanticGP.func.logic.Or;
import ec.gp.semantic.ISemantics;
import ec.gp.semantic.func.SimpleNodeBase;
import ec.gp.semantic.utils.InstructionJoiner;
import ec.util.Parameter;
import library.semantics.BitSet;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Tomasz Pawlak
 */
public class BooleanBasisProcessor implements IBasisProcessor {

	private EvolutionState state;

	public void setup(EvolutionState state, Parameter base) {
		this.state = state;
	}

	@Override
	public SimpleNodeBase<?> makeLinearCombination(ISemantics target, List<SimpleNodeBase<?>> basis) {
		BitSet t = (BitSet) target.getValue();

		List<SimpleNodeBase<?>> toJoin = new ArrayList<SimpleNodeBase<?>>();

		for (int i = 0; i < t.length(); ++i) {
			Boolean b = t.get(i);
			if (b) {
				SimpleNodeBase<Boolean> p = (SimpleNodeBase<Boolean>) basis.get(i);
				ISemantics ps = p.getSemantics();
				assert (Boolean) ps.getValue(i);

				toJoin.add(p);
			}
		}

		if (toJoin.size() == 0) {
			return new False();
		} else {
			return InstructionJoiner.join(toJoin, Or.class, 2);
		}
	}

	@Override
	public Matrix getMatrix(List<SimpleNodeBase<?>> programs) {
		int rows = programs.get(0).getSemantics().size();
		int cols = programs.size();
		double[] semantics;

		Matrix A = new Matrix(rows, cols);
		for (int p = 0; p < programs.size(); ++p) {
			semantics = this.toDouble((BitSet) programs.get(p).getSemantics().getValue());

			for (int row = 0; row < semantics.length; ++row) {
				A.set(row, p, semantics[row]);
			}
		}
		return A;
	}

	@Override
	public void extractBasis(List<SimpleNodeBase<?>> programs) {
		//empty
	}

	@Override
	public boolean isInFeasibleRange(ISemantics semantics) {
		return true;
	}

	private double[] toDouble(BitSet bitSet) {
		double[] doubles = new double[bitSet.length()];
		for (int i = 0; i < doubles.length; ++i) {
			doubles[i] = bitSet.get(i) ? 1.0 : 0.0;
		}
		return doubles;
	}

}
