Brandt modules

Introduction

The construction of Brandt modules provides us with a method to compute modular forms, as outlined in Pizer’s paper [Piz1980].

Given a prime number \(p\) and a positive integer \(M\) with \(p\nmid M\), the Brandt module \(B(p, M)\) is the free abelian group on right ideal classes of a quaternion order of level \(pM\) in the quaternion algebra ramified precisely at the places \(p\) and \(\infty\). This Brandt module carries a natural Hecke action given by Brandt matrices. There exists a non-canonical Hecke algebra isomorphism between \(B(p, M)\) and a certain subspace of \(S_{2}(\Gamma_0(pM))\) containing the newforms.

Quaternion Algebras

A quaternion algebra over \(\QQ\) is a central simple algebra of dimension 4 over \(\QQ\). Such an algebra \(A\) is said to be ramified at a place \(v\) of \(\QQ\) if and only if \(A \otimes \QQ_v\) is a division algebra. Otherwise \(A\) is said to be split at \(v\).

A = QuaternionAlgebra(p) returns the quaternion algebra \(A\) over \(\QQ\) ramified precisely at the places \(p\) and \(\infty\).

A = QuaternionAlgebra(a, b) returns the quaternion algebra \(A\) over \(\QQ\) with basis \(\{1, i, j, k\}\) such that \(i^2 = a\), \(j^2 = b\) and \(ij = -ji = k.\)

An order \(R\) in a quaternion algebra \(A\) over \(\QQ\) is a 4-dimensional lattice in \(A\) which is also a subring containing the identity. A maximal order is one that is not properly contained in another order.

A particularly important kind of orders are those that have a level; see Definition 1.2 in [Piz1980]. This is a positive integer \(N\) such that every prime that ramifies in \(A\) divides \(N\) to an odd power. The maximal orders are those that have level equal to the discriminant of \(A\).

R = A.maximal_order() returns a maximal order \(R\) in the quaternion algebra \(A.\)

A right \(\mathcal{O}\)-ideal \(I\) is a lattice in \(A\) such that for every prime \(p\) there exists \(a_p\in A_p^*\) with \(I_p = a_p\mathcal{O}_p\). Two right \(\mathcal{O}\)-ideals \(I\) and \(J\) are said to belong to the same class if \(I=aJ\) for some \(a \in A^*\). Left \(\mathcal{O}\)-ideals are defined in a similar fashion.

The right order of \(I\) is the subring of \(A\) consisting of elements \(a\) with \(Ia \subseteq I\).

Brandt Modules

B = BrandtModule(p, M=1) returns the Brandt module associated to the prime number \(p\) and the integer \(M\), with \(p\) not dividing \(M\).

A = B.quaternion_algebra() returns the quaternion algebra attached to \(B\); this is the quaternion algebra over \(\QQ\) ramified exactly at \(p\) and \(\infty\).

O = B.order_of_level_N() returns an order \(\mathcal{O}\) of level \(N = pM\) in \(A\).

B.right_ideals() returns a tuple of representatives for all right ideal classes of \(\mathcal{O}\).

The implementation of this method is especially interesting. It depends on the construction of a Hecke module defined as a free abelian group on right ideal classes of a quaternion algebra with the following action:

\[T_n[I] = \sum_{\phi} [J]\]

where \((n,pM)=1\) and the sum is over cyclic \(\mathcal{O}\)-module homomorphisms \(\phi\colon I\rightarrow J\) of degree \(n\) up to isomorphism of \(J\). Equivalently one can sum over the inclusions of the submodules \(J \rightarrow n^{-1}I\). The rough idea is to start with the trivial ideal class containing the order \(\mathcal{O}\) itself. Using the method cyclic_submodules(self, I, q) one then repeatedly computes \(T_q([\mathcal{O}])\) for some prime \(q\) not dividing the level of \(\mathcal{O}\) and tests for equivalence among the resulting ideals. A theorem of Serre asserts that one gets a complete set of ideal class representatives after a finite number of repetitions.

One can prove that two ideals \(I\) and \(J\) are equivalent if and only if there exists an element \(\alpha \in I \overline{J}\) such \(N(\alpha)=N(I)N(J)\).

is_right_equivalent(I,J) returns true if \(I\) and \(J\) are equivalent. This method first compares the theta series of \(I\) and \(J\). If they are the same, it computes the theta series of the lattice \(I\overline(J)\). It returns true if the \(n\)-th coefficient of this series is nonzero where \(n=N(J)N(I)\).

The theta series of a lattice \(L\) over the quaternion algebra \(A\) is defined as

\[\theta_L(q)=\sum_{x \in L} q^{\frac{N(x)}{N(L)}}\]

L.theta_series(T,q) returns a power series representing \(\theta_L(q)\) up to a precision of \(\mathcal{O}(q^{T+1})\).

Hecke Structure

The Hecke structure defined on the Brandt module is given by the Brandt matrices which can be computed using the definition of the Hecke operators given earlier.

hecke_matrix_from_defn(self,n) returns the matrix of the \(n\)-th Hecke operator \(B_{0}(n)\) acting on self, computed directly from the definition.

However, one can efficiently compute Brandt matrices using theta series. In fact, let \(\{I_{1},.....,I_{h}\}\) be a set of right \(\mathcal{O}\)-ideal class representatives. The (i,j) entry in the Brandt matrix \(B_{0}(n)\) is the product of the \(n\)-th coefficient in the theta series of the lattice \(I_{i}\overline{I_{j}}\) and the first coefficient in the theta series of the lattice \(I_{i}\overline{I_{i}}\).

compute_hecke_matrix_brandt(self,n) returns the \(n\)-th Hecke matrix, computed using theta series.

EXAMPLES:

sage: B = BrandtModule(23)

sage: B.maximal_order()
Order of Quaternion Algebra (-1, -23) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k)

sage: B.right_ideals()
(Fractional ideal (4, 4*i, 2 + 2*j, 2*i + 2*k),
     Fractional ideal (8, 8*i, 2 + 2*j, 6*i + 2*k),
     Fractional ideal (16, 16*i, 10 + 8*i + 2*j, 8 + 6*i + 2*k))

