package ec.gp.syntactic.equivalence;

import org.matheclipse.core.eval.EvalUtilities;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IExpr;

import ec.gp.semantic.func.SimpleNodeBase;

public class DoubleEquivalenceChecker implements IEquivalenceChecker {

	private EvalUtilities symja;

	public DoubleEquivalenceChecker() {
		// init symja
		F.initSymbols();
		this.symja = new EvalUtilities();
	}

	@Override
	public boolean areEquivalent(SimpleNodeBase<?> program1, SimpleNodeBase<?> program2) {
		return this.areEquivalent(program1.makeCTree(true, true, true), program2.makeCTree(true, true, true));
	}

	public boolean areEquivalent(String program1, String program2)
	{
		return this.areEquivalent(program1, this.getInternalRepresentation(program2));
	}

	public boolean areEquivalent(String program1, Object program2)
	{
		IExpr p1e = (IExpr) this.getInternalRepresentation(program1);
		IExpr p2e = (IExpr) program2;

		assert p1e.isSame(p2e) == p1e.toString().equals(p2e.toString());
		assert p1e.isSame(p2e) == (p1e.compareTo(p2e) == 0);

		return p1e.isSame(p2e);
	}

	public Object getInternalRepresentation(String program)
	{
		try {
			return this.symja.evaluate("FullSimplify[" + program + "]");
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}
}
