Skip to content

Commit

Permalink
Merge pull request #17017 from ArighnaIITG/convolution_fps
Browse files Browse the repository at this point in the history
[GSoC] Implemented convolution operation of two formal power series
  • Loading branch information
leosartaj committed Jul 4, 2019
2 parents 1bb112f + b91c21b commit 411757c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
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)

0 comments on commit 411757c

Please sign in to comment.