sage: B.hecke_matrix(2)
[1 2 0]
[1 1 1]
[0 3 0]

sage: B.brandt_series(3)
[1/4 + q + q^2 + O(q^3)     1/4 + q^2 + O(q^3)           1/4 + O(q^3)]
[  1/2 + 2*q^2 + O(q^3) 1/2 + q + q^2 + O(q^3)   1/2 + 3*q^2 + O(q^3)]
[          1/6 + O(q^3)     1/6 + q^2 + O(q^3)       1/6 + q + O(q^3)]
>>> from sage.all import *
>>> B = BrandtModule(Integer(23))

>>> B.maximal_order()
Order of Quaternion Algebra (-1, -23) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k)

>>> B.right_ideals()
(Fractional ideal (4, 4*i, 2 + 2*j, 2*i + 2*k),
     Fractional ideal (8, 8*i, 2 + 2*j, 6*i + 2*k),
     Fractional ideal (16, 16*i, 10 + 8*i + 2*j, 8 + 6*i + 2*k))

>>> B.hecke_matrix(Integer(2))
[1 2 0]
[1 1 1]
[0 3 0]

>>> B.brandt_series(Integer(3))
[1/4 + q + q^2 + O(q^3)     1/4 + q^2 + O(q^3)           1/4 + O(q^3)]
[  1/2 + 2*q^2 + O(q^3) 1/2 + q + q^2 + O(q^3)   1/2 + 3*q^2 + O(q^3)]
[          1/6 + O(q^3)     1/6 + q^2 + O(q^3)       1/6 + q + O(q^3)]
B = BrandtModule(23)
B.maximal_order()
B.right_ideals()
B.hecke_matrix(2)
B.brandt_series(3)

REFERENCES:

Further Examples

We decompose a Brandt module over both \(\ZZ\) and \(\QQ\).

sage: B = BrandtModule(43, base_ring=ZZ); B
Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring
sage: D = B.decomposition()
sage: D
[
Subspace of dimension 1 of Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring,
Subspace of dimension 1 of Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring,
Subspace of dimension 2 of Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring
]
sage: D[0].basis()
((0, 0, 1, -1),)
sage: D[1].basis()
((1, 2, 2, 2),)
sage: D[2].basis()
((1, 1, -1, -1), (0, 2, -1, -1))
sage: B = BrandtModule(43, base_ring=QQ); B
Brandt module of dimension 4 of level 43 of weight 2 over Rational Field
sage: B.decomposition()[2].basis()
((1, 0, -1/2, -1/2), (0, 1, -1/2, -1/2))
>>> from sage.all import *
>>> B = BrandtModule(Integer(43), base_ring=ZZ); B
Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring
>>> D = B.decomposition()
>>> D
[
Subspace of dimension 1 of Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring,
Subspace of dimension 1 of Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring,
Subspace of dimension 2 of Brandt module of dimension 4 of level 43 of weight 2 over Integer Ring
]
>>> D[Integer(0)].basis()
((0, 0, 1, -1),)
>>> D[Integer(1)].basis()
((1, 2, 2, 2),)
>>> D[Integer(2)].basis()
((1, 1, -1, -1), (0, 2, -1, -1))
>>> B = BrandtModule(Integer(43), base_ring=QQ); B
Brandt module of dimension 4 of level 43 of weight 2 over Rational Field
>>> B.decomposition()[Integer(2)].basis()
((1, 0, -1/2, -1/2), (0, 1, -1/2, -1/2))
B = BrandtModule(43, base_ring=ZZ); B
D = B.decomposition()
D
D[0].basis()
D[1].basis()
D[2].basis()
B = BrandtModule(43, base_ring=QQ); B
B.decomposition()[2].basis()

AUTHORS:

  • Jon Bober

  • Alia Hamieh

  • Victoria de Quehen

  • William Stein

  • Gonzalo Tornaria

sage.modular.quatalg.brandt.BrandtModule(N, M=1, weight=2, base_ring=Rational Field, use_cache=True)[source]

Return the Brandt module of given weight associated to the prime power \(p^r\) and integer \(M\), where \(p\) and \(M\) are coprime.

INPUT:

  • N – a product of primes with odd exponents

  • M – integer coprime to \(q\) (default: 1)

  • weight – integer that is at least 2 (default: 2)

  • base_ring – the base ring (default: QQ)

  • use_cache – whether to use the cache (default: True)

OUTPUT: a Brandt module

EXAMPLES:

sage: BrandtModule(17)
Brandt module of dimension 2 of level 17 of weight 2 over Rational Field
sage: BrandtModule(17,15)
Brandt module of dimension 32 of level 17*15 of weight 2 over Rational Field
sage: BrandtModule(3,7)
Brandt module of dimension 2 of level 3*7 of weight 2 over Rational Field
sage: BrandtModule(3,weight=2)
Brandt module of dimension 1 of level 3 of weight 2 over Rational Field
sage: BrandtModule(11, base_ring=ZZ)
Brandt module of dimension 2 of level 11 of weight 2 over Integer Ring
sage: BrandtModule(11, base_ring=QQbar)
Brandt module of dimension 2 of level 11 of weight 2 over Algebraic Field
>>> from sage.all import *
>>> BrandtModule(Integer(17))
Brandt module of dimension 2 of level 17 of weight 2 over Rational Field
>>> BrandtModule(Integer(17),Integer(15))
Brandt module of dimension 32 of level 17*15 of weight 2 over Rational Field
>>> BrandtModule(Integer(3),Integer(7))
Brandt module of dimension 2 of level 3*7 of weight 2 over Rational Field
>>> BrandtModule(Integer(3),weight=Integer(2))
Brandt module of dimension 1 of level 3 of weight 2 over Rational Field
>>> BrandtModule(Integer(11), base_ring=ZZ)
Brandt module of dimension 2 of level 11 of weight 2 over Integer Ring
>>> BrandtModule(Integer(11), base_ring=QQbar)
Brandt module of dimension 2 of level 11 of weight 2 over Algebraic Field
BrandtModule(17)
BrandtModule(17,15)
BrandtModule(3,7)
BrandtModule(3,weight=2)
BrandtModule(11, base_ring=ZZ)
BrandtModule(11, base_ring=QQbar)

