extracting terms from multinomial?

172 views
Skip to first unread message

Reckoner

unread,
Jun 21, 2012, 9:08:52 AM6/21/12
to sy...@googlegroups.com
Hi,

I'm trying to expand polynomials such as

(1+x+x**2+...+x**n)(1+y+y**2+...+y**n)

and I would like to keep only those terms where the sum of the
respective exponents is equal to some number. For example, I want only terms  x^k*y^m where (k+m)==N.

Can you help me get started with this using sympy? I read the documentation, but I'm not sure how to proceed with the extraction part. I can expand and create the polynomials just fine.

Thanks in advance.

manoj babu

unread,
Jun 21, 2012, 10:23:22 AM6/21/12
to sy...@googlegroups.com
Well i dont think there is some direct function in sympy doing this.
I would go for this.
suppose  expr = 1 + x*y + x**2 * y**2 + x**k * y**m .....
expr1 = expr.subs(x,y)
This would substitute all x's with y and ull now get a polynomial in y.
expr1.args
would return you  (1,y**2,y**4,y**k+m)
degree(expr1.args[..])
would return you the exponent.
I think you can sort it out from here and build a best code that suits your requirement.


--
You received this message because you are subscribed to the Google Groups "sympy" group.
To view this discussion on the web visit https://groups.google.com/d/msg/sympy/-/fU3tJk7pUDYJ.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.

krastano...@gmail.com

unread,
Jun 21, 2012, 10:37:56 AM6/21/12
to sy...@googlegroups.com
> expr1 = expr.subs(x,y)
This won't work because it will transform x**2+y**2 into 2*y**2

There must be something already implemented in the poly module,
however I do not know enough about it to tell.

manoj babu

unread,
Jun 21, 2012, 11:06:04 AM6/21/12
to sy...@googlegroups.com
I think you should anyway run a for loop...
using subs func in for loop where loop runs for each arg.
What we all need here is an index.
I think there is some function terms in polyclasses close to this.

--
You received this message because you are subscribed to the Google Groups "sympy" group.

Reckoner

unread,
Jun 21, 2012, 11:37:05 AM6/21/12
to sy...@googlegroups.com


To that end, how would I separate the multinomial by the '+' signs. In Mathematica one would do List@@polynomial. I want to take the 

'1+2*x**2'

and somehow get

{'1','2*x**2'}

This would help me iterate.

Thanks!


Chris Smith

unread,
Jun 21, 2012, 11:39:35 AM6/21/12
to sy...@googlegroups.com
Perhaps there is a method...if not, try

[a for a in Add.make_args(p.expand()) if sum(m.as_base_exp()[1] for m
in Mul.make_args(a)) == n]

e.g. if p = (1+x+x*y)*(x+y) and n = 2 then the result is [x*y, x**2]

krastano...@gmail.com

unread,
Jun 21, 2012, 11:42:37 AM6/21/12
to sy...@googlegroups.com
I would prefer using what is already implemented in the poly module.
This means that you must transform your expression into a polynomial:

In [2]: a = Poly(1+x**2+y)

In [6]: a.gens # the generators of the polynomial
Out[6]: (x, y)

In [3]: a.monoms() # the powers of each generator in each monomial
Out[3]: [(2, 0), (0, 1), (0, 0)]

In [4]: a.coeffs() # the coefficients in front of each monomial
Out[4]: [1, 1, 1]

krastano...@gmail.com

unread,
Jun 21, 2012, 11:43:56 AM6/21/12
to sy...@googlegroups.com
On 21 June 2012 17:42, krastano...@gmail.com
Disclaimer: I don't know much of the poly module, so a more direct
functionality may already be implemented there.

Aaron Meurer

