use of com.sri.ai.grinder.helper.MaximumExpressionStepSolver in project aic-expresso by aic-sri-international.
the class MaximumExpressionStepSolverTest method runTest.
private void runTest(List<String> expressions, String order, Expression orderMinimum, Expression orderMaximum, Expression expected, Context context) {
MaximumExpressionStepSolver stepSolver = new MaximumExpressionStepSolver(mapIntoArrayList(expressions, Expressions::parse), makeSymbol(order), orderMinimum, orderMaximum);
Expression solution = ContextDependentExpressionProblemSolver.staticSolve(stepSolver, context);
System.out.println("Maximum of " + expressions + " for order " + order + ": " + solution);
assertEquals(expected, solution);
}
use of com.sri.ai.grinder.helper.MaximumExpressionStepSolver 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);
}
Aggregations