Search in sources :

Example 1 with StepSolver

use of com.sri.ai.grinder.api.StepSolver 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.getStepSolverForWhenSplitterIsTrue();
        AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
        ifFalse.initialDisequalsGreaterThanMaximumLowerBoundStepSolver = disequalsGreaterThanGreatestStrictLowerBoundStep.getStepSolverForWhenSplitterIsFalse();
        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.getStepSolverForWhenSplitterIsTrue();
        AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
        ifFalse.initialDisequalsWithinBoundsStepSolver = disequalsWithinBoundsStep.getStepSolverForWhenSplitterIsFalse();
        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.getStepSolverForWhenSplitterIsTrue();
            AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
            ifFalse.initialNumberOfDistinctDisequalsIsLessThanBoundsDifferenceStepSolver = numberOfDistinctDisequalsIsLessThanBoundsDifferenceStep.getStepSolverForWhenSplitterIsFalse();
            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.getStepSolverForWhenSplitterIsTrue();
            AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver ifFalse = makeSequelStepSolver(sequelBase);
            ifFalse.initialDistinctDisequalsStepSolver = (DistinctExpressionsStepSolver) distinctDisequalsStep.getStepSolverForWhenSplitterIsFalse();
            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);
}
Also used : DistinctExpressionsStepSolver(com.sri.ai.grinder.theory.equality.DistinctExpressionsStepSolver) ArrayList(java.util.ArrayList) SelectExpressionsSatisfyingComparisonStepSolver(com.sri.ai.grinder.helper.SelectExpressionsSatisfyingComparisonStepSolver) SelectExpressionsSatisfyingComparisonStepSolver(com.sri.ai.grinder.helper.SelectExpressionsSatisfyingComparisonStepSolver) ExpressionLiteralSplitterStepSolver(com.sri.ai.grinder.api.ExpressionLiteralSplitterStepSolver) ConstantExpressionStepSolver(com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver) AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver(com.sri.ai.grinder.theory.numeric.AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver) ConstantStepSolver(com.sri.ai.grinder.theory.base.ConstantStepSolver) NumberOfDistinctExpressionsIsLessThanStepSolver(com.sri.ai.grinder.theory.equality.NumberOfDistinctExpressionsIsLessThanStepSolver) StepSolver(com.sri.ai.grinder.api.StepSolver) DistinctExpressionsStepSolver(com.sri.ai.grinder.theory.equality.DistinctExpressionsStepSolver) NumberOfDistinctExpressionsIsLessThanStepSolver(com.sri.ai.grinder.theory.equality.NumberOfDistinctExpressionsIsLessThanStepSolver) Expression(com.sri.ai.expresso.api.Expression) ExpressionLiteralSplitterStepSolver(com.sri.ai.grinder.api.ExpressionLiteralSplitterStepSolver) ArrayList(java.util.ArrayList) Util.arrayList(com.sri.ai.util.Util.arrayList) List(java.util.List) ConstantExpressionStepSolver(com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver)

Example 2 with StepSolver

use of com.sri.ai.grinder.api.StepSolver in project aic-expresso by aic-sri-international.

the class UnificationStepSolverTest method propositionalTest.

