package ec.app.semanticGP.func.numeric;

import ec.*;
import ec.app.semanticGP.func.*;
import ec.gp.semantic.*;
import ec.gp.semantic.evaluation.*;
import ec.gp.semantic.func.*;

public class Combiner extends CombinerBase<Double> {

	public Combiner(EvolutionState state, SimpleNodeBase<Double> parent1, SimpleNodeBase<Double> parent2,
					SimpleNodeBase<Double> randomTree) {
		super(state, parent1, parent2, randomTree);
	}

	public Combiner(EvolutionState state, SimpleNodeBase[] parents, SimpleNodeBase[] randomTrees) {
		super(state, parents, randomTrees);
	}

	@Override
	public ISemantics getSemantics() {
		EvaluationMode mode = EvaluationMode.TrainingSet;
		if (this.state.evaluator.p_problem instanceof IChangeableEvaluationMode) {
			((IChangeableEvaluationMode) this.state.evaluator.p_problem).getEvaluationMode();
		}

		ISemantics semantics = this.semantics.get(mode);
		if (semantics == null) {
			double[][] p = new double[this.firstRandomTree][];
			double[][] r = new double[this.children.length - this.firstRandomTree][];
			for (int i = 0; i < this.firstRandomTree; ++i) {
				p[i] = (double[]) ((SimpleNodeBase<?>) this.children[i]).getSemantics().getValue();
			}

			for (int i = this.firstRandomTree; i < this.children.length; ++i) {
				r[i - this.firstRandomTree] = (double[]) ((SimpleNodeBase<?>) this.children[i]).getSemantics().getValue();
			}

			int maxMask = 1 << r.length;
			double[] mySem = new double[p[0].length];

			/// mask%parents.length == number of current parent
			for (int mask = 0; mask < maxMask; ++mask) {
				for (int i = 0; i < mySem.length; ++i) {

					double mult = 1.0;
					for (int b = 0; b < r.length; ++b) {
						mult *= (((mask >>> b) & 1) == 1 ? r[b][i] : (1.0 - r[b][i]));
					}

					mySem[i] += p[mask % p.length][i] * mult;
				}
			}

			semantics = new DoubleSemantics(mySem);
			this.semantics.put(mode, semantics);
		}

		return semantics;
	}

}