unread,
Jun 21, 2012, 4:34:25 PM6/21/12
to sy...@googlegroups.com
I don't think there's an efficient function to do it, if that's what you're looking for (i.e., one that doesn't require full expansion). It's not too hard to come up with, though. 

Aaron Meurer
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To view this discussion on the web visit https://groups.google.com/d/msg/sympy/-/fU3tJk7pUDYJ.

Chris Smith

unread,
Jun 21, 2012, 5:17:23 PM6/21/12
to sy...@googlegroups.com
On Thu, Jun 21, 2012 at 3:34 PM, Aaron Meurer <asme...@gmail.com> wrote:
> I don't think there's an efficient function to do it, if that's what you're
> looking for (i.e., one that doesn't require full expansion). It's not too
> hard to come up with, though.

(I gave up when I started chasing the recursion rabbit...I don't think
it's a trivial problem to handle it in a general way.)

>

Putting together some of the suggestions so far gives something like this:

>>> def order(p, n):
... p = Poly(p, p.free_symbols or Dummy())
... gens = p.gens
... ok = []
... for m, c in p.terms():
... if sum(m) == n:
... ok.append(Mul(*[g**e for g, e in zip(gens, m)]))
... return ok
...
>>> order(p, 2)
[x*y, y**2]
>>> p
(x*y + 1)*(x + y**2 + 1)

Note that making a Poly out of something automatically expands it. And
using a Dummy in case there is no generator is necessary in case p is
a constant.

Regarding the question about getting the terms...If you don't use Poly
and want the terms of an expression, Add.make_args(expr) will give you
the terms that add together to give expr (even if expr isn't an Add).
If you know expr is an Add then you could simply do expr.args to get
the terms.

/chris

Aaron Meurer

unread,
Jul 23, 2012, 5:40:50 PM7/23/12
to sy...@googlegroups.com
On Thu, Jun 21, 2012 at 3:17 PM, Chris Smith <smi...@gmail.com> wrote:
> On Thu, Jun 21, 2012 at 3:34 PM, Aaron Meurer <asme...@gmail.com> wrote:
>> I don't think there's an efficient function to do it, if that's what you're
>> looking for (i.e., one that doesn't require full expansion). It's not too
>> hard to come up with, though.
>
> (I gave up when I started chasing the recursion rabbit...I don't think
> it's a trivial problem to handle it in a general way.)

You don't have to do it recursively. You just want the terms such that
k + m = N. Poly.monoms() gives all the monomials, ordered
lexicographically (i.e., by total degree).

For example, if the monomials for your polys are [5, 4, 3, 2, 1, 0]
and [4, 2, 1] (say you have x**5 + 2*x**4 - x**3 + x**2 - 2*x + 1 and
x**4 - x**2 + x), and you want the term in the product of degree 5,
then you just need to pair up (5, 0), (4, 1), (3, 2), (2, 3), (1, 4),
and (0, 5). In this case, only (4, 1), (3, 2), and (1, 4) are
non-zero, so the result is -2*1 + -1*-1 + 1*1 = 1. This can easily be
generalized to multivariate polynomials and total degree. You just
sum each term from monoms(), and be sure to catch all terms of
whatever degree you are looking for.

Aaron Meurer

>
>>
>
> Putting together some of the suggestions so far gives something like this:
>
>>>> def order(p, n):
> ... p = Poly(p, p.free_symbols or Dummy())
> ... gens = p.gens
> ... ok = []
> ... for m, c in p.terms():
> ... if sum(m) == n:
> ... ok.append(Mul(*[g**e for g, e in zip(gens, m)]))
> ... return ok
> ...
>>>> order(p, 2)
> [x*y, y**2]
>>>> p
> (x*y + 1)*(x + y**2 + 1)
>
> Note that making a Poly out of something automatically expands it. And
> using a Dummy in case there is no generator is necessary in case p is
> a constant.
>
> Regarding the question about getting the terms...If you don't use Poly
> and want the terms of an expression, Add.make_args(expr) will give you
> the terms that add together to give expr (even if expr isn't an Add).
> If you know expr is an Add then you could simply do expr.args to get
> the terms.
>
> /chris
>
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.

Chris Smith

unread,
Jul 25, 2012, 2:59:53 PM7/25/12
to sy...@googlegroups.com
On Tue, Jul 24, 2012 at 3:25 AM, Aaron Meurer <asme...@gmail.com> wrote:
On Thu, Jun 21, 2012 at 3:17 PM, Chris Smith <smi...@gmail.com> wrote:
> On Thu, Jun 21, 2012 at 3:34 PM, Aaron Meurer <asme...@gmail.com> wrote:
>> I don't think there's an efficient function to do it, if that's what you're
>> looking for (i.e., one that doesn't require full expansion). It's not too
>> hard to come up with, though.
>
> (I gave up when I started chasing the recursion rabbit...I don't think
> it's a trivial problem to handle it in a general way.)

You don't have to do it recursively. You just want the terms such that
k + m = N.  Poly.monoms() gives all the monomials, ordered
lexicographically (i.e., by total degree).

For example, if the monomials for your polys are [5, 4, 3, 2, 1, 0]
and [4, 2, 1] (say you have x**5 + 2*x**4 - x**3 + x**2 - 2*x + 1 and
x**4 - x**2 + x), and you want the term in the product of degree 5,
then you just need to pair up (5, 0), (4, 1), (3, 2), (2, 3), (1, 4),
and (0, 5).  In this case, only (4, 1), (3, 2), and (1, 4) are
non-zero, so the result is -2*1 + -1*-1 + 1*1 = 1.  This can easily be
generalized to multivariate polynomials and total degree.  You just
sum each term from monoms(), and be sure to catch all terms of
whatever degree you are looking for.


By general, I meant things like `(x + (x**2 + 2*x - 7)**3)**5`
Reply all
Reply to author
Forward
0 new messages