use of com.sri.ai.grinder.helper.AssignmentMapsIterator in project aic-expresso by aic-sri-international.
the class AbstractSingleQuantifierEliminationStepSolver method step.
@Override
public Step step(Context context) {
Step result;
Context contextForBody = getContextForBody(context);
if (contextForBody.isContradiction()) {
result = new Solution(getGroup().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 = context.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)
AbstractSingleQuantifierEliminationStepSolver ifTrue = clone();
AbstractSingleQuantifierEliminationStepSolver 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
Expression literalFreeBody = bodyStep.getValue();
result = eliminateQuantifierForLiteralFreeBody(literalFreeBody, context);
boolean solutionToQuantifiedLiteralFreeBodyIsNotConditionalItself = !result.itDepends();
if (solutionToQuantifiedLiteralFreeBodyIsNotConditionalItself) {
IntegrationRecording.registerGroupIntegration(problem, literalFreeBody, result, context);
}
}
}
if (context.getGlobalObject(BRUTE_FORCE_CHECKING_OF_NON_CONDITIONAL_PROBLEMS) != null) {
if (!result.itDepends()) {
Expression indexType = context.getTypeExpressionOfRegisteredSymbol(getIndex());
SingleQuantifierEliminationProblem problem = new DefaultSingleQuantifierEliminationProblem(getGroup(), getIndex(), indexType, getIndexConstraint(), getBody());
Expression problemExpression = problem.toExpression();
Set<Expression> freeVariables = Expressions.freeVariables(problemExpression, context);
AssignmentMapsIterator assignments = new AssignmentMapsIterator(freeVariables, context);
for (Map<Expression, Expression> assignment : in(assignments)) {
BruteForceCommonInterpreter bruteForceCommonInterpreter = new BruteForceCommonInterpreter();
Context extendedContext = Assignment.extendAssignments(assignment, context);
// Only go on if the assignment satisfies the context:
if (bruteForceCommonInterpreter.apply(context, extendedContext).equals(Expressions.TRUE)) {
Expression bruteForceResult = bruteForceCommonInterpreter.apply(problemExpression, extendedContext);
Expression resultGivenAssignment = bruteForceCommonInterpreter.apply(result.getValue(), extendedContext);
Expression evaluatedProblem = bruteForceCommonInterpreter.apply(problemExpression, extendedContext);
if (!bruteForceResult.equals(resultGivenAssignment)) {
String message = "Disagreement on " + problemExpression + "\nunder " + assignment + ".\n" + "Context: " + context + ".\n" + "Evaluated problem: " + evaluatedProblem + ".\n" + "Brute force says " + bruteForceResult + ", symbolic says " + resultGivenAssignment;
println(message);
throw new Error(message);
} else {
String message = "Agreement on " + problemExpression + "\nunder " + assignment + ".\n" + "Context: " + context + ".\n" + "Evaluated problem: " + evaluatedProblem + ".\n" + "Brute force says " + bruteForceResult + ", symbolic says " + resultGivenAssignment;
println(message);
}
}
}
}
}
return result;
}
use of com.sri.ai.grinder.helper.AssignmentMapsIterator in project aic-expresso by aic-sri-international.
the class FunctionType method iterator.
@Override
public Iterator<Expression> iterator() {
if (!(getCodomain().isDiscrete() && getArgumentTypes().stream().allMatch(Type::isFinite))) {
throw new Error("Only function types with left-finite argument types and a discrete codomain can be enumerated.");
}
if (cachedIterateRegistry == null) {
// Pre-compute
cachedIterateRegistry = new DefaultRegistry();
int numCodomainValues = argumentTypes.stream().map(Type::cardinality).map(Expression::rationalValue).reduce(Rational.ONE, Rational::multiply).intValue();
cachedIterateRegistry = cachedIterateRegistry.makeNewContextWithAddedType(getCodomain());
Expression codomainTypeExpression = parse(getCodomain().getName());
codomainVariables = new ArrayList<>(numCodomainValues);
Map<Expression, Expression> symbolsAndTypes = new LinkedHashMap<>();
for (int i = 0; i < numCodomainValues; i++) {
Expression coDomainVariableI = makeSymbol("C" + (i + 1));
codomainVariables.add(coDomainVariableI);
symbolsAndTypes.put(coDomainVariableI, codomainTypeExpression);
}
List<Expression> argVariables = new ArrayList<>();
for (int i = 0; i < getArgumentTypes().size(); i++) {
cachedIterateRegistry = cachedIterateRegistry.makeNewContextWithAddedType(getArgumentTypes().get(i));
argVariables.add(makeSymbol("A" + (i + 1)));
symbolsAndTypes.put(argVariables.get(i), parse(getArgumentTypes().get(i).getName()));
}
cachedIterateRegistry = cachedIterateRegistry.setSymbolsAndTypes(symbolsAndTypes);
StringJoiner lambdaApplicationPrefix = new StringJoiner(", ", "(lambda ", " : ");
for (Expression argVar : argVariables) {
lambdaApplicationPrefix.add(argVar + " in " + symbolsAndTypes.get(argVar));
}
AssignmentMapsIterator assignmentsIterator = new AssignmentMapsIterator(argVariables, cachedIterateRegistry);
StringJoiner lambdaApplicationBody = new StringJoiner(" else ", "", ")");
AtomicInteger counter = new AtomicInteger(0);
assignmentsIterator.forEachRemaining(assignment -> {
if (counter.incrementAndGet() != numCodomainValues) {
StringJoiner condition = new StringJoiner(" and ", "if ", " then C" + counter);
for (int i = 0; i < argVariables.size(); i++) {
Expression argVariable = argVariables.get(i);
condition.add(argVariable + " = " + assignment.get(argVariable));
}
lambdaApplicationBody.add(condition.toString());
} else {
lambdaApplicationBody.add("C" + numCodomainValues);
}
});
genericLambda = parse(lambdaApplicationPrefix.toString() + lambdaApplicationBody.toString());
}
return FunctionIterator.functionIterator(new AssignmentMapsIterator(codomainVariables, cachedIterateRegistry), assignment -> {
Expression lambda = genericLambda;
for (int i = 0; i < codomainVariables.size(); i++) {
Expression codomainVariable = codomainVariables.get(i);
// NOTE: There will only be one occurrence of the codomain variable to replace,
// so can avoid doing an AllOccurrences replacement.
lambda = lambda.replaceFirstOccurrence(codomainVariable, assignment.get(codomainVariable), cachedIterateRegistry);
}
return lambda;
});
}
use of com.sri.ai.grinder.helper.AssignmentMapsIterator in project aic-expresso by aic-sri-international.
the class AbstractSingleQuantifierEliminationStepSolver method bruteForceCheckingOfUnconditionalProblem.
private void bruteForceCheckingOfUnconditionalProblem(Step step, Context context) {
Expression problemExpression = makeProblemExpression(context);
AssignmentMapsIterator assignments = makeAssignmentsIterator(problemExpression, context);
for (Map<Expression, Expression> assignment : in(assignments)) {
bruteForceCheckAssignmentIfNeeded(assignment, problemExpression, step, context);
}
}
use of com.sri.ai.grinder.helper.AssignmentMapsIterator in project aic-expresso by aic-sri-international.
the class AbstractSingleQuantifierEliminationStepSolver method makeAssignmentsIterator.
private static AssignmentMapsIterator makeAssignmentsIterator(Expression problemExpression, Context context) {
Set<Expression> freeVariables = Expressions.freeVariables(problemExpression, context);
AssignmentMapsIterator assignments = new AssignmentMapsIterator(freeVariables, context);
return assignments;
}
use of com.sri.ai.grinder.helper.AssignmentMapsIterator in project aic-expresso by aic-sri-international.
the class TupleType method iterator.
@Override
public Iterator<Expression> iterator() {
if (!getElementTypes().stream().allMatch(Type::isDiscrete)) {
throw new Error("Only tuple types with discrete element types can be enumerated.");
}
if (cachedIterateRegistry == null) {
// Pre-compute
elementVariables = new ArrayList<>();
cachedIterateRegistry = new DefaultRegistry();
Map<Expression, Expression> symbolsAndTypes = new LinkedHashMap<>();
for (int i = 0; i < getArity(); i++) {
Expression elementVariableI = makeSymbol("E" + (i + 1));
elementVariables.add(elementVariableI);
symbolsAndTypes.put(elementVariableI, parse(getElementTypes().get(i).getName()));
cachedIterateRegistry = cachedIterateRegistry.makeNewContextWithAddedType(elementTypes.get(i));
}
cachedIterateRegistry = cachedIterateRegistry.setSymbolsAndTypes(symbolsAndTypes);
StringJoiner tupleVariableRepresentation = new StringJoiner(", ", "tuple(", ")");
for (Expression eleVar : elementVariables) {
tupleVariableRepresentation.add(eleVar.toString());
}
genericTuple = parse(tupleVariableRepresentation.toString());
}
return FunctionIterator.functionIterator(new AssignmentMapsIterator(elementVariables, cachedIterateRegistry), assignment -> {
Expression tuple = genericTuple;
for (int i = 0; i < elementVariables.size(); i++) {
Expression elementVariable = elementVariables.get(i);
// NOTE: There will only be one occurrence of the element variable to replace,
// so can avoid doing an AllOccurrences replacement.
tuple = tuple.replaceFirstOccurrence(elementVariable, assignment.get(elementVariable), cachedIterateRegistry);
}
return tuple;
});
}
Aggregations