Skip to content

Functionalities of Univariable & Multivariable Polynomials and Series

Iris Lui edited this page Jun 1, 2016 · 12 revisions

As of May 30, 2016 this contains accurate documentation on the functionalities of the univariate and multivariate polynomials/series classes.

Navigation

Univariate Polynomial

UExprPoly is a sparse polynomial representation class. A UExprPoly object holds:

  • A variable (symbol(std::string))
  • A dictionary (UExprDict(std::map))
  • The degree (int)

UExprDict is wrapper class of a std::map<int, Expression> that is typedef as map_int_Expr, where the key value is of type int and the mapped value is of type Expression. Expression can hold any Basic mathematical structure. For a univariable polynomial x**2 + 2*x + 1, UExprDict would hold {{0, 1}, {1, 2}, {1, 2}}.

UExprPoly is inherited from the UPolyBase base class, which also contains the basic methods needed to perform operations for any kind of univariable polynomials. This is also similar to UIntPoly.

To use UExprPoly in a C++ project, include:

#include <symengine/polys/uexprpoly.h>
using SymEngine::UExprPoly;
using SymEngine::UExprDict;
using SymEngine::Symbol;
using SymEngine::symbol;
using SymEngine::Expression;
using SymEngine::map_int_Expr;

Individual functionalities can be chosen separately, or can be used with just using namespace SymEngine;

Functions

int compare( const Basic &o ) const;

Compare two polynomials.

Parameter:

  • o
    • A Basic object, which represent any mathematical expression that can be created in SymEngine

Return:

  • 0 if both polynomials are equal.
  • -1 if either
    • Left polynomial has a lower degree than the right polynomial
    • The string value of left polynomial’s variable is lower than the right polynomial’s variable
    • The left polynomial’s dictionary is smaller than the right polynomial’s dictionary
    • The left polynomial’s nth-term is smaller than the right polynomial’s nth-term
  • Otherwise 1

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> P = uexpr_poly(x, {{0, 1}, {1, 2}});
    RCP<const UExprPoly> Q = uexpr_poly(x, {{0, 1}, {1, 2}, {2, 1}});
    RCP<const UExprPoly> R = uexpr_poly(y, {{0, 1}, {1, 2}, {3, 3}});
    std::cout << P->compare(*Q) << std::endl;
    std::cout << Q->compare(*Q) << std::endl;
    std::cout << R->compare(*Q) << std::endl;

Output:

    -1
    0
    1
Expression max_coef( ) const;

Return the coefficient value of the highest degree of the UExprPoly.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> a = uexpr_poly(x, {{0, 1}, {1, 2}, {2, 4}});
    std::cout << a->max_coef() << std::endl;

Output:

    4
Expression eval( const Expression &x ) const;

Evaluates the UExprPoly at value x.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> a = uexpr_poly(x, {{0, 1}, {1, 2}, {2, symbol("a")}});
    std::cout << a->eval(2) << std::endl;

Output:

    5 + 4*a
bool is_zero( ) const;

Return true if the polynomial equals 0.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> z = uexpr_poly(x, {{0, Expression(0)}});
    RCP<const UExprPoly> o = uexpr_poly(x, {{0, Expression(1)}});
    std::cout << z->is_zero() << std::endl;
    std::cout << o->is_zero() << std::endl;

Output:

    1
    0
bool is_one( ) const;

Return true if the polynomial equals 1.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> z = uexpr_poly(x, {{0, Expression(0)}});
    RCP<const UExprPoly> o = uexpr_poly(x, {{0, Expression(1)}});
    std::cout << z->is_one() << std::endl;
    std::cout << o->is_one() << std::endl;

Output:

    0
    1
bool is_minus_one( ) const;

Return true if the polynomial equals -1.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> mo = uexpr_poly(x, {{0, Expression(-1)}});
    RCP<const UExprPoly> o = uexpr_poly(x, {{0, Expression(1)}});
    std::cout << mo->is_minus_one() << std::endl;
    std::cout << o->is_minus_one() << std::endl;

