Search in sources :

Example 26 with Polynomial

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

the class DefaultPolynomial method make.

public static Polynomial make(Expression expression, List<Expression> variables) {
    Expression nonSymbolVariable = getFirstSatisfyingPredicateOrNull(variables, v -> !v.getSyntacticFormType().equals("Symbol"));
    if (nonSymbolVariable != null) {
        throw new IllegalArgumentException("Non-symbol variables in DefaultPolynomial no longer supported, but got " + nonSymbolVariable);
    }
    Polynomial result = null;
    if (expression.hasFunctor(PLUS_FUNCTOR)) {
        // E1 + E2 --> make(E1, F).add(make(E2, F))
        // Note: as + can have 0 or more arguments we start with 0 (i.e. the
        // neutral element).
        result = makeFromMonomial(Expressions.ZERO, variables);
        for (Expression summandExpression : expression.getArguments()) {
            Polynomial summand = make(summandExpression, variables);
            result = result.add(summand);
        }
    } else if (expression.hasFunctor(MINUS_FUNCTOR)) {
        // E1 - E2 --> make(E1, F).minus(make(E2, F))
        if (expression.numberOfArguments() == 1) {
            // is '-(something)' which is equivalent to
            // -1 * (something)
            Polynomial p1 = makeFromMonomial(Expressions.MINUS_ONE, variables);
            Polynomial p2 = make(expression.get(0), variables);
            result = p1.times(p2);
        } else if (expression.numberOfArguments() == 2) {
            Polynomial p1 = make(expression.get(0), variables);
            Polynomial p2 = make(expression.get(1), variables);
            result = p1.minus(p2);
        } else {
            throw new IllegalArgumentException("Not a legal minus expression: " + expression);
        }
    } else if (expression.hasFunctor(TIMES_FUNCTOR)) {
        // E1 * E2 --> make(E1, F).times(make(E2, F))
        // Note: as * can have 0 or more arguments we start with 1 (i.e. the
        // neutral element).
        result = makeFromMonomial(Expressions.ONE, variables);
        // Note: handle case when one of the multipliers is 0 (i.e. an
        // absorbing element).
        Polynomial absorbingElement = makeFromMonomial(Expressions.ZERO, variables);
        for (Expression multiplierExpression : expression.getArguments()) {
            Polynomial multiplier = make(multiplierExpression, variables);
            if (multiplier.equals(absorbingElement)) {
                // * by 0 so answer is 0, no need to worry about any other
                // multipliers.
                result = absorbingElement;
                break;
            } else {
                result = result.times(multiplier);
            }
        }
    } else if (expression.hasFunctor(DIVISION_FUNCTOR)) {
        // E1 / E2 --> make(E1, F).divide(make(E2, F))
        Polynomial dividend = make(expression.get(0), variables);
        Polynomial divisor = make(expression.get(1), variables);
        Pair<Polynomial, Polynomial> quotientAndRemainder = dividend.divide(divisor);
        Polynomial quotient = quotientAndRemainder.first;
        Polynomial remainder = quotientAndRemainder.second;
        if (!remainder.isZero()) {
            // divisor(x)                    divisor(x)
            if (containsAnyOfGivenCollectionAsSubExpression(divisor, variables)) {
                throw new IllegalArgumentException(expression + " is not a polynomial because it has divisor " + divisor);
            }
            Expression remainderDividedByDivisor = new DefaultFunctionApplication(DIVISION_FUNCTOR, Arrays.asList(remainder, divisor));
            result = quotient.add(makeFromMonomial(remainderDividedByDivisor, variables));
        } else {
            result = quotient;
        }
    } else if (expression.hasFunctor(EXPONENTIATION_FUNCTOR)) {
        // E1 ^ model with model an integer constant --> make(E1).exponentiate(model)
        Expression base = expression.get(0);
        Expression power = simplifyExponentIfPossible(expression.get(1));
        if (containsAnyOfGivenCollectionAsSubExpression(power, variables)) {
            throw new IllegalArgumentException("Polynomial variables cannot appear in exponent, but some of " + join(variables) + " appear in an exponent in " + expression);
        }
        if (isLegalExponent(power)) {
            Polynomial p1 = make(base, variables);
            result = p1.exponentiate(power.intValue());
        } else if (containsAnyOfGivenCollectionAsSubExpression(base, variables)) {
            throw new IllegalArgumentException("Exponents of the type " + power + " not recognized yet in " + DefaultPolynomial.class);
        } else {
            // constant multinomial
            result = makeFromMonomial(expression, variables);
        }
    } else if (variables.contains(expression)) {
        // single variable monomial
        result = makeFromMonomial(expression, variables);
    } else if (containsAnyOfGivenCollectionAsSubExpression(expression, variables)) {
        // contains variables but is none of recognized types of expressions
        throw new IllegalArgumentException("Polynomial variables " + join(variables) + " appear in illegal positions in " + expression);
    } else {
        // is constant monomial
        result = makeFromMonomial(expression, variables);
    }
    return result;
}
Also used : Polynomial(com.sri.ai.grinder.polynomial.api.Polynomial) Expression(com.sri.ai.expresso.api.Expression) Expressions.containsAnyOfGivenCollectionAsSubExpression(com.sri.ai.expresso.helper.Expressions.containsAnyOfGivenCollectionAsSubExpression) DefaultFunctionApplication(com.sri.ai.expresso.core.DefaultFunctionApplication) Pair(com.sri.ai.util.base.Pair)

