Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GSoC] Implemented convolution operation of two formal power series #17017

Merged
merged 7 commits into from Jul 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
66 changes: 65 additions & 1 deletion sympy/series/formal.py
Expand Up @@ -16,14 +16,15 @@
from sympy.core.singleton import S
from sympy.core.symbol import Wild, Dummy, symbols, Symbol
from sympy.core.sympify import sympify
from sympy.discrete.convolutions import convolution
from sympy.functions.combinatorial.factorials import binomial, factorial, rf
from sympy.functions.elementary.integers import floor, frac, ceiling
from sympy.functions.elementary.miscellaneous import Min, Max
from sympy.functions.elementary.piecewise import Piecewise
from sympy.series.limits import Limit
from sympy.series.order import Order
from sympy.simplify.powsimp import powsimp
from sympy.series.sequences import sequence
from sympy.series.sequences import sequence, SeqMul
from sympy.series.series_class import SeriesBase


Expand Down Expand Up @@ -1143,6 +1144,69 @@ def integrate(self, x=None, **kwargs):

return self.func(f, self.x, self.x0, self.dir, (ak, self.xk, ind))

def product(self, other, x=None, n=6):
"""Multiplies two Formal Power Series, using discrete convolution and
return the truncated terms upto specified order.

Parameters
==========

n : Number, optional
Specifies the order of the term up to which the polynomial should
be truncated.

Examples
========

>>> from sympy import fps, sin, exp, convolution
>>> from sympy.abc import x
>>> f1 = fps(sin(x))
>>> f2 = fps(exp(x))

>>> f1.product(f2, x, 4)
x + x**2 + x**3/3 + O(x**4)

See Also
========

sympy.discrete.convolutions
"""
if x is None:
x = self.x
if n is None:
return iter(self)

other = sympify(other)

if not isinstance(other, FormalPowerSeries):
raise ValueError("Both series should be an instance of FormalPowerSeries"
" class.")

if self.dir != other.dir:
raise ValueError("Both series should be calculated from the"
" same direction.")
elif self.x0 != other.x0:
raise ValueError("Both series should be calculated about the"
" same point.")

elif self.x != other.x:
raise ValueError("Both series should have the same symbol.")

k = self.ak.variables[0]
coeff1 = sequence(self.ak.formula, (k, 0, oo))

k = other.ak.variables[0]
coeff2 = sequence(other.ak.formula, (k, 0, oo))

conv_coeff = convolution(coeff1[:n], coeff2[:n])

conv_seq = sequence(tuple(conv_coeff), (k, 0, oo))
k = self.xk.variables[0]
xk_seq = sequence(self.xk.formula, (k, 0, oo))
terms_seq = xk_seq * conv_seq

return Add(*(terms_seq[:n])) + Order(self.xk.coeff(n), (self.x, self.x0))

def __add__(self, other):
other = sympify(other)

Expand Down
12 changes: 12 additions & 0 deletions sympy/series/tests/test_formal.py
Expand Up @@ -507,3 +507,15 @@ def test_fps__operations():
fi = f2.integrate(x)
assert fi.function == sin(x)
assert fi.truncate() == x - x**3/6 + x**5/120 + O(x**6)

def test_fps__convolution():
f1, f2, f3 = fps(sin(x)), fps(exp(x)), fps(cos(x))

raises(ValueError, lambda: f1.product(exp(x), x))
raises(ValueError, lambda: f1.product(fps(exp(x), dir=-1), x, 4))
raises(ValueError, lambda: f1.product(fps(exp(x), x0=1), x, 4))
raises(ValueError, lambda: f1.product(fps(exp(y)), x, 4))

assert f1.product(f2, x, 3) == x + x**2 + O(x**3)
assert f1.product(f2, x, 4) == x + x**2 + x**3/3 + O(x**4)
assert f1.product(f3, x, 4) == x - 2*x**3/3 + O(x**4)