Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2015, SRI International
* All rights reserved.
* Licensed under the The BSD 3-Clause License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://opensource.org/licenses/BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the aic-praise nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.sri.ai.grinder.polynomial.api;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.google.common.annotations.Beta;
import com.sri.ai.expresso.api.Expression;
import com.sri.ai.util.base.Pair;
import com.sri.ai.util.math.Rational;
/**
* A monomial is a product of factors, where the numeric factor (if
* any) is the first argument and the non-numeric factors are in order.
*
* Examples:
*
*
*
* @author oreilly
*/
@Beta
public interface Monomial extends Expression {
/**
*
* @return the numeric factor of the monomial (if not explicitly defined
* is 1).
*/
Rational getNumericFactor();
/**
*
* @return true if this monomial is equivalent to a numeric constant;
*/
default boolean isNumericConstant() {
boolean result = getOrderedNonNumericFactors().size() == 0;
return result;
}
/**
*
* @return true if this monomial is equivalent to the numeric constant zero.
*/
default boolean isZero() {
boolean result = getNumericFactor().equals(Rational.ZERO);
return result;
}
/**
*
* @return true if this monomial is equivalent to the numeric constant one.
*/
default boolean isOne() {
boolean result = getNumericFactor().equals(Rational.ONE)
&& getOrderedNonNumericFactors().size() == 0;
return result;
}
/**
* The factors of a monomialM is the Collection factors(M).
* They are the expressions being multiplied, and possibly exponentiated by
* non-negative integers. Example:
*
*
*
* @return a Set representation of the factors contained within the Monomial
* (this includes the numeric factor).
*/
Set getFactors();
/**
* Get a unique list, ordered, of the non-numeric factors in the
* monomial.
*
* @return an ordered list of the non-numeric factors contained in
* the monomial.
*/
List getOrderedNonNumericFactors();
/**
*
* @return the powers of the non-numeric factors in the monomial,
* which map to the order of these factors.
*/
List getPowersOfNonNumericFactors();
/**
* The coefficient of a monomial M wrt a set of factors
* F is the product of the remaining factors of M.
* Example:
*
*
*
* coefficient(3*x^2*y^4, { x }) = 3* y^4
*
*
*
* @param factors
* what are to be considered the factors of the monomial (i.e.
* not part of the coefficient).
* @return the product of the remaining factors in this monomial not in the
* given list of factors.
*/
Monomial getCoefficient(List factors);
/**
* Get the power of the given factor if it is a factor of the monomial
* otherwise return 0.
*
* @param factor
* the factor whose power is to be retrieved.
* @return the power of the given factor if the factor is contained in the
* monomial. If not contained in the monomial will return 0.
*/
Rational getPowerOfFactor(Expression factor);
/**
* The signature of a monomial M wrt a tuple of factors
* F is the tuple of the powers of the factors in F in
* M (the power is 0 if the factor is not present in M).
* Examples:
*
*
*
* @param factors
* a list of factors.
* @return the tuple of the powers of the given factors that are in this
* Monomial (0 is returned for the power of factors not present in
* this monomial).
*/
default List getSignature(List factors) {
List result = new ArrayList<>(factors.size());
factors.forEach(factor -> result.add(getPowerOfFactor(factor)));
return result;
}
/**
* Convenience method that gets the signature of this Monomial using the
* non-numeric factors contained within.
*
* @return the tuple of the powers of the non-numeric factors that
* are in this Monomial.
*/
default List getSignature() {
List factors = this.getOrderedNonNumericFactors();
List result = getSignature(factors);
return result;
}
/**
* Two monomials M1 and M2 are like terms
* wrt a tuple of factors F if signature(M1, F) =
* signature(M2, F).
* Examples:
*
*
*
* x^2 * y and 3 * y * x^2 wrt F = (x, y)
* x^2 * y and 3 * y * x^2 wrt F = (x)
* x^2 * y and 3 * y * x^2 wrt F = (y)
* x^2 * y and 3 * y * x^2 wrt F = ()
* x and 3 * x wrt F = (x)
* 10 and 20 wrt F = ()
*
*
*
* @param monomial
* the monomial to check if a like term to this monomial.
* @param factors
* the factors to construct the signature used to determine if
* two monomials are like terms.
* @return true if are like terms based on the given factors, false
* otherwise.
*/
default boolean areLikeTerms(Monomial other, List factors) {
List thisSignature = getSignature(factors);
List otherSignature = other.getSignature(factors);
boolean result = thisSignature.equals(otherSignature);
return result;
}
/**
* Convenience method that uses the ordered union of non-numeric factors
* from this and the other Monomial to provide the second argument to
* {@link #areLikeTerms(Monomial, List)}.
*
* @param other
* the monomial to check if a like term to this monomial.
* @return true if are like terms based on the combined non-numeric
* factors, false otherwise.
*/
default boolean areLikeTerms(Monomial other) {
List combinedNonNumericFactors =
Monomial.orderedUnionOfNonNumericFactors(this, other);
boolean result = areLikeTerms(other, combinedNonNumericFactors);
return result;
}
/**
* The degree of a monomial is the sum of the exponents of all its
* non-numeric factors (numeric factors have a degree of
* 0).
*
* @return the degree of the monomial.
*/
int degree();
/**
* Multiply this Monomial by another.
*
* @param multiplier
* the multiplier.
* @return a new Monomial representing the result of the multiplication.
*/
Monomial times(Monomial multiplier);
/**
* Divide this monomial by another.
*
*
*
* this.divide(that) = this/that
*
*
*
* @param divisor
* the divisor
* @return a pair consisting of the quotient and remainder of this/divisor.
*/
Pair divide(Monomial divisor);
/**
* Raise this monomial to a given power.
*
* @param exponent
* a non negative integer exponent to raise the monomial to.
* @return a monomial which is the result of raising this monomial to the
* given exponent.
* @throws IllegalArgumentException
* if the exponent is negative.
*/
Monomial exponentiate(int exponent) throws IllegalArgumentException;
/**
* Create an ordered union (no duplicates) of the non-numeric
* factors contained in two Monomials.
*
* @param m1
* the first monomial.
* @param m2
* the second monomial.
* @return the ordered union (no duplicates) of the non-numeric
* factors contained in two Monomials.
*/
public static List orderedUnionOfNonNumericFactors(
Monomial m1, Monomial m2) {
List m1Factors = m1.getOrderedNonNumericFactors();
List m2Factors = m2.getOrderedNonNumericFactors();
// For efficiency ensure we have enough capacity in the union up front.
List result = new ArrayList<>(m1Factors.size()
+ m2Factors.size());
// NOTE: we know m1 and m2's non-numeric factors are
// ordered, which we can take advantage of to perform the
// ordered union more efficiently.
int m1FactorsSize = m1Factors.size();
int m2FactorsSize = m2Factors.size();
Expression m1Factor, m2Factor;
for (int i1 = 0, i2 = 0; i1 < m1FactorsSize || i2 < m2FactorsSize;) {
if (i1 < m1FactorsSize && i2 < m2FactorsSize) {
m1Factor = m1Factors.get(i1);
m2Factor = m2Factors.get(i2);
int m1FactorComparisonToM2Factor = m1Factor.compareTo(m2Factor);
if (m1FactorComparisonToM2Factor == 0) { // are considered equal
// just add one of them (as considered same) as do not want
// duplicates in the returned union.
result.add(m1Factor);
i1++;
i2++;
} else if (m1FactorComparisonToM2Factor < 0) { // i.e. m1Factor
// is before
// m2Factor
result.add(m1Factor);
i1++;
} else { // i.e. m2Factor is before m1Factor
result.add(m2Factor);
i2++;
}
} else if (i1 < m1FactorsSize) { // implies i2 is exhausted
result.add(m1Factors.get(i1));
i1++;
} else { // implies i2 < m2FactorsSize and i1 is exhausted
result.add(m2Factors.get(i2));
i2++;
}
}
return result;
}
}