Some More Advanced Mathematics - Tutorial (original) (raw)

Algebraic Geometry

You can define arbitrary algebraic varieties in Sage, but sometimes nontrivial functionality is limited to rings over \(\QQ\) or finite fields. For example, we compute the union of two affine plane curves, then recover the curves as the irreducible components of the union.

Sage

sage: x, y = AffineSpace(2, QQ, 'xy').gens() sage: C2 = Curve(x^2 + y^2 - 1) sage: C3 = Curve(x^3 + y^3 - 1) sage: D = C2 + C3 sage: D Affine Plane Curve over Rational Field defined by x^5 + x^3y^2 + x^2y^3 + y^5 - x^3 - y^3 - x^2 - y^2 + 1 sage: D.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x^2 + y^2 - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x^3 + y^3 - 1]

Python

from sage.all import * x, y = AffineSpace(Integer(2), QQ, 'xy').gens() C2 = Curve(xInteger(2) + yInteger(2) - Integer(1)) C3 = Curve(xInteger(3) + yInteger(3) - Integer(1)) D = C2 + C3 D Affine Plane Curve over Rational Field defined by x^5 + x^3y^2 + x^2y^3 + y^5 - x^3 - y^3 - x^2 - y^2 + 1 D.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x^2 + y^2 - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x^3 + y^3 - 1]

We can also find all points of intersection of the two curves by intersecting them and computing the irreducible components.

Sage

sage: V = C2.intersection(C3) sage: V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y, x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2y^2 + 4y + 3]

Python

from sage.all import * V = C2.intersection(C3) V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y, x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2y^2 + 4y + 3]

Thus, e.g., \((1,0)\) and \((0,1)\) are on both curves (visibly clear), as are certain (quadratic) points whose\(y\) coordinates satisfy \(2y^2 + 4y + 3=0\).

Sage can compute the toric ideal of the twisted cubic in projective 3 space:

Sage

sage: R.<a,b,c,d> = PolynomialRing(QQ, 4) sage: I = ideal(b^2-ac, c^2-bd, ad-bc) sage: F = I.groebner_fan(); F Groebner fan of the ideal: Ideal (b^2 - ac, c^2 - bd, -bc + ad) of Multivariate Polynomial Ring in a, b, c, d over Rational Field sage: F.reduced_groebner_bases () [[-c^2 + bd, -bc + ad, -b^2 + ac], [-bc + ad, -c^2 + bd, b^2 - ac], [-c^3 + ad^2, -c^2 + bd, bc - ad, b^2 - ac], [-c^2 + bd, b^2 - ac, bc - ad, c^3 - ad^2], [-bc + ad, -b^2 + ac, c^2 - bd], [-b^3 + a^2d, -b^2 + ac, c^2 - bd, bc - ad], [-b^2 + ac, c^2 - bd, bc - ad, b^3 - a^2d], [c^2 - bd, bc - ad, b^2 - ac]] sage: F.polyhedralfan() Polyhedral fan in 4 dimensions of dimension 4

Python

from sage.all import * R = PolynomialRing(QQ, Integer(4), names=('a', 'b', 'c', 'd',)); (a, b, c, d,) = R._first_ngens(4) I = ideal(bInteger(2)-a*c, cInteger(2)-bd, ad-bc) F = I.groebner_fan(); F Groebner fan of the ideal: Ideal (b^2 - ac, c^2 - bd, -bc + ad) of Multivariate Polynomial Ring in a, b, c, d over Rational Field F.reduced_groebner_bases () [[-c^2 + bd, -bc + ad, -b^2 + ac], [-bc + ad, -c^2 + bd, b^2 - ac], [-c^3 + ad^2, -c^2 + bd, bc - ad, b^2 - ac], [-c^2 + bd, b^2 - ac, bc - ad, c^3 - ad^2], [-bc + ad, -b^2 + ac, c^2 - bd], [-b^3 + a^2d, -b^2 + ac, c^2 - bd, bc - ad], [-b^2 + ac, c^2 - bd, bc - ad, b^3 - a^2d], [c^2 - bd, bc - ad, b^2 - a*c]] F.polyhedralfan() Polyhedral fan in 4 dimensions of dimension 4

Elliptic Curves

