use of com.sri.ai.util.base.Pair in project aic-expresso by aic-sri-international.
the class PolynomialSummation method sum.
/**
* Compute the sum for the summation of a polynomial.
*
* @param indexOfSummation
* the index variable of the summation.
* @param lowerBoundExclusive
* the lower bound of the summation.
* @param upperBoundInclusive
* the upper bound of the summation.
* @param summand
* the polynomial to be summed.
* @return the sum of the given summation.
*/
public static Polynomial sum(Expression indexOfSummation, Expression lowerBoundExclusive, Expression upperBoundInclusive, Polynomial summand) {
Polynomial result;
List<Expression> indexVariable = Arrays.asList(indexOfSummation);
Polynomial summandAsPolynomialOfIndex = DefaultPolynomial.make(summand, indexVariable);
int n = summandAsPolynomialOfIndex.degree();
//
// collect the t coefficients
List<Expression> tCoefficients = new ArrayList<>(n);
for (int i = 0; i <= n; i++) {
tCoefficients.add(Expressions.ZERO);
}
for (int i = 0; i < summandAsPolynomialOfIndex.numberOfTerms(); i++) {
Monomial term = summandAsPolynomialOfIndex.getMonomials().get(i);
tCoefficients.set(term.getPowerOfFactor(indexOfSummation).intValue(), term.getCoefficient(indexVariable));
}
//
// compute polynomials R_i(x) = (x + l)^i for each i
Expression indexOfSummationPlusLowerBound = new DefaultFunctionApplication(PLUS_FUNCTOR, Arrays.asList(indexOfSummation, lowerBoundExclusive));
Polynomial indexOfSummationPlusLowerBoundPolynomial = DefaultPolynomial.make(indexOfSummationPlusLowerBound, indexVariable);
List<Polynomial> rPolynomials = new ArrayList<>(n);
rPolynomials.add(DefaultPolynomial.make(Expressions.ONE, indexVariable));
rPolynomials.add(indexOfSummationPlusLowerBoundPolynomial);
for (int i = 2; i <= n; i++) {
rPolynomials.add(rPolynomials.get(i - 1).times(indexOfSummationPlusLowerBoundPolynomial));
}
Map<Pair<Integer, Integer>, Expression> indexedRCoefficient = new LinkedHashMap<>();
for (int i = 0; i <= n; i++) {
Polynomial rPolynomial = rPolynomials.get(i);
for (int q = 0; q <= i; q++) {
Pair<Integer, Integer> indexKey = new Pair<>(i, q);
Monomial rqxq = rPolynomial.getMapFromSignatureToMonomial().get(Arrays.asList(new Rational(q)));
if (rqxq == null) {
indexedRCoefficient.put(indexKey, Expressions.ZERO);
} else {
indexedRCoefficient.put(indexKey, rqxq.getCoefficient(indexVariable));
}
}
}
//
// compute "constants" (may contain variables other than x)
// s_i,q,j = t_i*R_{i,q}/(q+1) (-1)^j choose(q+1,j) B_j
// where R_{i,q}(x) is the coefficient in R_i(x) multiplying x^q.
Map<Triple<Integer, Integer, Integer>, Polynomial> sConstants = new LinkedHashMap<>();
for (int i = 0; i <= n; i++) {
Expression ti = tCoefficients.get(i);
for (int q = 0; q <= i; q++) {
Expression riq = indexedRCoefficient.get(new Pair<>(i, q));
Expression tiByriq = new DefaultFunctionApplication(TIMES_FUNCTOR, Arrays.asList(ti, riq));
for (int j = 0; j <= q; j++) {
Triple<Integer, Integer, Integer> indexKey = new Triple<>(i, q, j);
Expression qPlus1 = Expressions.makeSymbol(q + 1);
Expression minus1PowerJ = Expressions.makeSymbol(j % 2 == 0 ? 1 : -1);
Expression chooseQplus1J = Expressions.makeSymbol(Util.binomialCoefficient(q + 1, j));
Expression bernoulliJ = Expressions.makeSymbol(BernoulliNumber.computeFirst(j));
Expression sConstant = new DefaultFunctionApplication(TIMES_FUNCTOR, Arrays.asList(new DefaultFunctionApplication(DIVISION_FUNCTOR, Arrays.asList(tiByriq, qPlus1)), minus1PowerJ, chooseQplus1J, bernoulliJ));
sConstants.put(indexKey, DefaultPolynomial.make(sConstant, indexVariable));
}
}
}
//
// compute polynomials, for each q, j, V_{q + 1 -j} = (u - l)^{q + 1 - j}
Expression upperBoundMinusLowerBound = new DefaultFunctionApplication(MINUS_FUNCTOR, Arrays.asList(upperBoundInclusive, lowerBoundExclusive));
Polynomial upperBoundMinusLowerBoundPolynomial = DefaultPolynomial.make(upperBoundMinusLowerBound, indexVariable);
Map<Integer, Polynomial> vValues = new LinkedHashMap<>();
for (int q = 0; q <= n; q++) {
for (int j = 0; j <= q; j++) {
Integer exponent = q + 1 - j;
if (!vValues.containsKey(exponent)) {
vValues.put(exponent, upperBoundMinusLowerBoundPolynomial.exponentiate(exponent));
}
}
}
//
// Compute the w values and construct the final result.
Polynomial ws = DefaultPolynomial.make(Expressions.ZERO, indexVariable);
for (int i = 0; i <= n; i++) {
for (int q = 0; q <= i; q++) {
for (int j = 0; j <= q; j++) {
Triple<Integer, Integer, Integer> sConstantKey = new Triple<>(i, q, j);
Integer valueKey = q + 1 - j;
Polynomial sConstant = sConstants.get(sConstantKey);
Polynomial vValue = vValues.get(valueKey);
Polynomial w = sConstant.times(vValue);
ws = ws.add(w);
}
}
}
List<Expression> generalizedVariables = DefaultPolynomial.extractGeneralizedVariables(ws);
if (generalizedVariables.size() > 0) {
// Simplify in the context of the contained generalized variables
// and then return as a single constant factor (i.e. the index variable should not be present).
ws = DefaultPolynomial.make(ws, generalizedVariables);
}
result = DefaultPolynomial.make(ws, indexVariable);
return result;
}
use of com.sri.ai.util.base.Pair in project aic-expresso by aic-sri-international.
the class AbstractSingleVariableNumericConstraintFeasibilityRegionStepSolver method makeUpperBoundsAndStrictness.
/**
* A method setting {@link #upperBoundsIncludingImplicitOnes} and {@link #fromUpperBoundsIncludingImplicitOnesToStrictness}
* from constraint and variable's type.
* @param context
*/
protected void makeUpperBoundsAndStrictness(Context context) {
AbstractSingleVariableConstraint abstractSingleVariableConstraint = (AbstractSingleVariableConstraint) constraint;
FunctionIterator<Expression, Pair<Expression, Boolean>> upperBoundsFromPositiveNormalizedAtomsIterator = functionIterator(predicateIterator(abstractSingleVariableConstraint.getPositiveNormalizedAtoms(), e -> e.hasFunctor(LESS_THAN)), // strict
e -> processExplicitUpperBoundAndStrictnessPair(e.get(1), true, context));
FunctionIterator<Expression, Pair<Expression, Boolean>> upperBoundsFromNegativeNormalizedAtomsIterator = functionIterator(predicateIterator(abstractSingleVariableConstraint.getNegativeNormalizedAtoms(), // not (X > Y) <=> X <= Y, so Y is a non-strict upper bound
e -> e.hasFunctor(GREATER_THAN)), // non-strict
e -> processExplicitUpperBoundAndStrictnessPair(e.get(1), false, context));
Pair<Expression, Boolean> typeUpperBound = getTypeUpperBoundAndStrictness(context);
Iterator<Pair<Expression, Boolean>> upperBoundsAndStrictnessIterator = new NestedIterator<>(upperBoundsFromPositiveNormalizedAtomsIterator, upperBoundsFromNegativeNormalizedAtomsIterator, typeUpperBound);
upperBoundsIncludingImplicitOnes = arrayList();
fromUpperBoundsIncludingImplicitOnesToStrictness = map();
for (Pair<Expression, Boolean> boundAndStrictness : in(upperBoundsAndStrictnessIterator)) {
Expression bound = boundAndStrictness.first;
upperBoundsIncludingImplicitOnes.add(bound);
Boolean strictness = boundAndStrictness.second;
Boolean previousStrictness = fromUpperBoundsIncludingImplicitOnesToStrictness.get(bound);
if (previousStrictness == null || (!previousStrictness && strictness)) {
// if no strictness information so far, store current one; otherwise, only need to change it if previous occurrences were non-strict and this one is strict
fromUpperBoundsIncludingImplicitOnesToStrictness.put(bound, strictness);
}
}
}
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-expresso by aic-sri-international.
the class TupleValuedFreeVariablesSimplifier method constructComponentMap.
private static Map<Expression, List<Pair<Expression, Integer>>> constructComponentMap(Map<Expression, TupleType> freeVariablesOfTupleType, Expression expression, Context context) {
Map<Expression, List<Pair<Expression, Integer>>> result = new LinkedHashMap<>();
for (Map.Entry<Expression, TupleType> freeVariableOfTupleType : freeVariablesOfTupleType.entrySet()) {
Expression freeVariable = freeVariableOfTupleType.getKey();
TupleType freeVariableTupleType = freeVariableOfTupleType.getValue();
List<Pair<Expression, Integer>> components = new ArrayList<>();
int tupleArity = freeVariableTupleType.getArity();
for (int i = 1; i <= tupleArity; i++) {
String proposedComponentVariableName = freeVariable.toString() + i;
Expression componentVariable = Expressions.makeUniqueVariable(proposedComponentVariableName, expression, context);
components.add(new Pair<>(componentVariable, i));
}
result.put(freeVariable, components);
}
return result;
}
use of com.sri.ai.util.base.Pair in project aic-expresso by aic-sri-international.
the class ModelGenerator method maxMinProbability.
public static Pair<Double, Double> maxMinProbability(Bound b, Model m) {
Context context = m.getContext();
Theory theory = m.getTheory();
Expression query = m.getQuery().getValue();
Type type = context.getTypeOfRegisteredSymbol(query);
if (type.getName().equals("Boolean")) {
double maxProbabilityOfTrue = -1;
double minProbabilityOfTrue = 10;
if (b.isExtensionalBound()) {
DefaultExtensionalBound extensionalBound = (DefaultExtensionalBound) b;
List<Expression> listOfElements = extensionalBound.getArguments();
for (Expression distribution : listOfElements) {
// replace and evaluate
Expression replacingQueryByTrue = distribution.replaceAllOccurrences(query, parse("true"), context);
Expression evaluating = theory.evaluate(replacingQueryByTrue, context);
// convert to double
double value = evaluating.doubleValue();
// update max and min
if (value > maxProbabilityOfTrue) {
maxProbabilityOfTrue = value;
}
if (value < minProbabilityOfTrue) {
minProbabilityOfTrue = value;
}
}
Pair<Double, Double> result = new Pair<>(minProbabilityOfTrue, maxProbabilityOfTrue);
return result;
} else if (b.isIntensionalBound()) {
}
}
return null;
}
Aggregations