Week 4 and the final week of the first phase of the Coding Period is coming to an end. The work, which was initially proposed to be done in `FormalPowerSeries` has been done on a term-by-term level, i.e. the operations which have been implemented return truncated terms of the resultant `FormalPowerSeries`, instead of returning a `FormalPowerSeries` object. Sartaj and I have already discussed about the `class` implementation, in a recent meeting. Here are the deliverables which has been completed this week :–

• The PR #17017 consisted of a `convolve` function, which takes in a order `n` term, and returns the truncated terms of the resultant convoluted formal power series. The `API` of the `convolve` function was in line with the `convolution` function in `sympy.discrete.convolutions`. More specifically, it was –
``````   def convolve(self, other, x=None, n=6, cycle=0, dyadic=False, subset=False):
"""The logic of the code"""
``````

Sartaj suggested that there should be a method kwarg, which can take in which `method` of convolution the user wants to apply, instead of passing various kwargs representing the various methods. So I changed the `API` of the function, in lines with the above comment. Currently it is –

``````   def convolve(self, other, x=None, n=6, cycle=0, method=None):
"""The logic of the code"""
``````

in which method will be one of `[dyadic, subset, None]`, and cycle will represent the no. of cycles in cyclic convolution. Docs have also been updated. The PR is now in a mergeable state !!

• I also opened a [PR #17064], which deals with the `composition` and `inversion` of formal power series. I had implemented a `CoeffBell` class, where essentially `CoeffBellCompose(f, n, k) represents Bell polynomials of the second kind`. Note that both `n` and `k` should be integers. The implementation of the `eval` function of the `CoeffBell` class is as follows –
``````@classmethod
def eval(cls, f, n, k):
fp = fps(f)
kv = fp.ak.variables
i = symbols('i')

if n.is_integer and k.is_integer:
fp_seq = sequence(fp.ak.formula, (kv, 1, n-k+1))
fact_seq = sequence(factorial(i), (i, 1, n-k+1))
bell_seq = fp_seq * fact_seq
return bell(n, k, tuple(bell_seq))
``````

Then we can easily define bell sequences in terms of `CoeffBell` classes. Once we define them, all other terms can defined as sequences, and then the sequences can be multiplied and then the terms can be added up. Once we implement them, we can add up the sequence terms, and get the desired resultant truncated terms.

The various tests implemented here will give you an idea. They are :-

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

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

raises(ValueError, lambda: f1.compose(f3, x))
raises(ValueError, lambda: f2.compose(f3, x))

assert f1.compose(f2, x) == 1 + x + x**2/2 - x**4/8 - x**5/15 + O(x**6)
assert f1.compose(f2, x, n=4) == 1 + x + x**2/2 + O(x**4)
assert f1.compose(f2, x, n=8) == \
1 + x + x**2/2 - x**4/8 - x**5/15 - x**6/240 + x**7/90 + O(x**8)

assert f2.compose(f2, x, n=4) == x - x**3/6 + O(x**4)
assert f2.compose(f2, x, n=8) == x - x**3/6 + 11*x**5/120 - 127*x**7/5040 + O(x**8)

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

raises(ValueError, lambda: f1.inverse(x))
raises(ValueError, lambda: f1.inverse(x, n=8))

assert f2.inverse(x) == 1 - x + x**2/2 - x**3/6 + x**4/24 - x**5/120 + O(x**6)
assert f2.inverse(x, n=8) == \
1 - x + x**2/2 - x**3/6 + x**4/24 - x**5/120 + x**6/720 - x**7/5040 + O(x**8)

assert f3.inverse(x) == 1 + x**2/2 + 5*x**4/24 + O(x**6)
assert f3.inverse(x, n=8) == 1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + O(x**8)
``````
• Now that these implementations are over with, I have to start thinking about how we can make FormalPowerSeries objects as a result of these functions, instead of returning only the truncated terms. The first step in doing that would be to make all the sequences infinite, and save whatever sequence can be saved. Then we can create a sub-class out of `FormalPowerSeries`, which can have a custom `_eval_terms` function which, instead of calculating term by term, will calculate the addition of all terms together. Once we have the base `sub-class` ready, we can then move forward with creating three sub-classes out of the sub-class, one each for `convolve`, `compose`, and `inverse`. I will publish a PR, consisting of these changes, by the end of this week.

The first phase is over !! Phew !! See you in the next week. Adios till then !!