Output:

    1
    0
bool is_integer( ) const;

Return true if the polynomial is an integer monomial.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> p = uexpr_poly(x, {{0, Expression(1)}, {1, Expression(2)}});
    RCP<const UExprPoly> i = uexpr_poly(x, {{0, Expression(6)}});
    std::cout << p->is_integer() << std::endl;
    std::cout << i->is_integer() << std::endl;

Output:

    0
    1
bool is_symbol( ) const;

Return true if the polynomial is a monomial with a coefficient of 1 and a degree of 1.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> i = uexpr_poly(x, {{0, Expression(6)}});
    RCP<const UExprPoly> s = uexpr_poly(x, {{1, Expression(1)}});
    std::cout << i->is_symbol() << std::endl;
    std::cout << s->is_symbol() << std::endl;

Output:

    0
    1
bool is_mul( ) const;

Return true if the polynomial is a monomial with a coefficient that is not 0 or 1 and a degree of 1 or greater.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> i = uexpr_poly(x, {{0, Expression(9)}});
    RCP<const UExprPoly> m = uexpr_poly(x, {{3, Expression(5)}});
    std::cout << i->is_mul() << std::endl;
    std::cout << m->is_mul() << std::endl;

Output:

    0
    1
bool is_pow( ) const;

Return true if the polynomial is a monomial with a coefficient of 1 and a degree greater than 1.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> m = uexpr_poly(x, {{3, Expression(5)}});
    RCP<const UExprPoly> po = uexpr_poly(x, {{5, Expression(1)}});
    std::cout << m->is_pow() << std::endl;
    std::cout << po->is_pow() << std::endl;

Output:

    0
    1
RCP<const Basic> diff( const RCP<const Symbol> &x ) const

Compute the derivative with respect to variable x.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> a = uexpr_poly(x, {{0, 1}, {1, 2}, {2, symbol("a")}});
    std::cout << a->diff(x)->__str__() << std::endl;

Output:

    2*a*x + 2
RCP<const Basic> expand( const RCP<const Basic> &self );

Expand self.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> a = uexpr_poly(x, {{1, 1}, {2, 1}, {3, symbol("a")}});
    RCP<const Basic> b = make_rcp<const Pow>(a, integer(3));
    std::cout << expand(b)->__str__() << std::endl;

Output:

    a**3*x**9 + 3*a**2*x**8 + (2*a + a*(1 + 2*a) + a**2)*x**7 + (1 + 6*a)*x**6 + (3 + 3*a)*x**5 + 3*x**4 + x**3
template <typename Poly> RCP<const Poly> add_upoly( const Poly &a, const Poly &b );

Return the sum of a and b when a and b have the same variable, otherwise throw a runtime exception.

Example:

    RCP<const Symbol> x = symbol("x");
    UExprDict adict_({{0, 1}, {1, 2}, {2, symbol("a")}});
    UExprDict bdict_({{0, 2}, {1, 3}, {2, symbol("b")}});
    const UExprPoly a(x, std::move(adict_));
    const UExprPoly b(x, std::move(bdict_));
    std::cout << add_upoly(a, b)->__str__() << std::endl;

Output:

    (a + b)*x**2 + 5*x + 3
template <typename Poly> RCP<const Poly> neg_upoly( const Poly &a );

Return the negation of a.

Example:

    RCP<const Symbol> x = symbol("x");
    UExprDict adict_({{0, 1}, {1, symbol("a")}, {2, symbol("c")}});
    const UExprPoly a(x, std::move(adict_));
    std::cout << neg_upoly(a)->__str__() << std::endl;

Output:

    -c*x**2 - a*x - 1
template <typename Poly> RCP<const Poly> sub_upoly( const Poly &a, const Poly &b );

Return the difference of a and b when a and b have the same variable, otherwise throw a runtime exception.

