package ec.gp.semantic.geometry;

import ec.EvolutionState;
import ec.app.semanticGP.func.classification.An;
import ec.app.semanticGP.func.classification.Cn;
import ec.app.semanticGP.func.classification.Eq;
import ec.app.semanticGP.func.classification.If;
import ec.app.semanticGP.func.logic.And;
import ec.app.semanticGP.func.numeric.Constant;
import ec.app.semanticGP.func.numeric.Xn;
import ec.app.semanticGP.func.numeric.Zero;
import ec.gp.*;
import ec.gp.semantic.ISemanticProblem;
import ec.gp.semantic.func.SimpleNodeBase;
import ec.gp.semantic.utils.InstructionJoiner;
import ec.util.Parameter;
import library.semantics.TestCase;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * Creates Classifier programs, which semantics are guaranteed to constitute a basis.
 *
 * @author Tomasz Pawlak
 */
public class ClassifierBasisConstructor extends GPNodeBuilder {
	private final static Parameter DEFAULT_BASE = new Parameter("LC");

	private final ClassifierInterpolator interpolator = new ClassifierInterpolator();
	private Queue<SimpleNodeBase<?>> programs = new LinkedList<SimpleNodeBase<?>>();

	@Override
	public Parameter defaultBase() {
		return DEFAULT_BASE;
	}

	@Override
	public GPNode newRootedTree(EvolutionState state, GPType type, int thread, GPNodeParent parent, GPFunctionSet set, int argposition, int requestedSize) {
		if (this.programs.size() > 0) {
			return this.programs.poll();
		}

		// build base here
		ISemanticProblem<Byte> problem = (ISemanticProblem<Byte>) state.evaluator.p_problem;
		List<TestCase<Byte>> fitnessCases = problem.getFitnessCases();
		this.programs.addAll(this.interpolator.getBasePrograms(state, fitnessCases));

		return this.programs.poll();
	}

}
