use of com.sri.ai.util.base.Pair in project aic-expresso by aic-sri-international.
the class TupleValuedFreeVariablesSimplifier method constructComponentTuple.
private static Expression constructComponentTuple(List<Pair<Expression, Integer>> replacementComponents) {
List<Expression> elements = replacementComponents.stream().map(pair -> pair.first).collect(Collectors.toList());
Expression result = Expressions.makeTuple(elements);
return result;
}
use of com.sri.ai.util.base.Pair in project aic-expresso by aic-sri-international.
the class TupleValuedFreeVariablesSimplifier method simplify.
public static Expression simplify(Expression expression, Context context) {
Expression result = expression;
// First see if we have any free variables.
Map<Expression, Expression> freeVariablesAndTypes = Expressions.freeVariablesAndTypes(expression, context);
if (freeVariablesAndTypes.size() > 0) {
// Retrieve those that are tuples
Map<Expression, TupleType> freeVariablesOfTupleType = freeVariablesAndTypes.entrySet().stream().filter(entry -> entry.getValue() != null && TupleType.isTupleType(entry.getValue())).collect(Collectors.toMap(e -> e.getKey(), e -> (TupleType) GrinderUtil.fromTypeExpressionToItsIntrinsicMeaning(e.getValue(), context)));
if (freeVariablesOfTupleType.size() > 0) {
final Map<Expression, List<Pair<Expression, Integer>>> freeVariableComponentsMap = constructComponentMap(freeVariablesOfTupleType, expression, context);
// Replace the free tuple variables with their componentised forms
// e.g. N --> (N1, N2)
Expression componentisedExpression = expression.replaceAllOccurrences(expr -> {
Expression replacement = expr;
List<Pair<Expression, Integer>> replacementComponents = freeVariableComponentsMap.get(expr);
if (replacementComponents != null) {
replacement = constructComponentTuple(replacementComponents);
}
return replacement;
}, context);
// Evaluate the expression with the un-componentized free tuple variables, within an extended
// context that knows about the newly componentized variables
Context contextExtendedWithComponentVariables = extendContextWithComponentVariables(context, freeVariablesOfTupleType, freeVariableComponentsMap);
Expression evaluatedResult = context.getTheory().evaluate(componentisedExpression, contextExtendedWithComponentVariables);
// Translate back the free variable components
// e.g:
// if N1 = 2 then 29 else 30
// ---->
// if get(N, 1) = 2 then 29 else 30
final Map<Expression, Pair<Expression, Integer>> componentToFreeVariableMap = createReverseLookupMap(freeVariableComponentsMap);
result = evaluatedResult.replaceAllOccurrences(expr -> {
Expression replacement = expr;
Pair<Expression, Integer> correspondingFreeVariableWithIndex = componentToFreeVariableMap.get(expr);
if (correspondingFreeVariableWithIndex != null) {
replacement = Expressions.apply(FunctorConstants.GET, correspondingFreeVariableWithIndex.first, correspondingFreeVariableWithIndex.second);
}
return replacement;
}, contextExtendedWithComponentVariables);
}
}
return result;
}
use of com.sri.ai.util.base.Pair in project aic-praise by aic-sri-international.
the class SGSolverEvaluator method prCallSGSolverCLI.
//
// PRIVATE
private SGSolverCallResult prCallSGSolverCLI(String model, String evidenceQuery) throws Exception {
String tempPagedModelContainer = PagedModelContainer.toInternalContainerRepresentation(ModelLanguage.HOGMv1, Arrays.asList(new Pair<String, List<String>>(model, Arrays.asList(evidenceQuery))));
File tempInput = File.createTempFile("sgsolver", PagedModelContainer.DEFAULT_CONTAINER_FILE_EXTENSION, getConfiguration().getWorkingDirectory());
Files.write(tempInput.toPath(), tempPagedModelContainer.getBytes());
//
File tempSTDERR = File.createTempFile("sgsolver", ".stderr", getConfiguration().getWorkingDirectory());
File tempSTDOUT = File.createTempFile("sgsolver", ".stdout", getConfiguration().getWorkingDirectory());
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(getConfiguration().getWorkingDirectory());
// TODO - add option to PRAiSE to indicate a timeout.
processBuilder.command("java", "-classpath", System.getProperty("java.class.path"), "-Xms" + getConfiguration().getTotalMemoryLimitInMegabytesPerSolveAttempt() + "M", "-Xmx" + getConfiguration().getTotalMemoryLimitInMegabytesPerSolveAttempt() + "M", PRAiSE.class.getName(), tempInput.getAbsolutePath());
processBuilder.redirectError(ProcessBuilder.Redirect.to(tempSTDERR));
processBuilder.redirectOutput(ProcessBuilder.Redirect.to(tempSTDOUT));
long sgSolverStart = System.currentTimeMillis();
Process sgSolverProcess = processBuilder.start();
if (!sgSolverProcess.waitFor(getConfiguration().getTotalCPURuntimeLimitSecondsPerSolveAttempt() + 5, TimeUnit.SECONDS)) {
// waiting time elapsed
sgSolverProcess.destroyForcibly();
}
long sgSolverEnd = System.currentTimeMillis();
List<String> sgsolverOutputs = Files.readAllLines(tempSTDOUT.toPath(), StandardCharsets.UTF_8);
tempInput.delete();
//
tempSTDOUT.delete();
tempSTDERR.delete();
SGSolverCallResult result = new SGSolverCallResult();
result.sgSolverProcessTookMS = sgSolverEnd - sgSolverStart;
result.resultExpression = sgsolverOutputs.stream().filter(line -> line.startsWith(PRAiSE.RESULT_PREFIX)).findFirst().orElse(null);
if (result.resultExpression != null) {
result.resultExpression = result.resultExpression.substring(PRAiSE.RESULT_PREFIX.length());
} else {
throw new Error("Error launching java process for SGSolver:\n" + sgsolverOutputs);
}
return result;
}
use of com.sri.ai.util.base.Pair in project aic-expresso by aic-sri-international.
the class InversionSimplifier method getIndexAndFunctionType.
private static Pair<Expression, FunctionType> getIndexAndFunctionType(Expression functionOnIntensionalSet, Context context) {
IndexExpressionsSet indexExpressionsSet = getIndexExpressions(functionOnIntensionalSet);
List<Expression> indices = IndexExpressions.getIndices(indexExpressionsSet);
if (indices.size() != 1) {
throw new UnsupportedOperationException("Currently only support singular indices");
}
Expression index = indices.get(0);
Context intensionalSetContext = context.extendWith(indexExpressionsSet);
Type type = GrinderUtil.getType(index, intensionalSetContext);
FunctionType functionType = null;
if (type instanceof FunctionType) {
functionType = (FunctionType) type;
}
Pair<Expression, FunctionType> result = new Pair<>(index, functionType);
return result;
}
use of com.sri.ai.util.base.Pair in project aic-praise by aic-sri-international.
the class TranslationOfTableToInequalities method constructGenericTableExpressionUsingInequalities.
/**
* Returns an {@link Expression} equivalent to a given {@link FunctionTable} but in the form of a decision tree
* (so hopefully more compact) using inequalities.
* @param functionTable
* @param solverListener if not null, invoked on solver used for compilation,
* before and after compilation is performed; returned solver from "before" invocation is used (it may be the same one used as argument, of course).
* @return
*/
public static Expression constructGenericTableExpressionUsingInequalities(FunctionTable functionTable, Function<MultiIndexQuantifierEliminator, MultiIndexQuantifierEliminator> solverListener) {
// the strategy in this method is the following:
// we collect all the contiguous indices sub-sets of the function table sharing their function value.
// They are kept in a map from each value to a list of indices sub-sets with that value.
//
// Then, we sort these groups of indices sub-sets by the sum of their sizes (number of entries), from smallest to largest.
// This will help us later to create an expression that tests for the largest groups first.
//
// Finally, we create an if-then-else expression, starting from the leaf (least common value).
// For each group of indices sub-sets with the same value, we obtain an inequalities expression describing
// the conditions for a variable assignment to be in that indices sub-set of the function table.
// Each portion generates a conjunction, and the group of portions generates a disjunction.
//
// The resulting if-then-else expression is linearly organized (only else clauses have nested if-then-else expressions).
// A more balanced (and thus efficient) representation is obtained by compiling it using SGDPLL(T).
Map<Double, List<FunctionTableIndicesSubSet>> functionValuesAndCorrespondingIndicesSubSet = map();
Double currentSubSetFunctionValueIfAny = null;
List<Integer> firstIndicesOfCurrentSubSetIfAny = null;
List<Integer> previousIndices = null;
List<Integer> indices = null;
CartesianProductEnumeration<Integer> cartesianProduct = new CartesianProductEnumeration<>(UAIUtil.cardinalityValues(functionTable));
while (cartesianProduct.hasMoreElements()) {
previousIndices = indices;
indices = new ArrayList<>(cartesianProduct.nextElement());
Double functionValue = Math.round(functionTable.entryFor(indices) * 100) / 100.0;
boolean hitNewFunctionValue = currentSubSetFunctionValueIfAny == null || !functionValue.equals(currentSubSetFunctionValueIfAny);
if (hitNewFunctionValue) {
storeIndicesSubSetOnAllVariables(functionTable, firstIndicesOfCurrentSubSetIfAny, previousIndices, currentSubSetFunctionValueIfAny, functionValuesAndCorrespondingIndicesSubSet);
// get information for next indices sub-set
currentSubSetFunctionValueIfAny = functionValue;
firstIndicesOfCurrentSubSetIfAny = indices;
}
}
previousIndices = indices;
storeIndicesSubSetOnAllVariables(functionTable, firstIndicesOfCurrentSubSetIfAny, previousIndices, currentSubSetFunctionValueIfAny, functionValuesAndCorrespondingIndicesSubSet);
// we sort (by using TreeMap) lists of indices sub-set with the same function value from those with smaller to greater sizes,
// and form the final expression backwards, thus prioritizing larger sub-sets
// whose conditions will be more often satisfied and leading to greater simplifications during inference.
List<Pair<BigInteger, List<FunctionTableIndicesSubSet>>> listOfPairsOfSizeAndListsOfIndicesSubSetsWithSameFunctionValue = new ArrayList<>(functionValuesAndCorrespondingIndicesSubSet.size());
for (Map.Entry<Double, List<FunctionTableIndicesSubSet>> functionValueAndIndicesSubSet : functionValuesAndCorrespondingIndicesSubSet.entrySet()) {
List<FunctionTableIndicesSubSet> indicesSubSetsWithSameFunctionValue = functionValueAndIndicesSubSet.getValue();
BigInteger sumOfSizes = BigInteger.ZERO;
for (FunctionTableIndicesSubSet indicesSubSet : indicesSubSetsWithSameFunctionValue) {
sumOfSizes = sumOfSizes.add(indicesSubSet.size());
}
listOfPairsOfSizeAndListsOfIndicesSubSetsWithSameFunctionValue.add(Pair.make(sumOfSizes, indicesSubSetsWithSameFunctionValue));
}
Collections.sort(listOfPairsOfSizeAndListsOfIndicesSubSetsWithSameFunctionValue, (Comparator<? super Pair<BigInteger, List<FunctionTableIndicesSubSet>>>) (p1, p2) -> p1.first.compareTo(p2.first));
List<List<FunctionTableIndicesSubSet>> listsOfIndicesSubSetsWithSameFunctionValue = mapIntoList(listOfPairsOfSizeAndListsOfIndicesSubSetsWithSameFunctionValue, p -> p.second);
Iterator<List<FunctionTableIndicesSubSet>> listsOfIndicesSubSetsWithSameFunctionValueIterator = listsOfIndicesSubSetsWithSameFunctionValue.iterator();
List<FunctionTableIndicesSubSet> firstListOfIndicesSubSets = listsOfIndicesSubSetsWithSameFunctionValueIterator.next();
Double valueOfFirstListOfIndicesSubSets = getFirstOrNull(firstListOfIndicesSubSets).getFunctionValue();
Expression currentExpression = makeSymbol(valueOfFirstListOfIndicesSubSets);
while (listsOfIndicesSubSetsWithSameFunctionValueIterator.hasNext()) {
List<FunctionTableIndicesSubSet> indicesSubSetsWithSameFunctionValue = listsOfIndicesSubSetsWithSameFunctionValueIterator.next();
Expression functionValueOfIndicesSubSetsWithSameFunctionValue = makeSymbol(getFirstOrNull(indicesSubSetsWithSameFunctionValue).getFunctionValue());
Expression conditionForThisFunctionValue = Or.make(mapIntoList(indicesSubSetsWithSameFunctionValue, TranslationOfTableToInequalities::getInequalitiesExpressionForFunctionTableIndicesSubSet));
currentExpression = IfThenElse.make(conditionForThisFunctionValue, functionValueOfIndicesSubSetsWithSameFunctionValue, currentExpression);
}
return currentExpression;
}
Aggregations