Example:

    RCP<const Symbol> x = symbol("x");
    UExprDict adict_({{0, 1}, {1, 2}, {2, 1}});
    UExprDict bdict_({{0, 2}, {1, symbol("b")}, {2, symbol("a")}});
    const UExprPoly a(x, std::move(adict_));
    const UExprPoly b(x, std::move(bdict_));
    std::cout << sub_upoly(b, a)->__str__() << std::endl;

Output:

    (-1 + a)*x**2 + (-2 + b)*x + 1
template <typename Poly> RCP<const Poly> mul_upoly( const Poly &a, const Poly &b );

Return the product of a and b when a and b have the same variable and neither a or b are monomial constants.

Example:

    RCP<const Symbol> x = symbol("x");
    RCP<const UExprPoly> a = uexpr_poly(x, {{0, 1}, {1, symbol("b")}, {2, symbol("a")}});
    RCP<const UExprPoly> b = uexpr_poly(x, {{0, -1}, {1, -2}, {2, mul(integer(-1), symbol("a"))}});
    std::cout << mul_upoly(*a, *b)->__str__() << std::endl;

Output:

    -a**2*x**4 + (-2*a - a*b)*x**3 + (-2*a - 2*b)*x**2 + (-2 - b)*x - 1
RCP<const UExprPoly> uexpr_poly( RCP<const Symbol> i, UExprDict &&dict );

Construct a UExprPoly object with variable i and a dictionary dict in the form of a UExprDict.

Example:

    RCP<const Symbol> x = symbol("x");
    UExprDict dict({{0, 1}, {1, 2}, {2, 1}});
    RCP<const UExprPoly> P = uexpr_poly(x, std::move(dict));
    std::cout << P->__str__() << std::endl;

Output:

    x**2 + 2*x + 1
RCP<const UExprPoly> uexpr_poly( RCP<const Symbol> i, map_int_Expr &&dict )

Construct a UExprPoly object with variable i and a dictionary dict in the form of a map_int_Expr.

Example:

    RCP<const Symbol> x = symbol("x");
    map_int_Expr dict = {{0, symbol("d")}, {1, 2}, {2, 3}, {3, symbol("a")}};
    RCP<const UExprPoly> P = uexpr_poly(x, std::move(dict));
    std::cout << P->__str__() << std::endl;

Output:

    a*x**3 + 3*x**2 + 2*x + d

Univariate Series

The UnivariateSeries class is a series expansion module that can perform the Taylor Series expansion of a univariable polynomial. A UnivariateSeries object holds:

  • A variable (std::string)
  • A dictionary (UExprDict(std::map))
  • The degree (long)

To use UnivariateSeries in a C++ project, include:

#include <symengine/series_generic.h>
using SymEngine::RCP;
using SymEngine::UnivariateSeries;
using SymEngine::UExprDict;
using SymEngine::Symbol;
using SymEngine::symbol;
using SymEngine::Expression;
using SymEngine::map_int_Expr;

Individual functionalities can be chosen separately, or can be used with just include using namespace SymEngine;

Functions

RCP<const Basic> get_coeff( int deg ) const

Return the coefficient at the degree deg.

Example:

    RCP<const Symbol> x = symbol("x");
    auto p = cos(x);
    auto ser = UnivariateSeries::series(p, x->get_name(), 3);
    // print the 2nd-term coefficient
    std::cout << *ser->get_coeff(2) << std::endl;

Output:

    -1/2
RCP<const UnivariateSeries> series( const RCP<const Basic> &t, const std::string &x, unsigned int prec )

Compute the series expansion of t with variable x with precision prec.

Example:

    RCP<const Symbol> x = symbol("x");
    auto p = sin(x);
    auto ser = UnivariateSeries::series(p, x->get_name(), 10);
    std::cout << *ser << std::endl;

Output:

    (1/362880)*x**9 + (-1/5040)*x**7 + (1/120)*x**5 + (-1/6)*x**3 + x + O(x**10)