@Test
public void propositionalTest() {
    TheoryTestingSupport theoryTestingSupport = TheoryTestingSupport.make(seededRandom, new PropositionalTheory());
    // NOTE: passing explicit FunctionTypes will prevent the general variables' argument types being randomly changed.
    theoryTestingSupport.setVariableNamesAndTypesForTesting(map("P", BOOLEAN_TYPE, "Q", BOOLEAN_TYPE, "R", BOOLEAN_TYPE, "unary_prop/1", new FunctionType(BOOLEAN_TYPE, BOOLEAN_TYPE), "binary_prop/2", new FunctionType(BOOLEAN_TYPE, BOOLEAN_TYPE, BOOLEAN_TYPE)));
    Context rootContext = theoryTestingSupport.makeContextWithTestingInformation();
    UnificationStepSolver unificationStepSolver = new UnificationStepSolver(parse("unary_prop(P)"), parse("unary_prop(P)"));
    StepSolver.Step<Boolean> step = unificationStepSolver.step(rootContext);
    Assert.assertEquals(false, step.itDepends());
    Assert.assertEquals(true, step.getValue());
    unificationStepSolver = new UnificationStepSolver(parse("unary_prop(P)"), parse("unary_prop(Q)"));
    step = unificationStepSolver.step(rootContext);
    Assert.assertEquals(true, step.itDepends());
    Assert.assertEquals(Expressions.parse("P = Q"), step.getSplitter());
    Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).itDepends());
    Assert.assertEquals(true, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).getValue());
    Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).itDepends());
    Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).getValue());
    Context localTestContext = rootContext.conjoinWithConjunctiveClause(parse("P and not Q"), rootContext);
    step = unificationStepSolver.step(localTestContext);
    Assert.assertEquals(false, step.itDepends());
    Assert.assertEquals(false, step.getValue());
    unificationStepSolver = new UnificationStepSolver(parse("unary_prop(P)"), parse("unary_prop(true)"));
    localTestContext = rootContext.conjoinWithConjunctiveClause(parse("P"), rootContext);
    step = unificationStepSolver.step(localTestContext);
    Assert.assertEquals(false, step.itDepends());
    Assert.assertEquals(true, step.getValue());
    localTestContext = rootContext.conjoinWithConjunctiveClause(parse("not P"), rootContext);
    step = unificationStepSolver.step(localTestContext);
    Assert.assertEquals(false, step.itDepends());
    Assert.assertEquals(false, step.getValue());
    unificationStepSolver = new UnificationStepSolver(parse("binary_prop(P, unary_prop(P))"), parse("binary_prop(unary_prop(Q), Q)"));
    step = unificationStepSolver.step(rootContext);
    Assert.assertEquals(true, step.itDepends());
    Assert.assertEquals(Expressions.parse("P = unary_prop(Q)"), step.getSplitter());
    // Ignore: PropositionalTheory will only deal with symbol variables for now
    // localTestContext = rootContext.conjoinWithConjunctiveClause(parse("not P and Q and not unary_prop(Q) and unary_prop(P)"), rootContext);
    // step = unificationStepSolver.step(localTestContext);
    // Assert.assertEquals(false,  step.itDepends());
    // Assert.assertEquals(true, step.getValue());
    // localTestContext = rootContext.conjoinWithConjunctiveClause(parse("P and Q and not unary_prop(Q) and unary_prop(P)"), rootContext);
    // step = unificationStepSolver.step(localTestContext);
    // Assert.assertEquals(false,  step.itDepends());
    // Assert.assertEquals(false, step.getValue());
    // Now test out individual branches
    unificationStepSolver = new UnificationStepSolver(parse("binary_prop(P, unary_prop(P))"), parse("binary_prop(unary_prop(Q), Q)"));
    step = unificationStepSolver.step(rootContext);
    Assert.assertEquals(true, step.itDepends());
    Assert.assertEquals(parse("P = unary_prop(Q)"), step.getSplitter());
    StepSolver<Boolean> falseItDependsSolver = step.getStepSolverForWhenSplitterIsFalse();
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).itDepends());
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).getValue());
    StepSolver<Boolean> trueItDependsSolver = step.getStepSolverForWhenSplitterIsTrue();
    localTestContext = rootContext.conjoin(parse("P"), rootContext);
    step = trueItDependsSolver.step(localTestContext);
    Assert.assertEquals(true, step.itDepends());
    Assert.assertEquals(parse("P = unary_prop(Q)"), step.getSplitter());
    falseItDependsSolver = step.getStepSolverForWhenSplitterIsFalse();
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).itDepends());
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).getValue());
    // Ignore: PropositionalTheory will only deal with symbol variables for now
    // localTestContext = localTestContext.conjoin(parse("unary_prop(Q)"), localTestContext);
    // step = trueItDependsSolver.step(localTestContext);
    // Assert.assertEquals(true,  step.itDepends());
    // Assert.assertEquals(parse("unary_prop(P) = Q"), step.getSplitter());
    falseItDependsSolver = step.getStepSolverForWhenSplitterIsFalse();
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).itDepends());
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).getValue());
    // Ignore: PropositionalTheory will only deal with symbol variables for now
    // localTestContext = localTestContext.conjoin(parse("unary_prop(P)"), localTestContext);
    // step = trueItDependsSolver.step(localTestContext);
    // Assert.assertEquals(true,  step.itDepends());
    // Assert.assertEquals(parse("unary_prop(P) = Q"), step.getSplitter());
    falseItDependsSolver = step.getStepSolverForWhenSplitterIsFalse();
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).itDepends());
    Assert.assertEquals(false, falseItDependsSolver.step(rootContext).getValue());