The use_cache option determines whether the Brandt module returned by this function is cached:

sage: BrandtModule(37) is BrandtModule(37)
True
sage: BrandtModule(37,use_cache=False) is BrandtModule(37,use_cache=False)
False
>>> from sage.all import *
>>> BrandtModule(Integer(37)) is BrandtModule(Integer(37))
True
>>> BrandtModule(Integer(37),use_cache=False) is BrandtModule(Integer(37),use_cache=False)
False
BrandtModule(37) is BrandtModule(37)
BrandtModule(37,use_cache=False) is BrandtModule(37,use_cache=False)
class sage.modular.quatalg.brandt.BrandtModuleElement(parent, x)[source]

Bases: HeckeModuleElement

EXAMPLES:

sage: B = BrandtModule(37)
sage: x = B([1,2,3]); x
(1, 2, 3)
sage: parent(x)
Brandt module of dimension 3 of level 37 of weight 2 over Rational Field
>>> from sage.all import *
>>> B = BrandtModule(Integer(37))
>>> x = B([Integer(1),Integer(2),Integer(3)]); x
(1, 2, 3)
>>> parent(x)
Brandt module of dimension 3 of level 37 of weight 2 over Rational Field
B = BrandtModule(37)
x = B([1,2,3]); x
parent(x)
monodromy_pairing(x)[source]

Return the monodromy pairing of self and x.

EXAMPLES:

sage: B = BrandtModule(5,13)
sage: B.monodromy_weights()
(1, 3, 1, 1, 1, 3)
sage: (B.0 + B.1).monodromy_pairing(B.0 + B.1)
4
>>> from sage.all import *
>>> B = BrandtModule(Integer(5),Integer(13))
>>> B.monodromy_weights()
(1, 3, 1, 1, 1, 3)
>>> (B.gen(0) + B.gen(1)).monodromy_pairing(B.gen(0) + B.gen(1))
4
B = BrandtModule(5,13)
B.monodromy_weights()
(B.0 + B.1).monodromy_pairing(B.0 + B.1)
class sage.modular.quatalg.brandt.BrandtModule_class(N, M, weight, base_ring)[source]

Bases: AmbientHeckeModule

A Brandt module.

EXAMPLES:

sage: BrandtModule(3, 10)
Brandt module of dimension 4 of level 3*10 of weight 2 over Rational Field
>>> from sage.all import *
>>> BrandtModule(Integer(3), Integer(10))
Brandt module of dimension 4 of level 3*10 of weight 2 over Rational Field
BrandtModule(3, 10)
Element[source]

alias of BrandtModuleElement

M()[source]

Return the auxiliary level (prime to \(p\) part) of the quaternion order used to compute this Brandt module.

EXAMPLES:

sage: BrandtModule(7,5,2,ZZ).M()
5
>>> from sage.all import *
>>> BrandtModule(Integer(7),Integer(5),Integer(2),ZZ).M()
5
BrandtModule(7,5,2,ZZ).M()
N()[source]

Return ramification level \(N\).

EXAMPLES:

sage: BrandtModule(7,5,2,ZZ).N()
7
>>> from sage.all import *
>>> BrandtModule(Integer(7),Integer(5),Integer(2),ZZ).N()
7
BrandtModule(7,5,2,ZZ).N()
brandt_series(prec, var='q')[source]

Return matrix of power series \(\sum T_n q^n\) to the given precision.

Note that the Hecke operators in this series are always over \(\QQ\), even if the base ring of this Brandt module is not \(\QQ\).

INPUT:

  • prec – positive integer

  • var – string (default: \(q\))

OUTPUT: matrix of power series with coefficients in \(\QQ\)

EXAMPLES:

sage: B = BrandtModule(11)
sage: B.brandt_series(2)
[1/4 + q + O(q^2)     1/4 + O(q^2)]
[    1/6 + O(q^2) 1/6 + q + O(q^2)]
sage: B.brandt_series(5)
[1/4 + q + q^2 + 2*q^3 + 5*q^4 + O(q^5)   1/4 + 3*q^2 + 3*q^3 + 3*q^4 + O(q^5)]
[  1/6 + 2*q^2 + 2*q^3 + 2*q^4 + O(q^5)         1/6 + q + q^3 + 4*q^4 + O(q^5)]
>>> from sage.all import *
>>> B = BrandtModule(Integer(11))
>>> B.brandt_series(Integer(2))
[1/4 + q + O(q^2)     1/4 + O(q^2)]
[    1/6 + O(q^2) 1/6 + q + O(q^2)]
>>> B.brandt_series(Integer(5))
[1/4 + q + q^2 + 2*q^3 + 5*q^4 + O(q^5)   1/4 + 3*q^2 + 3*q^3 + 3*q^4 + O(q^5)]
[  1/6 + 2*q^2 + 2*q^3 + 2*q^4 + O(q^5)         1/6 + q + q^3 + 4*q^4 + O(q^5)]
B = BrandtModule(11)
B.brandt_series(2)
B.brandt_series(5)

Asking for a smaller precision works:

sage: B.brandt_series(3)
[1/4 + q + q^2 + O(q^3)   1/4 + 3*q^2 + O(q^3)]
[  1/6 + 2*q^2 + O(q^3)       1/6 + q + O(q^3)]
sage: B.brandt_series(3,var='t')
[1/4 + t + t^2 + O(t^3)   1/4 + 3*t^2 + O(t^3)]
[  1/6 + 2*t^2 + O(t^3)       1/6 + t + O(t^3)]
>>> from sage.all import *
>>> B.brandt_series(Integer(3))
[1/4 + q + q^2 + O(q^3)   1/4 + 3*q^2 + O(q^3)]
[  1/6 + 2*q^2 + O(q^3)       1/6 + q + O(q^3)]
>>> B.brandt_series(Integer(3),var='t')
[1/4 + t + t^2 + O(t^3)   1/4 + 3*t^2 + O(t^3)]
[  1/6 + 2*t^2 + O(t^3)       1/6 + t + O(t^3)]
B.brandt_series(3)
B.brandt_series(3,var='t')
character()[source]

