use of com.sri.ai.grinder.sgdpllt.api.Context in project aic-expresso by aic-sri-international.
the class SatisfiabilityOfSingleVariableEqualityConstraintStepSolver method getPropagatedCNFBesidesPropagatedLiterals.
@Override
protected Iterable<Iterable<Expression>> getPropagatedCNFBesidesPropagatedLiterals(Context context) {
if (!variableIsBoundToUniquelyNamedConstant(context)) {
// the following logic only holds if the variable is not bound to a uniquely named constants,
// since that eliminates all disequalities to other uniquely named constants as redundant
long variableDomainSize = getConstraint().getVariableTypeSize(context);
if (variableDomainSize >= 0 && getConstraint().numberOfDisequals() >= variableDomainSize) {
// the following procedure can be very expensive but the condition above will rarely be satisfied
ArrayList<Expression> variableDisequals = getVariableDisequals(context);
Set<Expression> uniquelyNamedConstantDisequals = getUniquelyNamedConstantDisequals(context);
Expression typeExpression = GrinderUtil.getTypeExpression(getConstraint().getVariable(), context);
Type type = context.getType(typeExpression);
ArrayList<Expression> remainingUniquelyNamedConstants = arrayListFrom(new PredicateIterator<>(type.iterator(), c -> !uniquelyNamedConstantDisequals.contains(c)));
CartesianProductIterator<ArrayList<Expression>> subsetOfVariableDisequalsAndRemainingConstantsPermutationIterator = new CartesianProductIterator<ArrayList<Expression>>(() -> new SubsetsOfKIterator<Expression>(variableDisequals, remainingUniquelyNamedConstants.size()), () -> new PermutationIterator<Expression>(remainingUniquelyNamedConstants));
FunctionIterator<ArrayList<ArrayList<Expression>>, Iterable<Expression>> clausesIterator = FunctionIterator.make(subsetOfVariableDisequalsAndRemainingConstantsPermutationIterator, (ArrayList<ArrayList<Expression>> subsetAndPermutation) -> clauseNegatingAssignmentOfSubsetOfVariablesToParticularPermutationOfRemainingConstants(subsetAndPermutation));
Iterable<Iterable<Expression>> clauses = in(clausesIterator);
return clauses;
}
}
// otherwise, nothing is implied.
return list();
}
use of com.sri.ai.grinder.sgdpllt.api.Context in project aic-expresso by aic-sri-international.
the class DifferenceArithmeticTheoryTestingSupport method makeRandomAtomOn.
/**
* Makes a random atom on variable by summing or subtracting terms from two random atoms generated by super class implementation.
*/
@Override
public Expression makeRandomAtomOn(String mainVariable, Context context) {
String mainVariableName = getVariableName(mainVariable);
Type mainType = getTestingVariableType(mainVariable);
List<String> variableNamesThatAreSubtypesOf = getVariableNamesWhoseTypesAreSubtypesOf(mainType);
int maxNumberOfOtherVariablesInAtom = Math.min(variableNamesThatAreSubtypesOf.size(), 2);
// used to be 3, but if literal has more than two variables, it steps out of difference arithmetic and may lead
// to multiplied variables when literals are propagated.
// For example, X = Y + Z and X = -Y - Z + 3 imply 2Y + 2Z = 3
int numberOfOtherVariablesInAtom = getRandom().nextInt(maxNumberOfOtherVariablesInAtom);
// Note: that otherVariablesForAtom will contain only one or zero elements
ArrayList<String> otherVariablesForAtom = new ArrayList<>();
if (numberOfOtherVariablesInAtom > 0) {
otherVariablesForAtom.add(pickTestingVariableAtRandom(mainType, otherName -> !otherName.equals(mainVariableName)));
}
ArrayList<Expression> constants = new ArrayList<Expression>();
int numberOfConstants = getRandom().nextInt(3);
for (int i = 0; i != numberOfConstants; i++) {
// Note: We know we can safely sample from the Difference Arithmetic Theory Types.
Expression sampledConstant = mainType.sampleUniquelyNamedConstant(getRandom());
Expression constant;
if (getRandom().nextBoolean()) {
constant = sampledConstant;
} else {
constant = makeSymbol(-sampledConstant.intValue());
}
constants.add(constant);
}
ArrayList<Expression> leftHandSideArguments = new ArrayList<Expression>();
leftHandSideArguments.add(parse(mainVariable));
// needs to be difference, so it's added as negative
Util.mapIntoList(otherVariablesForAtom, otherVariable -> UnaryMinus.make(parse(otherVariable)), leftHandSideArguments);
leftHandSideArguments.addAll(constants);
int numberOfOtherVariablesToBeCanceled = getRandom().nextInt(otherVariablesForAtom.size() + 1);
ArrayList<String> otherVariablesToBeCanceled = Util.pickKElementsWithoutReplacement(otherVariablesForAtom, numberOfOtherVariablesToBeCanceled, getRandom());
// note that this term is positive, so it will cancel the previously negative term with the same "other variable"
Util.mapIntoList(otherVariablesToBeCanceled, v -> parse(v), leftHandSideArguments);
// Note: it may seem odd to generate an "other variable" and add another term that will cancel it later.
// However, this is useful for making sure canceling works properly.
Expression leftHandSide = Plus.make(leftHandSideArguments);
String functor = pickUniformly(getTheoryFunctors(), getRandom());
Expression unsimplifiedResult = apply(functor, leftHandSide, 0);
Expression result = getTheory().simplify(unsimplifiedResult, context);
return result;
}
use of com.sri.ai.grinder.sgdpllt.api.Context in project aic-expresso by aic-sri-international.
the class ExpressionStepSolverToLiteralSplitterStepSolverAdapterTest method testPropositionalTheoryWithFixedDisjunctiveFormulas.
@Test
public void testPropositionalTheoryWithFixedDisjunctiveFormulas() {
TheoryTestingSupport theoryTestingSupport = TheoryTestingSupport.make(makeRandom(), new PropositionalTheory());
extendTestingVaribles("P", theoryTestingSupport, "S", "T");
Context context = theoryTestingSupport.makeContextWithTestingInformation();
runTest(theoryTestingSupport, new GeneralFormulaExpressionTestStepSolver(Expressions.parse("P"), Expressions.parse("Q")), Expressions.parse("if P then if Q then P and Q else P and not Q else if Q then not P and Q else not P and not Q"), context);
runTest(theoryTestingSupport, new GeneralFormulaExpressionTestStepSolver(Expressions.parse("P or Q"), Expressions.parse("R or Q")), Expressions.parse("if P then if R then (P or Q) and (R or Q) else if Q then (P or Q) and (R or Q) else (P or Q) and not (R or Q) else if Q then (P or Q) and (R or Q) else if R then not (P or Q) and (R or Q) else not (P or Q) and not (R or Q)"), context);
runTest(theoryTestingSupport, new GeneralFormulaExpressionTestStepSolver(Expressions.parse("P or Q"), Expressions.parse("R or S")), Expressions.parse("if P then if R then (P or Q) and (R or S) else if S then (P or Q) and (R or S) else (P or Q) and not (R or S) else if Q then if R then (P or Q) and (R or S) else if S then (P or Q) and (R or S) else (P or Q) and not (R or S) else if R then not (P or Q) and (R or S) else if S then not (P or Q) and (R or S) else not (P or Q) and not (R or S)"), context);
}
use of com.sri.ai.grinder.sgdpllt.api.Context in project aic-expresso by aic-sri-international.
the class ExpressionStepSolverToLiteralSplitterStepSolverAdapterTest method runRandomDisjunctiveFormulasTest.
private void runRandomDisjunctiveFormulasTest(TheoryTestingSupport theoryTestingSupport) {
for (int numberDisjuncts = 1; numberDisjuncts < 4; numberDisjuncts++) {
// acts like a literal step solver for this case.
for (int numberLiteralsPerDisjunct = 1; numberLiteralsPerDisjunct < 4; numberLiteralsPerDisjunct++) {
// # tests to run for combination.
for (int j = 0; j < 3; j++) {
Context context = theoryTestingSupport.makeContextWithTestingInformation();
runTest(theoryTestingSupport, new GeneralFormulaExpressionTestStepSolver(theoryTestingSupport, context, numberDisjuncts, numberLiteralsPerDisjunct), null, context);
}
}
}
}
use of com.sri.ai.grinder.sgdpllt.api.Context in project aic-expresso by aic-sri-international.
the class SGDPLLTTester method runGroupProblemSolvingTestGivenConstraintAndProblem.
/**
* @param problem
* @param indices
* @param constraint
* @param body
* @param testAgainstBruteForce
* @param theoryTestingSupport
* @param context
* @throws Error
*/
public static void runGroupProblemSolvingTestGivenConstraintAndProblem(Expression problem, Collection<Expression> indices, Constraint constraint, Expression body, boolean testAgainstBruteForce, TheoryTestingSupport theoryTestingSupport, Context context) throws Error {
Theory theory = theoryTestingSupport.getTheory();
Collection<Expression> freeVariables = getFreeVariableMinusIndices(indices, constraint, body, context);
String problemDescription = problem.toString();
output(problemDescription);
Simplifier symbolicInterpreter = (e, c) -> theory.evaluate(e, c);
long start = System.currentTimeMillis();
Expression symbolicSolution = symbolicInterpreter.apply(problem, context);
long time = System.currentTimeMillis() - start;
output("Symbolic solution: " + symbolicSolution);
output("Computed in " + time + " ms");
if (Util.thereExists(new SubExpressionsDepthFirstIterator(symbolicSolution), e -> e instanceof QuantifiedExpression || Sets.isIntensionalSet(e))) {
throw new Error("Symbolic solution is not quantifier-free: " + symbolicSolution);
}
if (testAgainstBruteForce) {
BinaryFunction<BruteForceCommonInterpreter, Context, Expression> bruteForceSolutionGivenInterpreterAndContextWithAssignmentToOtherVariables = (i, c) -> i.apply(problem, c);
testSymbolicVsBruteForceComputationForEachAssignment(theory, problemDescription, freeVariables, symbolicSolution, bruteForceSolutionGivenInterpreterAndContextWithAssignmentToOtherVariables, context);
// A more elegant approach would be to create a "for all free variables : symbolic = problem" expression
// and solve it by brute force instead of using testSymbolicVsBruteForceComputation
// which replicates the brute force interpreter to some extent.
// The reason we do not do this is simply due to the fact that the brute force interpreter would return "false"
// in case of failure, without indicating which assignment failed, which is very useful for debugging.
// If interpreters, and in fact the whole framework, provided proofs of its calculations,
// then we could simply use the more elegant approach.
} else {
output("Skipping test againt brute-force.");
}
}
Aggregations