# Is there a way to get the homogeneous part of certain degree of a (multivariate) polynomial?

Every multivariate polynomial $f\in\Bbb F[x_1,\ldots,x_n]$ of degree $d$ can be written as $f = f_0+f_1+\cdots+f_d$, where $f_i$ is a homogeneous polynomial of degree $i$. Is there a direct way to get each $f_i$ given $f$ in SageMath? For a specific application I have where I only need $f_d$ I am homogenizing and then setting $h=0$, and based on this I wrote an ugly script that recursively finds $f_i$.

Is there a cleaner (and more efficient) way to do this?

Thanks for the help!

EDIT:

This is the code I'm using to obtain $f_d$ from $f$

fd = R( f.homogenize()(h=0) )


where R is the multivariate polynomial ring (parent of $f$). If I want $f_{d-1}$ for example, I can define $g$ as $f - f_d$ and apply the line to $g$. This recursive definition is not satisfactory since to get $f_i$ I need to have all $f_{i+1},\ldots,f_d$ first, which is inefficient. Also, that trick of homogenizing, evaluating $h=0$ and coercing the result back to the original polynomial ring is not very neat.

edit retag close merge delete

Hint: if you provide your code, the collective wisdom of Ask Sage answerers may help improve it!

( 2017-10-15 14:14:19 -0500 )edit

@slelievre Ok! I'm new in this forum, thanks for pointing that out! I've edited my answer, hopefully that helps :)

( 2017-10-15 16:56:12 -0500 )edit

Sort by ยป oldest newest most voted

Here is a possible way:

Landscape (a concrete example to fix ideas):

sage: R.<x,y> = QQ[]
sage: P = x^2+x*y+x+2


Instead of a list (with possibly lot of zeroes), let me use a defaultdict to collect the polynomials:

sage: from collections import defaultdict
sage: d = defaultdict(P.parent())


Then we can feed it by iterating over the polynomial:

sage: for coeff,monom in P:
....:     d[monom.degree()] += coeff * monom


So we have:

sage: d
defaultdict(Multivariate Polynomial Ring in x, y over Rational Field, {0: 2, 1: x, 2: x^2 + x*y})
sage: d[0]
2
sage: d[1]
x
sage: d[2]
x^2 + x*y
sage: d[3]
0
sage: d[123]
0
sage: d[123].parent()
Multivariate Polynomial Ring in x, y over Rational Field
sage: sum(d[i] for i in d)
x^2 + x*y + x + 2
sage: sum(d[i] for i in d) == P
True

more

Thanks a lot for the reply! Something I didn't know is that I could iterate over coefficients and monomials of a polynomial like you did (where is that stated in the documentation?), that makes the work much easier.

( 2017-10-16 07:35:04 -0500 )edit

The problem is that the __iter__ method is hidden, but you can get its documentation as follows:

 sage: P.__iter__?

( 2017-10-16 10:16:17 -0500 )edit

Just an other way, extract a version of dPart below adapted for the own needs...

Let us fix some test data.

sage: var( 'x,y,z' );
sage: F = 27*x^5 + x^2*y^2 + 19*z^4 + 55*x*y*z + 6
sage: F = F.polynomial( QQ )


(1)

sage: def dPart( F, d ):
....:     return sum( [ F.monomial_coefficient(m) * m
....:                   for m in F.monomials()
....:                   if  m.total_degree() == d ] )
....:

sage: for d in range(6):
....:     print "total degree %s -> %s" % ( d, dPart( F, d ) )
....:
total degree 0 -> 6
total degree 1 -> 0
total degree 2 -> 0
total degree 3 -> 55*x*y*z
total degree 4 -> x^2*y^2 + 19*z^4
total degree 5 -> 27*x^5


(2) "Same", but not so easy to digest:

dPart = lambda F, d: sum( [ c*m for c,m in F if m.total_degree() == d ] )


(3) Or parse correspondingly the information in F.dict(), but this would be the too explicit solution:

sage: def dPart( F, d ):
....:     vars = F.variables()
....:     return sum( [ coeff * prod( [ vars[k]^degrees[k] for k in range(len(vars)) ] )
....:                   for degrees, coeff in F.dict().items()
....:                   if  sum(degrees) == d ] )

more

Thanks for your answer! I like this approach. However, every time you need the same polynimial you need to do the same iteration over and over again, which is avoided in the solution in the other answer by using the dictionary. What I like about this one though is how concise it is (specially the lambda one)

( 2017-10-16 07:34:56 -0500 )edit

If you don't want to write your own functions, you can also try adding O(d+1) in the corresponding power series ring to kill all higher order terms, then extract the polynomial back using .polynomial(), and then using your homogenize idea

more