use of com.sri.ai.grinder.polynomial.api.Polynomial 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.grinder.polynomial.api.Polynomial in project aic-expresso by aic-sri-international.
the class LinearRealArithmeticTheory method applicationOfAtomFunctorIsIndeedAtom.
@Override
public boolean applicationOfAtomFunctorIsIndeedAtom(Expression applicationOfAtomFunctor, Context context) {
boolean result;
try {
Expression leftHandSideMinusRightHandSide = BinaryMinus.make(applicationOfAtomFunctor.get(0), applicationOfAtomFunctor.get(1));
Polynomial polynomial = DefaultPolynomial.make(leftHandSideMinusRightHandSide);
result = forAll(polynomial.getMonomials(), isLinearRealArithmeticTerm(context));
} catch (IllegalArgumentException exception) {
// leftHandSideMinusRightHandSide is not polynomial
result = false;
}
return result;
}
Aggregations