Search in sources :

Example 31 with Monomial

use of com.sri.ai.grinder.polynomial.api.Monomial in project aic-expresso by aic-sri-international.

the class DefaultPolynomial method times.

@Override
public Polynomial times(Polynomial multiplier) throws IllegalArgumentException {
    assertSameVariables(multiplier);
    Polynomial result;
    // Optimization: return 0 if either numeric constant factor is 0
    if (isZero()) {
        result = this;
    } else if (multiplier.isZero()) {
        result = multiplier;
    } else if (isOne()) {
        // Optimization, neutral element
        result = multiplier;
    } else if (multiplier.isOne()) {
        // Optimization, neutral element
        result = this;
    } else {
        // Base case
        if (isMonomial() && multiplier.isMonomial()) {
            result = makeFromMonomial(this.asMonomial().times(multiplier.asMonomial()), getVariables());
        } else {
            // OPTIMIZATION NOTE: Instead of incrementally adding to a result polynomial for each of the
            // products from the cross product of this polynomials and the multipliers terms. We instead
            // collect up the cross product computations first, then sort them based on monomial 'comes before'
            // and then add like monomials together. Only then is an actual Polynomial result constructed.
            // This reduces the number of additions required by the '# term in the result' and also removes
            // the need for the creation of 'cross product # of terms' of intermediate polynomial objects
            // in order to come up with a final result.
            List<Monomial> products = new ArrayList<>(getMonomials().size() + multiplier.getMonomials().size());
            for (Monomial multiplicandMonomial : getMonomials()) {
                for (Monomial multiplierMonomial : multiplier.getMonomials()) {
                    Monomial monomialProduct = multiplicandMonomial.times(multiplierMonomial);
                    products.add(monomialProduct);
                }
            }
            // Ensure we sort so that it is easy to add up like terms together for the final result
            Collections.sort(products, monomialComparator);
            List<Monomial> summedLikeProducts = new ArrayList<>(products.size());
            for (Monomial product : products) {
                int summedIdx = summedLikeProducts.size() - 1;
                if (summedIdx < 0) {
                    summedLikeProducts.add(product);
                } else {
                    Monomial sumOfLikeTerms = summedLikeProducts.get(summedIdx);
                    // are like terms, add them and track their sum
                    if (sumOfLikeTerms.areLikeTerms(product, getVariables())) {
                        sumOfLikeTerms = addMonomialsWithSameSignature(sumOfLikeTerms, product);
                        summedLikeProducts.set(summedIdx, sumOfLikeTerms);
                    } else {
                        summedLikeProducts.add(product);
                    }
                }
            }
            summedLikeProducts.removeIf(term -> term.isZero());
            result = new DefaultPolynomial(summedLikeProducts, getVariables());
        }
    }
    return result;
}
Also used : Polynomial(com.sri.ai.grinder.polynomial.api.Polynomial) Plus(com.sri.ai.grinder.library.number.Plus) Polynomial(com.sri.ai.grinder.polynomial.api.Polynomial) Arrays(java.util.Arrays) DefaultMonomial.simplifyExponentIfPossible(com.sri.ai.grinder.polynomial.core.DefaultMonomial.simplifyExponentIfPossible) Expressions(com.sri.ai.expresso.helper.Expressions) Rational(com.sri.ai.util.math.Rational) HashMap(java.util.HashMap) Expression(com.sri.ai.expresso.api.Expression) Util.getFirstSatisfyingPredicateOrNull(com.sri.ai.util.Util.getFirstSatisfyingPredicateOrNull) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) DefaultMonomial.isLegalExponent(com.sri.ai.grinder.polynomial.core.DefaultMonomial.isLegalExponent) Map(java.util.Map) DefaultFunctionApplication(com.sri.ai.expresso.core.DefaultFunctionApplication) ZERO(com.sri.ai.expresso.helper.Expressions.ZERO) LinkedHashSet(java.util.LinkedHashSet) Pair(com.sri.ai.util.base.Pair) BinaryMinus(com.sri.ai.grinder.library.number.BinaryMinus) Util.join(com.sri.ai.util.Util.join) Monomial(com.sri.ai.grinder.polynomial.api.Monomial) Util.list(com.sri.ai.util.Util.list) Set(java.util.Set) Beta(com.google.common.annotations.Beta) AbstractExpressionWrapper(com.sri.ai.expresso.helper.AbstractExpressionWrapper) List(java.util.List) ExpressionComparator(com.sri.ai.expresso.helper.ExpressionComparator) FunctorConstants(com.sri.ai.grinder.library.FunctorConstants) Multinomial(com.sri.ai.util.math.Multinomial) Expressions.containsAnyOfGivenCollectionAsSubExpression(com.sri.ai.expresso.helper.Expressions.containsAnyOfGivenCollectionAsSubExpression) Collections(java.util.Collections) Monomial(com.sri.ai.grinder.polynomial.api.Monomial) ArrayList(java.util.ArrayList) List(java.util.List)

Example 32 with Monomial

use of com.sri.ai.grinder.polynomial.api.Monomial 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;
}
Also used : Polynomial(com.sri.ai.grinder.polynomial.api.Polynomial) Rational(com.sri.ai.util.math.Rational) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Triple(com.sri.ai.util.base.Triple) Expression(com.sri.ai.expresso.api.Expression) Monomial(com.sri.ai.grinder.polynomial.api.Monomial) DefaultFunctionApplication(com.sri.ai.expresso.core.DefaultFunctionApplication) Pair(com.sri.ai.util.base.Pair)

Aggregations

Monomial (com.sri.ai.grinder.polynomial.api.Monomial)32 DefaultMonomial (com.sri.ai.grinder.polynomial.core.DefaultMonomial)19 Test (org.junit.Test)18 Rational (com.sri.ai.util.math.Rational)12 ArrayList (java.util.ArrayList)11 Expression (com.sri.ai.expresso.api.Expression)10 Polynomial (com.sri.ai.grinder.polynomial.api.Polynomial)8 Expressions.containsAnyOfGivenCollectionAsSubExpression (com.sri.ai.expresso.helper.Expressions.containsAnyOfGivenCollectionAsSubExpression)4 LinkedHashMap (java.util.LinkedHashMap)4 List (java.util.List)4 DefaultFunctionApplication (com.sri.ai.expresso.core.DefaultFunctionApplication)3 Pair (com.sri.ai.util.base.Pair)3 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 LinkedHashSet (java.util.LinkedHashSet)2 Set (java.util.Set)2 Beta (com.google.common.annotations.Beta)1 AbstractExpressionWrapper (com.sri.ai.expresso.helper.AbstractExpressionWrapper)1 ExpressionComparator (com.sri.ai.expresso.helper.ExpressionComparator)1 Expressions (com.sri.ai.expresso.helper.Expressions)1