RCP<const UnivariateSeries> univariate_series( RCP<const Symbol> i, unsigned int prec, const UExprDict &s )

Construct a UnivariateSeries object with variable i and a dictionary s with precision prec.

Example:

    RCP<const Symbol> x = symbol("x");
    UExprDict dict({{0, 1}, {1, 2}, {2, 1}});
    RCP<const UnivariateSeries> P = univariate_series(x, 2, dict);
    std::cout << P->__str__() << std::endl;

Output:

    x**2 + 2*x + 1 + O(x**2)

Multivariate Polynomial

To use the multivariable polynomial module, write #include <symengine/polynomial_multivariate.h> at the top of your file.

Both MultivariateIntPolynomialExpr and MultivariatePolynomialExpr objects and the associated functions exist in the namespace SymEngine.

Currently in SymEngine there are two multivariable polynomial classes: MultivariateIntPolynomialExpr and MultivariatePolynomialExpr. A MultivariateIntPolynomialExpr can hold a multivariable polynomial with integer_class coefficients, while a MultivariatePolynomialExpr can hold a multivariable Laurent polynomial with Expression coefficients. The creation of a multivariable polynomial should be handled by calling the appropriate create function

MultivariateIntPolynomialExpr p1 = MultivariateIntPolynomialExpr::create({x,y,z}, {{{0,0,0},1_z}
    {{0,0,1},2_z}, {{0,1,0},3_z},{{1,0,0},4_z},{{2,0,2},5_z}});

MultivariatePolynomialExpr p2 = MultivariatePolynomialExpr::create({x,y,z}, {{{0,0,0},Expression(symbol(“a”))},
    {{0,0,1},Expression(symbol(“b”))}, {{0,1,0},Expression(symbol(“c”))},{{1,0,0},Expression(symbol(“d”)
    {{1,2,0},Expression(symbol(“f”))}});

The first argument of the create function is a vec_basic (std::vector<RCP<const Basic>>) which contains the generators for the polynomial. The second argument is the dictionary of the polynomial, which is a map from vectors of exponents to coefficients -- so above, p1 is a polynomial representing 1 + 2*z + 3*y + 4*z + 5*x**2 z**2 and p2 represents a + b*z + c*y + d*x + f*x y**2. In the case of MultivariateIntPolynomialExpr the dictionary should be an umap_uvec_mpz (std::unordered_map<vec_uint, integer_class, vec_uint_hash>) and the dictionary of a MultivariatePolynomialExpr should be a umap_vec_expr (std::unordered_map<vec_int, Expression, vec_int_hash>).

Multivariable Polynomials can also be created from the appropriate univariable polynomials, like so

RCP<const UIntPoly> p1 = uint_poly(x, UExprDict({{1,1_z},{2,2_z},{3,2_z}}));
RCP<const UExprPoly> p2 = uexpr_poly(x, UExprDict({{1,Expression(1)},{2,Expression(2)},{3,Expression(2)}}));

MultivariateIntPolynomialExpr q1 = MultivariateIntPolynomialExpr::convert(*p1);
MultivariatePolynomialExpr q2 = MultivariatePolynomialExpr::convert(*p2);

String printing can be performed by means of the toString() function

MultivariateIntPolynomialExpr p1 = MultivariateIntPolynomialExpr::create({x,y,z}, {{{0,0,0},1_z}
    {{0,0,1},2_z}, {{0,1,0},3_z},{{1,0,0},4_z},{{2,0,2},5_z}});

MultivariatePolynomialExpr p2 = MultivariatePolynomialExpr::create({x,y,z}, {{{0,0,0},Expression(symbol(“a”))},
    {{0,0,1},Expression(symbol(“b”))}, {{0,1,0},Expression(symbol(“c”))},{{1,0,0},Expression(symbol(“d”)
    {{1,2,0},Expression(symbol(“f”))}});

std::cout << p1.toString() << std::endl;
std::cout << ps.toString() << std::endl;

Arithmetic operations

Addition, subtraction, and multiplication between multivariable polynomials and between multivariable polynomials and the associated univariable polynomial classes can be performed by non-member functions. For example, with MultivariatePolynomialExprs and UExprPoly’s:

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x,y,z},{{{0,0,0},Expression(1)}
    {{0,0,1},Expression(2)}, {{0,1,0},Expression(3)},{{1,0,0},Expression(4)},{{2,0,2},Expression(5)}});
MultivariatePolynomialExpr p2 = MultivariatePolynomialExpr::create({w,x,y},{{{0,0,0},Expression(6)}, 
    {{0,0,1},Expression(7)}, {{0,1,0},Expression(8)},{{1,0,0},Expression(9)},{{2,0,2},Expression(10)}});
RCP<const UExprPoly> p3 = uexpr_poly(x, UExprDict({{1,Expression(1)},{2,Expression(2)},{3,Expression(2)}}));
RCP<const UExprPoly> p4 = uexpr_poly(y, UExprDict({{1,Expression(1)},{2,Expression(2)},{3,Expression(2)}}));

MultivariatePolynomialExpr q1 = add_mult_poly(p1,p2);
q1 = add_mult_poly(p1,*p3);
q1 = add_mult_poly(*p3,*p4);

q1 = mul_mult_poly(p1,p2);
q1 = mul_mult_poly(p1,*p3);
q1 = mul_mult_poly(*p3,*p4);

q1 = sub_mult_poly(p1,p2);
q1 = sub_mult_poly(p1,*p3);
q1 = sub_mult_poly(*p3,*p4);

The operations with MultivariateIntPolynomialExprs are similar. Additionally, operations purely between multivariable polynomials can be performed by member functions.

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x,y,z},{{{0,0,0},Expression(1)}, 
    {{0,0,1},Expression(2)}, {{0,1,0},Expression(3)},{{1,0,0},Expression(4)},{{2,0,2},Expression(5)}});