The character of this space.

Always trivial.

EXAMPLES:

sage: BrandtModule(11,5).character()
Dirichlet character modulo 55 of conductor 1 mapping 12 |--> 1, 46 |--> 1
>>> from sage.all import *
>>> BrandtModule(Integer(11),Integer(5)).character()
Dirichlet character modulo 55 of conductor 1 mapping 12 |--> 1, 46 |--> 1
BrandtModule(11,5).character()
cyclic_submodules(I, p)[source]

Return a list of rescaled versions of the fractional right ideals \(J\) such that \(J\) contains \(I\) and the quotient has group structure the product of two cyclic groups of order \(p\).

We emphasize again that \(J\) is rescaled to be integral.

INPUT:

  • I – ideal \(I\) in R = self.order_of_level_N()

  • p – prime \(p\) coprime to self.level()

OUTPUT:

list of the \(p+1\) fractional right R-ideals that contain I such that J/I is GF(p) x GF(p).

EXAMPLES:

sage: B = BrandtModule(11)
sage: I = B.order_of_level_N().unit_ideal()
sage: B.cyclic_submodules(I, 2)
[Fractional ideal (2, 2*i, 3/2 + i + 1/2*j, 1 + 1/2*i + 1/2*k),
 Fractional ideal (2, 1 + i, 1 + j, 1/2 + 1/2*i + 1/2*j + 1/2*k),
 Fractional ideal (2, 2*i, 1/2 + i + 1/2*j, 1 + 3/2*i + 1/2*k)]
sage: B.cyclic_submodules(I, 3)
[Fractional ideal (3, 3*i, 1/2 + 1/2*j, 5/2*i + 1/2*k),
 Fractional ideal (3, 3*i, 3/2 + 2*i + 1/2*j, 2 + 3/2*i + 1/2*k),
 Fractional ideal (3, 3*i, 3/2 + i + 1/2*j, 1 + 3/2*i + 1/2*k),
 Fractional ideal (3, 3*i, 5/2 + 1/2*j, 1/2*i + 1/2*k)]
sage: B.cyclic_submodules(I, 11)
Traceback (most recent call last):
...
ValueError: p must be coprime to the level
>>> from sage.all import *
>>> B = BrandtModule(Integer(11))
>>> I = B.order_of_level_N().unit_ideal()
>>> B.cyclic_submodules(I, Integer(2))
[Fractional ideal (2, 2*i, 3/2 + i + 1/2*j, 1 + 1/2*i + 1/2*k),
 Fractional ideal (2, 1 + i, 1 + j, 1/2 + 1/2*i + 1/2*j + 1/2*k),
 Fractional ideal (2, 2*i, 1/2 + i + 1/2*j, 1 + 3/2*i + 1/2*k)]
>>> B.cyclic_submodules(I, Integer(3))
[Fractional ideal (3, 3*i, 1/2 + 1/2*j, 5/2*i + 1/2*k),
 Fractional ideal (3, 3*i, 3/2 + 2*i + 1/2*j, 2 + 3/2*i + 1/2*k),
 Fractional ideal (3, 3*i, 3/2 + i + 1/2*j, 1 + 3/2*i + 1/2*k),
 Fractional ideal (3, 3*i, 5/2 + 1/2*j, 1/2*i + 1/2*k)]
>>> B.cyclic_submodules(I, Integer(11))
Traceback (most recent call last):
...
ValueError: p must be coprime to the level
B = BrandtModule(11)
I = B.order_of_level_N().unit_ideal()
B.cyclic_submodules(I, 2)
B.cyclic_submodules(I, 3)
B.cyclic_submodules(I, 11)
eisenstein_subspace()[source]

Return the 1-dimensional subspace of self on which the Hecke operators \(T_p\) act as \(p+1\) for \(p\) coprime to the level.

Note

This function assumes that the base field has characteristic 0.

EXAMPLES:

sage: B = BrandtModule(11); B.eisenstein_subspace()
Subspace of dimension 1 of Brandt module of dimension 2 of level 11 of weight 2 over Rational Field
sage: B.eisenstein_subspace() is B.eisenstein_subspace()
True
sage: BrandtModule(3,11).eisenstein_subspace().basis()
((1, 1),)
sage: BrandtModule(7,10).eisenstein_subspace().basis()
((1, 1, 1, 1/2, 1, 1, 1/2, 1, 1, 1),)
sage: BrandtModule(7,10,base_ring=ZZ).eisenstein_subspace().basis()
((2, 2, 2, 1, 2, 2, 1, 2, 2, 2),)
>>> from sage.all import *
>>> B = BrandtModule(Integer(11)); B.eisenstein_subspace()
Subspace of dimension 1 of Brandt module of dimension 2 of level 11 of weight 2 over Rational Field
>>> B.eisenstein_subspace() is B.eisenstein_subspace()
True
>>> BrandtModule(Integer(3),Integer(11)).eisenstein_subspace().basis()
((1, 1),)
>>> BrandtModule(Integer(7),Integer(10)).eisenstein_subspace().basis()
((1, 1, 1, 1/2, 1, 1, 1/2, 1, 1, 1),)
>>> BrandtModule(Integer(7),Integer(10),base_ring=ZZ).eisenstein_subspace().basis()
((2, 2, 2, 1, 2, 2, 1, 2, 2, 2),)
B = BrandtModule(11); B.eisenstein_subspace()
B.eisenstein_subspace() is B.eisenstein_subspace()
BrandtModule(3,11).eisenstein_subspace().basis()
BrandtModule(7,10).eisenstein_subspace().basis()
BrandtModule(7,10,base_ring=ZZ).eisenstein_subspace().basis()
free_module()[source]

Return the underlying free module of the Brandt module.

EXAMPLES:

