use of com.sri.ai.grinder.sgdpllt.api.ExpressionLiteralSplitterStepSolver in project aic-expresso by aic-sri-international.
the class AbstractTheory method makeEvaluatorStepSolver.
@Override
public ExpressionLiteralSplitterStepSolver makeEvaluatorStepSolver(Expression expression) {
Rewriter literalExternalizer = new LiteralRewriter(new Recursive(new Exhaustive(getTopRewriter())));
Recursive completeEvaluator = new Recursive(new Exhaustive(new FirstOf(getTopRewriter(), literalExternalizer)));
// it is a good idea to leave the literal externalizer at the end,
// since it is expensive due to duplicating the entire problem at every split
ExpressionLiteralSplitterStepSolver result = completeEvaluator.makeStepSolver(expression);
return result;
}
use of com.sri.ai.grinder.sgdpllt.api.ExpressionLiteralSplitterStepSolver in project aic-expresso by aic-sri-international.
the class AbstractQuantifierEliminationStepSolver method step.
@Override
public Step step(Context context) {
Step result;
Context contextForBody = getContextForBody(context);
if (contextForBody.isContradiction()) {
result = new Solution(group.additiveIdentityElement());
} else {
ExpressionLiteralSplitterStepSolver bodyStepSolver = getInitialBodyStepSolver(context.getTheory());
ExpressionLiteralSplitterStepSolver.Step bodyStep = bodyStepSolver.step(contextForBody);
// Check (**) in this file to see where this happens
if (!bodyStep.itDepends()) {
ExpressionLiteralSplitterStepSolver evaluatorStepSolver = getTheory().makeEvaluatorStepSolver(bodyStep.getValue());
bodyStep = evaluatorStepSolver.step(context);
}
if (bodyStep.itDepends()) {
// "intercept" literals containing the index and split the quantifier based on it
if (isSubExpressionOf(getIndex(), bodyStep.getSplitterLiteral())) {
Expression literalOnIndex = bodyStep.getSplitterLiteral();
result = resultIfLiteralContainsIndex(literalOnIndex, bodyStep, contextForBody, context);
} else {
// not on index, just pass the expression on which we depend on, but with appropriate sub-step solvers (this, for now)
AbstractQuantifierEliminationStepSolver ifTrue = clone();
AbstractQuantifierEliminationStepSolver ifFalse = clone();
ifTrue.initialBodyEvaluationStepSolver = bodyStep.getStepSolverForWhenSplitterIsTrue();
ifFalse.initialBodyEvaluationStepSolver = bodyStep.getStepSolverForWhenSplitterIsFalse();
ifTrue.initialContextForBody = bodyStep.getContextSplittingWhenSplitterIsLiteral().getContextAndLiteral();
ifFalse.initialContextForBody = bodyStep.getContextSplittingWhenSplitterIsLiteral().getContextAndLiteralNegation();
// to compute the result's constraint splitting,
// we cannot directly re-use bodyStep.getConstraintSplitting() because it was not obtained from
// the context it is returning to,
// but from the context conjoined with the index constraint.
// In order to provide two contexts to work with the sequel step solvers,
// we calculate the splittings here.
// TODO: In the future, we expect it possible to efficiently extract the contextForBody component relative
// to the original context only, excluding the index.
ContextSplitting split = new ContextSplitting(bodyStep.getSplitterLiteral(), context);
result = new ItDependsOn(bodyStep.getSplitterLiteral(), split, ifTrue, ifFalse);
}
} else {
// body is already literal free
result = eliminateQuantifierForLiteralFreeBodyAndSingleVariableConstraint(indexConstraint, bodyStep.getValue(), context);
}
}
return result;
}
use of com.sri.ai.grinder.sgdpllt.api.ExpressionLiteralSplitterStepSolver in project aic-expresso by aic-sri-international.
the class ContextDependentExpressionProblemSolver method solve.
/**
* Returns the solution for a problem using a step solver.
* @param stepSolver
* @param context
* @return
*/
public Expression solve(ExpressionLiteralSplitterStepSolver stepSolver, Context context) {
if (interrupted) {
throw new Error("Solver interrupted.");
}
Expression result;
ExpressionLiteralSplitterStepSolver.Step step = stepSolver.step(context);
if (step.itDepends()) {
Expression splitter = step.getSplitter();
ContextSplitting split = (ContextSplitting) step.getContextSplittingWhenSplitterIsLiteral();
myAssert(() -> split.isUndefined(), () -> "Undefined " + ContextSplitting.class + " result value: " + split.getResult());
Expression subSolution1 = solve(step.getStepSolverForWhenSplitterIsTrue(), split.getConstraintAndLiteral());
Expression subSolution2 = solve(step.getStepSolverForWhenSplitterIsFalse(), split.getConstraintAndLiteralNegation());
result = IfThenElse.make(splitter, subSolution1, subSolution2, true);
} else {
result = step.getValue();
}
return result;
}
use of com.sri.ai.grinder.sgdpllt.api.ExpressionLiteralSplitterStepSolver 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.getStepSolverForWhenSplitterIsTrue();
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialMaximumLowerBoundStepSolver = maximumLowerBoundStep.getStepSolverForWhenSplitterIsFalse();
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.getStepSolverForWhenSplitterIsTrue();
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialMinimumUpperBoundStepSolver = minimumUpperBoundStep.getStepSolverForWhenSplitterIsFalse();
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.getStepSolverForWhenSplitterIsTrue();
AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
ifFalse.initialBoundedSpaceIsNotEmptyStepSolver = lowerBoundIsLessThanUpperBoundStep.getStepSolverForWhenSplitterIsFalse();
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.sgdpllt.api.ExpressionLiteralSplitterStepSolver in project aic-expresso by aic-sri-international.
the class PropositionalTheory method getSingleVariableConstraintQuantifierEliminatorStepSolver.
@Override
public ExpressionLiteralSplitterStepSolver getSingleVariableConstraintQuantifierEliminatorStepSolver(AssociativeCommutativeGroup group, SingleVariableConstraint constraintForThisIndex, Expression body, Context context) {
ExpressionStepSolver formulaSplitterStepSolver = new QuantifierEliminationOnBodyInWhichIndexOnlyOccursInsideLiteralsStepSolver(group, constraintForThisIndex, body);
ExpressionLiteralSplitterStepSolver result = new ExpressionStepSolverToLiteralSplitterStepSolverAdapter(formulaSplitterStepSolver);
return result;
}
Aggregations