The set \(\mathbb{P}^1(\QQ)\) of cusps - Modular Forms

Skip to content
Back to top
View this page
Edit this page

# The set \(\mathbb{P}^1(\QQ)\) of cusps

EXAMPLES:

Sage

    sage: Cusps
    Set P^1(QQ) of all cusps

Python

    >>> from sage.all import *
    >>> Cusps
    Set P^1(QQ) of all cusps

Sage

    sage: Cusp(oo)
    Infinity

[Python]

    >>> from sage.all import *
    >>> Cusp(oo)
    Infinity

class sage.modular.cusps.Cusp(a, b=None, parent=None, check=True)

  Bases: `Element`

  A cusp.

  A cusp is either a rational number or infinity, i.e., an element of the projective line over Q. A Cusp is stored as a pair (a,b), where gcd(a,b)=1 and a,b are of type Integer.

  EXAMPLES:

  Sage

      sage: a = Cusp(2/3); b = Cusp(oo)
      sage: a.parent()
      Set P^1(QQ) of all cusps
      sage: a.parent() is b.parent()
      True

  Python

      >>> from sage.all import *
      >>> a = Cusp(Integer(2)/Integer(3)); b = Cusp(oo)
      >>> a.parent()
      Set P^1(QQ) of all cusps
      >>> a.parent() is b.parent()
      True

  apply(g)

    Return g(self), where g=[a,b,c,d] is a list of length 4, which we view as a linear fractional transformation.

    EXAMPLES: Apply the identity matrix:

    Sage

        sage: Cusp(0).apply([1,0,0,1])
        0
        sage: Cusp(0).apply([0,-1,1,0])
        Infinity
        sage: Cusp(0).apply([1,-3,0,1])
        -3

    Python

        >>> from sage.all import *
        >>> Cusp(Integer(0)).apply([Integer(1),Integer(0),Integer(0),Integer(1)])
        0
        >>> Cusp(Integer(0)).apply([Integer(0),-Integer(1),Integer(1),Integer(0)])
        Infinity
        >>> Cusp(Integer(0)).apply([Integer(1),-Integer(3),Integer(0),Integer(1)])
        -3

  denominator()

    Return the denominator of the cusp a/b.

    EXAMPLES:

    Sage

        sage: x = Cusp(6,9); x
        2/3
        sage: x.denominator()
        3
        sage: Cusp(oo).denominator()
        0
        sage: Cusp(-5/10).denominator()
        2

    Python

        >>> from sage.all import *
        >>> x = Cusp(Integer(6),Integer(9)); x
        2/3
        >>> x.denominator()
        3
        >>> Cusp(oo).denominator()
        0
        >>> Cusp(-Integer(5)/Integer(10)).denominator()
        2

  galois_action(t, N)

    Suppose this cusp is \(\alpha\), \(G\) a congruence subgroup of level \(N\) and \(\sigma\) is the automorphism in the Galois group of \(\QQ(\zeta_N)/\QQ\) that sends \(\zeta_N\) to \(\zeta_N^t\). Then this function computes a cusp \(\beta\) such that \(\sigma([\alpha]) = [\beta]\), where \([\alpha]\) is the equivalence class of \(\alpha\) modulo \(G\).

    This code only needs as input the level and not the group since the action of Galois for a congruence group \(G\) of level \(N\) is compatible with the action of the full congruence group \(\Gamma(N)\).

    INPUT:

    - `t` – integer that is coprime to N

    - `N` – positive integer (level)

    OUTPUT: a cusp

    Warning

    In some cases \(N\) must fit in a long long, i.e., there are cases where this algorithm isn’t fully implemented.

    Note

    Modular curves can have multiple non-isomorphic models over \(\QQ\). The action of Galois depends on such a model. The model over \(\QQ\) of \(X(G)\) used here is the model where the function field \(\QQ(X(G))\) is given by the functions whose Fourier expansion at \(\infty\) have their coefficients in \(\QQ\). For \(X(N):=X(\Gamma(N))\) the corresponding moduli interpretation over \(\ZZ[1/N]\) is that \(X(N)\) parametrizes pairs \((E,a)\) where \(E\) is a (generalized) elliptic curve and \(a: \ZZ / N\ZZ \times \mu_N \to E\) is a closed immersion such that the Weil pairing of \(a(1,1)\) and \(a(0,\zeta_N)\) is \(\zeta_N\). In this parameterisation the point \(z \in H\) corresponds to the pair \((E_z,a_z)\) with \(E_z=\CC/(z \ZZ+\ZZ)\) and \(a_z: \ZZ / N\ZZ \times \mu_N \to E\) given by \(a_z(1,1) = z/N\) and \(a_z(0,\zeta_N) = 1/N\). Similarly \(X_1(N):=X(\Gamma_1(N))\) parametrizes pairs \((E,a)\) where \(a: \mu_N \to E\) is a closed immersion.

    EXAMPLES:

    Sage

        sage: Cusp(1/10).galois_action(3, 50)
        1/170
        sage: Cusp(oo).galois_action(3, 50)
        Infinity
        sage: c = Cusp(0).galois_action(3, 50); c
        50/17
        sage: Gamma0(50).reduce_cusp(c)
        0

    Python

        >>> from sage.all import *
        >>> Cusp(Integer(1)/Integer(10)).galois_action(Integer(3), Integer(50))
        1/170
        >>> Cusp(oo).galois_action(Integer(3), Integer(50))
        Infinity
        >>> c = Cusp(Integer(0)).galois_action(Integer(3), Integer(50)); c
        50/17
        >>> Gamma0(Integer(50)).reduce_cusp(c)
        0

    Here we compute the permutations of the action for t=3 on cusps for Gamma0(50).

    Sage

        sage: N = 50; t=3; G = Gamma0(N); C = G.cusps()
        sage: cl = lambda z: exists(C, lambda y:y.is_gamma0_equiv(z, N))[1]
        sage: for i in range(5):
        ....:     print((i, t^i))
        ....:     print([cl(alpha.galois_action(t^i,N)) for alpha in C])
        (0, 1)
        [0, 1/25, 1/10, 1/5, 3/10, 2/5, 1/2, 3/5, 7/10, 4/5, 9/10, Infinity]
        (1, 3)
        [0, 1/25, 7/10, 2/5, 1/10, 4/5, 1/2, 1/5, 9/10, 3/5, 3/10, Infinity]
        (2, 9)
        [0, 1/25, 9/10, 4/5, 7/10, 3/5, 1/2, 2/5, 3/10, 1/5, 1/10, Infinity]
        (3, 27)
        [0, 1/25, 3/10, 3/5, 9/10, 1/5, 1/2, 4/5, 1/10, 2/5, 7/10, Infinity]
        (4, 81)
        [0, 1/25, 1/10, 1/5, 3/10, 2/5, 1/2, 3/5, 7/10, 4/5, 9/10, Infinity]

    [Python]

        >>> from sage.all import *
        >>> N = Integer(50); t=Integer(3); G = Gamma0(N); C = G.cusps()
        >>> cl = lambda z: exists(C, lambda y:y.is_gamma0_equiv(z, N))[Integer(1)]
        >>> for i in range(Integer(5)):
        ...     print((i, t**i))
        ...     print([cl(alpha.galois_action(t**i,N)) for alpha in C])
        (0, 1)
        [0, 1/25, 1/10, 1/5, 3/10, 2/5, 1/2, 3/5, 7/10, 4/5, 9/10, Infinity]
        (1, 3)
        [0, 1/25, 7/10, 2/5, 1/10, 4/5, 1/2, 1/5, 9/10, 3/5, 3/10, Infinity]
        (2, 9)
        [0, 1/25, 9/10, 4/5, 7/10, 3/5, 1/2, 2/5, 3/10, 1/5, 1/10, Infinity]
        (3, 27)
        [0, 1/25, 3/10, 3/5, 9/10, 1/5, 1/2, 4/5, 1/10, 2/5, 7/10, Infinity]
        (4, 81)
        [0, 1/25, 1/10, 1/5, 3/10, 2/5, 1/2, 3/5, 7/10, 4/5, 9/10, Infinity]

    REFERENCES:

    - Section 1.3 of Glenn Stevens, “Arithmetic on Modular Curves”

    - There is a long comment about our algorithm in the source code for this function.

    AUTHORS:

    - William Stein, 2009-04-18

  is_gamma0_equiv(other, N, transformation=None)

    Return whether `self` and `other` are equivalent modulo the action of \(\Gamma_0(N)\) via linear fractional transformations.

    INPUT:

    - `other` – cusp

    - `N` – integer (specifies the group \(\Gamma_0(N)\))

    - `transformation` – `None` (default) or either the string ‘matrix’ or `'corner'`. If `'matrix'`, it also returns a matrix in \(\Gamma_0(N)\) that sends `self` to `other`. The matrix is chosen such that the lower left entry is as small as possible in absolute value. If `'corner'` (or `True` for backwards compatibility), it returns only the upper left entry of such a matrix.

    OUTPUT:

    - a boolean – `True` if `self` and `other` are equivalent

    - a matrix or an integer – returned only if transformation is ‘matrix’ or ‘corner’, respectively

    EXAMPLES:

    Sage

        sage: x = Cusp(2,3)
        sage: y = Cusp(4,5)
        sage: x.is_gamma0_equiv(y, 2)
        True
        sage: _, ga = x.is_gamma0_equiv(y, 2, 'matrix'); ga
        [-1  2]
        [-2  3]
        sage: x.is_gamma0_equiv(y, 3)
        False
        sage: x.is_gamma0_equiv(y, 3, 'matrix')
        (False, None)
        sage: Cusp(1/2).is_gamma0_equiv(1/3,11,'corner')
        (True, 19)

        sage: Cusp(1,0)
        Infinity
        sage: z = Cusp(1,0)
        sage: x.is_gamma0_equiv(z, 3, 'matrix')
        (
              [-1  1]
        True, [-3  2]
        )

    Python

        >>> from sage.all import *
        >>> x = Cusp(Integer(2),Integer(3))
        >>> y = Cusp(Integer(4),Integer(5))
        >>> x.is_gamma0_equiv(y, Integer(2))
        True
        >>> _, ga = x.is_gamma0_equiv(y, Integer(2), 'matrix'); ga
        [-1  2]
        [-2  3]
        >>> x.is_gamma0_equiv(y, Integer(3))
        False
        >>> x.is_gamma0_equiv(y, Integer(3), 'matrix')
        (False, None)
        >>> Cusp(Integer(1)/Integer(2)).is_gamma0_equiv(Integer(1)/Integer(3),Integer(11),'corner')
        (True, 19)

        >>> Cusp(Integer(1),Integer(0))
        Infinity
        >>> z = Cusp(Integer(1),Integer(0))
        >>> x.is_gamma0_equiv(z, Integer(3), 'matrix')
        (
              [-1  1]
        True, [-3  2]
        )

    ALGORITHM: See Proposition 2.2.3 of Cremona’s book ‘Algorithms for Modular Elliptic Curves’, or Prop 2.27 of Stein’s Ph.D. thesis.

  is_gamma1_equiv(other, N)

    Return whether `self` and `other` are equivalent modulo the action of \(\Gamma_1(N)\) via linear fractional transformations.

    INPUT:

    - `other` – cusp

    - `N` – integer (specifies the group \(\Gamma_1(N)\))

    OUTPUT:

    - `bool` – `True` if `self` and `other` are equivalent

    - `int` – 0, 1 or -1, gives further information about the equivalence: If the two cusps are u1/v1 and u2/v2, then they are equivalent if and only if v1 = v2 (mod N) and u1 = u2 (mod gcd(v1,N)) or v1 = -v2 (mod N) and u1 = -u2 (mod gcd(v1,N)) The sign is +1 for the first and -1 for the second. If the two cusps are not equivalent then 0 is returned.

    EXAMPLES:

    Sage

        sage: x = Cusp(2,3)
        sage: y = Cusp(4,5)
        sage: x.is_gamma1_equiv(y,2)
        (True, 1)
        sage: x.is_gamma1_equiv(y,3)
        (False, 0)
        sage: z = Cusp(QQ(x) + 10)
        sage: x.is_gamma1_equiv(z,10)
        (True, 1)
        sage: z = Cusp(1,0)
        sage: x.is_gamma1_equiv(z, 3)
        (True, -1)
        sage: Cusp(0).is_gamma1_equiv(oo, 1)
        (True, 1)
        sage: Cusp(0).is_gamma1_equiv(oo, 3)
        (False, 0)

    Python

        >>> from sage.all import *
        >>> x = Cusp(Integer(2),Integer(3))
        >>> y = Cusp(Integer(4),Integer(5))
        >>> x.is_gamma1_equiv(y,Integer(2))
        (True, 1)
        >>> x.is_gamma1_equiv(y,Integer(3))
        (False, 0)
        >>> z = Cusp(QQ(x) + Integer(10))
        >>> x.is_gamma1_equiv(z,Integer(10))
        (True, 1)
        >>> z = Cusp(Integer(1),Integer(0))
        >>> x.is_gamma1_equiv(z, Integer(3))
        (True, -1)
        >>> Cusp(Integer(0)).is_gamma1_equiv(oo, Integer(1))
        (True, 1)
        >>> Cusp(Integer(0)).is_gamma1_equiv(oo, Integer(3))
        (False, 0)

  is_gamma_h_equiv(other, G)

    Return a pair `(b, t)`, where `b` is `True` or `False` as `self` and `other` are equivalent under the action of \(G\), and \(t\) is 1 or -1, as described below.

    Two cusps \(u1/v1\) and \(u2/v2\) are equivalent modulo Gamma_H(N) if and only if \(v1 = h*v2 (\mathrm{mod} N)\) and \(u1 = h^{(-1)}*u2 (\mathrm{mod} gcd(v1,N))\) or \(v1 = -h*v2 (mod N)\) and \(u1 = -h^{(-1)}*u2 (\mathrm{mod} gcd(v1,N))\) for some \(h \in H\). Then t is 1 or -1 as c and c’ fall into the first or second case, respectively.

    INPUT:

    - `other` – cusp

    - `G` – a congruence subgroup Gamma_H(N)

    OUTPUT:

    - `bool` – `True` if `self` and `other` are equivalent

    - `int` – -1, 0, 1; extra info

    EXAMPLES:

    Sage

        sage: # needs sage.libs.pari
        sage: x = Cusp(2,3)
        sage: y = Cusp(4,5)
        sage: x.is_gamma_h_equiv(y,GammaH(13,[2]))
        (True, 1)
        sage: x.is_gamma_h_equiv(y,GammaH(13,[5]))
        (False, 0)
        sage: x.is_gamma_h_equiv(y,GammaH(5,[]))
        (False, 0)
        sage: x.is_gamma_h_equiv(y,GammaH(23,[4]))
        (True, -1)

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.pari
        >>> x = Cusp(Integer(2),Integer(3))
        >>> y = Cusp(Integer(4),Integer(5))
        >>> x.is_gamma_h_equiv(y,GammaH(Integer(13),[Integer(2)]))
        (True, 1)
        >>> x.is_gamma_h_equiv(y,GammaH(Integer(13),[Integer(5)]))
        (False, 0)
        >>> x.is_gamma_h_equiv(y,GammaH(Integer(5),[]))
        (False, 0)
        >>> x.is_gamma_h_equiv(y,GammaH(Integer(23),[Integer(4)]))
        (True, -1)

    Enumerating the cusps for a space of modular symbols uses this function.

    Sage

        sage: # needs sage.libs.pari
        sage: G = GammaH(25,[6]); M = G.modular_symbols(); M
        Modular Symbols space of dimension 11 for Congruence Subgroup Gamma_H(25)
         with H generated by [6] of weight 2 with sign 0 over Rational Field
        sage: M.cusps()
        [8/25, 1/3, 6/25, 1/4, 1/15, -7/15, 7/15, 4/15, 1/20, 3/20, 7/20, 9/20]
        sage: len(M.cusps())
        12

    [Python]

        >>> from sage.all import *
        >>> # needs sage.libs.pari
        >>> G = GammaH(Integer(25),[Integer(6)]); M = G.modular_symbols(); M
        Modular Symbols space of dimension 11 for Congruence Subgroup Gamma_H(25)
         with H generated by [6] of weight 2 with sign 0 over Rational Field
        >>> M.cusps()
        [8/25, 1/3, 6/25, 1/4, 1/15, -7/15, 7/15, 4/15, 1/20, 3/20, 7/20, 9/20]
        >>> len(M.cusps())
        12

    This is always one more than the associated space of weight 2 Eisenstein series.

    Sage

        sage: # needs sage.libs.pari
        sage: G.dimension_eis(2)
        11
        sage: M.cuspidal_subspace()
        Modular Symbols subspace of dimension 0 of
         Modular Symbols space of dimension 11 for Congruence Subgroup Gamma_H(25)
          with H generated by [6] of weight 2 with sign 0 over Rational Field
        sage: G.dimension_cusp_forms(2)
        0

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.pari
        >>> G.dimension_eis(Integer(2))
        11
        >>> M.cuspidal_subspace()
        Modular Symbols subspace of dimension 0 of
         Modular Symbols space of dimension 11 for Congruence Subgroup Gamma_H(25)
          with H generated by [6] of weight 2 with sign 0 over Rational Field
        >>> G.dimension_cusp_forms(Integer(2))
        0

  is_infinity()

    Return `True` if this is the cusp infinity.

    EXAMPLES:

    Sage

        sage: Cusp(3/5).is_infinity()
        False
        sage: Cusp(1,0).is_infinity()
        True
        sage: Cusp(0,1).is_infinity()
        False

    Python

        >>> from sage.all import *
        >>> Cusp(Integer(3)/Integer(5)).is_infinity()
        False
        >>> Cusp(Integer(1),Integer(0)).is_infinity()
        True
        >>> Cusp(Integer(0),Integer(1)).is_infinity()
        False

  numerator()

    Return the numerator of the cusp a/b.

    EXAMPLES:

    Sage

        sage: x = Cusp(6,9); x
        2/3
        sage: x.numerator()
        2
        sage: Cusp(oo).numerator()
        1
        sage: Cusp(-5/10).numerator()
        -1

    Python

        >>> from sage.all import *
        >>> x = Cusp(Integer(6),Integer(9)); x
        2/3
        >>> x.numerator()
        2
        >>> Cusp(oo).numerator()
        1
        >>> Cusp(-Integer(5)/Integer(10)).numerator()
        -1

class sage.modular.cusps.Cusps_class

  Bases: `Singleton`, `Parent`

  The set of cusps.

  EXAMPLES:

  Sage

      sage: C = Cusps; C
      Set P^1(QQ) of all cusps
      sage: loads(C.dumps()) == C
      True

  Python

      >>> from sage.all import *
      >>> C = Cusps; C
      Set P^1(QQ) of all cusps
      >>> loads(C.dumps()) == C
      True

  Element

    alias of `Cusp`