The Pushout of Two Modular Forms Spaces

1 minute read

Published:

In the previous post, I discussed about some changes made in the code for the graded ring of modular forms in SageMath. However, there was one lacking feature and it was the pushout of two modular forms space. I will explain this feature in this post.

Recall that our goal here was to give the class ModularFormsRing a ring structure. In other words, we want to be able to add, substract and multiply two given modular forms. This was implemented in SageMath by creating a new element class called GradedModularFormElement:

sage: M = ModularFormsRing(1)
sage: E4 = M.0 # GradedModularFormElement
sage: E6 = M.1 # GradedModularFormElement
sage: E4 + E6
2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
sage: (E4 + E6).parent()
Ring of modular forms for Modular Group SL(2,Z) with coefficients in Rational Field
sage: E4 - E6
744*q + 18792*q^2 + 129696*q^3 + 550248*q^4 + 1605744*q^5 + O(q^6)
sage: E4 * E6
1 - 264*q - 135432*q^2 - 5196576*q^3 - 69341448*q^4 - 515625264*q^5 + O(q^6)

To make the above example consistent with the actual implementation of modular forms in SageMath, we needed to implement the pushout of two modular forms spaces. In SageMath, the pushout of two parents \(P_1\) and \(P_2\) is a third parent \(Q\) such that \(P_1 \hookrightarrow Q\) and \(P_2 \hookrightarrow Q\). In our case, let’s take for example the following parents:

\[P_1 := \mathcal{M}_4(\mathrm{SL}_2(\mathbb{Z})) = \mathbb{C}E_4;\] \[P_2 := \mathcal{M}_6(\mathrm{SL}_2(\mathbb{Z})) = \mathbb{C}E_6;\] \[Q:= \mathcal{M}_*(\mathrm{SL}_2(\mathbb{Z})) = \bigoplus_{k\in \mathbb{Z}} \mathcal{M}_k(\mathrm{SL}_2(\mathbb{Z})).\]

We observe that \(P_1\) and \(P_2\) can both be embbeded into the ring \(Q\). So, it would be desirable to have that the sum of an element of \(P_1\) with an element of \(P_2\) would return and element of \(Q\). In SageMath, \(P_1\) and \(P_2\) are two instances of the class ModularFormsSpace. Hence, to make the pushout feature works, we simply added the following method:

    def _pushout_(self, other):
        r"""
        Implement the pushout of ``self`` and ``other``.

        INPUT:

        - ``other`` -- ``ModularFormSpace`` or a ``ModularFormRing``

        OUTPUT: If ``self`` and ``other`` have the same groups and base rings, then this method returns
        ``self`` if the weights of the two spaces are equal, otherwise it returns a ``ModularFormsRing``.
        """
        from .find_generators import ModularFormsRing
        if isinstance(other, ModularFormsSpace):
            if self.group() == other.group() and self.base_ring() == other.base_ring():
                if self.weight() == other.weight():
                    return self
                else:
                    return ModularFormsRing(self.group(), base_ring=self.base_ring())
        if isinstance(other, ModularFormsRing) and other.has_coerce_map_from(self):
            return other

Thus, the code above makes the following example works:

sage: e4 = ModularForms(1,4).0; e6 = ModularForms(1,6).0;
sage: e4.parent()
Modular Forms space of dimension 1 for Modular Group SL(2,Z) of weight 4 over Rational Field
sage: e4 + e6
2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
sage: (e4 + e6).parent()
Ring of modular forms for Modular Group SL(2,Z) with coefficients in Rational Field

Thanks for reading!