MultivariatePolynomialExpr p2 = MultivariatePolynomialExpr::create({w,x,y},{{{0,0,0},Expression(6)}, 
    {{0,0,1},Expression(7)}, {{0,1,0},Expression(8)},{{1,0,0},Expression(9)},{{2,0,2},Expression(10)}});

MultivariatePolynomialExpr q1 = p1.add(p2); 
q1 = p1.sub(p2); 
q1 = p1.mul(p2); 
q1 = p1.neg(); 

MultivariateIntPolynomialExpr p3 = MultivariateIntPolynomialExpr::create({x,y,z},{{{0,0,0},1_z}, 
    {{0,0,1},2_z}, {{0,1,0},3_z},{{1,0,0},4_z},{{2,0,2},5_z}});
MultivariateIntPolynomialExpr p4 = MultivariatePolynomialExpr::create({w,x,y},{{{0,0,0},6_z}, {{0,0,1},7_z}, 
    {{0,1,0},8_z},{{1,0,0},9_z},{{2,0,2},10_z}});

MultivariateIntPolynomialExpr q2 = p3.add(p4); 
q2 = p3.sub(p4); 
q2 = p3.mul(p4); 
q2 = p3.neg(); 

Multivariable polynomials can also be evaluated at n-tuples as follows:

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x,y,z},{{{0,0,0},Expression(1)}, 
    {{0,0,1},Expression(2)}, {{0,1,0},Expression(3)},{{1,0,0},Expression(4)},{{2,0,2},Expression(5)}});
MultivariateIntPolynomialExpr p2 = MultivariateIntPolynomialExpr::create({x,y,z},{{{0,0,0},1_z}, 
    {{0,0,1},2_z}, {{0,1,0},3_z},{{1,0,0},4_z},{{2,0,2},5_z}});

std::map<RCP<const Basic>, Expression, RCPBasicKeyLess> m1 = {{x,Expression(1)},{y,Expression(2)},{z,Expression(3)}};
std::map<RCP<const Basic>, integer_class, RCPBasicKeyLess> m2 = {{x,1_z},{y,2_z},{z,3_z}};