sage: B = BrandtModule(10007,389)
sage: B.free_module()
Vector space of dimension 325196 over Rational Field
>>> from sage.all import *
>>> B = BrandtModule(Integer(10007),Integer(389))
>>> B.free_module()
Vector space of dimension 325196 over Rational Field
B = BrandtModule(10007,389)
B.free_module()
hecke_matrix(n, algorithm='default', sparse=False, B=None)[source]

Return the matrix of the \(n\)-th Hecke operator.

INPUT:

  • n – integer

  • algorithm – string (default: 'default')

    • 'default' – let Sage guess which algorithm is best

    • 'direct' – use cyclic subideals (generally much better when you want few Hecke operators and the dimension is very large); uses ‘theta’ if n divides the level.

    • 'brandt' – use Brandt matrices (generally much better when you want many Hecke operators and the dimension is very small; bad when the dimension is large)

  • sparse – boolean (default: False)

  • B – integer or None (default: None); in direct algorithm, use theta series to this precision as an initial check for equality of ideal classes.

EXAMPLES:

sage: B = BrandtModule(3,7); B.hecke_matrix(2)
[0 3]
[1 2]
sage: B.hecke_matrix(5, algorithm='brandt')
[0 6]
[2 4]
sage: t = B.hecke_matrix(11, algorithm='brandt', sparse=True); t
[ 6  6]
[ 2 10]
sage: type(t)
<class 'sage.matrix.matrix_rational_sparse.Matrix_rational_sparse'>
sage: B.hecke_matrix(19, algorithm='direct', B=2)
[ 8 12]
[ 4 16]
>>> from sage.all import *
>>> B = BrandtModule(Integer(3),Integer(7)); B.hecke_matrix(Integer(2))
[0 3]
[1 2]
>>> B.hecke_matrix(Integer(5), algorithm='brandt')
[0 6]
[2 4]
>>> t = B.hecke_matrix(Integer(11), algorithm='brandt', sparse=True); t
[ 6  6]
[ 2 10]
>>> type(t)
<class 'sage.matrix.matrix_rational_sparse.Matrix_rational_sparse'>
>>> B.hecke_matrix(Integer(19), algorithm='direct', B=Integer(2))
[ 8 12]
[ 4 16]
B = BrandtModule(3,7); B.hecke_matrix(2)
B.hecke_matrix(5, algorithm='brandt')
t = B.hecke_matrix(11, algorithm='brandt', sparse=True); t
type(t)
B.hecke_matrix(19, algorithm='direct', B=2)
is_cuspidal()[source]

Return whether self is cuspidal, i.e. has no Eisenstein part.

EXAMPLES:

sage: B = BrandtModule(3, 4)
sage: B.is_cuspidal()
False
sage: B.eisenstein_subspace()
Brandt module of dimension 1 of level 3*4 of weight 2 over Rational Field
>>> from sage.all import *
>>> B = BrandtModule(Integer(3), Integer(4))
>>> B.is_cuspidal()
False
>>> B.eisenstein_subspace()
Brandt module of dimension 1 of level 3*4 of weight 2 over Rational Field
B = BrandtModule(3, 4)
B.is_cuspidal()
B.eisenstein_subspace()
maximal_order()[source]

Return a maximal order in the quaternion algebra associated to this Brandt module.

EXAMPLES:

sage: BrandtModule(17).maximal_order()
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, -1/3*i + 1/3*k, -k)
sage: BrandtModule(17).maximal_order() is BrandtModule(17).maximal_order()
True
>>> from sage.all import *
>>> BrandtModule(Integer(17)).maximal_order()
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, -1/3*i + 1/3*k, -k)
>>> BrandtModule(Integer(17)).maximal_order() is BrandtModule(Integer(17)).maximal_order()
True
BrandtModule(17).maximal_order()
BrandtModule(17).maximal_order() is BrandtModule(17).maximal_order()
monodromy_weights()[source]

Return the weights for the monodromy pairing on this Brandt module.

The weights are associated to each ideal class in our fixed choice of basis. The weight of an ideal class \([I]\) is half the number of units of the right order \(I\).

Note

The base ring must be \(\QQ\) or \(\ZZ\).

EXAMPLES:

sage: BrandtModule(11).monodromy_weights()
(2, 3)
sage: BrandtModule(37).monodromy_weights()
(1, 1, 1)
sage: BrandtModule(43).monodromy_weights()
(2, 1, 1, 1)
sage: BrandtModule(7,10).monodromy_weights()
(1, 1, 1, 2, 1, 1, 2, 1, 1, 1)
sage: BrandtModule(5,13).monodromy_weights()
(1, 3, 1, 1, 1, 3)
sage: BrandtModule(2).monodromy_weights()
(12,)
sage: BrandtModule(2,7).monodromy_weights()
(3, 3)
>>> from sage.all import *
>>> BrandtModule(Integer(11)).monodromy_weights()
(2, 3)
>>> BrandtModule(Integer(37)).monodromy_weights()
(1, 1, 1)
>>> BrandtModule(Integer(43)).monodromy_weights()
(2, 1, 1, 1)
>>> BrandtModule(Integer(7),Integer(10)).monodromy_weights()
(1, 1, 1, 2, 1, 1, 2, 1, 1, 1)
>>> BrandtModule(Integer(5),Integer(13)).monodromy_weights()
(1, 3, 1, 1, 1, 3)
>>> BrandtModule(Integer(2)).monodromy_weights()
(12,)
>>> BrandtModule(Integer(2),Integer(7)).monodromy_weights()
(3, 3)
BrandtModule(11).monodromy_weights()
BrandtModule(37).monodromy_weights()
BrandtModule(43).monodromy_weights()
BrandtModule(7,10).monodromy_weights()
BrandtModule(5,13).monodromy_weights()
BrandtModule(2).monodromy_weights()
BrandtModule(2,7).monodromy_weights()
order_of_level_N()[source]

Return an order of level \(N = p^{2 r + 1} M\) in the quaternion algebra.

EXAMPLES:

