Apart function

75 views
Skip to first unread message

clemens novak

unread,
Aug 20, 2014, 7:15:29 AM8/20/14
to sy...@googlegroups.com
I have a question regarding the apart function. I want to obtain the partial fractions for eq = z / (z**2-z-1) . 

The denominator has real roots solve(denom(eq)) yields [1/2 + sqrt(5)/2 , 1/2- sqrt(5)/2], but apart does not return the partial fractions; i,e. apart(eq, z) = z/(z**2 - z - 1) .

Using apart(eq, z, full=True) yields RootSum(_w**2 - _w - 1, Lambda(_a, (_a/5 + 2/5)/(-_a + z))) which doesn't seem to be of much help (at least for me).

Using apart with a fraction with "simpler" roots produces the desired partial fractions; e.g. apart (z / (z**2+z-2), z) yields 2/(3*(z + 2)) + 1/(3*(z - 1))

Are there any additional options I can provide to apart to obtain the desired result?

Thanks & regards - Clemens

Ondřej Čertík

unread,
Aug 20, 2014, 3:28:24 PM8/20/14
to sympy
Hi Clemens,
Good point. I checked Mathematica and it produces the same result as SymPy.
However, clearly this can be decomposed, so I don't quite understand
if this is a bug in Mathematica as well,
or whether perhaps there is some reason not to do the decomposition
for this case.

Ondrej

>
> Thanks & regards - Clemens
>
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/97ec7958-e6c8-4871-90fa-d53c06b0a2b6%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Mateusz Paprocki

unread,
Aug 20, 2014, 5:45:55 PM8/20/14
to sympy
Hi,

On 20 August 2014 21:28, Ondřej Čertík <ondrej...@gmail.com> wrote:
> Hi Clemens,
>
> On Wed, Aug 20, 2014 at 5:15 AM, clemens novak <clen...@gmail.com> wrote:
>> I have a question regarding the apart function. I want to obtain the partial
>> fractions for eq = z / (z**2-z-1) .
>>
>> The denominator has real roots solve(denom(eq)) yields [1/2 + sqrt(5)/2 ,
>> 1/2- sqrt(5)/2], but apart does not return the partial fractions; i,e.
>> apart(eq, z) = z/(z**2 - z - 1) .
>>
>> Using apart(eq, z, full=True) yields RootSum(_w**2 - _w - 1, Lambda(_a,
>> (_a/5 + 2/5)/(-_a + z))) which doesn't seem to be of much help (at least for
>> me).
>>
>> Using apart with a fraction with "simpler" roots produces the desired
>> partial fractions; e.g. apart (z / (z**2+z-2), z) yields 2/(3*(z + 2)) +
>> 1/(3*(z - 1))
>>
>> Are there any additional options I can provide to apart to obtain the
>> desired result?
>
> Good point. I checked Mathematica and it produces the same result as SymPy.
> However, clearly this can be decomposed, so I don't quite understand
> if this is a bug in Mathematica as well,
> or whether perhaps there is some reason not to do the decomposition
> for this case.

There is no bug in this case. apart() uses polynomial factorization
routines to "decompose" the denominator. By default, sympy (but also
many other computer algebra systems) work over the rationals and z**2
- z - 1 doesn't have rational zeros. If you invoke apart(f, z), then
you will get partial fraction decomposition over rationals. To get the
expected result, you have set the domain of computation properly, e.g.
apart(f, z, extension=sqrt(5)) is helpful in this case. apart()
accepts all options that factor() and other polynomial manipulation
functions accept.

In [1]: apart(z/(z**2 - z - 1), z, extension=sqrt(5))
Out[1]:
___ ___
╲╱ 5 + 5 -5 + ╲╱ 5
─────────────────── - ───────────────────
⎛ ___ ⎞ ⎛ ___⎞
5⋅⎝2⋅z - ╲╱ 5 - 1⎠ 5⋅⎝2⋅z - 1 + ╲╱ 5 ⎠

In [2]: simplify(_)
Out[2]:
z
──────────
2
z - z - 1

Another option is to use full=True (no need for extension, because
this method doesn't use factorization at all). The result seems
useless at first but you can use .doit() on the resulting RootSum to
get more familiar result:

In [1]: apart(z/(z**2 - z - 1), z, full=True)
Out[1]:
⎛ a 2 ⎞
⎜ ─ + ─ ⎟
⎜ 2 5 5 ⎟
RootSum⎜w - w - 1, a ↦ ──────⎟
⎝ -a + z⎠

In [2]: _.doit()
Out[2]:
___ ___
╲╱ 5 1 ╲╱ 5 1
───── + ─ - ───── + ─
10 2 10 2
───────────── + ─────────────
___ ___
╲╱ 5 1 1 ╲╱ 5
z - ───── - ─ z - ─ + ─────
2 2 2 2

In [3]: simplify(_)
Out[3]:
z
──────────
2
z - z - 1

It would be good to document this in apart()'s docstring (the current
one is pretty weak), because it's a common misconception that apart()
uses either roots() or solve() to decompose the denominator.

