package ec.gp.semantic.geometry;

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

public class BooleanGeometryProvider implements IGeometryProvider {

    @Override
    public GPNode combine(EvolutionState state, GPNode parent1, GPNode parent2, GPNode randomTree) {
        // the operation comes from Geometric Semantic Genetic Programming, by Moraglio, Krawiec and Johnson

		/*And and1 = new And();
        and1.children = new GPNode[] { parent1, randomTree };

		Inv inv = new Inv();
		inv.children = new GPNode[] { (GPNode) randomTree.clone() };

		And and2 = new And();
		and2.children = new GPNode[] { inv, parent2 };

		Or or = new Or();
		or.children = new GPNode[] { and1, and2 };

		return or;*/

        return new Combiner(state, (SimpleNodeBase<Boolean>) parent1, (SimpleNodeBase<Boolean>) parent2,
                (SimpleNodeBase<Boolean>) randomTree);

        //return new Averager((SimpleNodeBase<Boolean>)parent1, (SimpleNodeBase<Boolean>)parent2, constant);
        //return new AveragerSlim(state, (SimpleNodeBase<Boolean>) parent1, (SimpleNodeBase<Boolean>) parent2, constant);
    }

    @Override
    public GPNode combine(EvolutionState state, GPNode[] parents, GPNode[] randomTrees) {
        return new Combiner(state, (SimpleNodeBase[]) parents, (SimpleNodeBase[]) randomTrees);
    }

    @Override
    public GPNode differencingCombine(EvolutionState state, GPNode parent, GPNode random1, GPNode random2) {

        GPNode transformed;
        if (state.random[0].nextBoolean()) {
            Inv inv = new Inv();
            inv.children = new GPNode[]{random1};
            transformed = new And();
            transformed.children = new GPNode[]{parent, inv};
        } else {
            transformed = new Or();
            transformed.children = new GPNode[]{parent, random1};
        }

        return transformed;
    }
}