Expression n1 = p1->eval(m1);
integer_class n2 = p2->eval(m2);

The map passed to eval should contain a key-value pair for each variable of the polynomial; partial evaluation is not supported.

Equality can be tested with the function __eq__

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x,y,z},{{{0,0,0},Expression(1)}, 
    {{0,0,1},Expression(2)}, {{0,1,0},Expression(3)},{{1,0,0},Expression(4)},{{2,0,2},Expression(5)}});
MultivariatePolynomialExpr p2 = MultivariatePolynomialExpr::create({w,x,y},{{{0,0,0},Expression(6)}, 
    {{0,0,1},Expression(7)}, {{0,1,0},Expression(8)},{{1,0,0},Expression(9)},{{2,0,2},Expression(10)}});
RCP<const UExprPoly> p3 = uexpr_poly(x, UExprDict({{1,Expression(1)},{2,Expression(2)},{3,Expression(2)}}));
RCP<const UExprPoly> p4 = uexpr_poly(y, UExprDict({{1,Expression(1)},{2,Expression(2)},{3,Expression(2)}}));

bool eq1 = p1->__eq__(*p2);
bool eq2 = p3->__eq__(*p4);

The get_args function returns a vec_basic containing RCP<const Basic>s representing each term of the polynomial

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x,y,z},{{{0,0,0},Expression(1)}, 
    {{0,0,1},Expression(2)}, {{0,1,0},Expression(3)},{{1,0,0},Expression(4)},{{2,0,2},Expression(5)}});
MultivariateIntPolynomialExpr p2 = MultivariateIntPolynomialExpr::create({x,y,z},{{{0,0,0},1_z}, 
    {{0,0,1},2_z}, {{0,1,0},3_z},{{1,0,0},4_z},{{2,0,2},5_z}});

vec_basic b1 = p1->get_args();
vec_basic b2 = p2->get_args();

The following overloaded operators are provided for MultivariatePolynomialExpr:

MultivariatePolynomialExpr& operator=( const MultivariatePolynomialExpr& );
MultivariatePolynomialExpr& operator=( const Expression& );
friend MultivariatePolynomialExpr operator+( const MultivariatePolynomialExpr&, const MultivariatePolynomialExpr& );
friend MultivariatePolynomialExpr operator+( const MultivariatePolynomialExpr&, const Expression& );
friend MultivariatePolynomialExpr operator+( const Expression&, const MultivariatePolynomialExpr& );
MultivariatePolynomialExpr& operator+=( const MultivariatePolynomialExpr& );
MultivariatePolynomialExpr& operator+=( const Expression& );
friend MultivariatePolynomialExpr operator-( const MultivariatePolynomialExpr&, const MultivariatePolynomialExpr&  );
friend MultivariatePolynomialExpr operator-( const MultivariatePolynomialExpr&, const Expression& );
friend MultivariatePolynomialExpr operator-( const Expression&, const MultivariatePolynomialExpr& );
MultivariateExprPolynomial& operator-=( const MultivariatePolynomialExpr& );
MultivariatePolynomialExpr& operator-=( const Expression& );
MultivariateExprPolynomial operator-( ) const;
friend MultivariatePolynomialExpr operator*( const MultivariatePolynomialExpr&, const MultivariatePolynomialExpr& );
friend MultivariatePolynomialExpr operator*( const MultivariatePolynomialExpr&, const Expression& );
friend MultivariatePolynomialExpr operator*( const Expression&, const MultivariatePolynomialExpr& );
MultivariateExprPolynomial& operator*= (const MultivariatePolynomialExpr& );
MultivariatePolynomialExpr& operator*=( const Expression& );
friend MultivariatePolynomialExpr operator/( const MultivariatePolynomialExpr&, const Expression& )/
MultivariatePolynomialExpr& operator/=( const Expression &b );
bool operator==( const MultivariatePolynomialExpr& );
bool operator==( const Expression );
bool operator!=( const MultivariatePolynomialExpr& );
bool operator!=( const Expression& );

