use of com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver in project aic-expresso by aic-sri-international.
the class RecursiveTest method testConditionalRecursiveRewriter.
@Test
public void testConditionalRecursiveRewriter() {
Expression xIs0 = parse("XIs0");
RewriterFromStepMaker rewriter = (Expression e, Context c) -> {
if (Expressions.isNumber(e)) {
return new Solution(DefaultSymbol.createSymbol(e.intValue() + 1));
} else if (e.equals(parse("X"))) {
ContextSplitting splitting = new ContextSplitting(xIs0, c);
switch(splitting.getResult()) {
case LITERAL_IS_TRUE:
return new Solution(ZERO);
case LITERAL_IS_FALSE:
return new Solution(ONE);
case LITERAL_IS_UNDEFINED:
return new ItDependsOn(xIs0, splitting, new ConstantExpressionStepSolver(ZERO), new ConstantExpressionStepSolver(ONE));
default:
throw new Error("Unpredicted case.");
}
}
return new Solution(e);
};
Expression initial;
Expression expected;
initial = parse("X");
expected = parse("if " + xIs0 + " then 0 else 1");
runTest(rewriter, initial, expected, map(xIs0, parse("Boolean")));
initial = parse("f(9,g(X,7,6))");
expected = parse("if " + xIs0 + " then f(10,g(0,8,7)) else f(10,g(1,8,7))");
runTest(rewriter, initial, expected, map(xIs0, parse("Boolean")));
initial = parse("X(9,g(h(1,2,X),X,7,6))");
expected = parse("if " + xIs0 + " then 0(10,g(h(2,3,0),0,8,7)) else 1(10,g(h(2,3,1),1,8,7))");
runTest(rewriter, initial, expected, map(xIs0, parse("Boolean")));
}
use of com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver in project aic-expresso by aic-sri-international.
the class AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver method getSolutionStepAfterBoundsAreCheckedForFeasibility.
@Override
protected Step getSolutionStepAfterBoundsAreCheckedForFeasibility(Expression maximumLowerBound, Expression minimumUpperBound, AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver sequelBaseAsNumericStepSolver, Context context) {
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver sequelBase = (AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver) sequelBaseAsNumericStepSolver;
StepSolver<List<Expression>> disequalsGreaterThanMaximumLowerBoundStepSolver;
if (initialDisequalsGreaterThanMaximumLowerBoundStepSolver == null) {
disequalsGreaterThanMaximumLowerBoundStepSolver = new SelectExpressionsSatisfyingComparisonStepSolver(getDisequals(), GREATER_THAN, // relies on this class's enforcing of all lower bounds being strict
maximumLowerBound);
} else {
disequalsGreaterThanMaximumLowerBoundStepSolver = initialDisequalsGreaterThanMaximumLowerBoundStepSolver;
}
StepSolver.Step<List<Expression>> disequalsGreaterThanGreatestStrictLowerBoundStep = disequalsGreaterThanMaximumLowerBoundStepSolver.step(context);
if (disequalsGreaterThanGreatestStrictLowerBoundStep.itDepends()) {
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifTrue = makeSequelStepSolver(sequelBase);
ifTrue.initialDisequalsGreaterThanMaximumLowerBoundStepSolver = disequalsGreaterThanGreatestStrictLowerBoundStep.getStepSolverForWhenSplitterIs(true);
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialDisequalsGreaterThanMaximumLowerBoundStepSolver = disequalsGreaterThanGreatestStrictLowerBoundStep.getStepSolverForWhenSplitterIs(false);
ItDependsOn result = new ItDependsOn(disequalsGreaterThanGreatestStrictLowerBoundStep.getSplitter(), disequalsGreaterThanGreatestStrictLowerBoundStep.getContextSplittingWhenSplitterIsLiteral(), ifTrue, ifFalse);
return result;
}
List<Expression> disequalsGreaterThanGreatestStrictLowerBound = disequalsGreaterThanGreatestStrictLowerBoundStep.getValue();
sequelBase.initialDisequalsGreaterThanMaximumLowerBoundStepSolver = new ConstantStepSolver<List<Expression>>(disequalsGreaterThanGreatestStrictLowerBound);
StepSolver<List<Expression>> disequalsWithinBoundsStepSolver;
if (initialDisequalsWithinBoundsStepSolver == null) {
disequalsWithinBoundsStepSolver = new SelectExpressionsSatisfyingComparisonStepSolver(disequalsGreaterThanGreatestStrictLowerBound, LESS_THAN_OR_EQUAL_TO, // relies on this class's enforcing of all upper bounds being non-strict
minimumUpperBound);
} else {
disequalsWithinBoundsStepSolver = initialDisequalsWithinBoundsStepSolver;
}
StepSolver.Step<List<Expression>> disequalsWithinBoundsStep = disequalsWithinBoundsStepSolver.step(context);
if (disequalsWithinBoundsStep.itDepends()) {
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifTrue = makeSequelStepSolver(sequelBase);
ifTrue.initialDisequalsWithinBoundsStepSolver = disequalsWithinBoundsStep.getStepSolverForWhenSplitterIs(true);
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialDisequalsWithinBoundsStepSolver = disequalsWithinBoundsStep.getStepSolverForWhenSplitterIs(false);
ItDependsOn result = new ItDependsOn(disequalsWithinBoundsStep.getSplitter(), disequalsWithinBoundsStep.getContextSplittingWhenSplitterIsLiteral(), ifTrue, ifFalse);
return result;
}
ArrayList<Expression> disequalsWithinBounds = new ArrayList<>(disequalsWithinBoundsStep.getValue());
sequelBase.initialDisequalsWithinBoundsStepSolver = new ConstantStepSolver<List<Expression>>(disequalsWithinBounds);
Expression boundsDifference = applyAndSimplify(MINUS, arrayList(minimumUpperBound, maximumLowerBound), context);
// the goal of the upcoming 'if' is to define the values for these two next declared variables:
boolean weKnowThatNumberOfDistinctDisequalsExceedsNumberOfValuesWithinBounds;
// if true, number of distinct disequals exceeds number of values within bounds;
// if false, that may be true or false, we don't know.
DistinctExpressionsStepSolver distinctExpressionsStepSolver;
if (isNumber(boundsDifference)) {
ExpressionLiteralSplitterStepSolver numberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver;
if (initialNumberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver == null) {
numberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver = new NumberOfDistinctExpressionsIsLessThanStepSolver(boundsDifference.intValue(), disequalsWithinBounds);
} else {
numberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver = initialNumberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver;
}
ExpressionLiteralSplitterStepSolver.Step numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep = numberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver.step(context);
if (numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep.itDepends()) {
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifTrue = makeSequelStepSolver(sequelBase);
ifTrue.initialNumberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver = numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep.getStepSolverForWhenSplitterIs(true);
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialNumberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver = numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep.getStepSolverForWhenSplitterIs(false);
ItDependsOn result = new ItDependsOn(numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep.getSplitterLiteral(), numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep.getContextSplittingWhenSplitterIsLiteral(), ifTrue, ifFalse);
return result;
}
Expression numberOfDistinctDisequalsIsLessThanBoundsDifference = numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep.getValue();
sequelBase.initialNumberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver = new ConstantExpressionStepSolver(numberOfDistinctDisequalsIsLessThanBoundsDifference);
weKnowThatNumberOfDistinctDisequalsExceedsNumberOfValuesWithinBounds = numberOfDistinctDisequalsIsLessThanBoundsDifference.equals(FALSE);
if (initialDistinctDisequalsStepSolver == null) {
// if initialDistinctDisequalsStepSolver has not been set yet, it is because the predecessor of this step solver did not get to the point of using distinctExpressionsStepSolver; this means numberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver is not a ConstantExpressionStepSolver (if it were, then the predecessor would have proceeded to use distinctExpressionsStepSolver), so it must be a NumberOfDistinctExpressionsIsLessThanStepSolver.
distinctExpressionsStepSolver = ((NumberOfDistinctExpressionsIsLessThanStepSolver) numberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver).getDistinctExpressionsStepSolver();
} else {
distinctExpressionsStepSolver = initialDistinctDisequalsStepSolver;
}
} else {
weKnowThatNumberOfDistinctDisequalsExceedsNumberOfValuesWithinBounds = false;
if (initialDistinctDisequalsStepSolver == null) {
distinctExpressionsStepSolver = new DistinctExpressionsStepSolver(disequalsWithinBounds);
} else {
distinctExpressionsStepSolver = initialDistinctDisequalsStepSolver;
}
}
Expression solutionExpression;
if (weKnowThatNumberOfDistinctDisequalsExceedsNumberOfValuesWithinBounds) {
// there are no available values left
solutionExpression = getSolutionExpressionGivenContradiction();
} else if (!getEquals().isEmpty()) {
// if bound to a value
solutionExpression = getSolutionExpressionForBoundVariable();
} else {
Step distinctDisequalsStep = distinctExpressionsStepSolver.step(context);
if (distinctDisequalsStep.itDepends()) {
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifTrue = makeSequelStepSolver(sequelBase);
ifTrue.initialDistinctDisequalsStepSolver = (DistinctExpressionsStepSolver) distinctDisequalsStep.getStepSolverForWhenSplitterIs(true);
AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialDistinctDisequalsStepSolver = (DistinctExpressionsStepSolver) distinctDisequalsStep.getStepSolverForWhenSplitterIs(false);
ItDependsOn result = new ItDependsOn(distinctDisequalsStep.getSplitterLiteral(), distinctDisequalsStep.getContextSplittingWhenSplitterIsLiteral(), ifTrue, ifFalse);
return result;
}
Expression distinctDisequalsExtensionalUniSet = distinctDisequalsStep.getValue();
solutionExpression = getSolutionExpressionGivenBoundsAndDistinctDisequals(maximumLowerBound, minimumUpperBound, boundsDifference, distinctDisequalsExtensionalUniSet, context);
}
return new Solution(solutionExpression);
}
use of com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver in project aic-expresso by aic-sri-international.
the class BruteForceFunctionTheory method getSingleQuantifierEliminatorStepSolver.
@Override
public ExpressionLiteralSplitterStepSolver getSingleQuantifierEliminatorStepSolver(SingleQuantifierEliminationProblem problem, Context context) {
Expression variable = problem.getIndex();
Expression type = GrinderUtil.getTypeExpressionOfExpression(variable, context);
Expression indexExpression = IndexExpressions.makeIndexExpression(variable, type);
ExtensionalIndexExpressionsSet indexExpressionsSet = new ExtensionalIndexExpressionsSet(indexExpression);
MultiQuantifierEliminator quantifierEliminator = new BruteForceMultiQuantifierEliminator(context.getTheory().getTopRewriter());
// TODO: return conditional steps on literals on free variables.
// We are solving it straight here because there are no literals in this theory,
// however a more sophisticated solution would return conditional steps on literals on free variables.
Expression solution = quantifierEliminator.extendContextAndSolve(problem.getGroup(), indexExpressionsSet, problem.getConstraint(), problem.getBody(), context);
return new ConstantExpressionStepSolver(solution);
}
use of com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver in project aic-expresso by aic-sri-international.
the class AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver method solutionIfPropagatedLiteralsAndSplittersCNFAreSatisfied.
@Override
protected Step solutionIfPropagatedLiteralsAndSplittersCNFAreSatisfied(Context context) {
Expression solutionExpression;
// sequelBase keeps track of updates to non-splitting sub-step solvers so far.
// When a splitting sub-step solver is found, it is used as a basis
// for the sequel step solvers.
// The reason we keep this clone, that is itself cloned later,
// as opposed to updating and cloning "this" every time,
// is that step solvers must not be modified by their method "step",
// unless they are caching context-independent information.
// sequelBase serves as a blackboard for all the updates learned while executing this method,
// which then don't need to be kept by "this".
// These updates are then cloned into the sequel step solvers.
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver sequelBase = clone();
if (getConstraint().getPropagateAllLiteralsWhenVariableIsBound() && !getEquals().isEmpty()) {
solutionExpression = getSolutionExpressionForBoundVariable();
} else {
ExpressionLiteralSplitterStepSolver maximumLowerBoundStepSolver;
if (initialMaximumLowerBoundStepSolver == null) {
maximumLowerBoundStepSolver = new MaximumExpressionStepSolver(getLowerBoundsIncludingImplicitOnes(context), // use total order <
LESS_THAN_SYMBOL, MINUS_INFINITY, // at first, I placed the type minimum and maximum strict lower bounds here. This is incorrect because if the type maximum is, say, 4, and I have "X > 3 and X > I" (3 is the maximum strict lower bounds for values in the type), the step solver short-circuits and returns 3, without ever even looking at I. Looking at I is needed because if I is greater than 3 than this constraint is unsatisfiable.
INFINITY);
} else {
maximumLowerBoundStepSolver = initialMaximumLowerBoundStepSolver;
}
ExpressionLiteralSplitterStepSolver.Step maximumLowerBoundStep = maximumLowerBoundStepSolver.step(context);
if (maximumLowerBoundStep.itDepends()) {
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifTrue = makeSequelStepSolver(sequelBase);
ifTrue.initialMaximumLowerBoundStepSolver = maximumLowerBoundStep.getStepSolverForWhenSplitterIs(true);
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialMaximumLowerBoundStepSolver = maximumLowerBoundStep.getStepSolverForWhenSplitterIs(false);
ItDependsOn result = new ItDependsOn(maximumLowerBoundStep.getSplitterLiteral(), maximumLowerBoundStep.getContextSplittingWhenSplitterIsLiteral(), ifTrue, ifFalse);
return result;
}
Expression maximumLowerBound = maximumLowerBoundStep.getValue();
sequelBase.initialMaximumLowerBoundStepSolver = new ConstantExpressionStepSolver(maximumLowerBound);
ExpressionLiteralSplitterStepSolver minimumUpperBoundStepSolver;
if (initialMinimumUpperBoundStepSolver == null) {
minimumUpperBoundStepSolver = new MaximumExpressionStepSolver(getUpperBoundsIncludingImplicitOnes(context), // use total order > since "minimum" is maximum under it
GREATER_THAN_SYMBOL, // "minimum" is maximum value because we are operating on the inverse order
INFINITY, // "maximum" is minimum value because we are operating on the inverse order
MINUS_INFINITY);
} else {
minimumUpperBoundStepSolver = initialMinimumUpperBoundStepSolver;
}
ExpressionLiteralSplitterStepSolver.Step minimumUpperBoundStep = minimumUpperBoundStepSolver.step(context);
if (minimumUpperBoundStep.itDepends()) {
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifTrue = makeSequelStepSolver(sequelBase);
ifTrue.initialMinimumUpperBoundStepSolver = minimumUpperBoundStep.getStepSolverForWhenSplitterIs(true);
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialMinimumUpperBoundStepSolver = minimumUpperBoundStep.getStepSolverForWhenSplitterIs(false);
ItDependsOn result = new ItDependsOn(minimumUpperBoundStep.getSplitterLiteral(), minimumUpperBoundStep.getContextSplittingWhenSplitterIsLiteral(), ifTrue, ifFalse);
return result;
}
Expression minimumUpperBound = minimumUpperBoundStep.getValue();
sequelBase.initialMinimumUpperBoundStepSolver = new ConstantExpressionStepSolver(minimumUpperBound);
if (unboundedVariableProducesShortCircuitSolution() && (maximumLowerBound.equals(MINUS_INFINITY) || minimumUpperBound.equals(INFINITY))) {
solutionExpression = getSolutionExpressionForUnboundedVariables();
} else {
StepSolver<Boolean> boundedSpaceIsNotEmptyStepSolver;
if (initialBoundedSpaceIsNotEmptyStepSolver == null) {
Expression boundedSpaceIsNotEmpty = makeLiteralCheckingWhetherThereAreAnyValuesWithinBounds(maximumLowerBound, minimumUpperBound, context);
boundedSpaceIsNotEmptyStepSolver = new LiteralStepSolver(boundedSpaceIsNotEmpty);
} else {
boundedSpaceIsNotEmptyStepSolver = initialBoundedSpaceIsNotEmptyStepSolver;
}
StepSolver.Step<Boolean> lowerBoundIsLessThanUpperBoundStep = boundedSpaceIsNotEmptyStepSolver.step(context);
if (lowerBoundIsLessThanUpperBoundStep.itDepends()) {
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifTrue = makeSequelStepSolver(sequelBase);
ifTrue.initialBoundedSpaceIsNotEmptyStepSolver = lowerBoundIsLessThanUpperBoundStep.getStepSolverForWhenSplitterIs(true);
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialBoundedSpaceIsNotEmptyStepSolver = lowerBoundIsLessThanUpperBoundStep.getStepSolverForWhenSplitterIs(false);
ItDependsOn result = new ItDependsOn(lowerBoundIsLessThanUpperBoundStep.getSplitter(), lowerBoundIsLessThanUpperBoundStep.getContextSplittingWhenSplitterIsLiteral(), ifTrue, ifFalse);
return result;
}
if (!lowerBoundIsLessThanUpperBoundStep.getValue()) {
return new Solution(getSolutionExpressionGivenContradiction());
}
// else, bounds difference is positive and we can move on
sequelBase.initialBoundedSpaceIsNotEmptyStepSolver = new ConstantStepSolver<Boolean>(true);
Step result = getSolutionStepAfterBoundsAreCheckedForFeasibility(maximumLowerBound, minimumUpperBound, sequelBase, context);
return result;
}
}
return new Solution(solutionExpression);
}
use of com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver in project aic-expresso by aic-sri-international.
the class Switch method makeStepSolver.
@Override
public ExpressionLiteralSplitterStepSolver makeStepSolver(Expression expression) {
ExpressionLiteralSplitterStepSolver result;
T key = keyMaker.apply(expression);
Rewriter baseRewriter = fromKeyValueToRewriter.get(key);
if (baseRewriter != null) {
result = baseRewriter.makeStepSolver(expression);
} else {
result = new ConstantExpressionStepSolver(expression);
}
return result;
}
Aggregations