Mateusz

> Ondrej
>
>>
>> Thanks & regards - Clemens
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "sympy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to sympy+un...@googlegroups.com.
>> To post to this group, send email to sy...@googlegroups.com.
>> Visit this group at http://groups.google.com/group/sympy.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/sympy/97ec7958-e6c8-4871-90fa-d53c06b0a2b6%40googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CADDwiVA8P6izbs%2Ba2QtGm9ntFNzxO%2ByVMSROmuvuG5iqetvLMg%40mail.gmail.com.

clemens novak

unread,
Aug 21, 2014, 10:26:32 AM8/21/14
to sy...@googlegroups.com
Hello,

thanks for quick answer and support. Both suggestions (apart with full=True + doit() and apart with extension) work for me.


"By default, the factorization is computed over the rationals. To factor over other domain, e.g. an lgebraic or finite field, use appropriate options:
``extension``, ``modulus`` or ``domain``."

I don't quite get it:

"extension" allows providing a list of irrational numbers which shall be considered during factorization:

eq = x**2 - sqrt(2)*x + sqrt(3)*x - sqrt(6)
factor(eq, extension=[sqrt(2), sqrt(3)])

This works for complex numbers as well

eq = x**2+x+5
factor(eq, extension=sqrt(-19))


"modulus allows factorization over a finite field (there is an example in the "docstring)

However, I don't get the use of "domain" - from the name I would assume that you can restrict the domain (e.g. integer, ration, irrational, complex...) from which the factors are obtained? What domains does sympy provide (and where can I find that in the documentation)?

If you want I can try to improve the apart (maybe also the factor) docstring and send a corresponding PR (probably in the next few days).

Regards - Clemens

Ondřej Čertík

unread,
Aug 21, 2014, 11:53:44 AM8/21/14
to sympy
That would be awesome --- I was going to suggest if you could send a
PR with a better docstring. Those are best written by somebody new to
sympy like you, who just figured out how it works and so can document
it in a way that other new people will understand well.

Ondrej

>
> Regards - Clemens
>
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/ed1fcf30-233e-4551-8b34-040e047e42c5%40googlegroups.com.

Mateusz Paprocki

unread,
Aug 21, 2014, 4:05:42 PM8/21/14
to sympy
Hi,
Domain is the ultimate way to set the domain of computation.
extension, modulus, etc. are helpers, that, in the end, will generate
a domain. For example:

In [1]: Poly(x**2 + sqrt(2), extension=sqrt(2))
Out[1]: Poly(x**2 + sqrt(2), x, domain='QQ<sqrt(2)>')

You can see that extension=sqrt(2) really means an algebraic domain
over sqrt(2). In case of x**2 + sqrt(2) you could use extension=True
as well (equivalent of Mathematica's auto):

In [2]: Poly(x**2 + sqrt(2), extension=True)
Out[2]: Poly(x**2 + sqrt(2), x, domain='QQ<sqrt(2)>')

Ultimately you can construct domain yourself:

In [3]: Poly(x**2 + sqrt(2), domain=QQ.algebraic_field(sqrt(2)))
Out[3]: Poly(x**2 + sqrt(2), x, domain='QQ<sqrt(2)>')

extension allow you to type less and gives you Mathematica-like feel.
Domains can be useful on their own e.g.:

In [4]: x**2 + sqrt(2) in QQ[x]
Out[4]: False

In [5]: x**2 + sqrt(2) in QQ.algebraic_field(sqrt(2))[x]
Out[5]: True

Mateusz

> If you want I can try to improve the apart (maybe also the factor) docstring
> and send a corresponding PR (probably in the next few days).
>
> Regards - Clemens
>
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/ed1fcf30-233e-4551-8b34-040e047e42c5%40googlegroups.com.

Richard Fateman

unread,
Aug 21, 2014, 10:41:57 PM8/21/14
to sy...@googlegroups.com
You realize that you cannot express roots of polynomials in terms of radicals
generally?  

Maybe you should figure what you are doing with apart().
If it is integration of rational functions, maybe you should find another path.
RJF

clemens novak

unread,
Aug 22, 2014, 10:38:20 AM8/22/14
to sy...@googlegroups.com


I was trying to do the z-transform for a_n = a_{n-1} + a_{n-2} (Fibonacci Numbers) which leads to F(z) = z / (z**2-z-1). From my understanding, using apart to get a partial fraction decomposition is the way to go...? The discussion here sparked my curiosity...

Based on the dicussion I created a PR (#7905) which contains the (hopefully) improved apart docstring.

Thanks for the information regarding domains; I will need some time to understand this, though.

Regards - Clemens
Reply all
Reply to author
Forward
0 new messages