Multivariate Series

To access the multivariable series module, write #include <symengine/series_generic_multivariate.h> at the top of your file.

The MultivariateSeries object and the mult_series functions all exist in the namespace SymEngine.

Two MultivariateSeries constructors are provided. The first is the same constructor provided for all SeriesBase objects:

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x},{{{0},Expression(0)},{{1},Expression(1)},{{2},Expression(3)}}));
RCP<const MultivariateSeries> s = make_rcp<const MultivariateSeries>(p,”x”,10);

If the polynomial passed to this constructor has more than one generator, or the generator of the polynomial does not match the second argument, SYMENGINE_ASSERT will fail in debug mode.

The second constructor takes a map_basic_uint (std::map<RCP<const basic>, unsigned int, RCPSymbolCompare>) in addition to the parameters demanded by the first constructor. The map_basic_uint defines the precision of the series.

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x,y},{{{0},Expression(0)},{{1},Expression(1)},{{2},Expression(3)}}));
map_basic_uint m = {{x,10},{y,10},{z,240}}
RCP<const MultivariateSeries> s = make_rcp<const MultivariateSeries>(p,”x”,10, m);

If the image of a generator in the map_basic_uint is not greater than the degree of that generator in the polynomial, or if a generator of the polynomial is not represented in the map_basic_uint, SYMENGINE_ASSERT will fail in debug mode.

For both constructors, if the polynomial is non-constant and does not have the generator symbol(var), SYMENGINE_ASSERT will fail in debug mode.

A MultivariateSeries can also be created by the create or multivariate_series functions, both of which call the first constructor.

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x},{{{0},Expression(0)},{{1},Expression(1)},{{2},Expression(3)}});
RCP<const MultivariateSeries> s = MultivariateSeries::create(x,10,p1);
s = multivariate_series(x,10,p1) ;

get_coeff will return the coefficient of the series associated with a particular degree term. For this function, we treat the series as if it were solely in terms of the generator corresponding to the variable var, so that if the series s represents x**2 y + x**2 + x + y + O(|x|**3 + |y|**3) with var equal to “x”, s->get_coeff(2) should equal y + 1. This object is returned as an object of type Add rather than as a polynomial.

MultivariatePolynomialExpr p1 = MultivariatePolynomialExpr::create({x,y},{{{0,0},Expression(0)},{{2,0},Expression(1)},{{0,2},Expression(3)}}));
map_basic_uint m = {{x,10},{y,10},{z,240}}
RCP<const MultivariateSeries> s = make_rcp<const MultivariateSeries>(p,”x”,10, m);
RCP<const Basic> p = s->get_coeff(9);

Series expansion with respect to a single variable can be done in the same manner as any other SeriesBase object.

RCP<const Basic> f = sin(x);
RCP<const MultivariateSeries> s = MultivariateSeries::series(f,”x”,10);

There are a couple of methods for performing series expansion with respect to multiple variables. The first, mult_series1, is a reference implementation which calculates the expansion through repeated differentiation.

RCP<const Basic> f = sin(add(x,y));
RCP<const MultivariateSeries> s = mult_series1(f,{{x,5},{y,5}});

The first argument is a RCP<const Basic> representing the function to be expanded; the second determines the precision in each variable to which the function will be expanded.

The mult_series is a template which calculates the expansion by calculating the series expansion for each variable in turn. The template parameter Series determines the series object used in this expansion; it can take any SeriesBase type object. Regardless of the value of Series, mult_series will always return a MultivariableSeries. The arguments are the same as for mult_series1.

RCP<const Basic> f = sin(add(x,y));
RCP<const MultivariateSeries> s = mult_series<MultivariateSeries>(f,{{x,5},{y,5}});
RCP<const MultivariateSeries> s = mult_series<UnivariateSeries>(f,{{x,5},{y,5}});
Clone this wiki locally