use of com.sri.ai.util.math.Rational in project aic-expresso by aic-sri-international.
the class DefaultMonomial method make.
private static Monomial make(List<Expression> numericConstantsAndTerms) {
Rational numericFactor = Rational.ONE;
Map<Expression, Rational> factorToPower = new LinkedHashMap<>();
for (Expression numericConstantOrTerm : numericConstantsAndTerms) {
if (Expressions.isNumber(numericConstantOrTerm)) {
numericFactor = numericFactor.multiply(numericConstantOrTerm.rationalValue());
} else {
// Is a term
Expression factor = numericConstantOrTerm;
Rational power = Rational.ONE;
boolean attemptFlattening = false;
// Handle case where factor is negated, e.g.: -x
if (factor.hasFunctor(MINUS) && factor.numberOfArguments() == 1) {
factor = factor.get(0);
// i.e. same as having an explicit constant '-1' multiplicand in the expression
numericFactor = numericFactor.negate();
attemptFlattening = true;
}
// If exponentiation using a constant integer exponent then we need to extract the factor and the power
if (Expressions.hasFunctor(factor, Exponentiation.EXPONENTIATION_FUNCTOR)) {
Expression simplifiedPower = simplifyExponentIfPossible(factor.get(1));
if (isLegalExponent(simplifiedPower)) {
power = simplifiedPower.rationalValue();
// The factor is actually the base of the exponentiation
factor = factor.get(0);
attemptFlattening = true;
} else if (!simplifiedPower.equals(factor.get(1))) {
// Use the simplified version of the non legal exponent in the factor
// i.e. is a non numeric factor where the exponent has been simplified
// as best as possible.
factor = apply(EXPONENTIATION_FUNCTOR, factor.get(0), simplifiedPower);
}
}
// Handle nested *'s arguments
if (factor.hasFunctor(TIMES)) {
attemptFlattening = true;
}
// We attempt flattening if we were/are able to simplify the factor in some way
if (attemptFlattening) {
// Treat the factor as a Monomial and merge it in
// This lets you handle nested monomial expressions
// in a simplified/recursive manner.
Monomial factorAsMonomial = make(Times.getMultiplicands(factor));
// Need to raise to the current power
factorAsMonomial = factorAsMonomial.exponentiate(power.intValue());
numericFactor = numericFactor.multiply(factorAsMonomial.getNumericFactor());
List<Expression> factors = factorAsMonomial.getOrderedNonNumericFactors();
List<Rational> powers = factorAsMonomial.getPowersOfNonNumericFactors();
int factorSize = factors.size();
for (int i = 0; i < factorSize; i++) {
updateFactorToPowerMap(factorToPower, factors.get(i), powers.get(i));
}
} else {
updateFactorToPowerMap(factorToPower, factor, power);
}
}
}
Monomial result = null;
if (numericFactor.equals(Rational.ZERO)) {
result = ZERO;
} else {
List<Expression> orderedFactors = new ArrayList<>(factorToPower.keySet());
Collections.sort(orderedFactors, _factorComparator);
List<Rational> orderedPowers = new ArrayList<>(orderedFactors.size());
orderedFactors.forEach(factor -> orderedPowers.add(factorToPower.get(factor)));
result = make(numericFactor, orderedFactors, orderedPowers);
}
return result;
}
use of com.sri.ai.util.math.Rational in project aic-expresso by aic-sri-international.
the class DefaultPolynomial method makeFromMonomial.
private static Polynomial makeFromMonomial(Expression monomialExpression, List<Expression> variables) {
Monomial monomial = DefaultMonomial.make(monomialExpression);
if (!monomial.isNumericConstant()) {
// TODO: (Sept 2017) This treatment of coefficient factors (basically, combining factors into a single one)
// seems overly complicated and unnecessary.
// Need to pull out the factors that need to be treated together as a single factor
// based on the polynomial's signature of factors.
Monomial coefficient = monomial.getCoefficient(variables);
if (!coefficient.isNumericConstant()) {
// Have factors of the monomial that need to be treated as a single constant
// based on the polynomials signature of factors.
List<Expression> orderedFactors = new ArrayList<>();
Map<Expression, Rational> factorToPower = new HashMap<>();
orderedFactors.add(coefficient);
factorToPower.put(coefficient, Rational.ONE);
Set<Expression> coefficientFactors = coefficient.getFactors();
for (Expression factor : monomial.getOrderedNonNumericFactors()) {
if (!coefficientFactors.contains(factor)) {
orderedFactors.add(factor);
factorToPower.put(factor, monomial.getPowerOfFactor(factor));
}
}
Rational numericConstant = monomial.getNumericFactor();
// of the variables.
if (coefficient.getNumericFactor().equals(numericConstant)) {
// i.e. numeric constant was in variables.
numericConstant = Rational.ONE;
}
List<Rational> orderedPowers = new ArrayList<>();
Collections.sort(orderedFactors, _factorComparator);
orderedFactors.forEach(factor -> orderedPowers.add(factorToPower.get(factor)));
monomial = DefaultMonomial.make(numericConstant, orderedFactors, orderedPowers);
}
}
Polynomial result = new DefaultPolynomial(list(monomial), variables);
return result;
}
use of com.sri.ai.util.math.Rational in project aic-expresso by aic-sri-international.
the class DefaultPolynomial method addMonomialsWithSameSignature.
private Monomial addMonomialsWithSameSignature(Monomial m1, Monomial m2) {
Monomial result;
// Both have the same signature
Monomial m1Coefficient = m1.getCoefficient(getVariables());
Monomial m2Coefficient = m2.getCoefficient(getVariables());
Expression summedCoefficient;
if (m1Coefficient.isNumericConstant() && m2Coefficient.isNumericConstant()) {
// We can add them
summedCoefficient = Expressions.makeSymbol(m1Coefficient.getNumericFactor().add(m2Coefficient.getNumericFactor()));
} else if (m1Coefficient.equals(m2Coefficient)) {
// Compactly represent non-numeric coefficients that are equal
summedCoefficient = new DefaultFunctionApplication(TIMES_FUNCTOR, Arrays.asList(Expressions.TWO, m1Coefficient));
} else {
List<Expression> plusArgs = new ArrayList<>();
if (!m1Coefficient.isZero()) {
plusArgs.add(m1Coefficient);
}
if (!m2Coefficient.isZero()) {
plusArgs.add(m2Coefficient);
}
if (plusArgs.size() == 2) {
summedCoefficient = new DefaultFunctionApplication(PLUS_FUNCTOR, Arrays.asList(m1Coefficient, m2Coefficient));
} else {
summedCoefficient = plusArgs.get(0);
}
}
if (!Expressions.ZERO.equals(summedCoefficient)) {
List<Expression> args = new ArrayList<Expression>();
Rational numericConstantFactor = Rational.ONE;
if (Expressions.isNumber(summedCoefficient)) {
numericConstantFactor = summedCoefficient.rationalValue();
} else if (summedCoefficient.hasFunctor(TIMES_FUNCTOR)) {
// i.e. coefficients are equal so write in compact form.
numericConstantFactor = summedCoefficient.get(0).rationalValue();
args.add(summedCoefficient.get(1));
} else {
args.add(summedCoefficient);
}
args.addAll(getVariables());
Collections.sort(args, _factorComparator);
List<Rational> orderedPowers = new ArrayList<>();
for (Expression factor : args) {
if (factor == summedCoefficient) {
orderedPowers.add(Rational.ONE);
} else {
orderedPowers.add(m1.getPowerOfFactor(factor));
}
}
result = DefaultMonomial.make(numericConstantFactor, args, orderedPowers);
} else {
result = DefaultMonomial.ZERO;
}
return result;
}
use of com.sri.ai.util.math.Rational in project aic-expresso by aic-sri-international.
the class PolynomialIntegration method indefiniteIntegral.
/**
* Takes a polynomial:<br>
* <pre>
* t_1 * variable ^ n + ... + t_n * variable + t_{n+1}
* </pre>
* and returns the polynomial equivalent to:<br>
* <pre>
* (t_1/(n + 1)) * variable ^ {n + 1} + ... + (t_n / 2) * variable^2 + t_{n+1}*variable
* </pre>
*
* @param polynomial
* the polynomial the indefinite integral is to be found for.
* @param variable
* the variable integration is with respect to.
* @return the indefinite integral of the given polynomial.
*/
public static Polynomial indefiniteIntegral(Polynomial polynomial, Expression variable) {
List<Expression> variables = new ArrayList<>(polynomial.getVariables());
if (!variables.contains(variable)) {
variables.add(variable);
// recognized by the polynomial as being one (this is implied).
try {
polynomial = DefaultPolynomial.make(polynomial, variables);
} catch (IllegalArgumentException exception) {
throw new IllegalArgumentException("Integrating " + polynomial + " requires it to be an integral in the integral variable " + variable + " but it is not because " + exception);
}
}
// Get the integrals of its terms
List<Expression> integralsOfTerms = new ArrayList<>();
for (Monomial term : polynomial.getMonomials()) {
// indefinite integral of the term is:
// ∫ a*x^n dx = a*(x^(n+1)/(n+1) + C
// NOTE: we do not need to worry about the case where n = -1 (i.e. division by zero case)
// as our support for Polynomials only allows for positive integer exponents.
List<Expression> factorsOfIntegral = new ArrayList<>();
boolean variableFactorAdded = false;
for (Expression factor : term.getFactors()) {
Rational powerOfFactor = term.getPowerOfFactor(factor);
if (factor.equals(variable)) {
Expression nPlusOne = Expressions.makeSymbol(powerOfFactor.add(1));
factorsOfIntegral.add(Division.make(Exponentiation.make(variable, nPlusOne), nPlusOne));
variableFactorAdded = true;
} else {
factorsOfIntegral.add(Exponentiation.make(factor, powerOfFactor));
}
}
// ∫ a dx = a*x + C
if (!variableFactorAdded) {
factorsOfIntegral.add(variable);
}
integralsOfTerms.add(DefaultMonomial.make(Times.make(factorsOfIntegral)));
}
// The integral of any polynomial is the sum of the integrals of its terms.
Polynomial result = DefaultPolynomial.make(Plus.make(integralsOfTerms), variables);
return result;
}
use of com.sri.ai.util.math.Rational in project aic-expresso by aic-sri-international.
the class DifferenceArithmeticTheory method thereIsAtMostOnePositiveAndOneNegativeVariableMonomial.
private static boolean thereIsAtMostOnePositiveAndOneNegativeVariableMonomial(Polynomial polynomial) {
boolean result = true;
int numberOfPositiveVariableTerms = 0;
int numberOfNegativeVariableTerms = 0;
for (Monomial monomial : polynomial.getMonomials()) {
if (monomial.degree() == 1) {
Rational coefficient = monomial.getNumericFactor();
if (coefficient.isPositive()) {
numberOfPositiveVariableTerms++;
} else if (coefficient.isNegative()) {
numberOfNegativeVariableTerms++;
} else {
throw new Error("Monomial with zero coefficient should not be present: " + monomial);
}
}
if (numberOfPositiveVariableTerms > 1 || numberOfNegativeVariableTerms > 1) {
result = false;
break;
}
}
return result;
}
Aggregations