use of java.math.BigInteger.ONE 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