Elliptic curve functionality includes most of the elliptic curve functionality of PARI, access to the data in Cremona’s online tables (this requires an optional database package), the functionality of mwrank, i.e., 2-descents with computation of the full Mordell-Weil group, the SEA algorithm, computation of all isogenies, much new code for curves over \(\QQ\), and some of Denis Simon’s algebraic descent software.

The command EllipticCurve for creating an elliptic curve has many forms:

We illustrate each of these constructors:

Sage

sage: EllipticCurve([0,0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

sage: EllipticCurve([GF(5)(0),0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

sage: EllipticCurve([1,2]) Elliptic Curve defined by y^2 = x^3 + x + 2 over Rational Field

sage: EllipticCurve('37a') Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

sage: EllipticCurve_from_j(1) Elliptic Curve defined by y^2 + xy = x^3 + 36x + 3455 over Rational Field

sage: EllipticCurve(GF(5), [0,0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

Python

from sage.all import * EllipticCurve([Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)]) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

EllipticCurve([GF(Integer(5))(Integer(0)),Integer(0),Integer(1),-Integer(1),Integer(0)]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

EllipticCurve([Integer(1),Integer(2)]) Elliptic Curve defined by y^2 = x^3 + x + 2 over Rational Field

EllipticCurve('37a') Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

EllipticCurve_from_j(Integer(1)) Elliptic Curve defined by y^2 + xy = x^3 + 36x + 3455 over Rational Field

EllipticCurve(GF(Integer(5)), [Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

The pair \((0,0)\) is a point on the elliptic curve\(E\) defined by \(y^2 + y = x^3 - x\). To create this point in Sage type E([0,0]). Sage can add points on such an elliptic curve (recall elliptic curves support an additive group structure where the point at infinity is the zero element and three co-linear points on the curve add to zero):

Sage

sage: E = EllipticCurve([0,0,1,-1,0]) sage: E Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field sage: P = E([0,0]) sage: P + P (1 : 0 : 1) sage: 10P (161/16 : -2065/64 : 1) sage: 20P (683916417/264517696 : -18784454671297/4302115807744 : 1) sage: E.conductor() 37

Python

from sage.all import * E = EllipticCurve([Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)]) E Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field P = E([Integer(0),Integer(0)]) P + P (1 : 0 : 1) Integer(10)*P (161/16 : -2065/64 : 1) Integer(20)*P (683916417/264517696 : -18784454671297/4302115807744 : 1) E.conductor() 37

The elliptic curves over the complex numbers are parameterized by the \(j\)-invariant. Sage computes \(j\)-invariant as follows:

Sage

sage: E = EllipticCurve([0,0,0,-4,2]); E Elliptic Curve defined by y^2 = x^3 - 4*x + 2 over Rational Field sage: E.conductor() 2368 sage: E.j_invariant() 110592/37

Python

from sage.all import * E = EllipticCurve([Integer(0),Integer(0),Integer(0),-Integer(4),Integer(2)]); E Elliptic Curve defined by y^2 = x^3 - 4*x + 2 over Rational Field E.conductor() 2368 E.j_invariant() 110592/37

If we make a curve with the same \(j\)-invariant as that of\(E\), it need not be isomorphic to \(E\). In the following example, the curves are not isomorphic because their conductors are different.

Sage

sage: F = EllipticCurve_from_j(110592/37) sage: F.conductor() 37

Python

from sage.all import * F = EllipticCurve_from_j(Integer(110592)/Integer(37)) F.conductor() 37

However, the twist of \(F\) by 2 gives an isomorphic curve.

Sage

sage: G = F.quadratic_twist(2); G Elliptic Curve defined by y^2 = x^3 - 4*x + 2 over Rational Field sage: G.conductor() 2368 sage: G.j_invariant() 110592/37

Python

from sage.all import * G = F.quadratic_twist(Integer(2)); G Elliptic Curve defined by y^2 = x^3 - 4*x + 2 over Rational Field G.conductor() 2368 G.j_invariant() 110592/37

We can compute the coefficients \(a_n\) of the\(L\)-series or modular form\(\sum_{n=0}^\infty a_nq^n\) attached to the elliptic curve. This computation uses the PARI C-library:

Sage

sage: E = EllipticCurve([0,0,1,-1,0]) sage: E.anlist(30) [0, 1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 10, 2, 0, -1, 4, -9, -2, 6, -12] sage: v = E.anlist(10000)

Python

from sage.all import * E = EllipticCurve([Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)]) E.anlist(Integer(30)) [0, 1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 10, 2, 0, -1, 4, -9, -2, 6, -12] v = E.anlist(Integer(10000))

It only takes a second to compute all \(a_n\) for\(n\leq 10^5\):

Sage

sage: %time v = E.anlist(100000) CPU times: user 0.98 s, sys: 0.06 s, total: 1.04 s Wall time: 1.06

Python

from sage.all import * %time v = E.anlist(Integer(100000)) CPU times: user 0.98 s, sys: 0.06 s, total: 1.04 s Wall time: 1.06

Elliptic curves can be constructed using their Cremona labels. This pre-loads the elliptic curve with information about its rank, Tamagawa numbers, regulator, etc.

Sage

sage: E = EllipticCurve("37b2") sage: E Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873x - 31833 over Rational Field sage: E = EllipticCurve("389a") sage: E Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2x over Rational Field sage: E.rank() 2 sage: E = EllipticCurve("5077a") sage: E.rank() 3

Python

from sage.all import * E = EllipticCurve("37b2") E Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873x - 31833 over Rational Field E = EllipticCurve("389a") E Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2x over Rational Field E.rank() 2 E = EllipticCurve("5077a") E.rank() 3

We can also access the Cremona database directly.

Sage

sage: db = sage.databases.cremona.CremonaDatabase() sage: db.curves(37) {'a1': [[0, 0, 1, -1, 0], 1, 1], 'b1': [[0, 1, 1, -23, -50], 0, 3]} sage: db.allcurves(37) {'a1': [[0, 0, 1, -1, 0], 1, 1], 'b1': [[0, 1, 1, -23, -50], 0, 3], 'b2': [[0, 1, 1, -1873, -31833], 0, 1], 'b3': [[0, 1, 1, -3, 1], 0, 3]}

Python

from sage.all import * db = sage.databases.cremona.CremonaDatabase() db.curves(Integer(37)) {'a1': [[0, 0, 1, -1, 0], 1, 1], 'b1': [[0, 1, 1, -23, -50], 0, 3]} db.allcurves(Integer(37)) {'a1': [[0, 0, 1, -1, 0], 1, 1], 'b1': [[0, 1, 1, -23, -50], 0, 3], 'b2': [[0, 1, 1, -1873, -31833], 0, 1], 'b3': [[0, 1, 1, -3, 1], 0, 3]}

The objects returned from the database are not of typeEllipticCurve. They are elements of a database and have a couple of fields, and that’s it. There is a small version of Cremona’s database, which is distributed by default with Sage, and contains limited information about elliptic curves of conductor\(\leq 10000\). There is also a large optional version, which contains extensive data about all curves of conductor up to\(120000\) (as of October 2005). There is also a huge (2GB) optional database package for Sage that contains the hundreds of millions of elliptic curves in the Stein-Watkins database.

Dirichlet Characters

A Dirichlet character is the extension of a homomorphism\((\ZZ/N\ZZ)^* \to R^*\), for some ring \(R\), to the map\(\ZZ \to R\) obtained by sending those integers \(x\)with \(\gcd(N,x)>1\) to 0.

Sage

sage: G = DirichletGroup(12) sage: G.list() [Dirichlet character modulo 12 of conductor 1 mapping 7 |--> 1, 5 |--> 1, Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 12 of conductor 3 mapping 7 |--> 1, 5 |--> -1, Dirichlet character modulo 12 of conductor 12 mapping 7 |--> -1, 5 |--> -1] sage: G.gens() (Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 12 of conductor 3 mapping 7 |--> 1, 5 |--> -1) sage: len(G) 4

Python

from sage.all import * G = DirichletGroup(Integer(12)) G.list() [Dirichlet character modulo 12 of conductor 1 mapping 7 |--> 1, 5 |--> 1, Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 12 of conductor 3 mapping 7 |--> 1, 5 |--> -1, Dirichlet character modulo 12 of conductor 12 mapping 7 |--> -1, 5 |--> -1] G.gens() (Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 12 of conductor 3 mapping 7 |--> 1, 5 |--> -1) len(G) 4

Having created the group, we next create an element and compute with it.

Sage

sage: G = DirichletGroup(21) sage: chi = G.1; chi Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> zeta6 sage: chi.values() [0, 1, zeta6 - 1, 0, -zeta6, -zeta6 + 1, 0, 0, 1, 0, zeta6, -zeta6, 0, -1, 0, 0, zeta6 - 1, zeta6, 0, -zeta6 + 1, -1] sage: chi.conductor() 7 sage: chi.modulus() 21 sage: chi.order() 6 sage: chi(19) -zeta6 + 1 sage: chi(40) -zeta6 + 1

Python

from sage.all import * G = DirichletGroup(Integer(21)) chi = G.gen(1); chi Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> zeta6 chi.values() [0, 1, zeta6 - 1, 0, -zeta6, -zeta6 + 1, 0, 0, 1, 0, zeta6, -zeta6, 0, -1, 0, 0, zeta6 - 1, zeta6, 0, -zeta6 + 1, -1] chi.conductor() 7 chi.modulus() 21 chi.order() 6 chi(Integer(19)) -zeta6 + 1 chi(Integer(40)) -zeta6 + 1

It is also possible to compute the action of the Galois group\(\text{Gal}(\QQ(\zeta_N)/\QQ)\) on these characters, as well as the direct product decomposition corresponding to the factorization of the modulus.

Sage

sage: chi.galois_orbit() [Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> -zeta6 + 1, Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> zeta6]

sage: go = G.galois_orbits() sage: [len(orbit) for orbit in go] [1, 2, 2, 1, 1, 2, 2, 1]

sage: G.decomposition() [Group of Dirichlet characters modulo 3 with values in Cyclotomic Field of order 6 and degree 2, Group of Dirichlet characters modulo 7 with values in Cyclotomic Field of order 6 and degree 2]

Python

from sage.all import * chi.galois_orbit() [Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> -zeta6 + 1, Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> zeta6]

go = G.galois_orbits() [len(orbit) for orbit in go] [1, 2, 2, 1, 1, 2, 2, 1]

G.decomposition() [Group of Dirichlet characters modulo 3 with values in Cyclotomic Field of order 6 and degree 2, Group of Dirichlet characters modulo 7 with values in Cyclotomic Field of order 6 and degree 2]

Next, we construct the group of Dirichlet characters mod 20, but with values in \(\QQ(i)\):

Sage

sage: K. = NumberField(x^2+1) sage: G = DirichletGroup(20,K) sage: G Group of Dirichlet characters modulo 20 with values in Number Field in i with defining polynomial x^2 + 1

Python

from sage.all import * K = NumberField(x**Integer(2)+Integer(1), names=('i',)); (i,) = K._first_ngens(1) G = DirichletGroup(Integer(20),K) G Group of Dirichlet characters modulo 20 with values in Number Field in i with defining polynomial x^2 + 1

We next compute several invariants of G:

Sage

sage: G.gens() (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> i)

sage: G.unit_gens() (11, 17) sage: G.zeta() i sage: G.zeta_order() 4

Python

from sage.all import * G.gens() (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> i)

G.unit_gens() (11, 17) G.zeta() i G.zeta_order() 4

In this example we create a Dirichlet character with values in a number field. We explicitly specify the choice of root of unity by the third argument to DirichletGroup below.

Sage

sage: x = polygen(QQ, 'x') sage: K = NumberField(x^4 + 1, 'a'); a = K.0 sage: b = K.gen(); a == b True sage: K Number Field in a with defining polynomial x^4 + 1 sage: G = DirichletGroup(5, K, a); G Group of Dirichlet characters modulo 5 with values in the group of order 8 generated by a in Number Field in a with defining polynomial x^4 + 1 sage: chi = G.0; chi Dirichlet character modulo 5 of conductor 5 mapping 2 |--> a^2 sage: [(chi^i)(2) for i in range(4)] [1, a^2, -1, -a^2]

Python

from sage.all import * x = polygen(QQ, 'x') K = NumberField(xInteger(4) + Integer(1), 'a'); a = K.gen(0) b = K.gen(); a == b True K Number Field in a with defining polynomial x^4 + 1 G = DirichletGroup(Integer(5), K, a); G Group of Dirichlet characters modulo 5 with values in the group of order 8 generated by a in Number Field in a with defining polynomial x^4 + 1 chi = G.gen(0); chi Dirichlet character modulo 5 of conductor 5 mapping 2 |--> a^2 [(chii)(Integer(2)) for i in range(Integer(4))] [1, a^2, -1, -a^2]

Here NumberField(x^4 + 1, 'a') tells Sage to use the symbol “a” in printing what K is (a Number Field in a with defining polynomial\(x^4 + 1\)). The name “a” is undeclared at this point. Oncea = K.0 (or equivalently a = K.gen()) is evaluated, the symbol “a” represents a root of the generating polynomial\(x^4+1\).

Modular Forms

Sage can do some computations related to modular forms, including dimensions, computing spaces of modular symbols, Hecke operators, and decompositions.

There are several functions available for computing dimensions of spaces of modular forms. For example,

Sage

sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) 1 sage: dimension_cusp_forms(Gamma1(389),2) 6112

Python

from sage.all import * from sage.modular.dims import dimension_cusp_forms dimension_cusp_forms(Gamma0(Integer(11)),Integer(2)) 1 dimension_cusp_forms(Gamma0(Integer(1)),Integer(12)) 1 dimension_cusp_forms(Gamma1(Integer(389)),Integer(2)) 6112

Next we illustrate computation of Hecke operators on a space of modular symbols of level \(1\) and weight \(12\).

Sage

sage: M = ModularSymbols(1,12) sage: M.basis() ([X^8Y^2,(0,0)], [X^9Y,(0,0)], [X^10,(0,0)]) sage: t2 = M.T(2) sage: t2 Hecke operator T_2 on Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field sage: t2.matrix() [ -24 0 0] [ 0 -24 0] [4860 0 2049] sage: f = t2.charpoly('x'); f x^3 - 2001x^2 - 97776x - 1180224 sage: factor(f) (x - 2049) * (x + 24)^2 sage: M.T(11).charpoly('x').factor() (x - 285311670612) * (x - 534612)^2

Python

from sage.all import * M = ModularSymbols(Integer(1),Integer(12)) M.basis() ([X^8Y^2,(0,0)], [X^9Y,(0,0)], [X^10,(0,0)]) t2 = M.T(Integer(2)) t2 Hecke operator T_2 on Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field t2.matrix() [ -24 0 0] [ 0 -24 0] [4860 0 2049] f = t2.charpoly('x'); f x^3 - 2001x^2 - 97776x - 1180224 factor(f) (x - 2049) * (x + 24)^2 M.T(Integer(11)).charpoly('x').factor() (x - 285311670612) * (x - 534612)^2

We can also create spaces for \(\Gamma_0(N)\) and\(\Gamma_1(N)\).

Sage

sage: ModularSymbols(11,2) Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field sage: ModularSymbols(Gamma1(11),2) Modular Symbols space of dimension 11 for Gamma_1(11) of weight 2 with sign 0 over Rational Field

Python

from sage.all import * ModularSymbols(Integer(11),Integer(2)) Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field ModularSymbols(Gamma1(Integer(11)),Integer(2)) Modular Symbols space of dimension 11 for Gamma_1(11) of weight 2 with sign 0 over Rational Field

Let’s compute some characteristic polynomials and\(q\)-expansions.

Sage

sage: M = ModularSymbols(Gamma1(11),2) sage: M.T(2).charpoly('x') x^11 - 8x^10 + 20x^9 + 10x^8 - 145x^7 + 229x^6 + 58x^5 - 360x^4 + 70x^3 - 515x^2 + 1804x - 1452 sage: M.T(2).charpoly('x').factor() (x - 3) * (x + 2)^2 * (x^4 - 7x^3 + 19x^2 - 23x + 11) * (x^4 - 2x^3 + 4x^2 + 2x + 11) sage: S = M.cuspidal_submodule() sage: S.T(2).matrix() [-2 0] [ 0 -2] sage: S.q_expansion_basis(10) [q - 2q^2 - q^3 + 2q^4 + q^5 + 2q^6 - 2q^7 - 2*q^9 + O(q^10)]

Python

from sage.all import * M = ModularSymbols(Gamma1(Integer(11)),Integer(2)) M.T(Integer(2)).charpoly('x') x^11 - 8x^10 + 20x^9 + 10x^8 - 145x^7 + 229x^6 + 58x^5 - 360x^4 + 70x^3 - 515x^2 + 1804x - 1452 M.T(Integer(2)).charpoly('x').factor() (x - 3) * (x + 2)^2 * (x^4 - 7x^3 + 19x^2 - 23x + 11) * (x^4 - 2x^3 + 4x^2 + 2x + 11) S = M.cuspidal_submodule() S.T(Integer(2)).matrix() [-2 0] [ 0 -2] S.q_expansion_basis(Integer(10)) [q - 2q^2 - q^3 + 2q^4 + q^5 + 2q^6 - 2q^7 - 2*q^9 + O(q^10)]

We can even compute spaces of modular symbols with character.

Sage

sage: G = DirichletGroup(13) sage: e = G.0^2 sage: M = ModularSymbols(e,2); M Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2 sage: M.T(2).charpoly('x').factor() (x - zeta6 - 2) * (x - 2zeta6 - 1) * (x + zeta6 + 1)^2 sage: S = M.cuspidal_submodule(); S Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2 sage: S.T(2).charpoly('x').factor() (x + zeta6 + 1)^2 sage: S.q_expansion_basis(10) [q + (-zeta6 - 1)q^2 + (2zeta6 - 2)q^3 + zeta6q^4 + (-2zeta6 + 1)q^5 + (-2zeta6 + 4)q^6 + (2zeta6 - 1)q^8 - zeta6q^9 + O(q^10)]

Python

from sage.all import * G = DirichletGroup(Integer(13)) e = G.gen(0)*Integer(2) M = ModularSymbols(e,Integer(2)); M Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2 M.T(Integer(2)).charpoly('x').factor() (x - zeta6 - 2) * (x - 2zeta6 - 1) * (x + zeta6 + 1)^2 S = M.cuspidal_submodule(); S Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2 S.T(Integer(2)).charpoly('x').factor() (x + zeta6 + 1)^2 S.q_expansion_basis(Integer(10)) [q + (-zeta6 - 1)q^2 + (2zeta6 - 2)q^3 + zeta6q^4 + (-2*zeta6 + 1)q^5 + (-2zeta6 + 4)q^6 + (2zeta6 - 1)q^8 - zeta6q^9 + O(q^10)]

Here is another example of how Sage can compute the action of Hecke operators on a space of modular forms.

Sage

sage: T = ModularForms(Gamma0(11),2) sage: T Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field sage: T.degree() 2 sage: T.level() 11 sage: T.group() Congruence Subgroup Gamma0(11) sage: T.dimension() 2 sage: T.cuspidal_subspace() Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field sage: T.eisenstein_subspace() Eisenstein subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field sage: M = ModularSymbols(11); M Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field sage: M.weight() 2 sage: M.basis() ((1,0), (1,8), (1,9)) sage: M.sign() 0

Python

from sage.all import * T = ModularForms(Gamma0(Integer(11)),Integer(2)) T Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field T.degree() 2 T.level() 11 T.group() Congruence Subgroup Gamma0(11) T.dimension() 2 T.cuspidal_subspace() Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field T.eisenstein_subspace() Eisenstein subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field M = ModularSymbols(Integer(11)); M Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field M.weight() 2 M.basis() ((1,0), (1,8), (1,9)) M.sign() 0

Let \(T_p\) denote the usual Hecke operators (\(p\)prime). How do the Hecke operators \(T_2\), \(T_3\),\(T_5\) act on the space of modular symbols?

Sage

sage: M.T(2).matrix() [ 3 0 -1] [ 0 -2 0] [ 0 0 -2] sage: M.T(3).matrix() [ 4 0 -1] [ 0 -1 0] [ 0 0 -1] sage: M.T(5).matrix() [ 6 0 -1] [ 0 1 0] [ 0 0 1]

Python

from sage.all import * M.T(Integer(2)).matrix() [ 3 0 -1] [ 0 -2 0] [ 0 0 -2] M.T(Integer(3)).matrix() [ 4 0 -1] [ 0 -1 0] [ 0 0 -1] M.T(Integer(5)).matrix() [ 6 0 -1] [ 0 1 0] [ 0 0 1]