Ask Your Question

Revision history [back]

A multivariate polynomial has a method to produce a dictionary whose keys are exponent tuples and whose values are coefficients for the corresponding monomials.

A polynomial ring can in turn convert such a dictionary into a polynomial.

With these conversions in mind, the process becomes easy!

Define a polynomial ring and a polynomial:

sage: R.<x, y, z> = QQ[]
sage: f = x^10*y^5 + x^5*y^2 + x^2*z^2
sage: f
x^10*y^5 + x^5*y^2 + x^2*z^2

Turn it into a dictionary:

sage: d = f.dict()
sage: d
{(10, 5, 0): 1, (5, 2, 0): 1, (2, 0, 2): 1}

Extract a dictionary with the congruence condition:

sage: dd = {ee: c for ee, c in d.items() if all(e % 5 == 0 for e in ee)}
sage: dd
{(10, 5, 0): 1}

Turn the extracted dictionary back into a polynomial:

sage: R(dd)
x^10*y^5

These steps can be combined into a function.

Readable version:

def restrict_exponents_to_multiples(f, n):
    R = f.parent()
    d = f.dict()
    dd = {ee: c for ee, c in d.items() if all(e % n == 0 for e in ee)}
    return R(dd)

Compact version:

def restrict_exponents_to_multiples(f, n):
    return f.parent()({ee: c for ee, c in f.dict().items()
                             if all(e % n == 0 for e in ee)})

Use the function:

sage: R.<x,y,z> = QQ[]
sage: f = x^10*y^5 + x^5*y^2 + x^2*z^2
sage: restrict_exponents_to_multiples(f, 5)
x^10*y^5

Pure n-th power monomials of a polynomial

Two methods to extract the "pure n-th power monomials" in a multivariate polynomial in Sage:

  • "dictionary of monomials and coefficients" corresponds to "method 1" in the question

  • "taking n-th roots of monomials" corresponds to "method 2" in the question

Dictionary of monomials and coefficients

A multivariate polynomial has a method to produce a dictionary whose keys are exponent tuples and whose values are coefficients for the corresponding monomials.

A polynomial ring can in turn convert such a dictionary into a polynomial.

With these conversions in mind, the process becomes easy!

Define a polynomial ring and a polynomial:

sage: R.<x, y, z> = QQ[]
sage: f = x^10*y^5 + x^5*y^2 + x^2*z^2
sage: f
x^10*y^5 + x^5*y^2 + x^2*z^2

Turn it into a dictionary:

sage: d = f.dict()
sage: d
{(10, 5, 0): 1, (5, 2, 0): 1, (2, 0, 2): 1}

Extract a dictionary with the congruence condition:

sage: dd = {ee: c for ee, c in d.items() if all(e % 5 == 0 for e in ee)}
sage: dd
{(10, 5, 0): 1}

Turn the extracted dictionary back into a polynomial:

sage: R(dd)
x^10*y^5

These steps can be combined into a function.

Readable version:

def restrict_exponents_to_multiples(f, only_perfect_power_monomials(f, n):
    R = f.parent()
    d = f.dict()
    dd = {ee: c for ee, c in d.items() if all(e % n == 0 for e in ee)}
    return R(dd)

Compact version:

def restrict_exponents_to_multiples(f, only_perfect_power_monomials(f, n):
    return f.parent()({ee: c for ee, c in f.dict().items()
                             if all(e % n == 0 for e in ee)})

Use the function:

sage: R.<x,y,z> R.<x, y, z> = QQ[]
sage: f = x^10*y^5 + x^5*y^2 + x^2*z^2
sage: restrict_exponents_to_multiples(f, only_perfect_power_monomials(f, 5)
x^10*y^5

Taking n-th roots of monomials

We cannot take the fifth root of a polynomial variable, but if a monomial happens to be a perfect fifth power, then we can take its fifth root.

Let us illustrate this and then use it.

Define a polynomial ring and a polynomial:

sage: R.<x, y, z> = QQ[]
sage: f = x^10*y^5 + x^5*y^2 + x^2*z^2
sage: f
x^10*y^5 + x^5*y^2 + x^2*z^2

Extract its monomials and give them names:

sage: f.monomials()
[x^10*y^5, x^5*y^2, x^2*z^2]
sage: a, b, c = f.monomials()

Taking fifth roots of the monomials sometimes works:

sage: a^(1/5)
x^2*y

and sometimes fails:

sage: b^(1/5)
Traceback (most recent call last)
...
TypeError: no conversion of this rational to integer
...
During handling of the above exception, another exception occurred:
...
Traceback (most recent call last)
...
ValueError: not a 5th power

sage: c^(1/5)
Traceback (most recent call last)
...
TypeError: no conversion of this rational to integer
...
During handling of the above exception, another exception occurred:
...
Traceback (most recent call last)
...
ValueError: not a 5th power

Function that takes n-th roots of monomials if possible, zero otherwise:

def monomial_wise_nth_root_or_zero(f, n):
    R = f.parent()
    def nth_root_or_zero(m):
        try:
            return m^(1/n)
        except ValueError:
            return R.zero()
    mm = f.monomials()
    return sum([f[m] * nth_root_or_zero(m) for m in mm], R.zero())

Use the function:

sage: R.<x, y, z> = QQ[]
sage: f = x^10*y^5 + x^5*y^2 + x^2*z^2

sage: monomial_wise_nth_root_or_zero(f, 5)
x^2*y

Function that keeps only perfect n-th power monomials (choose your flavour):

def only_perfect_power_monomials(f, n):
    R = f.parent()
    def nth_root_or_zero(m):
        try:
            return m^(1/n)
        except ValueError:
            return R.zero()
    mm = f.monomials()
    return sum([f[m] * nth_root_or_zero(m)^n for m in mm], R.zero())

def only_perfect_power_monomials(f, n):
    R = f.parent()
    def keep_only_if_perfect_nth_power(m):
        try:
            return (m^(1/n))^n
        except ValueError:
            return R.zero()
    mm = f.monomials()
    return sum([f[m] * keep_only_if_perfect_nth_power(m) for m in mm], R.zero())

def only_perfect_power_monomials(f, n):
    R = f.parent()
    def keep_only_if_perfect_nth_power(m):
        try:
            m^(1/n)
            return m
        except ValueError:
            return R.zero()
    mm = f.monomials()
    return sum([f[m] * keep_only_if_perfect_nth_power(m) for m in mm], R.zero())

def only_perfect_power_monomials(f, n):
    R = f.parent()
    result = R.zero()
    for m in f.monomials():
        try:
            m^(1/n)
            result += f[m] * m
        except ValueError:
            pass
    return result

Use these functions:

sage: R.<x, y, z> = QQ[]
sage: f = x^10*y^5 + x^5*y^2 + x^2*z^2

sage: only_perfect_power_monomials(f, 5)
x^10*y^5