// Ignore: PropositionalTheory will only deal with symbol variables for now
// localTestContext = localTestContext.conjoin(parse("Q"), localTestContext);
// step = trueItDependsSolver.step(localTestContext);
// Assert.assertEquals(false,  step.itDepends());
// Assert.assertEquals(true, step.getValue());
}
Also used : Context(com.sri.ai.grinder.api.Context) TheoryTestingSupport(com.sri.ai.grinder.tester.TheoryTestingSupport) FunctionType(com.sri.ai.expresso.type.FunctionType) PropositionalTheory(com.sri.ai.grinder.theory.propositional.PropositionalTheory) StepSolver(com.sri.ai.grinder.api.StepSolver) UnificationStepSolver(com.sri.ai.grinder.theory.base.UnificationStepSolver) UnificationStepSolver(com.sri.ai.grinder.theory.base.UnificationStepSolver) Test(org.junit.Test)

Example 3 with StepSolver

use of com.sri.ai.grinder.api.StepSolver in project aic-expresso by aic-sri-international.

the class UnificationStepSolver method step.

@Override
public StepSolver.Step<Boolean> step(Context context) {
    StepSolver.Step<Boolean> result = null;
    if (precomputedResult != null) {
        result = precomputedResult;
    } else {
        List<Integer> stepUnknownSolutionIndexesForUnificationEqualities = new ArrayList<>(unknownSolutionIndexesForUnificationEqualities);
        List<Integer> stepFoundSolutions = new ArrayList<>();
        for (Integer unknownSolutionIndex : stepUnknownSolutionIndexesForUnificationEqualities) {
            Expression equality = unificationEqualitiesToTest.get(unknownSolutionIndex);
            ExpressionLiteralSplitterStepSolver evaluatorStepSolver = context.getTheory().makeEvaluatorStepSolver(equality);
            Expression equalityResult = evaluatorStepSolver.solve(context);
            if (equalityResult.equals(TRUE)) {
                stepFoundSolutions.add(unknownSolutionIndex);
            } else if (equalityResult.equals(FALSE)) {
                // Can't unify
                result = new StepSolver.Solution<>(Boolean.FALSE);
                break;
            } else {
            // Solution to unification equality still unknown
            }
        }
        if (result == null) {
            stepUnknownSolutionIndexesForUnificationEqualities.removeAll(stepFoundSolutions);
            if (stepUnknownSolutionIndexesForUnificationEqualities.size() == 0) {
                // No more unknown solutions and this means all of them were true if we got to here
                result = new StepSolver.Solution<>(Boolean.TRUE);
            } else {
                // We still have unknown equality unifications, so will split on the first unknown
                // of these equalities
                Integer firstUnknownUnificationEqualityIndex = stepUnknownSolutionIndexesForUnificationEqualities.get(0);
                Expression unknownUnificationEqualityToSplitOn = unificationEqualitiesToTest.get(firstUnknownUnificationEqualityIndex);
                StepSolver<Boolean> ifTrue;
                if (stepUnknownSolutionIndexesForUnificationEqualities.size() == 1) {
                    // If there is only 1 unknown unification equality remaining, then on the true branch
                    // we know the unification will result in true, so just return that known up front.
                    ifTrue = new ConstantStepSolver<>(Boolean.TRUE);
                } else {
                    ifTrue = this.clone();
                    ((UnificationStepSolver) ifTrue).unknownSolutionIndexesForUnificationEqualities = new ArrayList<>(stepUnknownSolutionIndexesForUnificationEqualities);
                }
                StepSolver<Boolean> ifFalse = new ConstantStepSolver<>(Boolean.FALSE);
                ContextSplitting contextSplitting = null;
                // information for the literal.
                if (context.getTheory().isLiteralOrBooleanConstant(unknownUnificationEqualityToSplitOn, context)) {
                    contextSplitting = new ContextSplitting(unknownUnificationEqualityToSplitOn, context);
                }
                result = new StepSolver.ItDependsOn<>(unknownUnificationEqualityToSplitOn, contextSplitting, ifTrue, ifFalse);
            }
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) ExpressionLiteralSplitterStepSolver(com.sri.ai.grinder.api.ExpressionLiteralSplitterStepSolver) StepSolver(com.sri.ai.grinder.api.StepSolver) Expression(com.sri.ai.expresso.api.Expression) ExpressionLiteralSplitterStepSolver(com.sri.ai.grinder.api.ExpressionLiteralSplitterStepSolver) ContextSplitting(com.sri.ai.grinder.core.constraint.ContextSplitting)

Example 4 with StepSolver

use of com.sri.ai.grinder.api.StepSolver 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);
}
Also used : LiteralStepSolver(com.sri.ai.grinder.theory.base.LiteralStepSolver) AbstractExpressionWithPropagatedLiteralsStepSolver(com.sri.ai.grinder.core.solver.AbstractExpressionWithPropagatedLiteralsStepSolver) ExpressionLiteralSplitterStepSolver(com.sri.ai.grinder.api.ExpressionLiteralSplitterStepSolver) ConstantExpressionStepSolver(com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver) AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver(com.sri.ai.grinder.theory.differencearithmetic.AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver) ConstantStepSolver(com.sri.ai.grinder.theory.base.ConstantStepSolver) LiteralStepSolver(com.sri.ai.grinder.theory.base.LiteralStepSolver) MaximumExpressionStepSolver(com.sri.ai.grinder.helper.MaximumExpressionStepSolver) StepSolver(com.sri.ai.grinder.api.StepSolver) Expression(com.sri.ai.expresso.api.Expression) ExpressionLiteralSplitterStepSolver(com.sri.ai.grinder.api.ExpressionLiteralSplitterStepSolver) MaximumExpressionStepSolver(com.sri.ai.grinder.helper.MaximumExpressionStepSolver) ConstantExpressionStepSolver(com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver)