Example 27 with Polynomial

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

the class DefaultPolynomial method make.

public static Polynomial make(Expression expression) {
    Polynomial result;
    boolean expressionAlreadyIsPolynomial = expression instanceof Polynomial;
    if (expressionAlreadyIsPolynomial) {
        result = (Polynomial) expression;
    } else {
        List<Expression> generalizedVariables = extractGeneralizedVariables(expression);
        result = make(expression, generalizedVariables);
    }
    return result;
}
Also used : Polynomial(com.sri.ai.grinder.polynomial.api.Polynomial) Expression(com.sri.ai.expresso.api.Expression) Expressions.containsAnyOfGivenCollectionAsSubExpression(com.sri.ai.expresso.helper.Expressions.containsAnyOfGivenCollectionAsSubExpression)

Example 28 with Polynomial

use of com.sri.ai.grinder.polynomial.api.Polynomial 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 29 with Polynomial

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

the class PolynomialIntegration method definiteIntegral.

/**
 * This method will return the polynomial equivalent to:<br>
 * <pre>
 * Q.replace(variable, end) - Q.replace(variable, start)
 * </pre>
 * where 'Q = indefiniteIntegral(polynomial, variable)'
 *
 * @param polynomial
 *        the polynomial the definite integral is to be found for.
 * @param variable
 *        the variable integration is with respect to.
 * @param start
 *        the starting limit of the integral.
 * @param end
 *        the ending limit of the integral.
 * @return the definite integral of the polynomial for the given limits.
 */
public static Polynomial definiteIntegral(Polynomial polynomial, Expression variable, Expression start, Expression end, Predicate<Expression> isVariable) {
    Polynomial q = indefiniteIntegral(polynomial, variable);
    // Note: will include variable due to calling indefiniteIntegral
    Set<Expression> variableSet = new LinkedHashSet<>(q.getVariables());
    variableSet.addAll(Expressions.freeVariables(start, isVariable));
    variableSet.addAll(Expressions.freeVariables(end, isVariable));
    // if (!isNumber(start) && !isPositiveOrNegativeInfinity(start)) {
    // variableSet.add(start);
    // }
    // if (!isNumber(end) && !isPositiveOrNegativeInfinity(end)) {
    // variableSet.add(end);
    // }
    List<Expression> variables = new ArrayList<>(variableSet);
    Polynomial minuendPolynomial = replaceFactor(q, variable, end, variables);
    Polynomial subtrahendPolynomial = replaceFactor(q, variable, start, variables);
    Polynomial result = minuendPolynomial.minus(subtrahendPolynomial);
    return result;
}
Also used : Polynomial(com.sri.ai.grinder.polynomial.api.Polynomial) LinkedHashSet(java.util.LinkedHashSet) Expression(com.sri.ai.expresso.api.Expression) ArrayList(java.util.ArrayList)

Example 30 with Polynomial

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

the class PolynomialIntegration method replaceFactor.

private static Polynomial replaceFactor(Polynomial q, Expression variable, Expression value, List<Expression> variablesToIncludeInResult) {
    List<Expression> replacedTerms = replaceVariableByValueInTerms(q, variable, value);
    Polynomial result = DefaultPolynomial.make(Plus.make(replacedTerms), variablesToIncludeInResult);
    return result;
}
Also used : Polynomial(com.sri.ai.grinder.polynomial.api.Polynomial) Expression(com.sri.ai.expresso.api.Expression)

Aggregations

Polynomial (com.sri.ai.grinder.polynomial.api.Polynomial)32 Expression (com.sri.ai.expresso.api.Expression)20 DefaultPolynomial (com.sri.ai.grinder.polynomial.core.DefaultPolynomial)20 ArrayList (java.util.ArrayList)12 Test (org.junit.Test)11 Monomial (com.sri.ai.grinder.polynomial.api.Monomial)8 Rational (com.sri.ai.util.math.Rational)7 List (java.util.List)5 Expressions.containsAnyOfGivenCollectionAsSubExpression (com.sri.ai.expresso.helper.Expressions.containsAnyOfGivenCollectionAsSubExpression)4 Pair (com.sri.ai.util.base.Pair)4 HashMap (java.util.HashMap)4 LinkedHashSet (java.util.LinkedHashSet)4 DefaultFunctionApplication (com.sri.ai.expresso.core.DefaultFunctionApplication)3 LinkedHashMap (java.util.LinkedHashMap)3 Polynomial.makeRandomPolynomial (com.sri.ai.grinder.polynomial.api.Polynomial.makeRandomPolynomial)2 HashSet (java.util.HashSet)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