sage: BrandtModule(7).order_of_level_N()
Order of Quaternion Algebra (-1, -7) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k)
sage: BrandtModule(7,13).order_of_level_N()
Order of Quaternion Algebra (-1, -7) with base ring Rational Field with basis (1/2 + 1/2*j + 12*k, 1/2*i + 9/2*k, j + 11*k, 13*k)
sage: BrandtModule(7,3*17).order_of_level_N()
Order of Quaternion Algebra (-1, -7) with base ring Rational Field with basis (1/2 + 1/2*j + 35*k, 1/2*i + 65/2*k, j + 19*k, 51*k)
>>> from sage.all import *
>>> BrandtModule(Integer(7)).order_of_level_N()
Order of Quaternion Algebra (-1, -7) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k)
>>> BrandtModule(Integer(7),Integer(13)).order_of_level_N()
Order of Quaternion Algebra (-1, -7) with base ring Rational Field with basis (1/2 + 1/2*j + 12*k, 1/2*i + 9/2*k, j + 11*k, 13*k)
>>> BrandtModule(Integer(7),Integer(3)*Integer(17)).order_of_level_N()
Order of Quaternion Algebra (-1, -7) with base ring Rational Field with basis (1/2 + 1/2*j + 35*k, 1/2*i + 65/2*k, j + 19*k, 51*k)
BrandtModule(7).order_of_level_N()
BrandtModule(7,13).order_of_level_N()
BrandtModule(7,3*17).order_of_level_N()
quaternion_algebra()[source]

Return the quaternion algebra \(A\) over \(\QQ\) ramified precisely at \(p\) and infinity used to compute this Brandt module.

EXAMPLES:

sage: BrandtModule(997).quaternion_algebra()
Quaternion Algebra (-2, -997) with base ring Rational Field
sage: BrandtModule(2).quaternion_algebra()
Quaternion Algebra (-1, -1) with base ring Rational Field
sage: BrandtModule(3).quaternion_algebra()
Quaternion Algebra (-1, -3) with base ring Rational Field
sage: BrandtModule(5).quaternion_algebra()
Quaternion Algebra (-2, -5) with base ring Rational Field
sage: BrandtModule(17).quaternion_algebra()
Quaternion Algebra (-3, -17) with base ring Rational Field
>>> from sage.all import *
>>> BrandtModule(Integer(997)).quaternion_algebra()
Quaternion Algebra (-2, -997) with base ring Rational Field
>>> BrandtModule(Integer(2)).quaternion_algebra()
Quaternion Algebra (-1, -1) with base ring Rational Field
>>> BrandtModule(Integer(3)).quaternion_algebra()
Quaternion Algebra (-1, -3) with base ring Rational Field
>>> BrandtModule(Integer(5)).quaternion_algebra()
Quaternion Algebra (-2, -5) with base ring Rational Field
>>> BrandtModule(Integer(17)).quaternion_algebra()
Quaternion Algebra (-3, -17) with base ring Rational Field
BrandtModule(997).quaternion_algebra()
BrandtModule(2).quaternion_algebra()
BrandtModule(3).quaternion_algebra()
BrandtModule(5).quaternion_algebra()
BrandtModule(17).quaternion_algebra()
right_ideals(B=None)[source]

Return sorted tuple of representatives for the equivalence classes of right ideals in self.

OUTPUT: sorted tuple of fractional ideals

EXAMPLES:

sage: B = BrandtModule(23)
sage: B.right_ideals()
(Fractional ideal (4, 4*i, 2 + 2*j, 2*i + 2*k),
 Fractional ideal (8, 8*i, 2 + 2*j, 6*i + 2*k),
 Fractional ideal (16, 16*i, 10 + 8*i + 2*j, 8 + 6*i + 2*k))
>>> from sage.all import *
>>> B = BrandtModule(Integer(23))
>>> B.right_ideals()
(Fractional ideal (4, 4*i, 2 + 2*j, 2*i + 2*k),
 Fractional ideal (8, 8*i, 2 + 2*j, 6*i + 2*k),
 Fractional ideal (16, 16*i, 10 + 8*i + 2*j, 8 + 6*i + 2*k))
B = BrandtModule(23)
B.right_ideals()
class sage.modular.quatalg.brandt.BrandtSubmodule(ambient, submodule, dual_free_module=None, check=True)[source]

Bases: HeckeSubmodule

sage.modular.quatalg.brandt.basis_for_left_ideal(R, gens)[source]

Return a basis for the left ideal of \(R\) with given generators.

INPUT:

  • R – quaternion order

  • gens – list of elements of \(R\)

OUTPUT: list of four elements of \(R\)

EXAMPLES:

sage: B = BrandtModule(17); A = B.quaternion_algebra(); i,j,k = A.gens()
sage: sage.modular.quatalg.brandt.basis_for_left_ideal(B.maximal_order(), [i+j,i-j,2*k,A(3)])
doctest:...:  DeprecationWarning: The function basis_for_left_ideal() is deprecated, use the _left_ideal_basis() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
[1, 1/2 + 1/2*i, j, 1/3*i + 1/2*j + 1/6*k]
sage: sage.modular.quatalg.brandt.basis_for_left_ideal(B.maximal_order(), [3*(i+j),3*(i-j),6*k,A(3)])
[3, 3/2 + 3/2*i, 3*j, i + 3/2*j + 1/2*k]
>>> from sage.all import *
>>> B = BrandtModule(Integer(17)); A = B.quaternion_algebra(); i,j,k = A.gens()
>>> sage.modular.quatalg.brandt.basis_for_left_ideal(B.maximal_order(), [i+j,i-j,Integer(2)*k,A(Integer(3))])
doctest:...:  DeprecationWarning: The function basis_for_left_ideal() is deprecated, use the _left_ideal_basis() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
[1, 1/2 + 1/2*i, j, 1/3*i + 1/2*j + 1/6*k]
>>> sage.modular.quatalg.brandt.basis_for_left_ideal(B.maximal_order(), [Integer(3)*(i+j),Integer(3)*(i-j),Integer(6)*k,A(Integer(3))])
[3, 3/2 + 3/2*i, 3*j, i + 3/2*j + 1/2*k]
B = BrandtModule(17); A = B.quaternion_algebra(); i,j,k = A.gens()
sage.modular.quatalg.brandt.basis_for_left_ideal(B.maximal_order(), [i+j,i-j,2*k,A(3)])
sage.modular.quatalg.brandt.basis_for_left_ideal(B.maximal_order(), [3*(i+j),3*(i-j),6*k,A(3)])
sage.modular.quatalg.brandt.benchmark_magma(levels, silent=False)[source]

