package inference.axioms;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import exceptions.SubstituteFailedException;
import inference.EquationAxiom;
import models.Position;
import models.algebra.Variable;
import models.formulas.Formula;
import models.formulas.meta.MetaDependencyFormula;
import models.formulas.meta.MetaEquationFormula;
import models.terms.EvaluatableTerm;
import models.terms.meta.MatchConstraint;
import models.terms.meta.MetaDynamicDependency;
import models.terms.meta.MetaDynamicDependencyTerm;
import models.terms.meta.MetaEvaluatableTermVariable;
import models.terms.meta.MetaRDLTerm;
import models.terms.meta.MetaTermGenerator;
import utils.ExpressionUtils;
public class Uncurrying extends EquationAxiom {
public Uncurrying() {
super("Uncurrying");
assumptions.add(new MetaDependencyFormula(
new MetaDynamicDependency(
new MetaTermGenerator() {
@Override
public MetaRDLTerm generate(int curIndex, int curDepth, int maxIndex, int maxDepth, Map<Object, Object> context) {
context.put("" + curDepth, maxIndex + 1);
context.put("i", Math.max(maxDepth - curDepth, (Integer) context.getOrDefault("i", 0)));
if (curDepth == maxDepth && curIndex == 0) {
return new MetaEvaluatableTermVariable(new Variable("se"), new Variable("n"));
} else if (curDepth == maxDepth && curIndex == 1) {
return new MetaEvaluatableTermVariable(new Variable("te"), new Variable("n"));
} else if (curIndex == 0) {
return new MetaDynamicDependency(this);
}
return new MetaEvaluatableTermVariable(new Variable("te" + curDepth + "_" + curIndex), ExpressionUtils.parse("n-" + (maxDepth - curDepth)));
}
}
)
));
conclusion = new MetaEquationFormula(
new MetaDynamicDependencyTerm(
new MetaTermGenerator() {
@Override
public MetaRDLTerm generate(int curIndex, int curDepth, int maxIndex, int maxDepth, Map<Object, Object> context) {
// maxIndex = (Integer) context.get(""+curDepth);
int i = (Integer) context.get("i");
if (curDepth == maxDepth) {
if (curIndex == 0) {
return new MetaEvaluatableTermVariable(new Variable("se"), new Variable("n"));
} else if (curIndex == 1) {
return new MetaEvaluatableTermVariable(new Variable("te"), new Variable("n"));
} else if (curIndex == 2) {
return new MetaEvaluatableTermVariable(new Variable("ve"), ExpressionUtils.parse("n-" + i));
}
} else if (curIndex == 0) {
return new MetaDynamicDependencyTerm(this);
}
if (i == maxDepth - curDepth && curIndex == maxIndex - 2) {
return new MetaEvaluatableTermVariable(new Variable("ve"), ExpressionUtils.parse("n-" + i));
} else if (i == maxDepth - curDepth && curIndex == maxIndex - 1) {
return new MetaEvaluatableTermVariable(new Variable("we"));
}
curIndex -= 1;
if (curIndex % 2 == 0) {
return new MetaEvaluatableTermVariable(new Variable("te" + curDepth + "_" + curIndex / 2), ExpressionUtils.parse("n-" + (maxDepth - curDepth)));
}
return new MetaEvaluatableTermVariable(new Variable("ue" + curDepth + "_" + curIndex / 2));
}
}
),
new MetaDynamicDependencyTerm(
new MetaTermGenerator() {
@Override
public MetaRDLTerm generate(int curIndex, int curDepth, int maxIndex, int maxDepth, Map<Object, Object> context) {
// maxIndex = (Integer) context.get(""+curDepth);
if (curDepth == maxDepth) {
if (curIndex == 0) {
return new MetaEvaluatableTermVariable(new Variable("se"), new Variable("n"));
} else if (curIndex == 1) {
return new MetaEvaluatableTermVariable(new Variable("te"), new Variable("n"));
} else if (curIndex == 2) {
return new MetaEvaluatableTermVariable(new Variable("we"));
}
} else if (curIndex == 0) {
return new MetaDynamicDependencyTerm(this);
}
curIndex -= 1;
if (curIndex >= maxIndex) {
return null;
}
if (curIndex % 2 == 0) {
return new MetaEvaluatableTermVariable(new Variable("te" + curDepth + "_" + curIndex / 2), ExpressionUtils.parse("n-" + (maxDepth - curDepth)));
}
return new MetaEvaluatableTermVariable(new Variable("ue" + curDepth + "_" + curIndex / 2));
}
}
)
);
}
@Override
public Set<EvaluatableTerm> apply(List<Formula> assumptions, EvaluatableTerm term, MatchConstraint constraint) {
Set<EvaluatableTerm> result = new HashSet<>();
if (assumptions.size() < this.assumptions.size()) {
return new HashSet<>();
}
Set<MatchConstraint> matchResult = assumptionMatch(assumptions, constraint);
Set<MatchConstraint> conclusionLeftMatchResult = conclusionLeftSideHandMatch(term, matchResult);
for (MatchConstraint leftConst: conclusionLeftMatchResult) {
leftConst.getContext().put("isLeft", true);
}
Set<MatchConstraint> conclusionRightMatchResult = conclusionRightSideHandMatch(term, matchResult);
for (MatchConstraint rightConst: conclusionRightMatchResult) {
rightConst.getContext().put("isLeft", false);
}
Set<MatchConstraint> conclusionMatchResult = new HashSet<>();
conclusionMatchResult.addAll(conclusionLeftMatchResult);
conclusionMatchResult.addAll(conclusionRightMatchResult);
MetaEquationFormula metaConclusion = (MetaEquationFormula) this.conclusion;
for (MatchConstraint matchRes: conclusionMatchResult) {
boolean isLeft =(Boolean) matchRes.getContext().get("isLeft");
if (defaultOrderConstraint != null && ! defaultOrderConstraint.check(matchRes.getOrderConstraint())) {
continue;
}
try {
if (isLeft) {
matchRes.getContext().put(new Position(), (Integer) matchRes.getContext().get(new Position()) - 2);
result.add((EvaluatableTerm)((MetaRDLTerm) metaConclusion.getRightSideHand()).substitute(matchRes.getBinding(), matchRes.getContext()));
} else {
matchRes.getContext().put(new Position(), (Integer) matchRes.getContext().get(new Position()) + 2);
result.add((EvaluatableTerm)((MetaRDLTerm) metaConclusion.getLeftSideHand()).substitute(matchRes.getBinding(), matchRes.getContext()));
}
} catch (SubstituteFailedException e) {
continue;
}
}
return result;
}
}