passagemath-schemes 10.6.47__cp312-cp312-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.6.47.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
- passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.47.dist-info/top_level.txt +3 -0
- sage/all__sagemath_schemes.py +23 -0
- sage/databases/all__sagemath_schemes.py +7 -0
- sage/databases/cremona.py +1723 -0
- sage/dynamics/all__sagemath_schemes.py +2 -0
- sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
- sage/dynamics/arithmetic_dynamics/all.py +14 -0
- sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
- sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
- sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
- sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
- sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
- sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
- sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-312-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +745 -0
- sage/lfunctions/pari.py +818 -0
- sage/lfunctions/zero_sums.cpython-312-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5135 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
- sage/modular/abvar/abvar_newform.py +244 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +186 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +720 -0
- sage/modular/abvar/homspace.py +998 -0
- sage/modular/abvar/lseries.py +415 -0
- sage/modular/abvar/morphism.py +935 -0
- sage/modular/abvar/torsion_point.py +274 -0
- sage/modular/abvar/torsion_subgroup.py +740 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1402 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +363 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +653 -0
- sage/modular/arithgroup/congroup_gammaH.py +1469 -0
- sage/modular/arithgroup/congroup_generic.py +628 -0
- sage/modular/arithgroup/congroup_sl2z.py +267 -0
- sage/modular/arithgroup/farey_symbol.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1066 -0
- sage/modular/arithgroup/tests.py +418 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3753 -0
- sage/modular/btquotients/pautomorphicform.py +2570 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1109 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +569 -0
- sage/modular/dirichlet.py +3310 -0
- sage/modular/drinfeld_modform/all.py +2 -0
- sage/modular/drinfeld_modform/element.py +446 -0
- sage/modular/drinfeld_modform/ring.py +773 -0
- sage/modular/drinfeld_modform/tutorial.py +236 -0
- sage/modular/etaproducts.py +1065 -0
- sage/modular/hecke/algebra.py +746 -0
- sage/modular/hecke/all.py +20 -0
- sage/modular/hecke/ambient_module.py +1019 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +325 -0
- sage/modular/hecke/hecke_operator.py +780 -0
- sage/modular/hecke/homspace.py +206 -0
- sage/modular/hecke/module.py +1767 -0
- sage/modular/hecke/morphism.py +174 -0
- sage/modular/hecke/submodule.py +989 -0
- sage/modular/hypergeometric_misc.cpython-312-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2017 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1071 -0
- sage/modular/local_comp/smoothchar.py +1825 -0
- sage/modular/local_comp/type_space.py +748 -0
- sage/modular/modform/all.py +30 -0
- sage/modular/modform/ambient.py +815 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +124 -0
- sage/modular/modform/ambient_g1.py +204 -0
- sage/modular/modform/constructor.py +545 -0
- sage/modular/modform/cuspidal_submodule.py +708 -0
- sage/modular/modform/defaults.py +14 -0
- sage/modular/modform/eis_series.py +505 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4131 -0
- sage/modular/modform/find_generators.py +59 -0
- sage/modular/modform/half_integral.py +154 -0
- sage/modular/modform/hecke_operator_on_qexp.py +247 -0
- sage/modular/modform/j_invariant.py +47 -0
- sage/modular/modform/l_series_gross_zagier.py +133 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-312-darwin.so +0 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
- sage/modular/modform/notes.py +45 -0
- sage/modular/modform/numerical.py +514 -0
- sage/modular/modform/periods.py +14 -0
- sage/modular/modform/ring.py +1257 -0
- sage/modular/modform/space.py +1860 -0
- sage/modular/modform/submodule.py +118 -0
- sage/modular/modform/tests.py +64 -0
- sage/modular/modform/theta.py +110 -0
- sage/modular/modform/vm_basis.py +381 -0
- sage/modular/modform/weight1.py +220 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
- sage/modular/modform_hecketriangle/all.py +30 -0
- sage/modular/modform_hecketriangle/analytic_type.py +590 -0
- sage/modular/modform_hecketriangle/constructor.py +416 -0
- sage/modular/modform_hecketriangle/element.py +351 -0
- sage/modular/modform_hecketriangle/functors.py +752 -0
- sage/modular/modform_hecketriangle/graded_ring.py +541 -0
- sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
- sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
- sage/modular/modform_hecketriangle/readme.py +1214 -0
- sage/modular/modform_hecketriangle/series_constructor.py +580 -0
- sage/modular/modform_hecketriangle/space.py +1037 -0
- sage/modular/modform_hecketriangle/subspace.py +423 -0
- sage/modular/modsym/all.py +17 -0
- sage/modular/modsym/ambient.py +3846 -0
- sage/modular/modsym/boundary.py +1420 -0
- sage/modular/modsym/element.py +336 -0
- sage/modular/modsym/g1list.py +178 -0
- sage/modular/modsym/ghlist.py +182 -0
- sage/modular/modsym/hecke_operator.py +73 -0
- sage/modular/modsym/manin_symbol.cpython-312-darwin.so +0 -0
- sage/modular/modsym/manin_symbol.pxd +5 -0
- sage/modular/modsym/manin_symbol.pyx +497 -0
- sage/modular/modsym/manin_symbol_list.py +1295 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
- sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
- sage/modular/modsym/space.py +2468 -0
- sage/modular/modsym/subspace.py +455 -0
- sage/modular/modsym/tests.py +375 -0
- sage/modular/multiple_zeta.py +2632 -0
- sage/modular/multiple_zeta_F_algebra.py +786 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1878 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +778 -0
- sage/modular/pollack_stevens/all.py +4 -0
- sage/modular/pollack_stevens/distributions.py +874 -0
- sage/modular/pollack_stevens/fund_domain.py +1572 -0
- sage/modular/pollack_stevens/manin_map.py +859 -0
- sage/modular/pollack_stevens/modsym.py +1593 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1076 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +845 -0
- sage/modular/quasimodform/ring.py +828 -0
- sage/modular/quatalg/all.py +3 -0
- sage/modular/quatalg/brandt.py +1642 -0
- sage/modular/ssmod/all.py +8 -0
- sage/modular/ssmod/ssmod.py +827 -0
- sage/rings/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/binary_form_reduce.py +585 -0
- sage/schemes/all.py +41 -0
- sage/schemes/berkovich/all.py +6 -0
- sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
- sage/schemes/berkovich/berkovich_space.py +748 -0
- sage/schemes/curves/affine_curve.py +2928 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +381 -0
- sage/schemes/curves/curve.py +542 -0
- sage/schemes/curves/plane_curve_arrangement.py +1283 -0
- sage/schemes/curves/point.py +463 -0
- sage/schemes/curves/projective_curve.py +3026 -0
- sage/schemes/curves/zariski_vankampen.py +1932 -0
- sage/schemes/cyclic_covers/all.py +2 -0
- sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
- sage/schemes/cyclic_covers/constructor.py +137 -0
- sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
- sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
- sage/schemes/elliptic_curves/BSD.py +1036 -0
- sage/schemes/elliptic_curves/Qcurves.py +592 -0
- sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
- sage/schemes/elliptic_curves/all.py +49 -0
- sage/schemes/elliptic_curves/cardinality.py +609 -0
- sage/schemes/elliptic_curves/cm.py +1102 -0
- sage/schemes/elliptic_curves/constructor.py +1552 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
- sage/schemes/elliptic_curves/ell_egros.py +459 -0
- sage/schemes/elliptic_curves/ell_field.py +2836 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
- sage/schemes/elliptic_curves/ell_generic.py +3760 -0
- sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
- sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
- sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
- sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
- sage/schemes/elliptic_curves/ell_point.py +4787 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
- sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
- sage/schemes/elliptic_curves/ell_torsion.py +436 -0
- sage/schemes/elliptic_curves/ell_wp.py +352 -0
- sage/schemes/elliptic_curves/formal_group.py +760 -0
- sage/schemes/elliptic_curves/gal_reps.py +1459 -0
- sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7335 -0
- sage/schemes/elliptic_curves/height.py +2109 -0
- sage/schemes/elliptic_curves/hom.py +1406 -0
- sage/schemes/elliptic_curves/hom_composite.py +934 -0
- sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
- sage/schemes/elliptic_curves/hom_scalar.py +531 -0
- sage/schemes/elliptic_curves/hom_sum.py +682 -0
- sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
- sage/schemes/elliptic_curves/homset.py +271 -0
- sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +237 -0
- sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
- sage/schemes/elliptic_curves/kraus.py +1014 -0
- sage/schemes/elliptic_curves/lseries_ell.py +943 -0
- sage/schemes/elliptic_curves/mod5family.py +105 -0
- sage/schemes/elliptic_curves/mod_poly.py +197 -0
- sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
- sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
- sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
- sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
- sage/schemes/elliptic_curves/padics.py +1816 -0
- sage/schemes/elliptic_curves/period_lattice.py +2234 -0
- sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +715 -0
- sage/schemes/elliptic_curves/sha_tate.py +1158 -0
- sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
- sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
- sage/schemes/hyperelliptic_curves/all.py +6 -0
- sage/schemes/hyperelliptic_curves/constructor.py +291 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
- sage/schemes/hyperelliptic_curves/invariants.py +410 -0
- sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
- sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
- sage/schemes/hyperelliptic_curves/mestre.py +302 -0
- sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
- sage/schemes/jacobians/abstract_jacobian.py +277 -0
- sage/schemes/jacobians/all.py +2 -0
- sage/schemes/overview.py +161 -0
- sage/schemes/plane_conics/all.py +22 -0
- sage/schemes/plane_conics/con_field.py +1296 -0
- sage/schemes/plane_conics/con_finite_field.py +158 -0
- sage/schemes/plane_conics/con_number_field.py +456 -0
- sage/schemes/plane_conics/con_rational_field.py +406 -0
- sage/schemes/plane_conics/con_rational_function_field.py +580 -0
- sage/schemes/plane_conics/constructor.py +249 -0
- sage/schemes/plane_quartics/all.py +2 -0
- sage/schemes/plane_quartics/quartic_constructor.py +71 -0
- sage/schemes/plane_quartics/quartic_generic.py +73 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
- sage_wheels/share/cremona/cremona_mini.db +0 -0
- sage_wheels/share/ellcurves/rank0 +30427 -0
- sage_wheels/share/ellcurves/rank1 +31871 -0
- sage_wheels/share/ellcurves/rank10 +6 -0
- sage_wheels/share/ellcurves/rank11 +6 -0
- sage_wheels/share/ellcurves/rank12 +1 -0
- sage_wheels/share/ellcurves/rank14 +1 -0
- sage_wheels/share/ellcurves/rank15 +1 -0
- sage_wheels/share/ellcurves/rank17 +1 -0
- sage_wheels/share/ellcurves/rank19 +1 -0
- sage_wheels/share/ellcurves/rank2 +2388 -0
- sage_wheels/share/ellcurves/rank20 +1 -0
- sage_wheels/share/ellcurves/rank21 +1 -0
- sage_wheels/share/ellcurves/rank22 +1 -0
- sage_wheels/share/ellcurves/rank23 +1 -0
- sage_wheels/share/ellcurves/rank24 +1 -0
- sage_wheels/share/ellcurves/rank28 +1 -0
- sage_wheels/share/ellcurves/rank3 +836 -0
- sage_wheels/share/ellcurves/rank4 +10 -0
- sage_wheels/share/ellcurves/rank5 +5 -0
- sage_wheels/share/ellcurves/rank6 +5 -0
- sage_wheels/share/ellcurves/rank7 +5 -0
- sage_wheels/share/ellcurves/rank8 +6 -0
- sage_wheels/share/ellcurves/rank9 +7 -0
|
@@ -0,0 +1,2468 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.libs.flint sage.libs.pari
|
|
3
|
+
"""
|
|
4
|
+
Base class of the space of modular symbols
|
|
5
|
+
|
|
6
|
+
All the spaces of modular symbols derive from this class. This class is an
|
|
7
|
+
abstract base class.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# ****************************************************************************
|
|
11
|
+
# Sage: Open Source Mathematical Software
|
|
12
|
+
#
|
|
13
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
14
|
+
#
|
|
15
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
16
|
+
#
|
|
17
|
+
# This code is distributed in the hope that it will be useful,
|
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
20
|
+
# General Public License for more details.
|
|
21
|
+
#
|
|
22
|
+
# The full text of the GPL is available at:
|
|
23
|
+
#
|
|
24
|
+
# https://www.gnu.org/licenses/
|
|
25
|
+
# ****************************************************************************
|
|
26
|
+
|
|
27
|
+
from sage.arith.misc import divisors, next_prime
|
|
28
|
+
from sage.categories.fields import Fields
|
|
29
|
+
from sage.matrix.matrix_space import MatrixSpace
|
|
30
|
+
from sage.misc.cachefunc import cached_method
|
|
31
|
+
from sage.misc.lazy_import import lazy_import
|
|
32
|
+
from sage.misc.misc_c import prod
|
|
33
|
+
from sage.modules.free_module import EchelonMatrixKey, FreeModule, VectorSpace
|
|
34
|
+
from sage.modules.free_module_element import FreeModuleElement
|
|
35
|
+
from sage.rings.fast_arith import prime_range
|
|
36
|
+
from sage.rings.finite_rings.integer_mod_ring import Zmod
|
|
37
|
+
from sage.rings.integer_ring import ZZ
|
|
38
|
+
from sage.rings.integer import Integer
|
|
39
|
+
from sage.rings.infinity import infinity
|
|
40
|
+
from sage.rings.number_field.number_field_base import NumberField
|
|
41
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
42
|
+
from sage.rings.rational_field import QQ
|
|
43
|
+
from sage.structure.all import Sequence, SageObject
|
|
44
|
+
from sage.structure.richcmp import (richcmp_method, richcmp,
|
|
45
|
+
rich_to_bool, richcmp_not_equal)
|
|
46
|
+
|
|
47
|
+
from sage.modular.arithgroup.all import Gamma0, Gamma0_class # for Sturm bound given a character
|
|
48
|
+
from sage.modular.hecke.module import HeckeModule_free_module
|
|
49
|
+
from sage.modular.modsym.element import ModularSymbolsElement
|
|
50
|
+
|
|
51
|
+
lazy_import('sage.modular.modsym', 'hecke_operator')
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def is_ModularSymbolsSpace(x):
|
|
55
|
+
r"""
|
|
56
|
+
Return ``True`` if ``x`` is a space of modular symbols.
|
|
57
|
+
|
|
58
|
+
EXAMPLES::
|
|
59
|
+
|
|
60
|
+
sage: M = ModularForms(3, 2)
|
|
61
|
+
sage: sage.modular.modsym.space.is_ModularSymbolsSpace(M)
|
|
62
|
+
doctest:warning...
|
|
63
|
+
DeprecationWarning: The function is_ModularSymbolsSpace is deprecated; use 'isinstance(..., ModularForms)' instead.
|
|
64
|
+
See https://github.com/sagemath/sage/issues/38035 for details.
|
|
65
|
+
False
|
|
66
|
+
sage: sage.modular.modsym.space.is_ModularSymbolsSpace(M.modular_symbols(sign=1))
|
|
67
|
+
True
|
|
68
|
+
"""
|
|
69
|
+
from sage.misc.superseded import deprecation
|
|
70
|
+
deprecation(38035, "The function is_ModularSymbolsSpace is deprecated; use 'isinstance(..., ModularForms)' instead.")
|
|
71
|
+
return isinstance(x, ModularSymbolsSpace)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@richcmp_method
|
|
75
|
+
class ModularSymbolsSpace(HeckeModule_free_module):
|
|
76
|
+
r"""
|
|
77
|
+
Base class for spaces of modular symbols.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
Element = ModularSymbolsElement
|
|
81
|
+
|
|
82
|
+
def __init__(self, group, weight, character, sign, base_ring, category=None):
|
|
83
|
+
"""
|
|
84
|
+
Create a space of modular symbols.
|
|
85
|
+
|
|
86
|
+
EXAMPLES::
|
|
87
|
+
|
|
88
|
+
sage: M = ModularSymbols(22,6) ; M
|
|
89
|
+
Modular Symbols space of dimension 30 for Gamma_0(22) of weight 6 with sign 0 over Rational Field
|
|
90
|
+
sage: M == loads(dumps(M))
|
|
91
|
+
True
|
|
92
|
+
"""
|
|
93
|
+
self.__group = group
|
|
94
|
+
self.__character = character
|
|
95
|
+
self.__sign = sign
|
|
96
|
+
HeckeModule_free_module.__init__(self, base_ring, group.level(), weight, category=category)
|
|
97
|
+
|
|
98
|
+
def __richcmp__(self, other, op):
|
|
99
|
+
"""
|
|
100
|
+
Compare ``self`` and ``other``.
|
|
101
|
+
|
|
102
|
+
When spaces are in a common ambient space, we order
|
|
103
|
+
lexicographically by the sequence of traces of Hecke operators
|
|
104
|
+
`T_p`, for all primes `p`. In general we order
|
|
105
|
+
first by the group, then the weight, then the character, then the
|
|
106
|
+
sign then the base ring, then the dimension.
|
|
107
|
+
|
|
108
|
+
EXAMPLES::
|
|
109
|
+
|
|
110
|
+
sage: M = ModularSymbols(21,4) ; N = ModularSymbols(Gamma1(5),6)
|
|
111
|
+
sage: M.cuspidal_submodule() > N
|
|
112
|
+
True
|
|
113
|
+
sage: M.cuspidal_submodule() == N
|
|
114
|
+
False
|
|
115
|
+
"""
|
|
116
|
+
if not isinstance(other, ModularSymbolsSpace):
|
|
117
|
+
return NotImplemented
|
|
118
|
+
|
|
119
|
+
lx = self.__group
|
|
120
|
+
rx = other.__group
|
|
121
|
+
if lx != rx:
|
|
122
|
+
return richcmp_not_equal(lx, rx, op)
|
|
123
|
+
|
|
124
|
+
lx = self.weight()
|
|
125
|
+
rx = other.weight()
|
|
126
|
+
if lx != rx:
|
|
127
|
+
return richcmp_not_equal(lx, rx, op)
|
|
128
|
+
|
|
129
|
+
lx = self.__character
|
|
130
|
+
rx = other.__character
|
|
131
|
+
if lx != rx:
|
|
132
|
+
return richcmp_not_equal(lx, rx, op)
|
|
133
|
+
|
|
134
|
+
lx = self.__sign
|
|
135
|
+
rx = other.__sign
|
|
136
|
+
if lx != rx:
|
|
137
|
+
return richcmp_not_equal(lx, rx, op)
|
|
138
|
+
|
|
139
|
+
lx = self.base_ring()
|
|
140
|
+
rx = other.base_ring()
|
|
141
|
+
if lx != rx:
|
|
142
|
+
return richcmp_not_equal(lx, rx, op)
|
|
143
|
+
|
|
144
|
+
if self.is_ambient() or other.is_ambient():
|
|
145
|
+
# if one is ambient they are equal iff they have same
|
|
146
|
+
# dimension at this point, since all defining properties
|
|
147
|
+
# are the same, so they are in the same ambient space.
|
|
148
|
+
return richcmp(self.dimension(), other.dimension(), op)
|
|
149
|
+
|
|
150
|
+
lx = self.ambient_hecke_module()
|
|
151
|
+
rx = other.ambient_hecke_module()
|
|
152
|
+
if lx != rx:
|
|
153
|
+
return richcmp_not_equal(lx, rx, op)
|
|
154
|
+
|
|
155
|
+
lx = self.dimension()
|
|
156
|
+
rx = other.dimension()
|
|
157
|
+
if lx != rx:
|
|
158
|
+
return richcmp_not_equal(lx, rx, op)
|
|
159
|
+
|
|
160
|
+
lx = EchelonMatrixKey(self.free_module())
|
|
161
|
+
rx = EchelonMatrixKey(other.free_module())
|
|
162
|
+
|
|
163
|
+
if lx == rx:
|
|
164
|
+
return rich_to_bool(op, 0)
|
|
165
|
+
|
|
166
|
+
# distinguish using Hecke operators, if possible.
|
|
167
|
+
try:
|
|
168
|
+
for p in prime_range(self.hecke_bound()):
|
|
169
|
+
ap = self.hecke_matrix(p).trace()
|
|
170
|
+
bp = other.hecke_matrix(p).trace()
|
|
171
|
+
if ap != bp:
|
|
172
|
+
return richcmp_not_equal(ap, bp, op)
|
|
173
|
+
except ArithmeticError:
|
|
174
|
+
pass
|
|
175
|
+
# fallback on subspace comparison
|
|
176
|
+
return richcmp_not_equal(lx, rx, op)
|
|
177
|
+
|
|
178
|
+
def _hecke_operator_class(self):
|
|
179
|
+
"""
|
|
180
|
+
Return the class to be used for instantiating Hecke operators
|
|
181
|
+
acting on ``self``.
|
|
182
|
+
|
|
183
|
+
EXAMPLES::
|
|
184
|
+
|
|
185
|
+
sage: ModularSymbols(81,2)._hecke_operator_class()
|
|
186
|
+
<class 'sage.modular.modsym.hecke_operator.HeckeOperator'>
|
|
187
|
+
"""
|
|
188
|
+
return hecke_operator.HeckeOperator
|
|
189
|
+
|
|
190
|
+
def compact_system_of_eigenvalues(self, v, names='alpha', nz=None):
|
|
191
|
+
r"""
|
|
192
|
+
Return a compact system of eigenvalues `a_n` for
|
|
193
|
+
`n\in v`.
|
|
194
|
+
|
|
195
|
+
This should only be called on simple factors of modular
|
|
196
|
+
symbols spaces.
|
|
197
|
+
|
|
198
|
+
INPUT:
|
|
199
|
+
|
|
200
|
+
- ``v`` -- list of positive integers
|
|
201
|
+
- ``nz`` -- (default: ``None``) if given specifies a column index
|
|
202
|
+
such that the dual module has that column nonzero
|
|
203
|
+
|
|
204
|
+
OUTPUT:
|
|
205
|
+
|
|
206
|
+
- ``E`` -- matrix such that E\*v is a vector with components
|
|
207
|
+
the eigenvalues `a_n` for `n \in v`
|
|
208
|
+
- ``v`` -- a vector over a number field
|
|
209
|
+
|
|
210
|
+
EXAMPLES::
|
|
211
|
+
|
|
212
|
+
sage: M = ModularSymbols(43,2,1)[2]; M
|
|
213
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 for Gamma_0(43) of weight 2 with sign 1 over Rational Field
|
|
214
|
+
sage: E, v = M.compact_system_of_eigenvalues(prime_range(10))
|
|
215
|
+
sage: E
|
|
216
|
+
[ 2/3 -4/3]
|
|
217
|
+
[-2/3 4/3]
|
|
218
|
+
[ 4/3 4/3]
|
|
219
|
+
[-4/3 -4/3]
|
|
220
|
+
sage: v
|
|
221
|
+
(1, -3/4*alpha + 1/2)
|
|
222
|
+
sage: E*v
|
|
223
|
+
(alpha, -alpha, -alpha + 2, alpha - 2)
|
|
224
|
+
|
|
225
|
+
TESTS:
|
|
226
|
+
|
|
227
|
+
Verify that :issue:`12772` is fixed::
|
|
228
|
+
|
|
229
|
+
sage: M = ModularSymbols(1,12,sign=1).cuspidal_subspace().new_subspace()
|
|
230
|
+
sage: A = M.decomposition()[0]
|
|
231
|
+
sage: A.compact_system_of_eigenvalues(prime_range(10))
|
|
232
|
+
(
|
|
233
|
+
[ -24]
|
|
234
|
+
[ 252]
|
|
235
|
+
[ 4830]
|
|
236
|
+
[-16744], (1)
|
|
237
|
+
)
|
|
238
|
+
"""
|
|
239
|
+
if nz is None:
|
|
240
|
+
nz = self._eigen_nonzero()
|
|
241
|
+
M = self.ambient()
|
|
242
|
+
try:
|
|
243
|
+
E = M.hecke_images(nz, v) * self.dual_free_module().basis_matrix().transpose()
|
|
244
|
+
except AttributeError:
|
|
245
|
+
# TODO!!!
|
|
246
|
+
raise NotImplementedError("ambient space must implement hecke_images but doesn't yet")
|
|
247
|
+
v = self.dual_eigenvector(names=names, lift=False, nz=nz)
|
|
248
|
+
return E, v
|
|
249
|
+
|
|
250
|
+
def character(self):
|
|
251
|
+
"""
|
|
252
|
+
Return the character associated to ``self``.
|
|
253
|
+
|
|
254
|
+
EXAMPLES::
|
|
255
|
+
|
|
256
|
+
sage: ModularSymbols(12,8).character()
|
|
257
|
+
Dirichlet character modulo 12 of conductor 1 mapping 7 |--> 1, 5 |--> 1
|
|
258
|
+
sage: ModularSymbols(DirichletGroup(25).0, 4).character()
|
|
259
|
+
Dirichlet character modulo 25 of conductor 25 mapping 2 |--> zeta20
|
|
260
|
+
"""
|
|
261
|
+
return self.__character
|
|
262
|
+
|
|
263
|
+
def cuspidal_submodule(self):
|
|
264
|
+
"""
|
|
265
|
+
Return the cuspidal submodule of ``self``.
|
|
266
|
+
|
|
267
|
+
.. NOTE::
|
|
268
|
+
|
|
269
|
+
This should be overridden by all derived classes.
|
|
270
|
+
|
|
271
|
+
EXAMPLES::
|
|
272
|
+
|
|
273
|
+
sage: sage.modular.modsym.space.ModularSymbolsSpace(Gamma0(11),2,DirichletGroup(11).gens()[0]**10,0,QQ).cuspidal_submodule()
|
|
274
|
+
Traceback (most recent call last):
|
|
275
|
+
...
|
|
276
|
+
NotImplementedError: computation of cuspidal submodule not yet implemented for this class
|
|
277
|
+
sage: ModularSymbols(Gamma0(11),2).cuspidal_submodule()
|
|
278
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
|
|
279
|
+
"""
|
|
280
|
+
raise NotImplementedError("computation of cuspidal submodule not yet implemented for this class")
|
|
281
|
+
|
|
282
|
+
def cuspidal_subspace(self):
|
|
283
|
+
"""
|
|
284
|
+
Synonym for cuspidal_submodule.
|
|
285
|
+
|
|
286
|
+
EXAMPLES::
|
|
287
|
+
|
|
288
|
+
sage: m = ModularSymbols(Gamma1(3),12); m.dimension()
|
|
289
|
+
8
|
|
290
|
+
sage: m.cuspidal_subspace().new_subspace().dimension()
|
|
291
|
+
2
|
|
292
|
+
"""
|
|
293
|
+
return self.cuspidal_submodule()
|
|
294
|
+
|
|
295
|
+
def new_subspace(self, p=None):
|
|
296
|
+
"""
|
|
297
|
+
Synonym for new_submodule.
|
|
298
|
+
|
|
299
|
+
EXAMPLES::
|
|
300
|
+
|
|
301
|
+
sage: m = ModularSymbols(Gamma0(5),12); m.dimension()
|
|
302
|
+
12
|
|
303
|
+
sage: m.new_subspace().dimension()
|
|
304
|
+
6
|
|
305
|
+
sage: m = ModularSymbols(Gamma1(3),12); m.dimension()
|
|
306
|
+
8
|
|
307
|
+
sage: m.new_subspace().dimension()
|
|
308
|
+
2
|
|
309
|
+
"""
|
|
310
|
+
return self.new_submodule(p)
|
|
311
|
+
|
|
312
|
+
def old_subspace(self, p=None):
|
|
313
|
+
"""
|
|
314
|
+
Synonym for old_submodule.
|
|
315
|
+
|
|
316
|
+
EXAMPLES::
|
|
317
|
+
|
|
318
|
+
sage: m = ModularSymbols(Gamma1(3),12); m.dimension()
|
|
319
|
+
8
|
|
320
|
+
sage: m.old_subspace().dimension()
|
|
321
|
+
6
|
|
322
|
+
"""
|
|
323
|
+
return self.old_submodule(p)
|
|
324
|
+
|
|
325
|
+
def eisenstein_subspace(self):
|
|
326
|
+
"""
|
|
327
|
+
Synonym for eisenstein_submodule.
|
|
328
|
+
|
|
329
|
+
EXAMPLES::
|
|
330
|
+
|
|
331
|
+
sage: m = ModularSymbols(Gamma1(3),12); m.dimension()
|
|
332
|
+
8
|
|
333
|
+
sage: m.eisenstein_subspace().dimension()
|
|
334
|
+
2
|
|
335
|
+
sage: m.cuspidal_subspace().dimension()
|
|
336
|
+
6
|
|
337
|
+
"""
|
|
338
|
+
return self.eisenstein_submodule()
|
|
339
|
+
|
|
340
|
+
def dimension_of_associated_cuspform_space(self):
|
|
341
|
+
"""
|
|
342
|
+
Return the dimension of the corresponding space of cusp forms.
|
|
343
|
+
|
|
344
|
+
The input space must be cuspidal, otherwise there is no
|
|
345
|
+
corresponding space of cusp forms.
|
|
346
|
+
|
|
347
|
+
EXAMPLES::
|
|
348
|
+
|
|
349
|
+
sage: m = ModularSymbols(Gamma0(389),2).cuspidal_subspace(); m.dimension()
|
|
350
|
+
64
|
|
351
|
+
sage: m.dimension_of_associated_cuspform_space()
|
|
352
|
+
32
|
|
353
|
+
sage: m = ModularSymbols(Gamma0(389),2,sign=1).cuspidal_subspace(); m.dimension()
|
|
354
|
+
32
|
|
355
|
+
sage: m.dimension_of_associated_cuspform_space()
|
|
356
|
+
32
|
|
357
|
+
"""
|
|
358
|
+
if not self.is_cuspidal():
|
|
359
|
+
raise ArithmeticError("space must be cuspidal")
|
|
360
|
+
if self.sign() == 0:
|
|
361
|
+
return self.dimension() // 2
|
|
362
|
+
return self.dimension()
|
|
363
|
+
|
|
364
|
+
def dual_star_involution_matrix(self):
|
|
365
|
+
"""
|
|
366
|
+
Return the matrix of the dual star involution, which is induced by
|
|
367
|
+
complex conjugation on the linear dual of modular symbols.
|
|
368
|
+
|
|
369
|
+
.. NOTE::
|
|
370
|
+
|
|
371
|
+
This should be overridden in all derived classes.
|
|
372
|
+
|
|
373
|
+
EXAMPLES::
|
|
374
|
+
|
|
375
|
+
sage: sage.modular.modsym.space.ModularSymbolsSpace(Gamma0(11),2,DirichletGroup(11).gens()[0]**10,0,QQ).dual_star_involution_matrix()
|
|
376
|
+
Traceback (most recent call last):
|
|
377
|
+
...
|
|
378
|
+
NotImplementedError: computation of dual star involution matrix not yet implemented for this class
|
|
379
|
+
sage: ModularSymbols(Gamma0(11),2).dual_star_involution_matrix()
|
|
380
|
+
[ 1 0 0]
|
|
381
|
+
[ 0 -1 0]
|
|
382
|
+
[ 0 1 1]
|
|
383
|
+
"""
|
|
384
|
+
raise NotImplementedError("computation of dual star involution matrix not yet implemented for this class")
|
|
385
|
+
|
|
386
|
+
def group(self):
|
|
387
|
+
"""
|
|
388
|
+
Return the group of this modular symbols space.
|
|
389
|
+
|
|
390
|
+
INPUT:
|
|
391
|
+
|
|
392
|
+
- ``ModularSymbols self`` -- an arbitrary space of
|
|
393
|
+
modular symbols
|
|
394
|
+
|
|
395
|
+
OUTPUT:
|
|
396
|
+
|
|
397
|
+
- ``CongruenceSubgroup`` -- the congruence subgroup
|
|
398
|
+
that this is a space of modular symbols for
|
|
399
|
+
|
|
400
|
+
ALGORITHM: The group is recorded when this space is created.
|
|
401
|
+
|
|
402
|
+
EXAMPLES::
|
|
403
|
+
|
|
404
|
+
sage: m = ModularSymbols(20)
|
|
405
|
+
sage: m.group()
|
|
406
|
+
Congruence Subgroup Gamma0(20)
|
|
407
|
+
"""
|
|
408
|
+
return self.__group
|
|
409
|
+
|
|
410
|
+
def is_ambient(self) -> bool:
|
|
411
|
+
"""
|
|
412
|
+
Return ``True`` if ``self`` is an ambient space of modular symbols.
|
|
413
|
+
|
|
414
|
+
EXAMPLES::
|
|
415
|
+
|
|
416
|
+
sage: ModularSymbols(21,4).is_ambient()
|
|
417
|
+
True
|
|
418
|
+
sage: ModularSymbols(21,4).cuspidal_submodule().is_ambient()
|
|
419
|
+
False
|
|
420
|
+
"""
|
|
421
|
+
from sage.modular.modsym.ambient import ModularSymbolsAmbient
|
|
422
|
+
return isinstance(self, ModularSymbolsAmbient)
|
|
423
|
+
|
|
424
|
+
def is_cuspidal(self) -> bool:
|
|
425
|
+
"""
|
|
426
|
+
Return ``True`` if ``self`` is a cuspidal space of modular symbols.
|
|
427
|
+
|
|
428
|
+
.. NOTE::
|
|
429
|
+
|
|
430
|
+
This should be overridden in all derived classes.
|
|
431
|
+
|
|
432
|
+
EXAMPLES::
|
|
433
|
+
|
|
434
|
+
sage: sage.modular.modsym.space.ModularSymbolsSpace(Gamma0(11),2,DirichletGroup(11).gens()[0]**10,0,QQ).is_cuspidal()
|
|
435
|
+
Traceback (most recent call last):
|
|
436
|
+
...
|
|
437
|
+
NotImplementedError: computation of cuspidal subspace not yet implemented for this class
|
|
438
|
+
sage: ModularSymbols(Gamma0(11),2).is_cuspidal()
|
|
439
|
+
False
|
|
440
|
+
"""
|
|
441
|
+
raise NotImplementedError("computation of cuspidal subspace not yet implemented for this class")
|
|
442
|
+
|
|
443
|
+
def is_simple(self) -> bool:
|
|
444
|
+
r"""
|
|
445
|
+
Return whether this modular symbols space is simple as a module
|
|
446
|
+
over the anemic Hecke algebra adjoin \*.
|
|
447
|
+
|
|
448
|
+
EXAMPLES::
|
|
449
|
+
|
|
450
|
+
sage: m = ModularSymbols(Gamma0(33),2,sign=1)
|
|
451
|
+
sage: m.is_simple()
|
|
452
|
+
False
|
|
453
|
+
sage: o = m.old_subspace()
|
|
454
|
+
sage: o.decomposition()
|
|
455
|
+
[Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 6 for Gamma_0(33) of weight 2 with sign 1 over Rational Field,
|
|
456
|
+
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 6 for Gamma_0(33) of weight 2 with sign 1 over Rational Field]
|
|
457
|
+
sage: C = ModularSymbols(1,14,0,GF(5)).cuspidal_submodule(); C
|
|
458
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(1) of weight 14 with sign 0 over Finite Field of size 5
|
|
459
|
+
sage: C.is_simple()
|
|
460
|
+
True
|
|
461
|
+
"""
|
|
462
|
+
try:
|
|
463
|
+
return self._is_simple
|
|
464
|
+
except AttributeError:
|
|
465
|
+
D = self.factorization()
|
|
466
|
+
if len(D) == 0 or len(D) == 1 and D[0][1] == 1:
|
|
467
|
+
self._is_simple = True
|
|
468
|
+
else:
|
|
469
|
+
self._is_simple = False
|
|
470
|
+
return self._is_simple
|
|
471
|
+
|
|
472
|
+
def multiplicity(self, S, check_simple=True):
|
|
473
|
+
"""
|
|
474
|
+
Return the multiplicity of the simple modular symbols space S in
|
|
475
|
+
``self``. S must be a simple anemic Hecke module.
|
|
476
|
+
|
|
477
|
+
ASSUMPTION: ``self`` is an anemic Hecke module with the same weight and
|
|
478
|
+
group as S, and S is simple.
|
|
479
|
+
|
|
480
|
+
EXAMPLES::
|
|
481
|
+
|
|
482
|
+
sage: M = ModularSymbols(11,2,sign=1)
|
|
483
|
+
sage: N1, N2 = M.decomposition()
|
|
484
|
+
sage: N1.multiplicity(N2)
|
|
485
|
+
0
|
|
486
|
+
sage: M.multiplicity(N1)
|
|
487
|
+
1
|
|
488
|
+
sage: M.multiplicity(ModularSymbols(14,2))
|
|
489
|
+
0
|
|
490
|
+
"""
|
|
491
|
+
if self.level() % S.level() != 0 or S.weight() != self.weight():
|
|
492
|
+
return 0
|
|
493
|
+
if check_simple and not S.is_simple():
|
|
494
|
+
raise ArithmeticError("S must be simple")
|
|
495
|
+
A = self.ambient_hecke_module()
|
|
496
|
+
B = A.submodule_generated_by_images(S)
|
|
497
|
+
C = self.intersection(B)
|
|
498
|
+
d = C.rank()
|
|
499
|
+
n = S.rank()
|
|
500
|
+
assert d % n == 0, "the dimension of intersection must be a multiple of dimension of simple space. bug!"
|
|
501
|
+
return d // n
|
|
502
|
+
|
|
503
|
+
def ngens(self):
|
|
504
|
+
"""
|
|
505
|
+
Return the number of generators of ``self``.
|
|
506
|
+
|
|
507
|
+
INPUT:
|
|
508
|
+
|
|
509
|
+
- ``ModularSymbols self`` -- arbitrary space of modular symbols
|
|
510
|
+
|
|
511
|
+
OUTPUT:
|
|
512
|
+
|
|
513
|
+
- ``int`` -- the number of generators, which is the same as the
|
|
514
|
+
dimension of ``self``
|
|
515
|
+
|
|
516
|
+
ALGORITHM: Call the dimension function.
|
|
517
|
+
|
|
518
|
+
EXAMPLES::
|
|
519
|
+
|
|
520
|
+
sage: m = ModularSymbols(33)
|
|
521
|
+
sage: m.ngens()
|
|
522
|
+
9
|
|
523
|
+
sage: m.rank()
|
|
524
|
+
9
|
|
525
|
+
sage: ModularSymbols(100, weight=2, sign=1).ngens()
|
|
526
|
+
18
|
|
527
|
+
"""
|
|
528
|
+
return self.rank()
|
|
529
|
+
|
|
530
|
+
#########################################################################
|
|
531
|
+
#
|
|
532
|
+
# Computation of q-expansions
|
|
533
|
+
#
|
|
534
|
+
#########################################################################
|
|
535
|
+
|
|
536
|
+
def default_prec(self):
|
|
537
|
+
r"""
|
|
538
|
+
Get the default precision for computation of `q`-expansion
|
|
539
|
+
associated to the ambient space of this space of modular symbols
|
|
540
|
+
(and all subspaces). Use ``set_default_prec`` to
|
|
541
|
+
change the default precision.
|
|
542
|
+
|
|
543
|
+
EXAMPLES::
|
|
544
|
+
|
|
545
|
+
sage: M = ModularSymbols(15)
|
|
546
|
+
sage: M.cuspidal_submodule().q_expansion_basis()
|
|
547
|
+
[q - q^2 - q^3 - q^4 + q^5 + q^6 + O(q^8)]
|
|
548
|
+
sage: M.set_default_prec(20)
|
|
549
|
+
|
|
550
|
+
Notice that setting the default precision of the ambient space
|
|
551
|
+
affects the subspaces.
|
|
552
|
+
|
|
553
|
+
::
|
|
554
|
+
|
|
555
|
+
sage: M.cuspidal_submodule().q_expansion_basis()
|
|
556
|
+
[q - q^2 - q^3 - q^4 + q^5 + q^6 + 3*q^8 + q^9 - q^10 - 4*q^11 + q^12 - 2*q^13 - q^15 - q^16 + 2*q^17 - q^18 + 4*q^19 + O(q^20)]
|
|
557
|
+
sage: M.cuspidal_submodule().default_prec()
|
|
558
|
+
20
|
|
559
|
+
"""
|
|
560
|
+
if not self.is_ambient():
|
|
561
|
+
return self.ambient_hecke_module().default_prec()
|
|
562
|
+
try:
|
|
563
|
+
return self.__default_prec
|
|
564
|
+
except AttributeError:
|
|
565
|
+
self.__default_prec = Integer(8)
|
|
566
|
+
return self.__default_prec
|
|
567
|
+
|
|
568
|
+
def set_default_prec(self, prec):
|
|
569
|
+
"""
|
|
570
|
+
Set the default precision for computation of `q`-expansion
|
|
571
|
+
associated to the ambient space of this space of modular symbols
|
|
572
|
+
(and all subspaces).
|
|
573
|
+
|
|
574
|
+
EXAMPLES::
|
|
575
|
+
|
|
576
|
+
sage: M = ModularSymbols(Gamma1(13),2)
|
|
577
|
+
sage: M.set_default_prec(5)
|
|
578
|
+
sage: M.cuspidal_submodule().q_expansion_basis()
|
|
579
|
+
[q - 4*q^3 - q^4 + O(q^5), q^2 - 2*q^3 - q^4 + O(q^5)]
|
|
580
|
+
"""
|
|
581
|
+
if not self.is_ambient():
|
|
582
|
+
return self.ambient_hecke_module().set_default_prec(prec)
|
|
583
|
+
else:
|
|
584
|
+
self.__default_prec = Integer(prec)
|
|
585
|
+
|
|
586
|
+
def set_precision(self, prec):
|
|
587
|
+
"""
|
|
588
|
+
Same as self.set_default_prec(prec).
|
|
589
|
+
|
|
590
|
+
EXAMPLES::
|
|
591
|
+
|
|
592
|
+
sage: M = ModularSymbols(17,2)
|
|
593
|
+
sage: M.cuspidal_submodule().q_expansion_basis()
|
|
594
|
+
[q - q^2 - q^4 - 2*q^5 + 4*q^7 + O(q^8)]
|
|
595
|
+
sage: M.set_precision(10)
|
|
596
|
+
sage: M.cuspidal_submodule().q_expansion_basis()
|
|
597
|
+
[q - q^2 - q^4 - 2*q^5 + 4*q^7 + 3*q^8 - 3*q^9 + O(q^10)]
|
|
598
|
+
"""
|
|
599
|
+
self.set_default_prec(prec)
|
|
600
|
+
|
|
601
|
+
def q_expansion_basis(self, prec=None, algorithm='default'):
|
|
602
|
+
r"""
|
|
603
|
+
Return a basis of `q`-expansions (as power series) to precision ``prec``
|
|
604
|
+
of the space of modular forms associated to ``self``.
|
|
605
|
+
|
|
606
|
+
The `q`-expansions are defined over the same base ring as ``self``,
|
|
607
|
+
and a put in echelon form.
|
|
608
|
+
|
|
609
|
+
INPUT:
|
|
610
|
+
|
|
611
|
+
- ``self`` -- a space of CUSPIDAL modular symbols
|
|
612
|
+
|
|
613
|
+
- ``prec`` -- integer
|
|
614
|
+
|
|
615
|
+
- ``algorithm`` -- string; one of
|
|
616
|
+
|
|
617
|
+
- ``'default'`` -- (default) decide which algorithm to
|
|
618
|
+
use based on heuristics
|
|
619
|
+
|
|
620
|
+
- ``'hecke'`` -- compute basis by computing
|
|
621
|
+
homomorphisms T - K, where T is the Hecke algebra
|
|
622
|
+
|
|
623
|
+
- ``'eigen'`` -- compute basis using eigenvectors for
|
|
624
|
+
the Hecke action and Atkin-Lehner-Li theory to patch them together
|
|
625
|
+
|
|
626
|
+
- ``'all'`` -- compute using hecke_dual and eigen
|
|
627
|
+
algorithms and verify that the results are the same
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
The computed basis is *not* cached, though of course Hecke
|
|
631
|
+
operators used in computing the basis are cached.
|
|
632
|
+
|
|
633
|
+
EXAMPLES::
|
|
634
|
+
|
|
635
|
+
sage: M = ModularSymbols(1, 12).cuspidal_submodule()
|
|
636
|
+
sage: M.q_expansion_basis(8)
|
|
637
|
+
[q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + O(q^8)]
|
|
638
|
+
|
|
639
|
+
::
|
|
640
|
+
|
|
641
|
+
sage: M.q_expansion_basis(8, algorithm='eigen')
|
|
642
|
+
[q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + O(q^8)]
|
|
643
|
+
|
|
644
|
+
::
|
|
645
|
+
|
|
646
|
+
sage: M = ModularSymbols(1, 24).cuspidal_submodule()
|
|
647
|
+
sage: M.q_expansion_basis(8, algorithm='eigen')
|
|
648
|
+
[q + 195660*q^3 + 12080128*q^4 + 44656110*q^5 - 982499328*q^6 - 147247240*q^7 + O(q^8),
|
|
649
|
+
q^2 - 48*q^3 + 1080*q^4 - 15040*q^5 + 143820*q^6 - 985824*q^7 + O(q^8)]
|
|
650
|
+
|
|
651
|
+
::
|
|
652
|
+
|
|
653
|
+
sage: M = ModularSymbols(11, 2, sign=-1).cuspidal_submodule()
|
|
654
|
+
sage: M.q_expansion_basis(8, algorithm='eigen')
|
|
655
|
+
[q - 2*q^2 - q^3 + 2*q^4 + q^5 + 2*q^6 - 2*q^7 + O(q^8)]
|
|
656
|
+
|
|
657
|
+
::
|
|
658
|
+
|
|
659
|
+
sage: M = ModularSymbols(Gamma1(13), 2, sign=1).cuspidal_submodule()
|
|
660
|
+
sage: M.q_expansion_basis(8, algorithm='eigen')
|
|
661
|
+
[q - 4*q^3 - q^4 + 3*q^5 + 6*q^6 + O(q^8),
|
|
662
|
+
q^2 - 2*q^3 - q^4 + 2*q^5 + 2*q^6 + O(q^8)]
|
|
663
|
+
|
|
664
|
+
::
|
|
665
|
+
|
|
666
|
+
sage: M = ModularSymbols(Gamma1(5), 3, sign=-1).cuspidal_submodule()
|
|
667
|
+
sage: M.q_expansion_basis(8, algorithm='eigen') # dimension is 0
|
|
668
|
+
[]
|
|
669
|
+
|
|
670
|
+
::
|
|
671
|
+
|
|
672
|
+
sage: M = ModularSymbols(Gamma1(7), 3, sign=-1).cuspidal_submodule()
|
|
673
|
+
sage: M.q_expansion_basis(8)
|
|
674
|
+
[q - 3*q^2 + 5*q^4 - 7*q^7 + O(q^8)]
|
|
675
|
+
|
|
676
|
+
::
|
|
677
|
+
|
|
678
|
+
sage: M = ModularSymbols(43, 2, sign=0).cuspidal_submodule()
|
|
679
|
+
sage: M[0]
|
|
680
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 for Gamma_0(43) of weight 2 with sign 0 over Rational Field
|
|
681
|
+
sage: M[0].q_expansion_basis()
|
|
682
|
+
[q - 2*q^2 - 2*q^3 + 2*q^4 - 4*q^5 + 4*q^6 + O(q^8)]
|
|
683
|
+
sage: M[1]
|
|
684
|
+
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 7 for Gamma_0(43) of weight 2 with sign 0 over Rational Field
|
|
685
|
+
sage: M[1].q_expansion_basis()
|
|
686
|
+
[q + 2*q^5 - 2*q^6 - 2*q^7 + O(q^8), q^2 - q^3 - q^5 + q^7 + O(q^8)]
|
|
687
|
+
"""
|
|
688
|
+
if prec is None:
|
|
689
|
+
prec = self.default_prec()
|
|
690
|
+
else:
|
|
691
|
+
prec = Integer(prec)
|
|
692
|
+
|
|
693
|
+
if prec < 1:
|
|
694
|
+
raise ValueError("prec (=%s) must be >= 1" % prec)
|
|
695
|
+
|
|
696
|
+
if not self.is_cuspidal():
|
|
697
|
+
raise ArithmeticError("space must be cuspidal")
|
|
698
|
+
|
|
699
|
+
if self.sign() == 0:
|
|
700
|
+
P = self.plus_submodule(compute_dual=True)
|
|
701
|
+
return Sequence(P.q_expansion_basis(prec=prec, algorithm=algorithm), cr=True)
|
|
702
|
+
|
|
703
|
+
if self.dimension() == 0:
|
|
704
|
+
return Sequence([])
|
|
705
|
+
|
|
706
|
+
if algorithm == 'default':
|
|
707
|
+
algorithm = 'hecke'
|
|
708
|
+
if algorithm == 'hecke':
|
|
709
|
+
return Sequence(self._q_expansion_basis_hecke_dual(prec), cr=True)
|
|
710
|
+
elif algorithm == 'eigen':
|
|
711
|
+
return Sequence(self._q_expansion_basis_eigen(prec, 'alpha'), cr=True)
|
|
712
|
+
elif algorithm == 'all':
|
|
713
|
+
B1 = self._q_expansion_basis_hecke_dual(prec)
|
|
714
|
+
B2 = self._q_expansion_basis_eigen(prec, 'alpha')
|
|
715
|
+
if B1 != B2:
|
|
716
|
+
raise RuntimeError("There is a bug in q_expansion_basis -- basis computed differently with two algorithms:\n%s\n%s\n" % (B1, B2,))
|
|
717
|
+
return Sequence(B1, cr=True)
|
|
718
|
+
else:
|
|
719
|
+
raise ValueError("no algorithm '%s'" % algorithm)
|
|
720
|
+
|
|
721
|
+
def q_expansion_module(self, prec=None, R=None):
|
|
722
|
+
r"""
|
|
723
|
+
Return a basis over R for the space spanned by the coefficient
|
|
724
|
+
vectors of the `q`-expansions corresponding to ``self``.
|
|
725
|
+
|
|
726
|
+
If R is not the base ring of ``self``, this returns the
|
|
727
|
+
restriction of scalars down to R (for this, ``self`` must have
|
|
728
|
+
base ring `\QQ` or a number field).
|
|
729
|
+
|
|
730
|
+
INPUT:
|
|
731
|
+
|
|
732
|
+
- ``self`` -- must be cuspidal
|
|
733
|
+
|
|
734
|
+
- ``prec`` -- integer (default: ``self.default_prec()``)
|
|
735
|
+
|
|
736
|
+
- ``R`` -- either `\ZZ`, `\QQ`, or the ``base_ring`` of ``self``
|
|
737
|
+
(which is the default)
|
|
738
|
+
|
|
739
|
+
OUTPUT: a free module over `R`
|
|
740
|
+
|
|
741
|
+
.. TODO::
|
|
742
|
+
|
|
743
|
+
extend to more general R (though that is fairly easy for the
|
|
744
|
+
user to get by just doing base_extend or change_ring on the
|
|
745
|
+
output of this function).
|
|
746
|
+
|
|
747
|
+
Note that the prec needed to distinguish elements of the
|
|
748
|
+
restricted-down-to-R basis may be bigger than ``self.hecke_bound()``,
|
|
749
|
+
since one must use the Sturm bound for modular forms on `\Gamma_H(N)`.
|
|
750
|
+
|
|
751
|
+
EXAMPLES WITH SIGN 1 and R=QQ:
|
|
752
|
+
|
|
753
|
+
Basic example with sign 1::
|
|
754
|
+
|
|
755
|
+
sage: M = ModularSymbols(11, sign=1).cuspidal_submodule()
|
|
756
|
+
sage: M.q_expansion_module(5, QQ)
|
|
757
|
+
Vector space of degree 5 and dimension 1 over Rational Field
|
|
758
|
+
Basis matrix:
|
|
759
|
+
[ 0 1 -2 -1 2]
|
|
760
|
+
|
|
761
|
+
Same example with sign -1::
|
|
762
|
+
|
|
763
|
+
sage: M = ModularSymbols(11, sign=-1).cuspidal_submodule()
|
|
764
|
+
sage: M.q_expansion_module(5, QQ)
|
|
765
|
+
Vector space of degree 5 and dimension 1 over Rational Field
|
|
766
|
+
Basis matrix:
|
|
767
|
+
[ 0 1 -2 -1 2]
|
|
768
|
+
|
|
769
|
+
An example involving old forms::
|
|
770
|
+
|
|
771
|
+
sage: M = ModularSymbols(22, sign=1).cuspidal_submodule()
|
|
772
|
+
sage: M.q_expansion_module(5, QQ)
|
|
773
|
+
Vector space of degree 5 and dimension 2 over Rational Field
|
|
774
|
+
Basis matrix:
|
|
775
|
+
[ 0 1 0 -1 -2]
|
|
776
|
+
[ 0 0 1 0 -2]
|
|
777
|
+
|
|
778
|
+
An example that (somewhat spuriously) is over a number field::
|
|
779
|
+
|
|
780
|
+
sage: x = polygen(QQ)
|
|
781
|
+
sage: k = NumberField(x^2+1, 'a')
|
|
782
|
+
sage: M = ModularSymbols(11, base_ring=k, sign=1).cuspidal_submodule()
|
|
783
|
+
sage: M.q_expansion_module(5, QQ)
|
|
784
|
+
Vector space of degree 5 and dimension 1 over Rational Field
|
|
785
|
+
Basis matrix:
|
|
786
|
+
[ 0 1 -2 -1 2]
|
|
787
|
+
|
|
788
|
+
An example that involves an eigenform with coefficients in a number
|
|
789
|
+
field::
|
|
790
|
+
|
|
791
|
+
sage: M = ModularSymbols(23, sign=1).cuspidal_submodule()
|
|
792
|
+
sage: M.q_eigenform(4, 'gamma')
|
|
793
|
+
q + gamma*q^2 + (-2*gamma - 1)*q^3 + O(q^4)
|
|
794
|
+
sage: M.q_expansion_module(11, QQ)
|
|
795
|
+
Vector space of degree 11 and dimension 2 over Rational Field
|
|
796
|
+
Basis matrix:
|
|
797
|
+
[ 0 1 0 -1 -1 0 -2 2 -1 2 2]
|
|
798
|
+
[ 0 0 1 -2 -1 2 1 2 -2 0 -2]
|
|
799
|
+
|
|
800
|
+
An example that is genuinely over a base field besides QQ.
|
|
801
|
+
|
|
802
|
+
::
|
|
803
|
+
|
|
804
|
+
sage: eps = DirichletGroup(11).0
|
|
805
|
+
sage: M = ModularSymbols(eps,3,sign=1).cuspidal_submodule(); M
|
|
806
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 and level 11, weight 3, character [zeta10], sign 1, over Cyclotomic Field of order 10 and degree 4
|
|
807
|
+
sage: M.q_eigenform(4, 'beta')
|
|
808
|
+
q + (-zeta10^3 + 2*zeta10^2 - 2*zeta10)*q^2 + (2*zeta10^3 - 3*zeta10^2 + 3*zeta10 - 2)*q^3 + O(q^4)
|
|
809
|
+
sage: M.q_expansion_module(7, QQ)
|
|
810
|
+
Vector space of degree 7 and dimension 4 over Rational Field
|
|
811
|
+
Basis matrix:
|
|
812
|
+
[ 0 1 0 0 0 -40 64]
|
|
813
|
+
[ 0 0 1 0 0 -24 41]
|
|
814
|
+
[ 0 0 0 1 0 -12 21]
|
|
815
|
+
[ 0 0 0 0 1 -4 4]
|
|
816
|
+
|
|
817
|
+
An example involving an eigenform rational over the base, but the
|
|
818
|
+
base is not QQ.
|
|
819
|
+
|
|
820
|
+
::
|
|
821
|
+
|
|
822
|
+
sage: k.<a> = NumberField(x^2-5)
|
|
823
|
+
sage: M = ModularSymbols(23, base_ring=k, sign=1).cuspidal_submodule()
|
|
824
|
+
sage: D = M.decomposition(); D
|
|
825
|
+
[Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(23) of weight 2 with sign 1 over Number Field in a with defining polynomial x^2 - 5,
|
|
826
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(23) of weight 2 with sign 1 over Number Field in a with defining polynomial x^2 - 5]
|
|
827
|
+
sage: M.q_expansion_module(8, QQ)
|
|
828
|
+
Vector space of degree 8 and dimension 2 over Rational Field
|
|
829
|
+
Basis matrix:
|
|
830
|
+
[ 0 1 0 -1 -1 0 -2 2]
|
|
831
|
+
[ 0 0 1 -2 -1 2 1 2]
|
|
832
|
+
|
|
833
|
+
An example involving an eigenform not rational over the base and
|
|
834
|
+
for which the base is not QQ.
|
|
835
|
+
|
|
836
|
+
::
|
|
837
|
+
|
|
838
|
+
sage: eps = DirichletGroup(25).0^2
|
|
839
|
+
sage: M = ModularSymbols(eps,2,sign=1).cuspidal_submodule(); M
|
|
840
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 and level 25, weight 2, character [zeta10], sign 1, over Cyclotomic Field of order 10 and degree 4
|
|
841
|
+
sage: D = M.decomposition(); D
|
|
842
|
+
[Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 and level 25, weight 2, character [zeta10], sign 1, over Cyclotomic Field of order 10 and degree 4]
|
|
843
|
+
sage: D[0].q_eigenform(4, 'mu')
|
|
844
|
+
q + mu*q^2 + ((zeta10^3 + zeta10 - 1)*mu + zeta10^2 - 1)*q^3 + O(q^4)
|
|
845
|
+
sage: D[0].q_expansion_module(11, QQ)
|
|
846
|
+
Vector space of degree 11 and dimension 8 over Rational Field
|
|
847
|
+
Basis matrix:
|
|
848
|
+
[ 0 1 0 0 0 0 0 0 -20 -3 0]
|
|
849
|
+
[ 0 0 1 0 0 0 0 0 -16 -1 0]
|
|
850
|
+
[ 0 0 0 1 0 0 0 0 -11 -2 0]
|
|
851
|
+
[ 0 0 0 0 1 0 0 0 -8 -1 0]
|
|
852
|
+
[ 0 0 0 0 0 1 0 0 -5 -1 0]
|
|
853
|
+
[ 0 0 0 0 0 0 1 0 -3 -1 0]
|
|
854
|
+
[ 0 0 0 0 0 0 0 1 -2 0 0]
|
|
855
|
+
[ 0 0 0 0 0 0 0 0 0 0 1]
|
|
856
|
+
sage: D[0].q_expansion_module(11)
|
|
857
|
+
Vector space of degree 11 and dimension 2 over Cyclotomic Field of order 10 and degree 4
|
|
858
|
+
Basis matrix:
|
|
859
|
+
[ 0 1 0 zeta10^2 - 1 -zeta10^2 - 1 -zeta10^3 - zeta10^2 zeta10^2 - zeta10 2*zeta10^3 + 2*zeta10 - 1 zeta10^3 - zeta10^2 - zeta10 + 1 zeta10^3 - zeta10^2 + zeta10 -2*zeta10^3 + 2*zeta10^2 - zeta10]
|
|
860
|
+
[ 0 0 1 zeta10^3 + zeta10 - 1 -zeta10 - 1 -zeta10^3 - zeta10^2 -2*zeta10^3 + zeta10^2 - zeta10 + 1 zeta10^2 0 zeta10^3 + 1 2*zeta10^3 - zeta10^2 + zeta10 - 1]
|
|
861
|
+
|
|
862
|
+
EXAMPLES WITH SIGN 0 and R=QQ:
|
|
863
|
+
|
|
864
|
+
.. TODO:: This doesn't work yet as it's not implemented!!
|
|
865
|
+
|
|
866
|
+
::
|
|
867
|
+
|
|
868
|
+
sage: M = ModularSymbols(11,2).cuspidal_submodule() #not tested
|
|
869
|
+
sage: M.q_expansion_module() #not tested
|
|
870
|
+
... boom ...
|
|
871
|
+
|
|
872
|
+
EXAMPLES WITH SIGN 1 and R=ZZ (computes saturation)::
|
|
873
|
+
|
|
874
|
+
sage: M = ModularSymbols(43,2, sign=1).cuspidal_submodule()
|
|
875
|
+
sage: M.q_expansion_module(8, QQ)
|
|
876
|
+
Vector space of degree 8 and dimension 3 over Rational Field
|
|
877
|
+
Basis matrix:
|
|
878
|
+
[ 0 1 0 0 0 2 -2 -2]
|
|
879
|
+
[ 0 0 1 0 -1/2 1 -3/2 0]
|
|
880
|
+
[ 0 0 0 1 -1/2 2 -3/2 -1]
|
|
881
|
+
sage: M.q_expansion_module(8, ZZ)
|
|
882
|
+
Free module of degree 8 and rank 3 over Integer Ring
|
|
883
|
+
Echelon basis matrix:
|
|
884
|
+
[ 0 1 0 0 0 2 -2 -2]
|
|
885
|
+
[ 0 0 1 1 -1 3 -3 -1]
|
|
886
|
+
[ 0 0 0 2 -1 4 -3 -2]
|
|
887
|
+
"""
|
|
888
|
+
if prec is None:
|
|
889
|
+
prec = self.default_prec()
|
|
890
|
+
if R == ZZ and self.base_ring() == QQ:
|
|
891
|
+
return self._q_expansion_module_integral(prec)
|
|
892
|
+
elif R == QQ:
|
|
893
|
+
return self._q_expansion_module_rational(prec)
|
|
894
|
+
elif R is None or R == self.base_ring():
|
|
895
|
+
# names is never used in this case
|
|
896
|
+
return self._q_expansion_module(prec)
|
|
897
|
+
else:
|
|
898
|
+
raise NotImplementedError("R must be ZZ, QQ, or the base ring of the modular symbols space.")
|
|
899
|
+
|
|
900
|
+
def _q_eigenform_images(self, A, prec, names):
|
|
901
|
+
"""
|
|
902
|
+
Return list of images in space corresponding to ``self`` of eigenform
|
|
903
|
+
corresponding to A under the degeneracy maps.
|
|
904
|
+
|
|
905
|
+
This is mainly a helper function for other internal functions.
|
|
906
|
+
|
|
907
|
+
INPUT:
|
|
908
|
+
|
|
909
|
+
- ``self`` -- space of modular symbols
|
|
910
|
+
|
|
911
|
+
- ``A`` -- cuspidal simple space of level dividing the
|
|
912
|
+
level of ``self`` and the same weight
|
|
913
|
+
|
|
914
|
+
- ``prec`` -- positive integer
|
|
915
|
+
|
|
916
|
+
EXAMPLES::
|
|
917
|
+
|
|
918
|
+
sage: M = ModularSymbols(33,2,sign=1)
|
|
919
|
+
sage: A = M.modular_symbols_of_level(11).cuspidal_submodule()
|
|
920
|
+
sage: M._q_eigenform_images(A, 10, names='a')
|
|
921
|
+
[q - 2*q^2 - q^3 + 2*q^4 + q^5 + 2*q^6 - 2*q^7 - 2*q^9 + O(q^10),
|
|
922
|
+
q^3 - 2*q^6 - q^9 + 2*q^12 + q^15 + 2*q^18 - 2*q^21 - 2*q^27 + O(q^30)]
|
|
923
|
+
"""
|
|
924
|
+
f = A.q_eigenform(prec, names)
|
|
925
|
+
if A.level() == self.level():
|
|
926
|
+
return [f]
|
|
927
|
+
D = divisors(self.level() // A.level())
|
|
928
|
+
q = f.parent().gen()
|
|
929
|
+
return [f] + [f(q**d) for d in D if d > 1]
|
|
930
|
+
|
|
931
|
+
def _q_expansion_module(self, prec, algorithm='hecke'):
|
|
932
|
+
"""
|
|
933
|
+
Return module spanned by the `q`-expansions corresponding to ``self``.
|
|
934
|
+
|
|
935
|
+
See the docstring for ``q_expansion_module`` (without
|
|
936
|
+
underscore) for further details. Note that this will not work
|
|
937
|
+
if ``algorithm=eigen`` and the sign is 0.
|
|
938
|
+
|
|
939
|
+
EXAMPLES::
|
|
940
|
+
|
|
941
|
+
sage: ModularSymbols(11, 2, base_ring=GF(4,'a')).cuspidal_submodule()._q_expansion_module(prec=4, algorithm='hecke')
|
|
942
|
+
Vector space of degree 4 and dimension 1 over Finite Field in a of size 2^2
|
|
943
|
+
Basis matrix:
|
|
944
|
+
[0 1 0 1]
|
|
945
|
+
sage: ModularSymbols(11, 2, base_ring=QuadraticField(-7,'b'), sign=1).cuspidal_submodule()._q_expansion_module(prec=4, algorithm='eigen')
|
|
946
|
+
Vector space of degree 4 and dimension 1 over Number Field in b with defining polynomial x^2 + 7 with b = 2.645751311064591?*I
|
|
947
|
+
Basis matrix:
|
|
948
|
+
[ 0 1 -2 -1]
|
|
949
|
+
"""
|
|
950
|
+
if not self.is_cuspidal():
|
|
951
|
+
raise ValueError("self must be cuspidal")
|
|
952
|
+
R = self.base_ring()
|
|
953
|
+
if R not in Fields():
|
|
954
|
+
if R == ZZ:
|
|
955
|
+
return self._q_expansion_module_integral(prec)
|
|
956
|
+
raise NotImplementedError("base ring must be a field (or ZZ).")
|
|
957
|
+
|
|
958
|
+
V = R ** prec
|
|
959
|
+
if algorithm == 'hecke' or algorithm == 'default':
|
|
960
|
+
return V.span([f.padded_list(prec) for f in self.q_expansion_basis(prec, algorithm)])
|
|
961
|
+
|
|
962
|
+
if algorithm != 'eigen':
|
|
963
|
+
raise ValueError("unknown algorithm '%s'" % algorithm)
|
|
964
|
+
|
|
965
|
+
def q_eigen_gens(d, f):
|
|
966
|
+
r"""
|
|
967
|
+
Temporary function for internal use.
|
|
968
|
+
|
|
969
|
+
EXAMPLES::
|
|
970
|
+
|
|
971
|
+
sage: ModularSymbols(11, 4, base_ring=QuadraticField(-7,'b'),sign=1).cuspidal_submodule()._q_expansion_module(prec=5, algorithm='eigen') # indirect doctest
|
|
972
|
+
Vector space of degree 5 and dimension 2 over Number Field in b with defining polynomial x^2 + 7 with b = 2.645751311064591?*I
|
|
973
|
+
Basis matrix:
|
|
974
|
+
[ 0 1 0 3 -6]
|
|
975
|
+
[ 0 0 1 -4 2]
|
|
976
|
+
"""
|
|
977
|
+
X = f.padded_list(prec)
|
|
978
|
+
if d == 1:
|
|
979
|
+
# X is just a list of elements of R
|
|
980
|
+
return [X]
|
|
981
|
+
else:
|
|
982
|
+
# X is a list of elements of a poly quotient ring
|
|
983
|
+
return [[X[i][j] for i in range(prec)] for j in range(d)]
|
|
984
|
+
|
|
985
|
+
if self.sign() == 0:
|
|
986
|
+
X = self.plus_submodule(compute_dual=True)
|
|
987
|
+
else:
|
|
988
|
+
X = self
|
|
989
|
+
|
|
990
|
+
B = [sum([q_eigen_gens(A.dimension(), f)
|
|
991
|
+
for f in self._q_eigenform_images(A, prec, 'zeta')], [])
|
|
992
|
+
for A, _ in X.factorization()]
|
|
993
|
+
|
|
994
|
+
return V.span(sum(B, []))
|
|
995
|
+
|
|
996
|
+
def _q_expansion_module_rational(self, prec):
|
|
997
|
+
r"""
|
|
998
|
+
Return a vector space over `\QQ` for the space spanned by the
|
|
999
|
+
`q`-expansions corresponding to ``self``.
|
|
1000
|
+
|
|
1001
|
+
The base ring of ``self`` must be `\QQ` or a number field, and
|
|
1002
|
+
``self`` must be cuspidal. The returned space is a
|
|
1003
|
+
`\QQ`-vector space, where the coordinates are the coefficients
|
|
1004
|
+
of `q`-expansions.
|
|
1005
|
+
|
|
1006
|
+
INPUT:
|
|
1007
|
+
|
|
1008
|
+
- ``prec`` -- integer; number of `q`-expansion terms to calculate
|
|
1009
|
+
|
|
1010
|
+
EXAMPLES::
|
|
1011
|
+
|
|
1012
|
+
sage: ModularSymbols(11, 4).cuspidal_submodule()._q_expansion_module_rational(5)
|
|
1013
|
+
Vector space of degree 5 and dimension 2 over Rational Field
|
|
1014
|
+
Basis matrix:
|
|
1015
|
+
[ 0 1 0 3 -6]
|
|
1016
|
+
[ 0 0 1 -4 2]
|
|
1017
|
+
"""
|
|
1018
|
+
if not self.is_cuspidal():
|
|
1019
|
+
raise ValueError("self must be cuspidal")
|
|
1020
|
+
K = self.base_ring()
|
|
1021
|
+
if not isinstance(K, NumberField):
|
|
1022
|
+
raise TypeError("self must be over QQ or a number field.")
|
|
1023
|
+
n = K.degree()
|
|
1024
|
+
if n == 1:
|
|
1025
|
+
return self._q_expansion_module(prec)
|
|
1026
|
+
|
|
1027
|
+
# Construct the vector space over QQ of dimension equal to
|
|
1028
|
+
# the degree of the base field times the dimension over C
|
|
1029
|
+
# of the space of cusp forms corresponding to self.
|
|
1030
|
+
def q_eigen_gens(d, f):
|
|
1031
|
+
r"""
|
|
1032
|
+
Temporary function for internal use.
|
|
1033
|
+
|
|
1034
|
+
EXAMPLES::
|
|
1035
|
+
|
|
1036
|
+
sage: ModularSymbols(13, 6).cuspidal_submodule()._q_expansion_module_rational(4) # indirect doctest
|
|
1037
|
+
Vector space of degree 4 and dimension 3 over Rational Field
|
|
1038
|
+
Basis matrix:
|
|
1039
|
+
[0 1 0 0]
|
|
1040
|
+
[0 0 1 0]
|
|
1041
|
+
[0 0 0 1]
|
|
1042
|
+
"""
|
|
1043
|
+
# Return restricted down to QQ gens for cusp space corresponding
|
|
1044
|
+
# to the simple factor A.
|
|
1045
|
+
X = f.padded_list(prec)
|
|
1046
|
+
if d == 1:
|
|
1047
|
+
return [[X[i][j] for i in range(prec)] for j in range(n)]
|
|
1048
|
+
else:
|
|
1049
|
+
# This looks like it might be really slow -- though
|
|
1050
|
+
# perhaps it's nothing compared to the time taken by
|
|
1051
|
+
# whatever computed this in the first place.
|
|
1052
|
+
return [[(X[i].list())[j][k] for i in range(prec)]
|
|
1053
|
+
for j in range(d) for k in range(n)]
|
|
1054
|
+
if self.sign() == 0:
|
|
1055
|
+
X = self.plus_submodule(compute_dual=True)
|
|
1056
|
+
else:
|
|
1057
|
+
X = self
|
|
1058
|
+
|
|
1059
|
+
B = [sum([q_eigen_gens(A.dimension(), f)
|
|
1060
|
+
for f in self._q_eigenform_images(A, prec, 'alpha')], [])
|
|
1061
|
+
for A, _ in X.factorization()]
|
|
1062
|
+
A = QQ**prec
|
|
1063
|
+
return A.span(sum(B, []))
|
|
1064
|
+
|
|
1065
|
+
def _q_expansion_module_integral(self, prec):
|
|
1066
|
+
r"""
|
|
1067
|
+
Return module over `\ZZ` for the space spanned by
|
|
1068
|
+
the `q`-expansions corresponding to ``self``.
|
|
1069
|
+
|
|
1070
|
+
The base ring of ``self`` must be `\QQ` or a number field, and
|
|
1071
|
+
``self`` must be cuspidal. The returned space is a `\ZZ`-module,
|
|
1072
|
+
where the coordinates are the coefficients of `q`-expansions.
|
|
1073
|
+
|
|
1074
|
+
EXAMPLES::
|
|
1075
|
+
|
|
1076
|
+
sage: M = ModularSymbols(11, sign=1).cuspidal_submodule()
|
|
1077
|
+
sage: M._q_expansion_module_integral(5)
|
|
1078
|
+
Free module of degree 5 and rank 1 over Integer Ring
|
|
1079
|
+
Echelon basis matrix:
|
|
1080
|
+
[ 0 1 -2 -1 2]
|
|
1081
|
+
sage: V = M.complement().cuspidal_submodule()
|
|
1082
|
+
sage: V._q_expansion_module_integral(5)
|
|
1083
|
+
Free module of degree 5 and rank 0 over Integer Ring
|
|
1084
|
+
Echelon basis matrix:
|
|
1085
|
+
[]
|
|
1086
|
+
"""
|
|
1087
|
+
V = self.q_expansion_module(prec, QQ)
|
|
1088
|
+
return FreeModule(ZZ, V.degree()).span(V.basis()).saturation()
|
|
1089
|
+
|
|
1090
|
+
def congruence_number(self, other, prec=None):
|
|
1091
|
+
r"""
|
|
1092
|
+
Given two cuspidal spaces of modular symbols, compute the
|
|
1093
|
+
congruence number, using ``prec`` terms of the `q`-expansions.
|
|
1094
|
+
|
|
1095
|
+
The congruence number is defined as follows. If `V` is the
|
|
1096
|
+
submodule of integral cusp forms corresponding to ``self`` (saturated in
|
|
1097
|
+
`\ZZ[[q]]`, by definition) and `W` is the
|
|
1098
|
+
submodule corresponding to other, each computed to precision ``prec``,
|
|
1099
|
+
the congruence number is the index of `V+W` in its
|
|
1100
|
+
saturation in `\ZZ[[q]]`.
|
|
1101
|
+
|
|
1102
|
+
If ``prec`` is not given it is set equal to the max of the
|
|
1103
|
+
``hecke_bound`` function called on each space.
|
|
1104
|
+
|
|
1105
|
+
EXAMPLES::
|
|
1106
|
+
|
|
1107
|
+
sage: A, B = ModularSymbols(48, 2).cuspidal_submodule().decomposition()
|
|
1108
|
+
sage: A.congruence_number(B)
|
|
1109
|
+
2
|
|
1110
|
+
"""
|
|
1111
|
+
if not self.is_cuspidal():
|
|
1112
|
+
raise ValueError("self must be cuspidal")
|
|
1113
|
+
if not other.is_cuspidal():
|
|
1114
|
+
raise ValueError("right must be cuspidal")
|
|
1115
|
+
if prec is None:
|
|
1116
|
+
prec = max(self.hecke_bound(), other.hecke_bound())
|
|
1117
|
+
prec = int(prec)
|
|
1118
|
+
|
|
1119
|
+
V = self.q_expansion_module(prec, ZZ)
|
|
1120
|
+
W = other.q_expansion_module(prec, ZZ)
|
|
1121
|
+
K = V + W
|
|
1122
|
+
return K.index_in_saturation()
|
|
1123
|
+
|
|
1124
|
+
#########################################################################
|
|
1125
|
+
#
|
|
1126
|
+
# Computation of a basis using eigenforms
|
|
1127
|
+
#
|
|
1128
|
+
#########################################################################
|
|
1129
|
+
|
|
1130
|
+
@cached_method
|
|
1131
|
+
def q_eigenform_character(self, names=None):
|
|
1132
|
+
"""
|
|
1133
|
+
Return the Dirichlet character associated to the specific
|
|
1134
|
+
choice of `q`-eigenform attached to this simple cuspidal
|
|
1135
|
+
modular symbols space.
|
|
1136
|
+
|
|
1137
|
+
INPUT:
|
|
1138
|
+
|
|
1139
|
+
- ``names`` -- string; name of the variable
|
|
1140
|
+
|
|
1141
|
+
OUTPUT:
|
|
1142
|
+
|
|
1143
|
+
- a Dirichlet character taking values in the Hecke eigenvalue
|
|
1144
|
+
field, where the indeterminate of that field is determined
|
|
1145
|
+
by the given variable name.
|
|
1146
|
+
|
|
1147
|
+
EXAMPLES::
|
|
1148
|
+
|
|
1149
|
+
sage: f = ModularSymbols(Gamma1(13),2,sign=1).cuspidal_subspace().decomposition()[0]
|
|
1150
|
+
sage: eps = f.q_eigenform_character('a'); eps
|
|
1151
|
+
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -a - 1
|
|
1152
|
+
sage: parent(eps)
|
|
1153
|
+
Group of Dirichlet characters modulo 13 with values in Number Field in a with defining polynomial x^2 + 3*x + 3
|
|
1154
|
+
sage: eps(3)
|
|
1155
|
+
a + 1
|
|
1156
|
+
|
|
1157
|
+
The modular symbols space must be simple.::
|
|
1158
|
+
|
|
1159
|
+
sage: ModularSymbols(Gamma1(17),2,sign=1).cuspidal_submodule().q_eigenform_character('a')
|
|
1160
|
+
Traceback (most recent call last):
|
|
1161
|
+
...
|
|
1162
|
+
ArithmeticError: self must be simple
|
|
1163
|
+
|
|
1164
|
+
If the character is specified when making the modular symbols
|
|
1165
|
+
space, then names need not be given and the returned character
|
|
1166
|
+
is just the character of the space.::
|
|
1167
|
+
|
|
1168
|
+
sage: f = ModularSymbols(kronecker_character(19),2,sign=1).cuspidal_subspace().decomposition()[0]
|
|
1169
|
+
sage: f
|
|
1170
|
+
Modular Symbols subspace of dimension 8 of Modular Symbols space of dimension 10 and level 76, weight 2, character [-1, -1], sign 1, over Rational Field
|
|
1171
|
+
sage: f.q_eigenform_character()
|
|
1172
|
+
Dirichlet character modulo 76 of conductor 76 mapping 39 |--> -1, 21 |--> -1
|
|
1173
|
+
sage: f.q_eigenform_character() is f.character()
|
|
1174
|
+
True
|
|
1175
|
+
|
|
1176
|
+
The input space need not be cuspidal::
|
|
1177
|
+
|
|
1178
|
+
sage: M = ModularSymbols(Gamma1(13),2,sign=1).eisenstein_submodule()[0]
|
|
1179
|
+
sage: M.q_eigenform_character('a')
|
|
1180
|
+
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -1
|
|
1181
|
+
|
|
1182
|
+
The modular symbols space does not have to come from a decomposition::
|
|
1183
|
+
|
|
1184
|
+
sage: ModularSymbols(Gamma1(16),2,sign=1).cuspidal_submodule().q_eigenform_character('a')
|
|
1185
|
+
Dirichlet character modulo 16 of conductor 16 mapping 15 |--> 1, 5 |--> -a - 1
|
|
1186
|
+
"""
|
|
1187
|
+
eps = self.character()
|
|
1188
|
+
if eps is not None:
|
|
1189
|
+
# easy case
|
|
1190
|
+
return eps
|
|
1191
|
+
|
|
1192
|
+
v = self.dual_eigenvector(names=names)
|
|
1193
|
+
i = v.nonzero_positions()[0]
|
|
1194
|
+
K = v.base_ring()
|
|
1195
|
+
from sage.modular.dirichlet import DirichletGroup
|
|
1196
|
+
G = DirichletGroup(self.level(), K)
|
|
1197
|
+
M = self.ambient_module()
|
|
1198
|
+
# act on right since v is a in the dual
|
|
1199
|
+
b = [(M.diamond_bracket_matrix(u) * v)[i] / v[i]
|
|
1200
|
+
for u in G.unit_gens()]
|
|
1201
|
+
return G(b)
|
|
1202
|
+
|
|
1203
|
+
def q_eigenform(self, prec, names=None):
|
|
1204
|
+
"""
|
|
1205
|
+
Return the `q`-expansion to precision ``prec`` of a new eigenform
|
|
1206
|
+
associated to ``self``.
|
|
1207
|
+
|
|
1208
|
+
Here ``self`` must be new, cuspidal, and simple.
|
|
1209
|
+
|
|
1210
|
+
EXAMPLES::
|
|
1211
|
+
|
|
1212
|
+
sage: ModularSymbols(2, 8)[1].q_eigenform(5, 'a')
|
|
1213
|
+
q - 8*q^2 + 12*q^3 + 64*q^4 + O(q^5)
|
|
1214
|
+
sage: ModularSymbols(2, 8)[0].q_eigenform(5,'a')
|
|
1215
|
+
Traceback (most recent call last):
|
|
1216
|
+
...
|
|
1217
|
+
ArithmeticError: self must be cuspidal.
|
|
1218
|
+
"""
|
|
1219
|
+
if self.dimension() > 1 and names is None:
|
|
1220
|
+
raise ValueError("please specify a name to use for the field of eigenvalues")
|
|
1221
|
+
|
|
1222
|
+
if prec is None:
|
|
1223
|
+
prec = self.default_prec()
|
|
1224
|
+
try:
|
|
1225
|
+
f = self._q_expansion_dict[names]
|
|
1226
|
+
except (AttributeError, KeyError):
|
|
1227
|
+
self._q_expansion_dict = {}
|
|
1228
|
+
if not self.is_cuspidal():
|
|
1229
|
+
raise ArithmeticError("self must be cuspidal.")
|
|
1230
|
+
|
|
1231
|
+
if not self.is_simple():
|
|
1232
|
+
if self.sign() == 0:
|
|
1233
|
+
return self.plus_submodule(compute_dual=True).q_eigenform(prec, names)
|
|
1234
|
+
raise ArithmeticError("self must be simple.")
|
|
1235
|
+
a2 = self.eigenvalue(2, names)
|
|
1236
|
+
R = PowerSeriesRing(a2.parent(), "q")
|
|
1237
|
+
q = R.gen(0)
|
|
1238
|
+
f = (q + a2 * q**2).O(3)
|
|
1239
|
+
|
|
1240
|
+
if f.prec() < prec:
|
|
1241
|
+
R = f.parent()
|
|
1242
|
+
ext = [self.eigenvalue(n, names) for n in range(f.prec(), prec)]
|
|
1243
|
+
f = R(f.padded_list(f.prec()) + ext)
|
|
1244
|
+
self._q_expansion_dict[names] = f.add_bigoh(prec)
|
|
1245
|
+
return self._q_expansion_dict[names]
|
|
1246
|
+
else:
|
|
1247
|
+
return f.O(prec)
|
|
1248
|
+
|
|
1249
|
+
def _q_expansion_basis_eigen(self, prec, names):
|
|
1250
|
+
r"""
|
|
1251
|
+
Return a basis of eigenforms corresponding to this space, which must be
|
|
1252
|
+
new, cuspidal and simple.
|
|
1253
|
+
|
|
1254
|
+
EXAMPLES::
|
|
1255
|
+
|
|
1256
|
+
sage: ModularSymbols(17, 2,sign=1).cuspidal_submodule()._q_expansion_basis_eigen(2, "a")
|
|
1257
|
+
[q + O(q^2)]
|
|
1258
|
+
"""
|
|
1259
|
+
if self.is_simple():
|
|
1260
|
+
# should we perhaps check at this point if self is new?
|
|
1261
|
+
f = self.q_eigenform(prec, names)
|
|
1262
|
+
R = PowerSeriesRing(self.base_ring(), 'q')
|
|
1263
|
+
return [R([f[i][j] for i in range(prec)], prec)
|
|
1264
|
+
for j in range(self.rank())]
|
|
1265
|
+
raise NotImplementedError
|
|
1266
|
+
|
|
1267
|
+
#########################################################################
|
|
1268
|
+
#
|
|
1269
|
+
# Computation of a basis using linear functionals on the Hecke algebra.
|
|
1270
|
+
#
|
|
1271
|
+
#########################################################################
|
|
1272
|
+
|
|
1273
|
+
def q_expansion_cuspforms(self, prec=None):
|
|
1274
|
+
r"""
|
|
1275
|
+
Return a function f(i,j) such that each value f(i,j) is the
|
|
1276
|
+
`q`-expansion, to the given precision, of an element of the
|
|
1277
|
+
corresponding space `S` of cusp forms.
|
|
1278
|
+
|
|
1279
|
+
Together these functions span `S`. Here `i,j` are integers
|
|
1280
|
+
with `0\leq i,j < d`, where `d` is the dimension of ``self``.
|
|
1281
|
+
|
|
1282
|
+
For a reduced echelon basis, use the function
|
|
1283
|
+
``q_expansion_basis`` instead.
|
|
1284
|
+
|
|
1285
|
+
More precisely, this function returns the `q`-expansions
|
|
1286
|
+
obtained by taking the `ij` entry of the matrices of the
|
|
1287
|
+
Hecke operators `T_n` acting on the subspace of the linear
|
|
1288
|
+
dual of modular symbols corresponding to ``self``.
|
|
1289
|
+
|
|
1290
|
+
EXAMPLES::
|
|
1291
|
+
|
|
1292
|
+
sage: S = ModularSymbols(11,2, sign=1).cuspidal_submodule()
|
|
1293
|
+
sage: f = S.q_expansion_cuspforms(8)
|
|
1294
|
+
sage: f(0,0)
|
|
1295
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + 2*q^6 - 2*q^7 + O(q^8)
|
|
1296
|
+
|
|
1297
|
+
::
|
|
1298
|
+
|
|
1299
|
+
sage: S = ModularSymbols(37,2).cuspidal_submodule()
|
|
1300
|
+
sage: f = S.q_expansion_cuspforms(8)
|
|
1301
|
+
sage: f(0,0)
|
|
1302
|
+
q + q^3 - 2*q^4 - q^7 + O(q^8)
|
|
1303
|
+
sage: f(3,3)
|
|
1304
|
+
q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + O(q^8)
|
|
1305
|
+
sage: f(1,2)
|
|
1306
|
+
q^2 + 2*q^3 - 2*q^4 + q^5 - 3*q^6 + O(q^8)
|
|
1307
|
+
|
|
1308
|
+
::
|
|
1309
|
+
|
|
1310
|
+
sage: S = ModularSymbols(Gamma1(13),2,sign=-1).cuspidal_submodule()
|
|
1311
|
+
sage: f = S.q_expansion_cuspforms(8)
|
|
1312
|
+
sage: f(0,0)
|
|
1313
|
+
q - 2*q^2 + q^4 - q^5 + 2*q^6 + O(q^8)
|
|
1314
|
+
sage: f(0,1)
|
|
1315
|
+
-q^2 + 2*q^3 + q^4 - 2*q^5 - 2*q^6 + O(q^8)
|
|
1316
|
+
|
|
1317
|
+
::
|
|
1318
|
+
|
|
1319
|
+
sage: S = ModularSymbols(1,12,sign=-1).cuspidal_submodule()
|
|
1320
|
+
sage: f = S.q_expansion_cuspforms(8)
|
|
1321
|
+
sage: f(0,0)
|
|
1322
|
+
q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + O(q^8)
|
|
1323
|
+
"""
|
|
1324
|
+
if prec is None:
|
|
1325
|
+
prec = self.default_prec()
|
|
1326
|
+
if not self.is_cuspidal():
|
|
1327
|
+
raise ArithmeticError("self must be cuspidal")
|
|
1328
|
+
T = [self.dual_hecke_matrix(n) for n in range(1, prec)]
|
|
1329
|
+
R = PowerSeriesRing(self.base_ring(), 'q')
|
|
1330
|
+
return lambda i, j: R([0] + [t[i, j] for t in T], prec)
|
|
1331
|
+
|
|
1332
|
+
def _q_expansion_basis_hecke_dual(self, prec):
|
|
1333
|
+
r"""
|
|
1334
|
+
Compute a basis of `q`-expansions for the associated space of cusp forms
|
|
1335
|
+
to the given precision, by using linear functionals on the Hecke
|
|
1336
|
+
algebra as described in William Stein's book (Algorithm 3.26, page 56)
|
|
1337
|
+
|
|
1338
|
+
EXAMPLES::
|
|
1339
|
+
|
|
1340
|
+
sage: ModularSymbols(37, 2).cuspidal_submodule()._q_expansion_basis_hecke_dual(12)
|
|
1341
|
+
[q + q^3 - 2*q^4 - q^7 - 2*q^9 + 3*q^11 + O(q^12),
|
|
1342
|
+
q^2 + 2*q^3 - 2*q^4 + q^5 - 3*q^6 - 4*q^9 - 2*q^10 + 4*q^11 + O(q^12)]
|
|
1343
|
+
sage: ModularSymbols(37, 2).cuspidal_submodule()._q_expansion_basis_hecke_dual(2)
|
|
1344
|
+
[q + O(q^2)]
|
|
1345
|
+
"""
|
|
1346
|
+
from sage.misc.verbose import verbose
|
|
1347
|
+
d = self.dimension_of_associated_cuspform_space()
|
|
1348
|
+
prec = Integer(prec)
|
|
1349
|
+
if prec < 1:
|
|
1350
|
+
raise ValueError("prec (=%s) must be >= 1" % prec)
|
|
1351
|
+
d = min(prec - 1, d)
|
|
1352
|
+
K = self.base_ring()
|
|
1353
|
+
|
|
1354
|
+
A = VectorSpace(K, prec - 1)
|
|
1355
|
+
M = MatrixSpace(K, prec - 1, self.dimension())
|
|
1356
|
+
|
|
1357
|
+
V = A.zero_submodule()
|
|
1358
|
+
i = self.dimension() - 1
|
|
1359
|
+
j = 0
|
|
1360
|
+
|
|
1361
|
+
t = verbose('computing basis to precision %s' % prec)
|
|
1362
|
+
while V.dimension() < d and i >= 0:
|
|
1363
|
+
v = [self.dual_hecke_matrix(n).column(i) for n in range(1, prec)]
|
|
1364
|
+
t = verbose('iteration: %s' % j, t)
|
|
1365
|
+
X = M(v).transpose()
|
|
1366
|
+
V += X.row_space()
|
|
1367
|
+
t = verbose('addition of row space: %s' % j, t)
|
|
1368
|
+
i -= 1
|
|
1369
|
+
j += 1
|
|
1370
|
+
|
|
1371
|
+
R = PowerSeriesRing(K, 'q')
|
|
1372
|
+
B = V.basis()
|
|
1373
|
+
if len(B) < d:
|
|
1374
|
+
B += [V(0)] * (d - len(B))
|
|
1375
|
+
return [R([0] + b.list(), prec) for b in B]
|
|
1376
|
+
|
|
1377
|
+
#########################################################################
|
|
1378
|
+
#
|
|
1379
|
+
# Decomposition of spaces
|
|
1380
|
+
#
|
|
1381
|
+
##########################################################################
|
|
1382
|
+
|
|
1383
|
+
# def factorization(self):
|
|
1384
|
+
# """
|
|
1385
|
+
# Return a list of pairs `(S,e)` where `S` is simple
|
|
1386
|
+
# spaces of modular symbols and self is isomorphic to the direct sum
|
|
1387
|
+
# of the `S^e` as a module over the *anemic* Hecke algebra
|
|
1388
|
+
# adjoin the star involution.
|
|
1389
|
+
#
|
|
1390
|
+
# ASSUMPTION: self is a module over the anemic Hecke algebra.
|
|
1391
|
+
# """
|
|
1392
|
+
# try:
|
|
1393
|
+
# return self._factorization
|
|
1394
|
+
# except AttributeError:
|
|
1395
|
+
# raise NotImplementedError
|
|
1396
|
+
|
|
1397
|
+
def hecke_module_of_level(self, level):
|
|
1398
|
+
r"""
|
|
1399
|
+
Alias for ``self.modular_symbols_of_level(level)``.
|
|
1400
|
+
|
|
1401
|
+
EXAMPLES::
|
|
1402
|
+
|
|
1403
|
+
sage: ModularSymbols(11, 2).hecke_module_of_level(22)
|
|
1404
|
+
Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field
|
|
1405
|
+
"""
|
|
1406
|
+
return self.modular_symbols_of_level(Integer(level))
|
|
1407
|
+
|
|
1408
|
+
def sign(self):
|
|
1409
|
+
r"""
|
|
1410
|
+
Return the sign of ``self``.
|
|
1411
|
+
|
|
1412
|
+
For efficiency reasons, it is often useful to compute in the
|
|
1413
|
+
(largest) quotient of modular symbols where the \* involution acts
|
|
1414
|
+
as +1, or where it acts as -1.
|
|
1415
|
+
|
|
1416
|
+
INPUT:
|
|
1417
|
+
|
|
1418
|
+
- ``ModularSymbols self`` -- arbitrary space of modular symbols
|
|
1419
|
+
|
|
1420
|
+
OUTPUT:
|
|
1421
|
+
|
|
1422
|
+
- ``-1`` -- if this is factor of quotient where \* acts as -1,
|
|
1423
|
+
|
|
1424
|
+
- ``+1`` -- if this is factor of quotient where \* acts as +1,
|
|
1425
|
+
|
|
1426
|
+
- ``0`` -- if this is full space of modular symbols (no quotient)
|
|
1427
|
+
|
|
1428
|
+
EXAMPLES::
|
|
1429
|
+
|
|
1430
|
+
sage: m = ModularSymbols(33)
|
|
1431
|
+
sage: m.rank()
|
|
1432
|
+
9
|
|
1433
|
+
sage: m.sign()
|
|
1434
|
+
0
|
|
1435
|
+
sage: m = ModularSymbols(33, sign=0)
|
|
1436
|
+
sage: m.sign()
|
|
1437
|
+
0
|
|
1438
|
+
sage: m.rank()
|
|
1439
|
+
9
|
|
1440
|
+
sage: m = ModularSymbols(33, sign=-1)
|
|
1441
|
+
sage: m.sign()
|
|
1442
|
+
-1
|
|
1443
|
+
sage: m.rank()
|
|
1444
|
+
3
|
|
1445
|
+
"""
|
|
1446
|
+
return self.__sign
|
|
1447
|
+
|
|
1448
|
+
def simple_factors(self):
|
|
1449
|
+
"""
|
|
1450
|
+
Return a list modular symbols spaces `S` where `S`
|
|
1451
|
+
is simple spaces of modular symbols (for the anemic Hecke algebra)
|
|
1452
|
+
and ``self`` is isomorphic to the direct sum of the `S` with
|
|
1453
|
+
some multiplicities, as a module over the *anemic* Hecke algebra.
|
|
1454
|
+
|
|
1455
|
+
For the multiplicities use factorization() instead.
|
|
1456
|
+
|
|
1457
|
+
ASSUMPTION: self is a module over the anemic Hecke algebra.
|
|
1458
|
+
|
|
1459
|
+
EXAMPLES::
|
|
1460
|
+
|
|
1461
|
+
sage: ModularSymbols(1,100,sign=-1).simple_factors()
|
|
1462
|
+
[Modular Symbols subspace of dimension 8 of Modular Symbols space of dimension 8 for Gamma_0(1) of weight 100 with sign -1 over Rational Field]
|
|
1463
|
+
sage: ModularSymbols(1,16,0,GF(5)).simple_factors()
|
|
1464
|
+
[Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(1) of weight 16 with sign 0 over Finite Field of size 5,
|
|
1465
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(1) of weight 16 with sign 0 over Finite Field of size 5,
|
|
1466
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(1) of weight 16 with sign 0 over Finite Field of size 5]
|
|
1467
|
+
"""
|
|
1468
|
+
return [S for S, _ in self.factorization()]
|
|
1469
|
+
|
|
1470
|
+
def star_eigenvalues(self):
|
|
1471
|
+
"""
|
|
1472
|
+
Return the eigenvalues of the star involution acting on ``self``.
|
|
1473
|
+
|
|
1474
|
+
EXAMPLES::
|
|
1475
|
+
|
|
1476
|
+
sage: M = ModularSymbols(11)
|
|
1477
|
+
sage: D = M.decomposition()
|
|
1478
|
+
sage: M.star_eigenvalues()
|
|
1479
|
+
[1, -1]
|
|
1480
|
+
sage: D[0].star_eigenvalues()
|
|
1481
|
+
[1]
|
|
1482
|
+
sage: D[1].star_eigenvalues()
|
|
1483
|
+
[1, -1]
|
|
1484
|
+
sage: D[1].plus_submodule().star_eigenvalues()
|
|
1485
|
+
[1]
|
|
1486
|
+
sage: D[1].minus_submodule().star_eigenvalues()
|
|
1487
|
+
[-1]
|
|
1488
|
+
"""
|
|
1489
|
+
try:
|
|
1490
|
+
return self.__star_eigenvalues
|
|
1491
|
+
except AttributeError:
|
|
1492
|
+
pass
|
|
1493
|
+
if self.sign() != 0:
|
|
1494
|
+
return [self.sign()]
|
|
1495
|
+
M = self.star_involution().matrix()
|
|
1496
|
+
R = self.base_ring()
|
|
1497
|
+
if M == R(1):
|
|
1498
|
+
self.__star_eigenvalues = [R(1)]
|
|
1499
|
+
elif M == R(-1):
|
|
1500
|
+
self.__star_eigenvalues = [R(-1)]
|
|
1501
|
+
else:
|
|
1502
|
+
self.__star_eigenvalues = [R(1), R(-1)]
|
|
1503
|
+
return self.__star_eigenvalues
|
|
1504
|
+
|
|
1505
|
+
def star_decomposition(self):
|
|
1506
|
+
r"""
|
|
1507
|
+
Decompose ``self`` into subspaces which are eigenspaces for the star
|
|
1508
|
+
involution.
|
|
1509
|
+
|
|
1510
|
+
EXAMPLES::
|
|
1511
|
+
|
|
1512
|
+
sage: ModularSymbols(Gamma1(19), 2).cuspidal_submodule().star_decomposition()
|
|
1513
|
+
[Modular Symbols subspace of dimension 7 of Modular Symbols space of dimension 31 for Gamma_1(19) of weight 2 with sign 0 over Rational Field,
|
|
1514
|
+
Modular Symbols subspace of dimension 7 of Modular Symbols space of dimension 31 for Gamma_1(19) of weight 2 with sign 0 over Rational Field]
|
|
1515
|
+
"""
|
|
1516
|
+
S = self.star_involution()
|
|
1517
|
+
return S.decomposition()
|
|
1518
|
+
|
|
1519
|
+
def integral_structure(self):
|
|
1520
|
+
r"""
|
|
1521
|
+
Return the `\ZZ`-structure of this modular symbols
|
|
1522
|
+
spaces generated by all integral modular symbols.
|
|
1523
|
+
|
|
1524
|
+
EXAMPLES::
|
|
1525
|
+
|
|
1526
|
+
sage: M = ModularSymbols(11,4)
|
|
1527
|
+
sage: M.integral_structure()
|
|
1528
|
+
Free module of degree 6 and rank 6 over Integer Ring
|
|
1529
|
+
Echelon basis matrix:
|
|
1530
|
+
[ 1 0 0 0 0 0]
|
|
1531
|
+
[ 0 1/14 1/7 5/14 1/2 13/14]
|
|
1532
|
+
[ 0 0 1/2 0 0 1/2]
|
|
1533
|
+
[ 0 0 0 1 0 0]
|
|
1534
|
+
[ 0 0 0 0 1 0]
|
|
1535
|
+
[ 0 0 0 0 0 1]
|
|
1536
|
+
sage: M.cuspidal_submodule().integral_structure()
|
|
1537
|
+
Free module of degree 6 and rank 4 over Integer Ring
|
|
1538
|
+
Echelon basis matrix:
|
|
1539
|
+
[ 0 1/14 1/7 5/14 1/2 -15/14]
|
|
1540
|
+
[ 0 0 1/2 0 0 -1/2]
|
|
1541
|
+
[ 0 0 0 1 0 -1]
|
|
1542
|
+
[ 0 0 0 0 1 -1]
|
|
1543
|
+
"""
|
|
1544
|
+
try:
|
|
1545
|
+
return self.__integral_structure
|
|
1546
|
+
except AttributeError:
|
|
1547
|
+
pass
|
|
1548
|
+
A = self.ambient_hecke_module()
|
|
1549
|
+
I = A.integral_structure()
|
|
1550
|
+
if I.echelonized_basis_matrix().is_one() and (self.free_module().denominator() == 1):
|
|
1551
|
+
J = I.submodule(self.free_module().basis(), check=False, already_echelonized=True)
|
|
1552
|
+
else:
|
|
1553
|
+
J = self.free_module().intersection(I)
|
|
1554
|
+
self.__integral_structure = J
|
|
1555
|
+
return J
|
|
1556
|
+
|
|
1557
|
+
def intersection_number(self, M):
|
|
1558
|
+
"""
|
|
1559
|
+
Given modular symbols spaces ``self`` and ``M`` in some common ambient
|
|
1560
|
+
space, returns the intersection number of these two spaces.
|
|
1561
|
+
|
|
1562
|
+
This is the index in their saturation of the sum of their
|
|
1563
|
+
underlying integral structures.
|
|
1564
|
+
|
|
1565
|
+
If ``self`` and ``M`` are of weight two and defined over QQ,
|
|
1566
|
+
and correspond to newforms f and g, then this number equals
|
|
1567
|
+
the order of the intersection of the modular abelian varieties
|
|
1568
|
+
attached to f and g.
|
|
1569
|
+
|
|
1570
|
+
EXAMPLES::
|
|
1571
|
+
|
|
1572
|
+
sage: m = ModularSymbols(389,2)
|
|
1573
|
+
sage: d = m.decomposition(2)
|
|
1574
|
+
sage: eis = d[0]
|
|
1575
|
+
sage: ell = d[1]
|
|
1576
|
+
sage: af = d[-1]
|
|
1577
|
+
sage: af.intersection_number(eis)
|
|
1578
|
+
97
|
|
1579
|
+
sage: af.intersection_number(ell)
|
|
1580
|
+
400
|
|
1581
|
+
"""
|
|
1582
|
+
if not isinstance(M, ModularSymbolsSpace):
|
|
1583
|
+
raise TypeError("M must be a modular symbols space")
|
|
1584
|
+
if M.ambient() != self.ambient():
|
|
1585
|
+
raise ValueError("self and M must be in the same ambient space.")
|
|
1586
|
+
A = self.integral_structure()
|
|
1587
|
+
B = M.integral_structure()
|
|
1588
|
+
return (A + B).index_in_saturation()
|
|
1589
|
+
|
|
1590
|
+
def integral_basis(self):
|
|
1591
|
+
r"""
|
|
1592
|
+
Return a basis for the `\ZZ`-submodule of this
|
|
1593
|
+
modular symbols space spanned by the generators.
|
|
1594
|
+
|
|
1595
|
+
Modular symbols spaces for congruence subgroups have a
|
|
1596
|
+
`\ZZ`-structure. Computing this
|
|
1597
|
+
`\ZZ`-structure is expensive, so by default modular
|
|
1598
|
+
symbols spaces for congruence subgroups in Sage are defined over
|
|
1599
|
+
`\QQ`. This function returns a tuple of independent
|
|
1600
|
+
elements in this modular symbols space whose
|
|
1601
|
+
`\ZZ`-span is the corresponding space of modular
|
|
1602
|
+
symbols over `\ZZ`.
|
|
1603
|
+
|
|
1604
|
+
EXAMPLES::
|
|
1605
|
+
|
|
1606
|
+
sage: M = ModularSymbols(11)
|
|
1607
|
+
sage: M.basis()
|
|
1608
|
+
((1,0), (1,8), (1,9))
|
|
1609
|
+
sage: M.integral_basis()
|
|
1610
|
+
((1,0), (1,8), (1,9))
|
|
1611
|
+
sage: S = M.cuspidal_submodule()
|
|
1612
|
+
sage: S.basis()
|
|
1613
|
+
((1,8), (1,9))
|
|
1614
|
+
sage: S.integral_basis()
|
|
1615
|
+
((1,8), (1,9))
|
|
1616
|
+
|
|
1617
|
+
::
|
|
1618
|
+
|
|
1619
|
+
sage: M = ModularSymbols(13,4)
|
|
1620
|
+
sage: M.basis()
|
|
1621
|
+
([X^2,(0,1)], [X^2,(1,4)], [X^2,(1,5)], [X^2,(1,7)], [X^2,(1,9)], [X^2,(1,10)], [X^2,(1,11)], [X^2,(1,12)])
|
|
1622
|
+
sage: M.integral_basis()
|
|
1623
|
+
([X^2,(0,1)], 1/28*[X^2,(1,4)] + 2/7*[X^2,(1,5)] + 3/28*[X^2,(1,7)] + 11/14*[X^2,(1,9)] + 2/7*[X^2,(1,10)] + 11/28*[X^2,(1,11)] + 3/28*[X^2,(1,12)], [X^2,(1,5)], 1/2*[X^2,(1,7)] + 1/2*[X^2,(1,9)], [X^2,(1,9)], [X^2,(1,10)], [X^2,(1,11)], [X^2,(1,12)])
|
|
1624
|
+
sage: S = M.cuspidal_submodule()
|
|
1625
|
+
sage: S.basis()
|
|
1626
|
+
([X^2,(1,4)] - [X^2,(1,12)], [X^2,(1,5)] - [X^2,(1,12)], [X^2,(1,7)] - [X^2,(1,12)], [X^2,(1,9)] - [X^2,(1,12)], [X^2,(1,10)] - [X^2,(1,12)], [X^2,(1,11)] - [X^2,(1,12)])
|
|
1627
|
+
sage: S.integral_basis()
|
|
1628
|
+
(1/28*[X^2,(1,4)] + 2/7*[X^2,(1,5)] + 3/28*[X^2,(1,7)] + 11/14*[X^2,(1,9)] + 2/7*[X^2,(1,10)] + 11/28*[X^2,(1,11)] - 53/28*[X^2,(1,12)], [X^2,(1,5)] - [X^2,(1,12)], 1/2*[X^2,(1,7)] + 1/2*[X^2,(1,9)] - [X^2,(1,12)], [X^2,(1,9)] - [X^2,(1,12)], [X^2,(1,10)] - [X^2,(1,12)], [X^2,(1,11)] - [X^2,(1,12)])
|
|
1629
|
+
|
|
1630
|
+
This function currently raises a NotImplementedError on modular
|
|
1631
|
+
symbols spaces with character of order bigger than `2`:
|
|
1632
|
+
|
|
1633
|
+
EXAMPLES::
|
|
1634
|
+
|
|
1635
|
+
sage: M = ModularSymbols(DirichletGroup(13).0^2, 2); M
|
|
1636
|
+
Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2
|
|
1637
|
+
sage: M.basis()
|
|
1638
|
+
((1,0), (1,5), (1,10), (1,11))
|
|
1639
|
+
sage: M.integral_basis()
|
|
1640
|
+
Traceback (most recent call last):
|
|
1641
|
+
...
|
|
1642
|
+
NotImplementedError
|
|
1643
|
+
"""
|
|
1644
|
+
try:
|
|
1645
|
+
return self.__integral_basis
|
|
1646
|
+
except AttributeError:
|
|
1647
|
+
pass
|
|
1648
|
+
B = self.integral_structure().basis()
|
|
1649
|
+
self.__integral_basis = tuple([self(b) for b in B])
|
|
1650
|
+
return self.__integral_basis
|
|
1651
|
+
|
|
1652
|
+
def integral_hecke_matrix(self, n):
|
|
1653
|
+
r"""
|
|
1654
|
+
Return the matrix of the `n`-th Hecke operator acting on the integral
|
|
1655
|
+
structure on ``self`` (as returned by ``self.integral_structure()``).
|
|
1656
|
+
|
|
1657
|
+
This is often (but not always) different from the matrix
|
|
1658
|
+
returned by ``self.hecke_matrix``, even if the latter has
|
|
1659
|
+
integral entries.
|
|
1660
|
+
|
|
1661
|
+
EXAMPLES::
|
|
1662
|
+
|
|
1663
|
+
sage: M = ModularSymbols(6,4)
|
|
1664
|
+
sage: M.hecke_matrix(3)
|
|
1665
|
+
[27 0 0 0 6 -6]
|
|
1666
|
+
[ 0 1 -4 4 8 10]
|
|
1667
|
+
[18 0 1 0 6 -6]
|
|
1668
|
+
[18 0 4 -3 6 -6]
|
|
1669
|
+
[ 0 0 0 0 9 18]
|
|
1670
|
+
[ 0 0 0 0 12 15]
|
|
1671
|
+
sage: M.integral_hecke_matrix(3)
|
|
1672
|
+
[ 27 0 0 0 6 -6]
|
|
1673
|
+
[ 0 1 -8 8 12 14]
|
|
1674
|
+
[ 18 0 5 -4 14 8]
|
|
1675
|
+
[ 18 0 8 -7 2 -10]
|
|
1676
|
+
[ 0 0 0 0 9 18]
|
|
1677
|
+
[ 0 0 0 0 12 15]
|
|
1678
|
+
"""
|
|
1679
|
+
n = int(n)
|
|
1680
|
+
try:
|
|
1681
|
+
return self.__integral_hecke_matrix[n]
|
|
1682
|
+
except AttributeError:
|
|
1683
|
+
self.__integral_hecke_matrix = {}
|
|
1684
|
+
except KeyError:
|
|
1685
|
+
pass
|
|
1686
|
+
A = self.ambient_hecke_module()
|
|
1687
|
+
T = A.hecke_matrix(n)
|
|
1688
|
+
S = T.restrict(self.integral_structure()).change_ring(ZZ)
|
|
1689
|
+
self.__integral_hecke_matrix[n] = S
|
|
1690
|
+
return S
|
|
1691
|
+
|
|
1692
|
+
def sturm_bound(self):
|
|
1693
|
+
r"""
|
|
1694
|
+
Return the Sturm bound for this space of modular symbols.
|
|
1695
|
+
|
|
1696
|
+
Type ``sturm_bound?`` for more details.
|
|
1697
|
+
|
|
1698
|
+
EXAMPLES::
|
|
1699
|
+
|
|
1700
|
+
sage: ModularSymbols(11,2).sturm_bound()
|
|
1701
|
+
2
|
|
1702
|
+
sage: ModularSymbols(389,2).sturm_bound()
|
|
1703
|
+
65
|
|
1704
|
+
sage: ModularSymbols(1,12).sturm_bound()
|
|
1705
|
+
1
|
|
1706
|
+
sage: ModularSymbols(1,36).sturm_bound()
|
|
1707
|
+
3
|
|
1708
|
+
sage: ModularSymbols(DirichletGroup(31).0^2).sturm_bound()
|
|
1709
|
+
6
|
|
1710
|
+
sage: ModularSymbols(Gamma1(31)).sturm_bound()
|
|
1711
|
+
160
|
|
1712
|
+
"""
|
|
1713
|
+
# For Gamma_0(N), n = \frac{k}{12}[\SL_2(\Z):\Gamma_0(N)]
|
|
1714
|
+
try:
|
|
1715
|
+
return self.__sturm_bound
|
|
1716
|
+
except AttributeError:
|
|
1717
|
+
if self.character() is not None:
|
|
1718
|
+
self.__sturm_bound = Gamma0(self.level()).sturm_bound(self.weight())
|
|
1719
|
+
else:
|
|
1720
|
+
self.__sturm_bound = self.group().sturm_bound(self.weight())
|
|
1721
|
+
return self.__sturm_bound
|
|
1722
|
+
|
|
1723
|
+
def plus_submodule(self, compute_dual=True):
|
|
1724
|
+
"""
|
|
1725
|
+
Return the subspace of ``self`` on which the star involution acts as +1.
|
|
1726
|
+
|
|
1727
|
+
INPUT:
|
|
1728
|
+
|
|
1729
|
+
- ``compute_dual`` -- boolean (default: ``True``); also
|
|
1730
|
+
compute dual subspace. This is useful for many algorithms.
|
|
1731
|
+
|
|
1732
|
+
OUTPUT: subspace of modular symbols
|
|
1733
|
+
|
|
1734
|
+
EXAMPLES::
|
|
1735
|
+
|
|
1736
|
+
sage: ModularSymbols(17,2)
|
|
1737
|
+
Modular Symbols space of dimension 3 for Gamma_0(17) of weight 2 with sign 0 over Rational Field
|
|
1738
|
+
sage: ModularSymbols(17,2).plus_submodule()
|
|
1739
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(17) of weight 2 with sign 0 over Rational Field
|
|
1740
|
+
"""
|
|
1741
|
+
return self.sign_submodule(+1, compute_dual)
|
|
1742
|
+
|
|
1743
|
+
def minus_submodule(self, compute_dual=True):
|
|
1744
|
+
"""
|
|
1745
|
+
Return the subspace of ``self`` on which the star involution acts as -1.
|
|
1746
|
+
|
|
1747
|
+
INPUT:
|
|
1748
|
+
|
|
1749
|
+
- ``compute_dual`` -- boolean (default: ``True``); also
|
|
1750
|
+
compute dual subspace. This is useful for many algorithms.
|
|
1751
|
+
|
|
1752
|
+
OUTPUT: subspace of modular symbols
|
|
1753
|
+
|
|
1754
|
+
EXAMPLES::
|
|
1755
|
+
|
|
1756
|
+
sage: ModularSymbols(14,4)
|
|
1757
|
+
Modular Symbols space of dimension 12 for Gamma_0(14) of weight 4 with sign 0 over Rational Field
|
|
1758
|
+
sage: ModularSymbols(14,4).minus_submodule()
|
|
1759
|
+
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 12 for Gamma_0(14) of weight 4 with sign 0 over Rational Field
|
|
1760
|
+
"""
|
|
1761
|
+
return self.sign_submodule(-1, compute_dual)
|
|
1762
|
+
|
|
1763
|
+
def _compute_sign_submodule(self, sign, compute_dual=True):
|
|
1764
|
+
r"""
|
|
1765
|
+
Compute the submodule of ``self`` which is an eigenspace for the star involution with the given sign.
|
|
1766
|
+
|
|
1767
|
+
INPUT:
|
|
1768
|
+
|
|
1769
|
+
- ``sign`` -- integer; 1 or -1
|
|
1770
|
+
|
|
1771
|
+
- ``compute_dual`` -- boolean (default: ``True``); also compute the
|
|
1772
|
+
dual submodule (useful for some algorithms)
|
|
1773
|
+
|
|
1774
|
+
OUTPUT: a submodule of ``self``
|
|
1775
|
+
|
|
1776
|
+
EXAMPLES::
|
|
1777
|
+
|
|
1778
|
+
sage: ModularSymbols(Gamma1(11), 3)._compute_sign_submodule(-1)
|
|
1779
|
+
Modular Symbols subspace of dimension 10 of Modular Symbols space of dimension 20 for Gamma_1(11) of weight 3 with sign 0 over Rational Field
|
|
1780
|
+
"""
|
|
1781
|
+
A = self.ambient()
|
|
1782
|
+
S = A.sign_submodule(sign, compute_dual=compute_dual)
|
|
1783
|
+
V = S.free_module().intersection(self.free_module())
|
|
1784
|
+
if compute_dual:
|
|
1785
|
+
W = S.dual_free_module()
|
|
1786
|
+
Y = self.dual_free_module()
|
|
1787
|
+
D = W.intersection(Y)
|
|
1788
|
+
M = A.submodule(V, D, check=False)
|
|
1789
|
+
else:
|
|
1790
|
+
M = A.submodule(V, check=False)
|
|
1791
|
+
M._set_sign(sign)
|
|
1792
|
+
return M
|
|
1793
|
+
|
|
1794
|
+
def _set_sign(self, sign):
|
|
1795
|
+
r"""
|
|
1796
|
+
Store the sign of this module (used by various initialisation
|
|
1797
|
+
routines).
|
|
1798
|
+
|
|
1799
|
+
INPUT:
|
|
1800
|
+
|
|
1801
|
+
- (integer) sign (must be -1, 0 or 1)
|
|
1802
|
+
|
|
1803
|
+
OUTPUT: none
|
|
1804
|
+
|
|
1805
|
+
EXAMPLES::
|
|
1806
|
+
|
|
1807
|
+
sage: ModularSymbols(11, 2)._set_sign(123)
|
|
1808
|
+
Traceback (most recent call last):
|
|
1809
|
+
...
|
|
1810
|
+
ValueError: sign (=123) must be -1, 0, or 1
|
|
1811
|
+
sage: M = ModularSymbols(11, 2); M
|
|
1812
|
+
Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
|
|
1813
|
+
sage: M._set_sign(-1); M
|
|
1814
|
+
Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign -1 over Rational Field
|
|
1815
|
+
sage: M._set_sign(0)
|
|
1816
|
+
"""
|
|
1817
|
+
sign = int(sign)
|
|
1818
|
+
if sign not in [-1, 0, 1]:
|
|
1819
|
+
raise ValueError("sign (=%s) must be -1, 0, or 1" % sign)
|
|
1820
|
+
self.__sign = sign
|
|
1821
|
+
|
|
1822
|
+
def sign_submodule(self, sign, compute_dual=True):
|
|
1823
|
+
"""
|
|
1824
|
+
Return the subspace of ``self`` that is fixed under the star involution.
|
|
1825
|
+
|
|
1826
|
+
INPUT:
|
|
1827
|
+
|
|
1828
|
+
- ``sign`` -- integer (either -1, 0 or +1)
|
|
1829
|
+
|
|
1830
|
+
- ``compute_dual`` -- boolean (default: ``True``); also
|
|
1831
|
+
compute dual subspace. This is useful for many algorithms.
|
|
1832
|
+
|
|
1833
|
+
OUTPUT: subspace of modular symbols
|
|
1834
|
+
|
|
1835
|
+
EXAMPLES::
|
|
1836
|
+
|
|
1837
|
+
sage: M = ModularSymbols(29,2)
|
|
1838
|
+
sage: M.sign_submodule(1)
|
|
1839
|
+
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 5 for Gamma_0(29) of weight 2 with sign 0 over Rational Field
|
|
1840
|
+
sage: M.sign_submodule(-1)
|
|
1841
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(29) of weight 2 with sign 0 over Rational Field
|
|
1842
|
+
sage: M.sign_submodule(-1).sign()
|
|
1843
|
+
-1
|
|
1844
|
+
"""
|
|
1845
|
+
sign = int(sign)
|
|
1846
|
+
if sign not in [-1, 0, 1]:
|
|
1847
|
+
raise ValueError("sign must be -1, 0 or 1")
|
|
1848
|
+
if self.sign() == sign: # an easy case
|
|
1849
|
+
return self
|
|
1850
|
+
if self.sign() == -sign: # another easy case
|
|
1851
|
+
return self.zero_submodule()
|
|
1852
|
+
if sign == 0:
|
|
1853
|
+
# if sign is zero then self.sign() isn't 0 because
|
|
1854
|
+
# of the above checks.
|
|
1855
|
+
raise ArithmeticError("There is no sign 0 subspace of a space of modular symbols with nonzero sign.")
|
|
1856
|
+
try:
|
|
1857
|
+
return self.__plus_submodule[(sign, compute_dual)]
|
|
1858
|
+
except AttributeError:
|
|
1859
|
+
self.__plus_submodule = {}
|
|
1860
|
+
except KeyError:
|
|
1861
|
+
pass
|
|
1862
|
+
P = self._compute_sign_submodule(sign, compute_dual)
|
|
1863
|
+
P.__star_eigenvalue = sign
|
|
1864
|
+
self.__plus_submodule[(sign, compute_dual)] = P
|
|
1865
|
+
return P
|
|
1866
|
+
|
|
1867
|
+
def star_involution(self):
|
|
1868
|
+
"""
|
|
1869
|
+
Return the star involution on ``self``, which is induced by complex
|
|
1870
|
+
conjugation on modular symbols.
|
|
1871
|
+
|
|
1872
|
+
Not implemented in this abstract base class.
|
|
1873
|
+
|
|
1874
|
+
EXAMPLES::
|
|
1875
|
+
|
|
1876
|
+
sage: M = ModularSymbols(11, 2); sage.modular.modsym.space.ModularSymbolsSpace.star_involution(M)
|
|
1877
|
+
Traceback (most recent call last):
|
|
1878
|
+
...
|
|
1879
|
+
NotImplementedError
|
|
1880
|
+
"""
|
|
1881
|
+
raise NotImplementedError
|
|
1882
|
+
|
|
1883
|
+
def abelian_variety(self):
|
|
1884
|
+
"""
|
|
1885
|
+
Return the corresponding abelian variety.
|
|
1886
|
+
|
|
1887
|
+
INPUT:
|
|
1888
|
+
|
|
1889
|
+
- ``self`` -- modular symbols space of weight 2 for a
|
|
1890
|
+
congruence subgroup such as Gamma0, Gamma1 or GammaH
|
|
1891
|
+
|
|
1892
|
+
EXAMPLES::
|
|
1893
|
+
|
|
1894
|
+
sage: ModularSymbols(Gamma0(11)).cuspidal_submodule().abelian_variety()
|
|
1895
|
+
Abelian variety J0(11) of dimension 1
|
|
1896
|
+
sage: ModularSymbols(Gamma1(11)).cuspidal_submodule().abelian_variety()
|
|
1897
|
+
Abelian variety J1(11) of dimension 1
|
|
1898
|
+
sage: ModularSymbols(GammaH(11,[3])).cuspidal_submodule().abelian_variety()
|
|
1899
|
+
Abelian variety JH(11,[3]) of dimension 1
|
|
1900
|
+
|
|
1901
|
+
The abelian variety command only works on cuspidal modular symbols
|
|
1902
|
+
spaces::
|
|
1903
|
+
|
|
1904
|
+
sage: M = ModularSymbols(37)
|
|
1905
|
+
sage: M[0].abelian_variety()
|
|
1906
|
+
Traceback (most recent call last):
|
|
1907
|
+
...
|
|
1908
|
+
ValueError: self must be cuspidal
|
|
1909
|
+
sage: M[1].abelian_variety()
|
|
1910
|
+
Abelian subvariety of dimension 1 of J0(37)
|
|
1911
|
+
sage: M[2].abelian_variety()
|
|
1912
|
+
Abelian subvariety of dimension 1 of J0(37)
|
|
1913
|
+
"""
|
|
1914
|
+
try:
|
|
1915
|
+
return self.__modular_abelian_variety
|
|
1916
|
+
except AttributeError:
|
|
1917
|
+
if not self.is_cuspidal():
|
|
1918
|
+
raise ValueError("self must be cuspidal")
|
|
1919
|
+
from sage.modular.abvar.abvar import ModularAbelianVariety_modsym
|
|
1920
|
+
A = ModularAbelianVariety_modsym(self, check=False)
|
|
1921
|
+
self.__modular_abelian_variety = A
|
|
1922
|
+
return A
|
|
1923
|
+
|
|
1924
|
+
def rational_period_mapping(self):
|
|
1925
|
+
r"""
|
|
1926
|
+
Return the rational period mapping associated to ``self``.
|
|
1927
|
+
|
|
1928
|
+
This is a homomorphism to a vector space whose kernel is the
|
|
1929
|
+
same as the kernel of the period mapping associated to
|
|
1930
|
+
``self``. For this to exist, ``self`` must be Hecke equivariant.
|
|
1931
|
+
|
|
1932
|
+
Use :meth:`integral_period_mapping` to obtain a homomorphism to a
|
|
1933
|
+
`\ZZ`-module, normalized so the image of integral modular symbols is
|
|
1934
|
+
exactly `\ZZ^n`.
|
|
1935
|
+
|
|
1936
|
+
EXAMPLES::
|
|
1937
|
+
|
|
1938
|
+
sage: M = ModularSymbols(37)
|
|
1939
|
+
sage: A = M[1]; A
|
|
1940
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
|
|
1941
|
+
sage: r = A.rational_period_mapping(); r
|
|
1942
|
+
Rational period mapping associated to Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
|
|
1943
|
+
sage: r(M.0)
|
|
1944
|
+
(0, 0)
|
|
1945
|
+
sage: r(M.1)
|
|
1946
|
+
(1, 0)
|
|
1947
|
+
sage: r.matrix()
|
|
1948
|
+
[ 0 0]
|
|
1949
|
+
[ 1 0]
|
|
1950
|
+
[ 0 1]
|
|
1951
|
+
[-1 -1]
|
|
1952
|
+
[ 0 0]
|
|
1953
|
+
sage: r.domain()
|
|
1954
|
+
Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
|
|
1955
|
+
sage: r.codomain()
|
|
1956
|
+
Vector space of degree 2 and dimension 2 over Rational Field
|
|
1957
|
+
Basis matrix:
|
|
1958
|
+
[1 0]
|
|
1959
|
+
[0 1]
|
|
1960
|
+
"""
|
|
1961
|
+
try:
|
|
1962
|
+
return self.__rational_period_mapping
|
|
1963
|
+
except AttributeError:
|
|
1964
|
+
pass
|
|
1965
|
+
V = self.dual_free_module()
|
|
1966
|
+
# the rational period mapping is just dotting with
|
|
1967
|
+
# each element of V.
|
|
1968
|
+
A = V.basis_matrix().transpose()
|
|
1969
|
+
A.set_immutable()
|
|
1970
|
+
R = RationalPeriodMapping(self, A)
|
|
1971
|
+
self.__rational_period_mapping = R
|
|
1972
|
+
return R
|
|
1973
|
+
|
|
1974
|
+
def integral_period_mapping(self):
|
|
1975
|
+
r"""
|
|
1976
|
+
Return the integral period mapping associated to ``self``.
|
|
1977
|
+
|
|
1978
|
+
This is a homomorphism to a vector space whose kernel is the same
|
|
1979
|
+
as the kernel of the period mapping associated to ``self``, normalized
|
|
1980
|
+
so the image of integral modular symbols is exactly `\ZZ^n`.
|
|
1981
|
+
|
|
1982
|
+
EXAMPLES::
|
|
1983
|
+
|
|
1984
|
+
sage: m = ModularSymbols(23).cuspidal_submodule()
|
|
1985
|
+
sage: i = m.integral_period_mapping()
|
|
1986
|
+
sage: i
|
|
1987
|
+
Integral period mapping associated to Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Rational Field
|
|
1988
|
+
sage: i.matrix()
|
|
1989
|
+
[-1/11 1/11 0 3/11]
|
|
1990
|
+
[ 1 0 0 0]
|
|
1991
|
+
[ 0 1 0 0]
|
|
1992
|
+
[ 0 0 1 0]
|
|
1993
|
+
[ 0 0 0 1]
|
|
1994
|
+
sage: [i(b) for b in m.integral_structure().basis()]
|
|
1995
|
+
[(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)]
|
|
1996
|
+
sage: [i(b) for b in m.ambient_module().basis()]
|
|
1997
|
+
[(-1/11, 1/11, 0, 3/11),
|
|
1998
|
+
(1, 0, 0, 0),
|
|
1999
|
+
(0, 1, 0, 0),
|
|
2000
|
+
(0, 0, 1, 0),
|
|
2001
|
+
(0, 0, 0, 1)]
|
|
2002
|
+
|
|
2003
|
+
We compute the image of the winding element::
|
|
2004
|
+
|
|
2005
|
+
sage: m = ModularSymbols(37,sign=1)
|
|
2006
|
+
sage: a = m[1]
|
|
2007
|
+
sage: f = a.integral_period_mapping()
|
|
2008
|
+
sage: e = m([0,oo])
|
|
2009
|
+
sage: f(e)
|
|
2010
|
+
(-2/3)
|
|
2011
|
+
|
|
2012
|
+
The input space must be cuspidal::
|
|
2013
|
+
|
|
2014
|
+
sage: m = ModularSymbols(37,2,sign=1)
|
|
2015
|
+
sage: m.integral_period_mapping()
|
|
2016
|
+
Traceback (most recent call last):
|
|
2017
|
+
...
|
|
2018
|
+
ValueError: integral mapping only defined for cuspidal spaces
|
|
2019
|
+
"""
|
|
2020
|
+
try:
|
|
2021
|
+
return self.__integral_period_mapping
|
|
2022
|
+
except AttributeError:
|
|
2023
|
+
pass
|
|
2024
|
+
if self.base_ring() != QQ:
|
|
2025
|
+
raise ValueError("integral mapping only defined for spaces over QQ")
|
|
2026
|
+
if not self.is_cuspidal():
|
|
2027
|
+
raise ValueError("integral mapping only defined for cuspidal spaces")
|
|
2028
|
+
D = self.dual_free_module().basis_matrix().transpose()
|
|
2029
|
+
I = self.ambient_module().cuspidal_submodule().integral_structure().basis_matrix()
|
|
2030
|
+
# image of cuspidal integral submodule
|
|
2031
|
+
C = I * D
|
|
2032
|
+
if not C.is_one():
|
|
2033
|
+
if not C.is_square():
|
|
2034
|
+
C = (ZZ**C.ncols()).span(C.rows()).basis_matrix()
|
|
2035
|
+
D = D * C**(-1)
|
|
2036
|
+
D.set_immutable()
|
|
2037
|
+
R = IntegralPeriodMapping(self, D)
|
|
2038
|
+
self.__integral_period_mapping = R
|
|
2039
|
+
return R
|
|
2040
|
+
|
|
2041
|
+
@cached_method
|
|
2042
|
+
def modular_symbols_of_sign(self, sign, bound=None):
|
|
2043
|
+
"""
|
|
2044
|
+
Return a space of modular symbols with the same defining
|
|
2045
|
+
properties (weight, level, etc.) and Hecke eigenvalues as this
|
|
2046
|
+
space except with given sign.
|
|
2047
|
+
|
|
2048
|
+
INPUT:
|
|
2049
|
+
|
|
2050
|
+
- ``self`` -- a cuspidal space of modular symbols
|
|
2051
|
+
|
|
2052
|
+
- ``sign`` -- integer, one of -1, 0, or 1
|
|
2053
|
+
|
|
2054
|
+
- ``bound`` -- integer (default: ``None``); if specified
|
|
2055
|
+
only use Hecke operators up to the given bound
|
|
2056
|
+
|
|
2057
|
+
EXAMPLES::
|
|
2058
|
+
|
|
2059
|
+
sage: S = ModularSymbols(Gamma0(11),2,sign=0).cuspidal_subspace()
|
|
2060
|
+
sage: S
|
|
2061
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
|
|
2062
|
+
sage: S.modular_symbols_of_sign(-1)
|
|
2063
|
+
Modular Symbols space of dimension 1 for Gamma_0(11) of weight 2 with sign -1 over Rational Field
|
|
2064
|
+
|
|
2065
|
+
::
|
|
2066
|
+
|
|
2067
|
+
sage: S = ModularSymbols(43,2,sign=1)[2]; S
|
|
2068
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 for Gamma_0(43) of weight 2 with sign 1 over Rational Field
|
|
2069
|
+
sage: S.modular_symbols_of_sign(-1)
|
|
2070
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(43) of weight 2 with sign -1 over Rational Field
|
|
2071
|
+
|
|
2072
|
+
::
|
|
2073
|
+
|
|
2074
|
+
sage: S.modular_symbols_of_sign(0)
|
|
2075
|
+
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 7 for Gamma_0(43) of weight 2 with sign 0 over Rational Field
|
|
2076
|
+
|
|
2077
|
+
::
|
|
2078
|
+
|
|
2079
|
+
sage: S = ModularSymbols(389,sign=1)[3]; S
|
|
2080
|
+
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 33 for Gamma_0(389) of weight 2 with sign 1 over Rational Field
|
|
2081
|
+
sage: S.modular_symbols_of_sign(-1)
|
|
2082
|
+
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 32 for Gamma_0(389) of weight 2 with sign -1 over Rational Field
|
|
2083
|
+
sage: S.modular_symbols_of_sign(0)
|
|
2084
|
+
Modular Symbols subspace of dimension 6 of Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field
|
|
2085
|
+
|
|
2086
|
+
::
|
|
2087
|
+
|
|
2088
|
+
sage: S = ModularSymbols(23,sign=1,weight=4)[2]; S
|
|
2089
|
+
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 7 for Gamma_0(23) of weight 4 with sign 1 over Rational Field
|
|
2090
|
+
sage: S.modular_symbols_of_sign(1) is S
|
|
2091
|
+
True
|
|
2092
|
+
sage: S.modular_symbols_of_sign(0)
|
|
2093
|
+
Modular Symbols subspace of dimension 8 of Modular Symbols space of dimension 12 for Gamma_0(23) of weight 4 with sign 0 over Rational Field
|
|
2094
|
+
sage: S.modular_symbols_of_sign(-1)
|
|
2095
|
+
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 5 for Gamma_0(23) of weight 4 with sign -1 over Rational Field
|
|
2096
|
+
"""
|
|
2097
|
+
if sign == self.sign():
|
|
2098
|
+
return self
|
|
2099
|
+
if not self.is_cuspidal():
|
|
2100
|
+
raise ValueError("self must be cuspidal for modular symbols space with given sign to be defined.")
|
|
2101
|
+
d = self.dimension()
|
|
2102
|
+
if d == 0:
|
|
2103
|
+
return self
|
|
2104
|
+
if sign != 0:
|
|
2105
|
+
if self.sign() == 0:
|
|
2106
|
+
d = d // 2
|
|
2107
|
+
elif sign == 0: # self has nonzero sign
|
|
2108
|
+
d = 2 * d
|
|
2109
|
+
B = self.ambient_module().modular_symbols_of_sign(sign)
|
|
2110
|
+
p = 2
|
|
2111
|
+
if bound is None:
|
|
2112
|
+
bound = self.hecke_bound()
|
|
2113
|
+
while B.dimension() > d and p <= bound:
|
|
2114
|
+
while self.level() % p == 0:
|
|
2115
|
+
p = next_prime(p)
|
|
2116
|
+
f = self.hecke_polynomial(p)
|
|
2117
|
+
g = prod(g for g, _ in f.factor()) # square free part
|
|
2118
|
+
t = B.hecke_operator(p)
|
|
2119
|
+
s = g(t)
|
|
2120
|
+
B = s.kernel()
|
|
2121
|
+
p = next_prime(p)
|
|
2122
|
+
return B
|
|
2123
|
+
|
|
2124
|
+
#########################################################
|
|
2125
|
+
# Cuspidal torsion groups
|
|
2126
|
+
#########################################################
|
|
2127
|
+
|
|
2128
|
+
@cached_method
|
|
2129
|
+
def abvarquo_cuspidal_subgroup(self):
|
|
2130
|
+
"""
|
|
2131
|
+
Compute the rational subgroup of the cuspidal subgroup (as an
|
|
2132
|
+
abstract abelian group) of the abelian variety quotient A of
|
|
2133
|
+
the relevant modular Jacobian attached to this modular symbols
|
|
2134
|
+
space.
|
|
2135
|
+
|
|
2136
|
+
We assume that ``self`` is defined over QQ and has weight 2. If
|
|
2137
|
+
the sign of ``self`` is not 0, then the power of 2 may be wrong.
|
|
2138
|
+
|
|
2139
|
+
EXAMPLES::
|
|
2140
|
+
|
|
2141
|
+
sage: D = ModularSymbols(66,2,sign=0).cuspidal_subspace().new_subspace().decomposition()
|
|
2142
|
+
sage: D[0].abvarquo_cuspidal_subgroup()
|
|
2143
|
+
Finitely generated module V/W over Integer Ring with invariants (3)
|
|
2144
|
+
sage: [A.abvarquo_cuspidal_subgroup().invariants() for A in D]
|
|
2145
|
+
[(3,), (2,), ()]
|
|
2146
|
+
sage: D = ModularSymbols(66,2,sign=1).cuspidal_subspace().new_subspace().decomposition()
|
|
2147
|
+
sage: [A.abvarquo_cuspidal_subgroup().invariants() for A in D]
|
|
2148
|
+
[(3,), (2,), ()]
|
|
2149
|
+
sage: D = ModularSymbols(66,2,sign=-1).cuspidal_subspace().new_subspace().decomposition()
|
|
2150
|
+
sage: [A.abvarquo_cuspidal_subgroup().invariants() for A in D]
|
|
2151
|
+
[(), (), ()]
|
|
2152
|
+
"""
|
|
2153
|
+
if self.base_ring() != QQ:
|
|
2154
|
+
raise ValueError("base ring must be QQ")
|
|
2155
|
+
if self.weight() != 2:
|
|
2156
|
+
raise NotImplementedError("only implemented when weight is 2")
|
|
2157
|
+
M = self.ambient_module()
|
|
2158
|
+
phi = self.integral_period_mapping()
|
|
2159
|
+
|
|
2160
|
+
# Make a list of all the finite cusps.
|
|
2161
|
+
P = (c for c in M.cusps() if not c.is_infinity())
|
|
2162
|
+
|
|
2163
|
+
# Compute the images of the cusp classes (c)-(oo) in the
|
|
2164
|
+
# rational homology of the quotient modular abelian variety.
|
|
2165
|
+
ims = [phi(M([c, infinity])) for c in P]
|
|
2166
|
+
|
|
2167
|
+
# Take the span of the ims over ZZ
|
|
2168
|
+
A = phi.codomain().span(ims, ZZ)
|
|
2169
|
+
|
|
2170
|
+
# The cuspidal subgroup is then the quotient of that module +
|
|
2171
|
+
# H_1(A) by H_1(A)
|
|
2172
|
+
return (A.ambient_module() + A) / A.ambient_module()
|
|
2173
|
+
|
|
2174
|
+
@cached_method
|
|
2175
|
+
def abvarquo_rational_cuspidal_subgroup(self):
|
|
2176
|
+
r"""
|
|
2177
|
+
Compute the rational subgroup of the cuspidal subgroup (as an
|
|
2178
|
+
abstract abelian group) of the abelian variety quotient A of
|
|
2179
|
+
the relevant modular Jacobian attached to this modular symbols
|
|
2180
|
+
space.
|
|
2181
|
+
|
|
2182
|
+
If C is the subgroup of A generated by differences of
|
|
2183
|
+
cusps, then C is equipped with an action of Gal(Qbar/Q), and
|
|
2184
|
+
this function computes the fixed subgroup, i.e., C(Q).
|
|
2185
|
+
|
|
2186
|
+
We assume that ``self`` is defined over QQ and has weight 2. If
|
|
2187
|
+
the sign of ``self`` is not 0, then the power of 2 may be wrong.
|
|
2188
|
+
|
|
2189
|
+
EXAMPLES:
|
|
2190
|
+
|
|
2191
|
+
First we consider the fairly straightforward level 37 case,
|
|
2192
|
+
where the torsion subgroup of the optimal quotients (which are
|
|
2193
|
+
all elliptic curves) are all cuspidal::
|
|
2194
|
+
|
|
2195
|
+
sage: M = ModularSymbols(37).cuspidal_subspace().new_subspace()
|
|
2196
|
+
sage: D = M.decomposition()
|
|
2197
|
+
sage: [(A.abvarquo_rational_cuspidal_subgroup().invariants(), A.T(19)[0,0]) for A in D]
|
|
2198
|
+
[((), 0), ((3,), 2)]
|
|
2199
|
+
sage: [(E.torsion_subgroup().invariants(),E.ap(19)) for E in cremona_optimal_curves([37])]
|
|
2200
|
+
[((), 0), ((3,), 2)]
|
|
2201
|
+
|
|
2202
|
+
Next we consider level 54, where the rational cuspidal
|
|
2203
|
+
subgroups of the quotients are also cuspidal::
|
|
2204
|
+
|
|
2205
|
+
sage: M = ModularSymbols(54).cuspidal_subspace().new_subspace()
|
|
2206
|
+
sage: D = M.decomposition()
|
|
2207
|
+
sage: [A.abvarquo_rational_cuspidal_subgroup().invariants() for A in D]
|
|
2208
|
+
[(3,), (3,)]
|
|
2209
|
+
sage: [E.torsion_subgroup().invariants() for E in cremona_optimal_curves([54])]
|
|
2210
|
+
[(3,), (3,)]
|
|
2211
|
+
|
|
2212
|
+
Level 66 is interesting, since not all torsion of the quotient
|
|
2213
|
+
is rational. In fact, for each elliptic curve quotient, the
|
|
2214
|
+
`\QQ`-rational subgroup of the image of the cuspidal subgroup
|
|
2215
|
+
in the quotient is a nontrivial subgroup of `E(\QQ)_{tor}`.
|
|
2216
|
+
Thus not all torsion in the quotient is cuspidal!::
|
|
2217
|
+
|
|
2218
|
+
sage: M = ModularSymbols(66).cuspidal_subspace().new_subspace()
|
|
2219
|
+
sage: D = M.decomposition()
|
|
2220
|
+
sage: [(A.abvarquo_rational_cuspidal_subgroup().invariants(), A.T(19)[0,0]) for A in D]
|
|
2221
|
+
[((3,), -4), ((2,), 4), ((), 0)]
|
|
2222
|
+
sage: [(E.torsion_subgroup().invariants(),E.ap(19)) for E in cremona_optimal_curves([66])]
|
|
2223
|
+
[((6,), -4), ((4,), 4), ((10,), 0)]
|
|
2224
|
+
sage: [A.abelian_variety().rational_cuspidal_subgroup().invariants() for A in D]
|
|
2225
|
+
[[6], [4], [10]]
|
|
2226
|
+
|
|
2227
|
+
In this example, the abelian varieties involved all having
|
|
2228
|
+
dimension bigger than 1 (unlike above). We find that all torsion
|
|
2229
|
+
in the quotient in each of these cases is cuspidal::
|
|
2230
|
+
|
|
2231
|
+
sage: M = ModularSymbols(125).cuspidal_subspace().new_subspace()
|
|
2232
|
+
sage: D = M.decomposition()
|
|
2233
|
+
sage: [A.abvarquo_rational_cuspidal_subgroup().invariants() for A in D]
|
|
2234
|
+
[(), (5,), (5,)]
|
|
2235
|
+
sage: [A.abelian_variety().rational_torsion_subgroup().multiple_of_order() for A in D]
|
|
2236
|
+
[1, 5, 5]
|
|
2237
|
+
"""
|
|
2238
|
+
if self.base_ring() != QQ:
|
|
2239
|
+
raise ValueError("base ring must be QQ")
|
|
2240
|
+
if self.weight() != 2:
|
|
2241
|
+
raise NotImplementedError("only implemented when weight is 2")
|
|
2242
|
+
if not isinstance(self.group(), Gamma0_class):
|
|
2243
|
+
# todo -- do Gamma1 and GammaH, which are easy
|
|
2244
|
+
raise NotImplementedError("only implemented when group is Gamma0")
|
|
2245
|
+
N = self.level()
|
|
2246
|
+
if N.is_squarefree():
|
|
2247
|
+
return self.abvarquo_cuspidal_subgroup()
|
|
2248
|
+
|
|
2249
|
+
M = self.ambient_module()
|
|
2250
|
+
phi = self.integral_period_mapping()
|
|
2251
|
+
|
|
2252
|
+
# Make a list of all the finite cusps.
|
|
2253
|
+
P = [c for c in M.cusps() if not c.is_infinity()]
|
|
2254
|
+
|
|
2255
|
+
# Define the vector space V, which we think of as
|
|
2256
|
+
# the vector space with basis (c)-(oo), where c runs
|
|
2257
|
+
# through the finite cusp *classes*.
|
|
2258
|
+
V = ZZ**len(P) # vector space on (c)-(oo)
|
|
2259
|
+
|
|
2260
|
+
# Compute the images of the cusp classes (c)-(oo) in the
|
|
2261
|
+
# rational homology of the quotient modular abelian variety.
|
|
2262
|
+
ims = [phi(M([c, infinity])) for c in P]
|
|
2263
|
+
|
|
2264
|
+
# Take the span of the ims over ZZ
|
|
2265
|
+
A = phi.codomain().span(ims, ZZ)
|
|
2266
|
+
|
|
2267
|
+
# The cuspidal subgroup is then the quotient of that module +
|
|
2268
|
+
# H_1(A) by H_1(A)
|
|
2269
|
+
C = (A.ambient_module() + A) / A.ambient_module()
|
|
2270
|
+
|
|
2271
|
+
# Make fgp module version of V.
|
|
2272
|
+
D = V / V.zero_submodule()
|
|
2273
|
+
psi = D.hom([C(x) for x in ims])
|
|
2274
|
+
|
|
2275
|
+
# The rational cuspidal subgroup is got by intersecting kernels
|
|
2276
|
+
# of tau - 1, for all automorphisms tau.
|
|
2277
|
+
G = Zmod(N).unit_gens()
|
|
2278
|
+
CQ = C
|
|
2279
|
+
for t in G:
|
|
2280
|
+
T = self._matrix_of_galois_action(t, P) - 1
|
|
2281
|
+
if not T:
|
|
2282
|
+
continue
|
|
2283
|
+
im_gens = [psi(psi.lift(g).lift() * T) for g in CQ.gens()]
|
|
2284
|
+
h = CQ.hom(im_gens)
|
|
2285
|
+
CQ = h.kernel()
|
|
2286
|
+
if CQ.cardinality() == 1:
|
|
2287
|
+
break # done -- no point in wasting more time shrinking CQ
|
|
2288
|
+
|
|
2289
|
+
return CQ
|
|
2290
|
+
|
|
2291
|
+
def _matrix_of_galois_action(self, t, P):
|
|
2292
|
+
"""
|
|
2293
|
+
Compute the matrix of the action of the element of the
|
|
2294
|
+
cyclotomic Galois group defined by t on the set of cusps in P
|
|
2295
|
+
(which is the set of finite cusps).
|
|
2296
|
+
|
|
2297
|
+
This function is used internally by the (rational) cuspidal
|
|
2298
|
+
subgroup and quotient functions.
|
|
2299
|
+
|
|
2300
|
+
INPUT:
|
|
2301
|
+
|
|
2302
|
+
- ``t`` -- integer
|
|
2303
|
+
|
|
2304
|
+
- ``P`` -- list of cusps
|
|
2305
|
+
|
|
2306
|
+
EXAMPLES:
|
|
2307
|
+
|
|
2308
|
+
We compute the matrix of the element of the Galois group
|
|
2309
|
+
associated to 5 and 31 for level 32. In the first case the
|
|
2310
|
+
Galois action is trivial, and in the second it is
|
|
2311
|
+
nontrivial. ::
|
|
2312
|
+
|
|
2313
|
+
sage: M = ModularSymbols(32)
|
|
2314
|
+
sage: P = [c for c in Gamma0(32).cusps() if not c.is_infinity()]
|
|
2315
|
+
sage: M._matrix_of_galois_action(5, P)
|
|
2316
|
+
[1 0 0 0 0 0 0]
|
|
2317
|
+
[0 1 0 0 0 0 0]
|
|
2318
|
+
[0 0 1 0 0 0 0]
|
|
2319
|
+
[0 0 0 1 0 0 0]
|
|
2320
|
+
[0 0 0 0 1 0 0]
|
|
2321
|
+
[0 0 0 0 0 1 0]
|
|
2322
|
+
[0 0 0 0 0 0 1]
|
|
2323
|
+
sage: z = M._matrix_of_galois_action(31, P); z
|
|
2324
|
+
[1 0 0 0 0 0 0]
|
|
2325
|
+
[0 1 0 0 0 0 0]
|
|
2326
|
+
[0 0 0 0 1 0 0]
|
|
2327
|
+
[0 0 0 0 0 0 1]
|
|
2328
|
+
[0 0 1 0 0 0 0]
|
|
2329
|
+
[0 0 0 0 0 1 0]
|
|
2330
|
+
[0 0 0 1 0 0 0]
|
|
2331
|
+
sage: z.charpoly().factor()
|
|
2332
|
+
(x + 1)^2 * (x - 1)^5
|
|
2333
|
+
"""
|
|
2334
|
+
N = self.level()
|
|
2335
|
+
from sage.matrix.constructor import matrix
|
|
2336
|
+
A = matrix(ZZ, len(P))
|
|
2337
|
+
for i, c in enumerate(P):
|
|
2338
|
+
d = c.galois_action(t, N)
|
|
2339
|
+
for j, e in enumerate(P):
|
|
2340
|
+
if d.is_gamma0_equiv(e, N, False):
|
|
2341
|
+
A[i, j] = 1
|
|
2342
|
+
A.set_immutable()
|
|
2343
|
+
return A
|
|
2344
|
+
|
|
2345
|
+
|
|
2346
|
+
class PeriodMapping(SageObject):
|
|
2347
|
+
r"""
|
|
2348
|
+
Base class for representing a period mapping attached to a space of modular
|
|
2349
|
+
symbols.
|
|
2350
|
+
|
|
2351
|
+
To be used via the derived classes :class:`RationalPeriodMapping` and
|
|
2352
|
+
:class:`IntegralPeriodMapping`.
|
|
2353
|
+
"""
|
|
2354
|
+
def __init__(self, modsym, A):
|
|
2355
|
+
r"""
|
|
2356
|
+
Standard initialisation function.
|
|
2357
|
+
|
|
2358
|
+
INPUT:
|
|
2359
|
+
|
|
2360
|
+
- ``modsym`` -- a space of modular symbols
|
|
2361
|
+
|
|
2362
|
+
- ``A`` -- matrix of the associated period map
|
|
2363
|
+
|
|
2364
|
+
EXAMPLES::
|
|
2365
|
+
|
|
2366
|
+
sage: ModularSymbols(2, 8).cuspidal_submodule().integral_period_mapping() # indirect doctest
|
|
2367
|
+
Integral period mapping associated to Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 for Gamma_0(2) of weight 8 with sign 0 over Rational Field
|
|
2368
|
+
"""
|
|
2369
|
+
self.__modsym = modsym
|
|
2370
|
+
self.__domain = modsym.ambient_module()
|
|
2371
|
+
self.__A = A
|
|
2372
|
+
A.set_immutable()
|
|
2373
|
+
|
|
2374
|
+
def modular_symbols_space(self):
|
|
2375
|
+
r"""
|
|
2376
|
+
Return the space of modular symbols to which this period mapping
|
|
2377
|
+
corresponds.
|
|
2378
|
+
|
|
2379
|
+
EXAMPLES::
|
|
2380
|
+
|
|
2381
|
+
sage: ModularSymbols(17, 2).rational_period_mapping().modular_symbols_space()
|
|
2382
|
+
Modular Symbols space of dimension 3 for Gamma_0(17) of weight 2 with sign 0 over Rational Field
|
|
2383
|
+
"""
|
|
2384
|
+
return self.__modsym
|
|
2385
|
+
|
|
2386
|
+
def __call__(self, x):
|
|
2387
|
+
r"""
|
|
2388
|
+
Evaluate this mapping at an element of the domain.
|
|
2389
|
+
|
|
2390
|
+
EXAMPLES::
|
|
2391
|
+
|
|
2392
|
+
sage: M = ModularSymbols(17, 2).cuspidal_submodule().integral_period_mapping()
|
|
2393
|
+
sage: M(vector([1,0,2]))
|
|
2394
|
+
(0, 9/4)
|
|
2395
|
+
"""
|
|
2396
|
+
if isinstance(x, FreeModuleElement):
|
|
2397
|
+
v = x
|
|
2398
|
+
else:
|
|
2399
|
+
v = self.__domain(x).element()
|
|
2400
|
+
return v * self.__A
|
|
2401
|
+
|
|
2402
|
+
def matrix(self):
|
|
2403
|
+
r"""
|
|
2404
|
+
Return the matrix of this period mapping.
|
|
2405
|
+
|
|
2406
|
+
EXAMPLES::
|
|
2407
|
+
|
|
2408
|
+
sage: ModularSymbols(11, 2).cuspidal_submodule().integral_period_mapping().matrix()
|
|
2409
|
+
[ 0 1/5]
|
|
2410
|
+
[ 1 0]
|
|
2411
|
+
[ 0 1]
|
|
2412
|
+
"""
|
|
2413
|
+
return self.__A
|
|
2414
|
+
|
|
2415
|
+
def domain(self):
|
|
2416
|
+
r"""
|
|
2417
|
+
Return the domain of this mapping (which is the ambient space of the
|
|
2418
|
+
corresponding modular symbols space).
|
|
2419
|
+
|
|
2420
|
+
EXAMPLES::
|
|
2421
|
+
|
|
2422
|
+
sage: ModularSymbols(17, 2).cuspidal_submodule().integral_period_mapping().domain()
|
|
2423
|
+
Modular Symbols space of dimension 3 for Gamma_0(17) of weight 2 with sign 0 over Rational Field
|
|
2424
|
+
"""
|
|
2425
|
+
return self.__domain
|
|
2426
|
+
|
|
2427
|
+
def codomain(self):
|
|
2428
|
+
r"""
|
|
2429
|
+
Return the codomain of this mapping.
|
|
2430
|
+
|
|
2431
|
+
EXAMPLES:
|
|
2432
|
+
|
|
2433
|
+
Note that this presently returns the wrong answer, as a consequence of
|
|
2434
|
+
various bugs in the free module routines::
|
|
2435
|
+
|
|
2436
|
+
sage: ModularSymbols(11, 2).cuspidal_submodule().integral_period_mapping().codomain()
|
|
2437
|
+
Vector space of degree 2 and dimension 2 over Rational Field
|
|
2438
|
+
Basis matrix:
|
|
2439
|
+
[1 0]
|
|
2440
|
+
[0 1]
|
|
2441
|
+
"""
|
|
2442
|
+
return self.__A.row_module()
|
|
2443
|
+
|
|
2444
|
+
|
|
2445
|
+
class RationalPeriodMapping(PeriodMapping):
|
|
2446
|
+
def _repr_(self):
|
|
2447
|
+
"""
|
|
2448
|
+
Return the string representation of ``self``.
|
|
2449
|
+
|
|
2450
|
+
EXAMPLES::
|
|
2451
|
+
|
|
2452
|
+
sage: ModularSymbols(40,2).rational_period_mapping()._repr_()
|
|
2453
|
+
'Rational period mapping associated to Modular Symbols space of dimension 13 for Gamma_0(40) of weight 2 with sign 0 over Rational Field'
|
|
2454
|
+
"""
|
|
2455
|
+
return "Rational period mapping associated to %s" % self.modular_symbols_space()
|
|
2456
|
+
|
|
2457
|
+
|
|
2458
|
+
class IntegralPeriodMapping(PeriodMapping):
|
|
2459
|
+
def _repr_(self):
|
|
2460
|
+
"""
|
|
2461
|
+
Return the string representation of ``self``.
|
|
2462
|
+
|
|
2463
|
+
EXAMPLES::
|
|
2464
|
+
|
|
2465
|
+
sage: ModularSymbols(40,2).cuspidal_submodule().integral_period_mapping()._repr_()
|
|
2466
|
+
'Integral period mapping associated to Modular Symbols subspace of dimension 6 of Modular Symbols space of dimension 13 for Gamma_0(40) of weight 2 with sign 0 over Rational Field'
|
|
2467
|
+
"""
|
|
2468
|
+
return "Integral period mapping associated to %s" % self.modular_symbols_space()
|