INPUT:

  • levels – list of pairs \((p,M)\) where \(p\) is a prime not dividing \(M\)

  • silent – boolean (default: False); if True suppress printing during computation

OUTPUT:

list of 4-tuples (‘magma’, p, M, tm), where tm is the CPU time in seconds to compute T2 using Magma

EXAMPLES:

sage: a = sage.modular.quatalg.brandt.benchmark_magma([(11,1), (37,1), (43,1), (97,1)])  # optional - magma
('magma', 11, 1, ...)
('magma', 37, 1, ...)
('magma', 43, 1, ...)
('magma', 97, 1, ...)
sage: a = sage.modular.quatalg.brandt.benchmark_magma([(11,2), (37,2), (43,2), (97,2)])  # optional - magma
('magma', 11, 2, ...)
('magma', 37, 2, ...)
('magma', 43, 2, ...)
('magma', 97, 2, ...)
>>> from sage.all import *
>>> a = sage.modular.quatalg.brandt.benchmark_magma([(Integer(11),Integer(1)), (Integer(37),Integer(1)), (Integer(43),Integer(1)), (Integer(97),Integer(1))])  # optional - magma
('magma', 11, 1, ...)
('magma', 37, 1, ...)
('magma', 43, 1, ...)
('magma', 97, 1, ...)
>>> a = sage.modular.quatalg.brandt.benchmark_magma([(Integer(11),Integer(2)), (Integer(37),Integer(2)), (Integer(43),Integer(2)), (Integer(97),Integer(2))])  # optional - magma
('magma', 11, 2, ...)
('magma', 37, 2, ...)
('magma', 43, 2, ...)
('magma', 97, 2, ...)
a = sage.modular.quatalg.brandt.benchmark_magma([(11,1), (37,1), (43,1), (97,1)])  # optional - magma
a = sage.modular.quatalg.brandt.benchmark_magma([(11,2), (37,2), (43,2), (97,2)])  # optional - magma
sage.modular.quatalg.brandt.benchmark_sage(levels, silent=False)[source]

INPUT:

  • levels – list of pairs \((p,M)\) where \(p\) is a prime not dividing \(M\)

  • silent – boolean (default: False); if True suppress printing during computation

OUTPUT:

list of 4-tuples (‘sage’, p, M, tm), where tm is the CPU time in seconds to compute T2 using Sage

EXAMPLES:

sage: a = sage.modular.quatalg.brandt.benchmark_sage([(11,1), (37,1), (43,1), (97,1)])
('sage', 11, 1, ...)
('sage', 37, 1, ...)
('sage', 43, 1, ...)
('sage', 97, 1, ...)
sage: a = sage.modular.quatalg.brandt.benchmark_sage([(11,2), (37,2), (43,2), (97,2)])
('sage', 11, 2, ...)
('sage', 37, 2, ...)
('sage', 43, 2, ...)
('sage', 97, 2, ...)
>>> from sage.all import *
>>> a = sage.modular.quatalg.brandt.benchmark_sage([(Integer(11),Integer(1)), (Integer(37),Integer(1)), (Integer(43),Integer(1)), (Integer(97),Integer(1))])
('sage', 11, 1, ...)
('sage', 37, 1, ...)
('sage', 43, 1, ...)
('sage', 97, 1, ...)
>>> a = sage.modular.quatalg.brandt.benchmark_sage([(Integer(11),Integer(2)), (Integer(37),Integer(2)), (Integer(43),Integer(2)), (Integer(97),Integer(2))])
('sage', 11, 2, ...)
('sage', 37, 2, ...)
('sage', 43, 2, ...)
('sage', 97, 2, ...)
a = sage.modular.quatalg.brandt.benchmark_sage([(11,1), (37,1), (43,1), (97,1)])
a = sage.modular.quatalg.brandt.benchmark_sage([(11,2), (37,2), (43,2), (97,2)])
sage.modular.quatalg.brandt.class_number(p, r, M)[source]

Return the class number of an order of level \(N = p^r M\) in the quaternion algebra over \(\QQ\) ramified precisely at \(p\) and infinity.

This is an implementation of Theorem 1.12 of [Piz1980].

INPUT:

  • p – a prime

  • r – an odd positive integer (default: 1)

  • M – integer coprime to \(q\) (default: 1)

OUTPUT: integer

EXAMPLES:

sage: sage.modular.quatalg.brandt.class_number(389,1,1)
33
sage: sage.modular.quatalg.brandt.class_number(389,1,2)  # TODO -- right?
97
sage: sage.modular.quatalg.brandt.class_number(389,3,1)  # TODO -- right?
4892713
>>> from sage.all import *
>>> sage.modular.quatalg.brandt.class_number(Integer(389),Integer(1),Integer(1))
33
>>> sage.modular.quatalg.brandt.class_number(Integer(389),Integer(1),Integer(2))  # TODO -- right?
97
>>> sage.modular.quatalg.brandt.class_number(Integer(389),Integer(3),Integer(1))  # TODO -- right?
4892713
sage.modular.quatalg.brandt.class_number(389,1,1)
sage.modular.quatalg.brandt.class_number(389,1,2)  # TODO -- right?
sage.modular.quatalg.brandt.class_number(389,3,1)  # TODO -- right?
sage.modular.quatalg.brandt.maximal_order(A)[source]

Return a maximal order in the quaternion algebra ramified at \(p\) and infinity.

This is an implementation of Proposition 5.2 of [Piz1980].

INPUT:

  • A – quaternion algebra ramified precisely at \(p\) and infinity

