sympy / sympy

A computer algebra system written in pure Python

Home Page:https://sympy.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Formal Power Series with even or odd terms shouldn't return Piecewise formula for coefficients

pierre-haessig opened this issue · comments

In relation to Stack Overflow question about the Formal Power Series of the Sine function, it appears that current fps function returns a Formal Power Series with a coefficient formula which is a Piecewise-defined function (base on the oddity of the index k). Instead, the result would be simpler if the series was reindexed (k = 2n+1).

So here is an illustrative example to obtain the nth term of the power series of the sine function (which has only odd nonzero terms):

from sympy import simplify, fps, sin
from sympy.abc import x, n
sin_fps = fps(sin(x))

Here is the LaTeX display of the series, which isn't as compact as classically written since the series summation is done for all integers while only odd terms are non zeros.
LaTeX display of Formal Power Series of sine computed by sympy.fps(sin(x))

This expression can be simplified by replacing k by 2*n+1, but it requires quite some work:

  1. extract coefficient formula
  2. extract the formula of the odd term from within Piecewise expression
  3. substitute k replaced by 2n+1

Extraction of odd term formula:

ak = sin_fps.ak.formula # Piecewise expression
ak_odd = ak.args[0][0] # digging into Piecewise.args

odd coefficient of the power series of sine

Substitute k by 2n+1 (this requires some extra work to get a reference to the Dummy variable k that got actually used when building the formula):

k = sin_fps.ak.variables[0]
ak_odd.subs(k, 2*n+1)

odd coefficient of the power series of sine with k replaced by 2n+1

and this matches the classical formulation of sine series coefficients by having in mind that Γ(2n+2) = (2n+1)! (cf Gamma function).

It looks like the given form comes from here:

result = _rsolve_hypergeometric(f, x, P, Q, k, m)
if result is None:
return None
sol_list, ind, mp = result
sol_dict = defaultdict(lambda: S.Zero)
for res, cond in sol_list:
j, mk = cond.as_coeff_Add()
c = mk.coeff(k)
if j.is_integer is False:
res *= x**frac(j)
j = floor(j)
res = res.subs(k, (k - j) / c)
cond = Eq(k % c, j % c)
sol_dict[cond] += res # Group together formula for same conditions
sol = []
for cond, res in sol_dict.items():
sol.append((res, cond))
sol.append((S.Zero, True))
sol = Piecewise(*sol)

Maybe that code or some other code could be a bit smarter about recognising a Piecewise where the expression is zero in one of the cases.

Thanks for identifying the region. For now I don't have a development setup for SymPy and I guess that understanding the code would be really helped by using a step-by-step debugger.

By the way, is it just me or there are missing doc in rsolve_hypergeometric(f, x, P, Q, k, m): f and x are not documented? Is f(x) the function such that its power series coefficients are the a(n) coefficients mentioned in the docstring?

f and x are not documented?

Ideally they would be documented but this is an internal function and not all internal functions have docs.