# 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.

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.

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