OUTPUT: a maximal order in \(A\)

EXAMPLES:

sage: A = BrandtModule(17).quaternion_algebra()

sage: sage.modular.quatalg.brandt.maximal_order(A)
doctest:...:  DeprecationWarning: The function maximal_order() is deprecated, use the maximal_order() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, -1/3*i + 1/3*k, -k)

sage: A = QuaternionAlgebra(17,names='i,j,k')
sage: A.maximal_order()
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, -1/3*i + 1/3*k, -k)
>>> from sage.all import *
>>> A = BrandtModule(Integer(17)).quaternion_algebra()

>>> sage.modular.quatalg.brandt.maximal_order(A)
doctest:...:  DeprecationWarning: The function maximal_order() is deprecated, use the maximal_order() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, -1/3*i + 1/3*k, -k)

>>> A = QuaternionAlgebra(Integer(17),names='i,j,k')
>>> A.maximal_order()
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, -1/3*i + 1/3*k, -k)
A = BrandtModule(17).quaternion_algebra()
sage.modular.quatalg.brandt.maximal_order(A)
A = QuaternionAlgebra(17,names='i,j,k')
A.maximal_order()
sage.modular.quatalg.brandt.quaternion_order_with_given_level(A, level)[source]

Return an order in the quaternion algebra A with given level.

This is implemented only when the base field is the rational numbers.

INPUT:

  • level – the level of the order to be returned. Currently this is only implemented when the level is divisible by at most one power of a prime that ramifies in this quaternion algebra.

EXAMPLES:

sage: from sage.modular.quatalg.brandt import quaternion_order_with_given_level, maximal_order
sage: A.<i,j,k> = QuaternionAlgebra(5)
sage: level = 2 * 5 * 17
sage: O = quaternion_order_with_given_level(A, level)
doctest:...:  DeprecationWarning: The function quaternion_order_with_given_level() is deprecated, use the order_with_level() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
sage: M = A.maximal_order()
sage: L = O.free_module()
sage: N = M.free_module()
sage: L.index_in(N) == level/5  #check that the order has the right index in the maximal order
True
>>> from sage.all import *
>>> from sage.modular.quatalg.brandt import quaternion_order_with_given_level, maximal_order
>>> A = QuaternionAlgebra(Integer(5), names=('i', 'j', 'k',)); (i, j, k,) = A._first_ngens(3)
>>> level = Integer(2) * Integer(5) * Integer(17)
>>> O = quaternion_order_with_given_level(A, level)
doctest:...:  DeprecationWarning: The function quaternion_order_with_given_level() is deprecated, use the order_with_level() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
>>> M = A.maximal_order()
>>> L = O.free_module()
>>> N = M.free_module()
>>> L.index_in(N) == level/Integer(5)  #check that the order has the right index in the maximal order
True
from sage.modular.quatalg.brandt import quaternion_order_with_given_level, maximal_order
A.<i,j,k> = QuaternionAlgebra(5)
level = 2 * 5 * 17
O = quaternion_order_with_given_level(A, level)
M = A.maximal_order()
L = O.free_module()
N = M.free_module()
L.index_in(N) == level/5  #check that the order has the right index in the maximal order
sage.modular.quatalg.brandt.right_order(R, basis)[source]

Given a basis for a left ideal \(I\), return the right order in the quaternion order \(R\) of elements \(x\) such that \(I x\) is contained in \(I\).

INPUT:

  • R – order in quaternion algebra

  • basis – basis for an ideal \(I\)

OUTPUT: order in quaternion algebra

EXAMPLES:

We do a consistency check with the ideal equal to a maximal order:

sage: B = BrandtModule(17); basis = B.maximal_order()._left_ideal_basis([1])
sage: sage.modular.quatalg.brandt.right_order(B.maximal_order(), basis)
doctest:...:  DeprecationWarning: The function right_order() is deprecated, use the _right_order_from_ideal_basis() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/6*i + 1/3*k, 1/3*i + 2/3*k, 1/2*j + 1/2*k, k)
sage: basis
[1, 1/2 + 1/2*i, j, 1/3*i + 1/2*j + 1/6*k]

sage: B = BrandtModule(17); A = B.quaternion_algebra(); i,j,k = A.gens()
sage: basis = B.maximal_order()._left_ideal_basis([i*j - j])
sage: sage.modular.quatalg.brandt.right_order(B.maximal_order(), basis)
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/6*i + 1/3*k, 1/3*i + 2/3*k, 1/2*j + 1/2*k, k)
>>> from sage.all import *
>>> B = BrandtModule(Integer(17)); basis = B.maximal_order()._left_ideal_basis([Integer(1)])
>>> sage.modular.quatalg.brandt.right_order(B.maximal_order(), basis)
doctest:...:  DeprecationWarning: The function right_order() is deprecated, use the _right_order_from_ideal_basis() method of quaternion algebras
See https://github.com/sagemath/sage/issues/37090 for details.
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/6*i + 1/3*k, 1/3*i + 2/3*k, 1/2*j + 1/2*k, k)
>>> basis
[1, 1/2 + 1/2*i, j, 1/3*i + 1/2*j + 1/6*k]

>>> B = BrandtModule(Integer(17)); A = B.quaternion_algebra(); i,j,k = A.gens()
>>> basis = B.maximal_order()._left_ideal_basis([i*j - j])
>>> sage.modular.quatalg.brandt.right_order(B.maximal_order(), basis)
Order of Quaternion Algebra (-3, -17) with base ring Rational Field with basis (1/2 + 1/6*i + 1/3*k, 1/3*i + 2/3*k, 1/2*j + 1/2*k, k)
B = BrandtModule(17); basis = B.maximal_order()._left_ideal_basis([1])
sage.modular.quatalg.brandt.right_order(B.maximal_order(), basis)
basis
B = BrandtModule(17); A = B.quaternion_algebra(); i,j,k = A.gens()
basis = B.maximal_order()._left_ideal_basis([i*j - j])
sage.modular.quatalg.brandt.right_order(B.maximal_order(), basis)