Aggregations

StepSolver (com.sri.ai.grinder.api.StepSolver)4 Expression (com.sri.ai.expresso.api.Expression)3 ExpressionLiteralSplitterStepSolver (com.sri.ai.grinder.api.ExpressionLiteralSplitterStepSolver)3 ConstantExpressionStepSolver (com.sri.ai.grinder.theory.base.ConstantExpressionStepSolver)2 ConstantStepSolver (com.sri.ai.grinder.theory.base.ConstantStepSolver)2 ArrayList (java.util.ArrayList)2 FunctionType (com.sri.ai.expresso.type.FunctionType)1 Context (com.sri.ai.grinder.api.Context)1 ContextSplitting (com.sri.ai.grinder.core.constraint.ContextSplitting)1 AbstractExpressionWithPropagatedLiteralsStepSolver (com.sri.ai.grinder.core.solver.AbstractExpressionWithPropagatedLiteralsStepSolver)1 MaximumExpressionStepSolver (com.sri.ai.grinder.helper.MaximumExpressionStepSolver)1 SelectExpressionsSatisfyingComparisonStepSolver (com.sri.ai.grinder.helper.SelectExpressionsSatisfyingComparisonStepSolver)1 TheoryTestingSupport (com.sri.ai.grinder.tester.TheoryTestingSupport)1 LiteralStepSolver (com.sri.ai.grinder.theory.base.LiteralStepSolver)1 UnificationStepSolver (com.sri.ai.grinder.theory.base.UnificationStepSolver)1 AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver (com.sri.ai.grinder.theory.differencearithmetic.AbstractSingleVariableDifferenceArithmeticConstraintFeasibilityRegionStepSolver)1 DistinctExpressionsStepSolver (com.sri.ai.grinder.theory.equality.DistinctExpressionsStepSolver)1 NumberOfDistinctExpressionsIsLessThanStepSolver (com.sri.ai.grinder.theory.equality.NumberOfDistinctExpressionsIsLessThanStepSolver)1 AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver (com.sri.ai.grinder.theory.numeric.AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver)1 PropositionalTheory (com.sri.ai.grinder.theory.propositional.PropositionalTheory)1