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,3846 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.libs.flint sage.libs.pari
|
|
3
|
+
r"""
|
|
4
|
+
Ambient spaces of modular symbols
|
|
5
|
+
|
|
6
|
+
This module defines the following classes. There is an abstract base
|
|
7
|
+
class ``ModularSymbolsAmbient``, derived from
|
|
8
|
+
``space.ModularSymbolsSpace`` and ``hecke.AmbientHeckeModule``. As
|
|
9
|
+
this is an abstract base class, only derived classes should be
|
|
10
|
+
instantiated. There are five derived classes:
|
|
11
|
+
|
|
12
|
+
- ``ModularSymbolsAmbient_wtk_g0``, for modular symbols of general
|
|
13
|
+
weight `k` for `\Gamma_0(N)`;
|
|
14
|
+
|
|
15
|
+
- ``ModularSymbolsAmbient_wt2_g0`` (derived from
|
|
16
|
+
``ModularSymbolsAmbient_wtk_g0``), for modular symbols of weight 2
|
|
17
|
+
for `\Gamma_0(N)`;
|
|
18
|
+
|
|
19
|
+
- ``ModularSymbolsAmbient_wtk_g1``, for modular symbols of general
|
|
20
|
+
weight `k` for `\Gamma_1(N)`;
|
|
21
|
+
|
|
22
|
+
- ``ModularSymbolsAmbient_wtk_gamma_h``, for modular symbols of
|
|
23
|
+
general weight `k` for `\Gamma_H`, where `H` is a subgroup of
|
|
24
|
+
`\ZZ/N\ZZ`;
|
|
25
|
+
|
|
26
|
+
- ``ModularSymbolsAmbient_wtk_eps``, for modular symbols of general
|
|
27
|
+
weight `k` and character `\epsilon`.
|
|
28
|
+
|
|
29
|
+
EXAMPLES:
|
|
30
|
+
|
|
31
|
+
We compute a space of modular symbols modulo 2. The dimension is
|
|
32
|
+
different from that of the corresponding space in characteristic
|
|
33
|
+
0::
|
|
34
|
+
|
|
35
|
+
sage: M = ModularSymbols(11,4,base_ring=GF(2)); M
|
|
36
|
+
Modular Symbols space of dimension 7 for Gamma_0(11) of weight 4
|
|
37
|
+
with sign 0 over Finite Field of size 2
|
|
38
|
+
sage: M.basis()
|
|
39
|
+
([X*Y,(1,0)], [X*Y,(1,8)], [X*Y,(1,9)], [X^2,(0,1)], [X^2,(1,8)], [X^2,(1,9)], [X^2,(1,10)])
|
|
40
|
+
sage: M0 = ModularSymbols(11,4,base_ring=QQ); M0
|
|
41
|
+
Modular Symbols space of dimension 6 for Gamma_0(11) of weight 4
|
|
42
|
+
with sign 0 over Rational Field
|
|
43
|
+
sage: M0.basis()
|
|
44
|
+
([X^2,(0,1)], [X^2,(1,6)], [X^2,(1,7)], [X^2,(1,8)], [X^2,(1,9)], [X^2,(1,10)])
|
|
45
|
+
|
|
46
|
+
The characteristic polynomial of the Hecke operator `T_2` has an extra
|
|
47
|
+
factor `x`.
|
|
48
|
+
|
|
49
|
+
::
|
|
50
|
+
|
|
51
|
+
sage: M.T(2).matrix().fcp('x')
|
|
52
|
+
(x + 1)^2 * x^5
|
|
53
|
+
sage: M0.T(2).matrix().fcp('x')
|
|
54
|
+
(x - 9)^2 * (x^2 - 2*x - 2)^2
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
################################################################################
|
|
58
|
+
# Sage: Open Source Mathematical Software
|
|
59
|
+
#
|
|
60
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
61
|
+
#
|
|
62
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
63
|
+
#
|
|
64
|
+
# This code is distributed in the hope that it will be useful,
|
|
65
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
66
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
67
|
+
# General Public License for more details.
|
|
68
|
+
#
|
|
69
|
+
# The full text of the GPL is available at:
|
|
70
|
+
#
|
|
71
|
+
# https://www.gnu.org/licenses/
|
|
72
|
+
################################################################################
|
|
73
|
+
|
|
74
|
+
import sage.modular.arithgroup.all as arithgroup
|
|
75
|
+
|
|
76
|
+
from sage.arith.misc import is_prime, divisors, number_of_divisors, crt
|
|
77
|
+
from sage.categories.homset import Hom
|
|
78
|
+
from sage.matrix.matrix_space import MatrixSpace
|
|
79
|
+
from sage.misc.cachefunc import cached_method
|
|
80
|
+
from sage.misc.latex import latex
|
|
81
|
+
from sage.misc.verbose import verbose
|
|
82
|
+
from sage.modular.arithgroup.arithgroup_element import M2Z
|
|
83
|
+
from sage.modular.dirichlet import DirichletCharacter, TrivialCharacter
|
|
84
|
+
from sage.modular.hecke.ambient_module import AmbientHeckeModule
|
|
85
|
+
from sage.modular.cusps import Cusp
|
|
86
|
+
from sage.modular.modsym.apply import apply_to_monomial
|
|
87
|
+
from sage.modular.modsym.manin_symbol import ManinSymbol
|
|
88
|
+
from sage.modular.modsym.manin_symbol_list import (ManinSymbolList_gamma0,
|
|
89
|
+
ManinSymbolList_gamma1,
|
|
90
|
+
ManinSymbolList_gamma_h,
|
|
91
|
+
ManinSymbolList_character)
|
|
92
|
+
from sage.modules.free_module import FreeModule_generic
|
|
93
|
+
from sage.modules.free_module_element import FreeModuleElement
|
|
94
|
+
from sage.rings.integer import Integer
|
|
95
|
+
from sage.rings.integer_ring import ZZ
|
|
96
|
+
from sage.rings.polynomial.multi_polynomial import MPolynomial
|
|
97
|
+
from sage.rings.rational_field import QQ
|
|
98
|
+
from sage.categories.fields import Fields
|
|
99
|
+
from sage.structure.factorization import Factorization
|
|
100
|
+
from sage.structure.formal_sum import FormalSum
|
|
101
|
+
|
|
102
|
+
from . import boundary
|
|
103
|
+
from . import element
|
|
104
|
+
from . import heilbronn
|
|
105
|
+
from . import modular_symbols
|
|
106
|
+
from . import modsym
|
|
107
|
+
from . import p1list
|
|
108
|
+
from . import relation_matrix
|
|
109
|
+
from .space import ModularSymbolsSpace
|
|
110
|
+
from . import subspace
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ModularSymbolsAmbient(ModularSymbolsSpace, AmbientHeckeModule):
|
|
114
|
+
r"""
|
|
115
|
+
An ambient space of modular symbols for a congruence subgroup of
|
|
116
|
+
`SL_2(\ZZ)`.
|
|
117
|
+
|
|
118
|
+
This class is an abstract base class, so only derived classes
|
|
119
|
+
should be instantiated.
|
|
120
|
+
|
|
121
|
+
INPUT:
|
|
122
|
+
|
|
123
|
+
- ``weight`` -- integer
|
|
124
|
+
- ``group`` -- a congruence subgroup
|
|
125
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
126
|
+
- ``base_ring`` -- a commutative ring
|
|
127
|
+
- ``custom_init`` -- a function that is called with ``self`` as input
|
|
128
|
+
before any computations are done using self; this could be used
|
|
129
|
+
to set a custom modular symbols presentation
|
|
130
|
+
|
|
131
|
+
TESTS::
|
|
132
|
+
|
|
133
|
+
sage: ModularSymbols(11,2) == ModularSymbols(11,2)
|
|
134
|
+
True
|
|
135
|
+
sage: ModularSymbols(11,2) == ModularSymbols(11,4)
|
|
136
|
+
False
|
|
137
|
+
sage: ModularSymbols(11,2) != ModularSymbols(11,2)
|
|
138
|
+
False
|
|
139
|
+
sage: ModularSymbols(11,2) != ModularSymbols(11,4)
|
|
140
|
+
True
|
|
141
|
+
sage: hash(ModularSymbols(11,2)) != hash(ModularSymbols(11,4))
|
|
142
|
+
True
|
|
143
|
+
"""
|
|
144
|
+
def __init__(self, group, weight, sign, base_ring,
|
|
145
|
+
character=None, custom_init=None, category=None):
|
|
146
|
+
"""
|
|
147
|
+
Initialize a space of modular symbols.
|
|
148
|
+
|
|
149
|
+
INPUT:
|
|
150
|
+
|
|
151
|
+
- ``weight`` -- integer
|
|
152
|
+
|
|
153
|
+
- ``group`` -- a congruence subgroup
|
|
154
|
+
|
|
155
|
+
- ``sign`` -- integer, either -1, 0, or 1
|
|
156
|
+
|
|
157
|
+
- ``base_ring`` -- a commutative ring
|
|
158
|
+
|
|
159
|
+
EXAMPLES::
|
|
160
|
+
|
|
161
|
+
sage: ModularSymbols(2,2)
|
|
162
|
+
Modular Symbols space of dimension 1 for Gamma_0(2) of weight 2 with sign 0 over Rational Field
|
|
163
|
+
"""
|
|
164
|
+
weight = int(weight)
|
|
165
|
+
if weight <= 1:
|
|
166
|
+
raise ValueError("Weight (=%s) Modular symbols of weight <= 1 not defined." % weight)
|
|
167
|
+
if not isinstance(group, arithgroup.CongruenceSubgroupBase):
|
|
168
|
+
raise TypeError("group must be a congruence subgroup")
|
|
169
|
+
|
|
170
|
+
sign = int(sign)
|
|
171
|
+
if base_ring not in Fields():
|
|
172
|
+
raise TypeError("base_ring must be a field")
|
|
173
|
+
|
|
174
|
+
if character is None and isinstance(group, arithgroup.Gamma0_class):
|
|
175
|
+
character = TrivialCharacter(group.level(), base_ring)
|
|
176
|
+
|
|
177
|
+
ModularSymbolsSpace.__init__(self, group, weight,
|
|
178
|
+
character, sign, base_ring,
|
|
179
|
+
category=category)
|
|
180
|
+
|
|
181
|
+
if custom_init is not None:
|
|
182
|
+
custom_init(self)
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
formula = self._dimension_formula()
|
|
186
|
+
except NotImplementedError:
|
|
187
|
+
formula = None
|
|
188
|
+
|
|
189
|
+
rank = self.rank()
|
|
190
|
+
if formula is not None:
|
|
191
|
+
assert rank == formula, \
|
|
192
|
+
"Computed dimension (=%s) of ambient space \"%s\" doesn't match dimension formula (=%s)!\n" % (rank, self, formula) + \
|
|
193
|
+
"ModularSymbolsAmbient: group = %s, weight = %s, sign = %s, base_ring = %s, character = %s" % (
|
|
194
|
+
group, weight, sign, base_ring, character)
|
|
195
|
+
|
|
196
|
+
AmbientHeckeModule.__init__(self, base_ring, rank, group.level(), weight, category=category)
|
|
197
|
+
|
|
198
|
+
def new_submodule(self, p=None):
|
|
199
|
+
r"""
|
|
200
|
+
Return the new or `p`-new submodule of this modular symbols ambient space.
|
|
201
|
+
|
|
202
|
+
INPUT:
|
|
203
|
+
|
|
204
|
+
- ``p`` -- (default: ``None``) if not ``None``, return only
|
|
205
|
+
the `p`-new submodule
|
|
206
|
+
|
|
207
|
+
OUTPUT: the new or `p`-new submodule of this modular symbols ambient space
|
|
208
|
+
|
|
209
|
+
EXAMPLES::
|
|
210
|
+
|
|
211
|
+
sage: ModularSymbols(100).new_submodule()
|
|
212
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 31 for Gamma_0(100) of weight 2 with sign 0 over Rational Field
|
|
213
|
+
sage: ModularSymbols(389).new_submodule()
|
|
214
|
+
Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field
|
|
215
|
+
"""
|
|
216
|
+
# Check for special cases where the answer is easy.
|
|
217
|
+
# If not in one of those cases, use the generic code.
|
|
218
|
+
if self.level().is_prime() and self.weight() == 2:
|
|
219
|
+
return self
|
|
220
|
+
return AmbientHeckeModule.new_submodule(self, p=p)
|
|
221
|
+
|
|
222
|
+
def manin_symbols(self):
|
|
223
|
+
"""
|
|
224
|
+
Return the list of Manin symbols for this modular symbols ambient space.
|
|
225
|
+
|
|
226
|
+
EXAMPLES::
|
|
227
|
+
|
|
228
|
+
sage: ModularSymbols(11,2).manin_symbols()
|
|
229
|
+
Manin Symbol List of weight 2 for Gamma0(11)
|
|
230
|
+
"""
|
|
231
|
+
raise NotImplementedError
|
|
232
|
+
|
|
233
|
+
def manin_generators(self):
|
|
234
|
+
"""
|
|
235
|
+
Return list of all Manin symbols for this space. These are the
|
|
236
|
+
generators in the presentation of this space by Manin symbols.
|
|
237
|
+
|
|
238
|
+
EXAMPLES::
|
|
239
|
+
|
|
240
|
+
sage: M = ModularSymbols(2,2)
|
|
241
|
+
sage: M.manin_generators()
|
|
242
|
+
[(0,1), (1,0), (1,1)]
|
|
243
|
+
|
|
244
|
+
::
|
|
245
|
+
|
|
246
|
+
sage: M = ModularSymbols(1,6)
|
|
247
|
+
sage: M.manin_generators()
|
|
248
|
+
[[Y^4,(0,0)], [X*Y^3,(0,0)], [X^2*Y^2,(0,0)], [X^3*Y,(0,0)], [X^4,(0,0)]]
|
|
249
|
+
"""
|
|
250
|
+
return self._manin_generators
|
|
251
|
+
|
|
252
|
+
def manin_basis(self):
|
|
253
|
+
r"""
|
|
254
|
+
Return a list of indices into the list of Manin generators (see
|
|
255
|
+
``self.manin_generators()``) such that those symbols
|
|
256
|
+
form a basis for the quotient of the `\QQ`-vector
|
|
257
|
+
space spanned by Manin symbols modulo the relations.
|
|
258
|
+
|
|
259
|
+
EXAMPLES::
|
|
260
|
+
|
|
261
|
+
sage: M = ModularSymbols(2,2)
|
|
262
|
+
sage: M.manin_basis()
|
|
263
|
+
[1]
|
|
264
|
+
sage: [M.manin_generators()[i] for i in M.manin_basis()]
|
|
265
|
+
[(1,0)]
|
|
266
|
+
sage: M = ModularSymbols(6,2)
|
|
267
|
+
sage: M.manin_basis()
|
|
268
|
+
[1, 10, 11]
|
|
269
|
+
sage: [M.manin_generators()[i] for i in M.manin_basis()]
|
|
270
|
+
[(1,0), (3,1), (3,2)]
|
|
271
|
+
"""
|
|
272
|
+
try:
|
|
273
|
+
return self._manin_basis
|
|
274
|
+
except AttributeError:
|
|
275
|
+
self.compute_presentation()
|
|
276
|
+
return self._manin_basis
|
|
277
|
+
|
|
278
|
+
def p1list(self):
|
|
279
|
+
"""
|
|
280
|
+
Return a P1list of the level of this modular symbol space.
|
|
281
|
+
|
|
282
|
+
EXAMPLES::
|
|
283
|
+
|
|
284
|
+
sage: ModularSymbols(11,2).p1list()
|
|
285
|
+
The projective line over the integers modulo 11
|
|
286
|
+
"""
|
|
287
|
+
try:
|
|
288
|
+
return self.__p1list
|
|
289
|
+
except AttributeError:
|
|
290
|
+
self.__p1list = p1list.P1List(self.level())
|
|
291
|
+
return self.__p1list
|
|
292
|
+
|
|
293
|
+
# See the file relation_matrix.py
|
|
294
|
+
#
|
|
295
|
+
# def relation_matrix(self):
|
|
296
|
+
# raise NotImplementedError
|
|
297
|
+
|
|
298
|
+
def compute_presentation(self):
|
|
299
|
+
r"""
|
|
300
|
+
Compute and cache the presentation of this space.
|
|
301
|
+
|
|
302
|
+
EXAMPLES::
|
|
303
|
+
|
|
304
|
+
sage: ModularSymbols(11,2).compute_presentation() # no output
|
|
305
|
+
"""
|
|
306
|
+
B, basis, mod = relation_matrix.compute_presentation(
|
|
307
|
+
self.manin_symbols(), self.sign(),
|
|
308
|
+
self.base_ring())
|
|
309
|
+
self._manin_generators = self.manin_symbols().manin_symbol_list()
|
|
310
|
+
self._manin_basis = basis
|
|
311
|
+
self._manin_gens_to_basis = B
|
|
312
|
+
self._mod2term = mod
|
|
313
|
+
|
|
314
|
+
def manin_gens_to_basis(self):
|
|
315
|
+
r"""
|
|
316
|
+
Return the matrix expressing the manin symbol generators in terms of the basis.
|
|
317
|
+
|
|
318
|
+
EXAMPLES::
|
|
319
|
+
|
|
320
|
+
sage: ModularSymbols(11,2).manin_gens_to_basis()
|
|
321
|
+
[-1 0 0]
|
|
322
|
+
[ 1 0 0]
|
|
323
|
+
[ 0 0 0]
|
|
324
|
+
[ 0 0 1]
|
|
325
|
+
[ 0 -1 1]
|
|
326
|
+
[ 0 -1 0]
|
|
327
|
+
[ 0 0 -1]
|
|
328
|
+
[ 0 0 -1]
|
|
329
|
+
[ 0 1 -1]
|
|
330
|
+
[ 0 1 0]
|
|
331
|
+
[ 0 0 1]
|
|
332
|
+
[ 0 0 0]
|
|
333
|
+
"""
|
|
334
|
+
try:
|
|
335
|
+
return self._manin_gens_to_basis
|
|
336
|
+
except AttributeError:
|
|
337
|
+
self.compute_presentation()
|
|
338
|
+
return self._manin_gens_to_basis
|
|
339
|
+
|
|
340
|
+
#####################################################################
|
|
341
|
+
# Coercion
|
|
342
|
+
#####################################################################
|
|
343
|
+
def _element_constructor_(self, x, computed_with_hecke=False):
|
|
344
|
+
r"""
|
|
345
|
+
Coerce `x` into this modular symbols space. The result is
|
|
346
|
+
either an element of ``self`` or a subspace of ``self``.
|
|
347
|
+
|
|
348
|
+
INPUT:
|
|
349
|
+
|
|
350
|
+
The allowed input types for `x` are as follows:
|
|
351
|
+
|
|
352
|
+
- ``Vector`` -- a vector of the same degree. This
|
|
353
|
+
defines the corresponding linear combination of the basis of ``self``
|
|
354
|
+
|
|
355
|
+
- ``ManinSymbol`` -- a Manin symbol of the same weight
|
|
356
|
+
as the space
|
|
357
|
+
|
|
358
|
+
- ``ModularSymbolsElement`` -- a modular symbol whose
|
|
359
|
+
ambient parent is this space of modular symbols. (TODO: make more
|
|
360
|
+
sophisticated)
|
|
361
|
+
|
|
362
|
+
- 0 -- the integer 0; results in the 0 modular symbol
|
|
363
|
+
|
|
364
|
+
- 3-tuple -- given a 3-tuple (i,u,v), returns the modular symbol
|
|
365
|
+
element defined by the Manin symbol
|
|
366
|
+
`[X^{i}\cdot Y^{k-2-i}, (u,v)]`, where k is the weight.
|
|
367
|
+
Note that we must have `0\leq i \leq k-2`.
|
|
368
|
+
|
|
369
|
+
- 2-tuple -- given a 2-tuple (u,v), returns the element defined by
|
|
370
|
+
the Manin symbol `[X^0 \cdot Y^{2-k}, (u,v)]`
|
|
371
|
+
|
|
372
|
+
- 2-elements list -- given a list ``[alpha, beta]``,
|
|
373
|
+
where `\alpha` and `\beta` are (coercible to)
|
|
374
|
+
cusps, return the modular symbol `\{\alpha, \beta\}`. When
|
|
375
|
+
the weight `k > 2` return
|
|
376
|
+
`Y^{k-2} \{\alpha, \beta\}`.
|
|
377
|
+
|
|
378
|
+
- 3-element list -- given a list ``[i, alpha, beta]``,
|
|
379
|
+
where `i` is an integer, and `\alpha`,
|
|
380
|
+
`\beta` are (coercible to) cusps, return the modular symbol
|
|
381
|
+
`X^i Y^{k-2-i} \{\alpha, \beta\}`.
|
|
382
|
+
|
|
383
|
+
If our list is ``[f, alpha, beta]``, where `f`
|
|
384
|
+
is a homogeneous polynomial in two variables of degree k-2 with
|
|
385
|
+
integer coefficients, and alpha and beta are cusps, return the
|
|
386
|
+
corresponding sum of modular symbols as an element of ``self``. So if
|
|
387
|
+
`f = \sum_{i=0}^{k-2} a_i X^i Y^{k-2-i}`, return
|
|
388
|
+
`\sum_{i=0}^{k-2} a_i * [ i, alpha, beta ]`.
|
|
389
|
+
|
|
390
|
+
EXAMPLES::
|
|
391
|
+
|
|
392
|
+
sage: M = ModularSymbols(37,2)
|
|
393
|
+
|
|
394
|
+
M(0) is the 0 element of the space::
|
|
395
|
+
|
|
396
|
+
sage: M(0)
|
|
397
|
+
0
|
|
398
|
+
sage: type(M(0))
|
|
399
|
+
<class 'sage.modular.modsym.ambient.ModularSymbolsAmbient_wt2_g0_with_category.element_class'>
|
|
400
|
+
|
|
401
|
+
From a vector of the correct dimension we construct the
|
|
402
|
+
corresponding linear combination of the basis elements::
|
|
403
|
+
|
|
404
|
+
sage: M.dimension()
|
|
405
|
+
5
|
|
406
|
+
sage: M.basis()
|
|
407
|
+
((1,0), (1,23), (1,32), (1,34), (1,35))
|
|
408
|
+
sage: M(vector([1,2,3,4,5]))
|
|
409
|
+
(1,0) + 2*(1,23) + 3*(1,32) + 4*(1,34) + 5*(1,35)
|
|
410
|
+
sage: M(vector([1/2,2/3,3/4,4/5,5/6]))
|
|
411
|
+
1/2*(1,0) + 2/3*(1,23) + 3/4*(1,32) + 4/5*(1,34) + 5/6*(1,35)
|
|
412
|
+
|
|
413
|
+
Manin symbols can be converted to elements of the space::
|
|
414
|
+
|
|
415
|
+
sage: S = M.manin_symbols()
|
|
416
|
+
sage: S((0,2,3))
|
|
417
|
+
(2,3)
|
|
418
|
+
sage: M( S((0,2,3)) )
|
|
419
|
+
(1,34) - (1,35)
|
|
420
|
+
|
|
421
|
+
However, it is easier to use one of the following forms.
|
|
422
|
+
Either a 3-tuple `(i,u,v)` or a 2-tuple `(u,v)` with `i=0`
|
|
423
|
+
assumed::
|
|
424
|
+
|
|
425
|
+
sage: M((0,2,3))
|
|
426
|
+
(1,34) - (1,35)
|
|
427
|
+
sage: M((2,3))
|
|
428
|
+
(1,34) - (1,35)
|
|
429
|
+
|
|
430
|
+
Or a 3-list `[i,\alpha,\beta]` where `i` is the degree and
|
|
431
|
+
`\alpha` and `beta` are cusps, or a 2-tuple `[\alpha,\beta]`
|
|
432
|
+
with `i=0` assumed::
|
|
433
|
+
|
|
434
|
+
sage: M([0,Cusp(1/2),Cusp(0)])
|
|
435
|
+
(1,35)
|
|
436
|
+
sage: M([Cusp(1/2),Cusp(0)])
|
|
437
|
+
(1,35)
|
|
438
|
+
"""
|
|
439
|
+
if isinstance(x, FreeModuleElement):
|
|
440
|
+
if x.degree() != self.dimension():
|
|
441
|
+
raise TypeError("Incompatible degrees: x has degree "
|
|
442
|
+
f"{x.degree()} but modular symbols space has "
|
|
443
|
+
f"dimension {self.dimension()}")
|
|
444
|
+
return self.element_class(self, x)
|
|
445
|
+
|
|
446
|
+
elif isinstance(x, (ManinSymbol, element.ModularSymbolsElement)):
|
|
447
|
+
return self.element(x)
|
|
448
|
+
|
|
449
|
+
elif isinstance(x, modular_symbols.ModularSymbol):
|
|
450
|
+
return self(x.manin_symbol_rep())
|
|
451
|
+
|
|
452
|
+
elif isinstance(x, (int, Integer)) and x == 0:
|
|
453
|
+
return self.element_class(self, self.free_module()(0))
|
|
454
|
+
|
|
455
|
+
elif isinstance(x, tuple):
|
|
456
|
+
return self.manin_symbol(x)
|
|
457
|
+
|
|
458
|
+
elif isinstance(x, FormalSum):
|
|
459
|
+
return sum([c * self(y) for c, y in x], self(0))
|
|
460
|
+
|
|
461
|
+
elif isinstance(x, list):
|
|
462
|
+
if len(x) == 3 and isinstance(x[0], MPolynomial):
|
|
463
|
+
return self.modular_symbol_sum(x)
|
|
464
|
+
else:
|
|
465
|
+
return self.modular_symbol(x)
|
|
466
|
+
|
|
467
|
+
raise TypeError("No coercion of %s into %s defined." % (x, self))
|
|
468
|
+
|
|
469
|
+
def change_ring(self, R):
|
|
470
|
+
r"""
|
|
471
|
+
Change the base ring to R.
|
|
472
|
+
|
|
473
|
+
EXAMPLES::
|
|
474
|
+
|
|
475
|
+
sage: ModularSymbols(Gamma1(13), 2).change_ring(GF(17))
|
|
476
|
+
Modular Symbols space of dimension 15 for Gamma_1(13) of weight 2 with sign 0 over Finite Field of size 17
|
|
477
|
+
sage: M = ModularSymbols(DirichletGroup(5).0, 7); MM=M.change_ring(CyclotomicField(8)); MM
|
|
478
|
+
Modular Symbols space of dimension 6 and level 5, weight 7, character [zeta8^2], sign 0, over Cyclotomic Field of order 8 and degree 4
|
|
479
|
+
sage: MM.change_ring(CyclotomicField(4)) == M
|
|
480
|
+
True
|
|
481
|
+
sage: M.change_ring(QQ)
|
|
482
|
+
Traceback (most recent call last):
|
|
483
|
+
...
|
|
484
|
+
TypeError: Unable to coerce zeta4 to a rational
|
|
485
|
+
|
|
486
|
+
Similarly with :meth:`base_extend`::
|
|
487
|
+
|
|
488
|
+
sage: M = ModularSymbols(DirichletGroup(5).0, 7); MM = M.base_extend(CyclotomicField(8)); MM
|
|
489
|
+
Modular Symbols space of dimension 6 and level 5, weight 7, character [zeta8^2], sign 0, over Cyclotomic Field of order 8 and degree 4
|
|
490
|
+
sage: MM.base_extend(CyclotomicField(4))
|
|
491
|
+
Traceback (most recent call last):
|
|
492
|
+
...
|
|
493
|
+
TypeError: Base extension of self (over 'Cyclotomic Field of order 8 and degree 4') to ring 'Cyclotomic Field of order 4 and degree 2' not defined.
|
|
494
|
+
"""
|
|
495
|
+
if self.character() is None:
|
|
496
|
+
return modsym.ModularSymbols(self.group(), self.weight(), self.sign(), R)
|
|
497
|
+
else:
|
|
498
|
+
return modsym.ModularSymbols(self.character(), self.weight(), self.sign(), R)
|
|
499
|
+
|
|
500
|
+
def _action_on_modular_symbols(self, g):
|
|
501
|
+
r"""
|
|
502
|
+
Return the matrix of the action of a 2x2 matrix on this space.
|
|
503
|
+
|
|
504
|
+
INPUT:
|
|
505
|
+
|
|
506
|
+
- ``g`` -- list; `g=[a,b,c,d]` where `a,b,c,d` are integers
|
|
507
|
+
defining a `2\times2` integer matrix
|
|
508
|
+
|
|
509
|
+
OUTPUT:
|
|
510
|
+
|
|
511
|
+
(matrix) The matrix of the action of `g` on this Modular
|
|
512
|
+
Symbol space, with respect to the standard basis.
|
|
513
|
+
|
|
514
|
+
.. NOTE::
|
|
515
|
+
|
|
516
|
+
Use ``_matrix_of_operator_on_modular_symbols`` for more general
|
|
517
|
+
operators.
|
|
518
|
+
|
|
519
|
+
EXAMPLES::
|
|
520
|
+
|
|
521
|
+
sage: M = ModularSymbols(11,4,1)
|
|
522
|
+
sage: M._action_on_modular_symbols([1,2,3,7])
|
|
523
|
+
[0 0 1 0]
|
|
524
|
+
[0 0 0 1]
|
|
525
|
+
[0 1 0 0]
|
|
526
|
+
[0 1 0 0]
|
|
527
|
+
"""
|
|
528
|
+
if not isinstance(g, list):
|
|
529
|
+
raise TypeError("g must be a list")
|
|
530
|
+
if not len(g) == 4:
|
|
531
|
+
raise TypeError("g must be a list of length 4")
|
|
532
|
+
return self._matrix_of_operator_on_modular_symbols(self, [g])
|
|
533
|
+
|
|
534
|
+
def manin_symbol(self, x, check=True):
|
|
535
|
+
r"""
|
|
536
|
+
Construct a Manin Symbol from the given data.
|
|
537
|
+
|
|
538
|
+
INPUT:
|
|
539
|
+
|
|
540
|
+
- ``x`` -- list; either `[u,v]` or `[i,u,v]`, where `0\le
|
|
541
|
+
i\le k-2` where `k` is the weight, and `u`,`v` are integers
|
|
542
|
+
defining a valid element of `\mathbb{P}^1(N)`, where `N` is
|
|
543
|
+
the level
|
|
544
|
+
|
|
545
|
+
OUTPUT:
|
|
546
|
+
|
|
547
|
+
(ManinSymbol) the Manin Symbol associated to `[i;(u,v)]`, with
|
|
548
|
+
`i=0` if not supplied, corresponding to the monomial symbol
|
|
549
|
+
`[X^i*Y^{k-2-i}, (u,v)]`.
|
|
550
|
+
|
|
551
|
+
EXAMPLES::
|
|
552
|
+
|
|
553
|
+
sage: M = ModularSymbols(11,4,1)
|
|
554
|
+
sage: M.manin_symbol([2,5,6])
|
|
555
|
+
-2/3*[X^2,(1,6)] + 5/3*[X^2,(1,9)]
|
|
556
|
+
"""
|
|
557
|
+
if check:
|
|
558
|
+
if len(x) == 2:
|
|
559
|
+
x = (0, x[0], x[1])
|
|
560
|
+
if len(x) == 3:
|
|
561
|
+
# Manin symbol of the form (i, u, v), which corresponds to [X^i*Y^(k-2-i), (u,v)].
|
|
562
|
+
if x[0] < 0 or x[0] > self.weight() - 2:
|
|
563
|
+
raise ValueError("The first entry of the tuple (=%s)\
|
|
564
|
+
must be an integer between 0 and k-2 (=%s)." % (
|
|
565
|
+
x, self.weight() - 2))
|
|
566
|
+
else:
|
|
567
|
+
raise ValueError("x (=%s) must be of length 2 or 3" % x)
|
|
568
|
+
# end check
|
|
569
|
+
|
|
570
|
+
N = self.level()
|
|
571
|
+
x = (x[0], x[1] % N, x[2] % N)
|
|
572
|
+
try:
|
|
573
|
+
return self.__manin_symbol[x]
|
|
574
|
+
except AttributeError:
|
|
575
|
+
self.__manin_symbol = {}
|
|
576
|
+
except KeyError:
|
|
577
|
+
pass
|
|
578
|
+
y = self.manin_symbols()(x)
|
|
579
|
+
z = self(y)
|
|
580
|
+
self.__manin_symbol[x] = z
|
|
581
|
+
return z
|
|
582
|
+
|
|
583
|
+
def _modular_symbol_0_to_alpha(self, alpha, i=0):
|
|
584
|
+
r"""
|
|
585
|
+
Return the modular symbol `\{0,\alpha\}` in this space.
|
|
586
|
+
|
|
587
|
+
INPUT:
|
|
588
|
+
|
|
589
|
+
- ``alpha`` -- rational or Infinity a cusp
|
|
590
|
+
|
|
591
|
+
- ``i`` -- integer (default: 0); the degree of the symbol
|
|
592
|
+
|
|
593
|
+
OUTPUT:
|
|
594
|
+
|
|
595
|
+
(ModularSymbol) The modular symbol `X^iY^{k-2-i}\{0,\alpha\}`.
|
|
596
|
+
|
|
597
|
+
EXAMPLES::
|
|
598
|
+
|
|
599
|
+
sage: M = ModularSymbols(11,4,1)
|
|
600
|
+
sage: M._modular_symbol_0_to_alpha(Cusp(3/5))
|
|
601
|
+
11*[X^2,(1,4)] + 40/3*[X^2,(1,6)] - 1/3*[X^2,(1,9)]
|
|
602
|
+
sage: M._modular_symbol_0_to_alpha(Cusp(3/5),1)
|
|
603
|
+
15/2*[X^2,(1,4)] + 20/3*[X^2,(1,6)] + 5/6*[X^2,(1,9)]
|
|
604
|
+
sage: M._modular_symbol_0_to_alpha(Cusp(Infinity))
|
|
605
|
+
2/3*[X^2,(1,6)] - 5/3*[X^2,(1,9)]
|
|
606
|
+
sage: M._modular_symbol_0_to_alpha(Cusp(Infinity),1)
|
|
607
|
+
0
|
|
608
|
+
"""
|
|
609
|
+
if alpha.is_infinity():
|
|
610
|
+
return self.manin_symbol((i, 0, 1), check=False)
|
|
611
|
+
# v, c = arith.continued_fraction_list(alpha._rational_(), partial_convergents=True)
|
|
612
|
+
cf = alpha._rational_().continued_fraction()
|
|
613
|
+
v = list(cf)
|
|
614
|
+
c = [(cf.p(k), cf.q(k)) for k in range(len(cf))]
|
|
615
|
+
a = self(0)
|
|
616
|
+
one = ZZ.one()
|
|
617
|
+
two = ZZ(2)
|
|
618
|
+
if self.weight() > two:
|
|
619
|
+
R = ZZ['X']
|
|
620
|
+
X = R.gen(0)
|
|
621
|
+
# need to add first two terms, which aren't necessarily
|
|
622
|
+
# zero in this case. we do the first here, and the
|
|
623
|
+
# second in the k=0 case below, so as to avoid code
|
|
624
|
+
# duplication
|
|
625
|
+
a += self.manin_symbol((i, 0, 1), check=False)
|
|
626
|
+
for k in range(len(c)):
|
|
627
|
+
# matrix entries associated to this partial sum
|
|
628
|
+
if k == 0:
|
|
629
|
+
x = c[0][0]
|
|
630
|
+
y = -1
|
|
631
|
+
z = 1
|
|
632
|
+
w = 0
|
|
633
|
+
else:
|
|
634
|
+
x = c[k][0]
|
|
635
|
+
y = c[k-1][0]
|
|
636
|
+
z = c[k][1]
|
|
637
|
+
w = c[k-1][1]
|
|
638
|
+
if k % 2 == 0:
|
|
639
|
+
y = -y
|
|
640
|
+
w = -w
|
|
641
|
+
|
|
642
|
+
# two options here: write out the polynomial directly,
|
|
643
|
+
# and deal with all the separate cases, or create two
|
|
644
|
+
# polynomials and then exponentiate and multiply them.
|
|
645
|
+
# given how fast ntl/flint/etc are, the second may
|
|
646
|
+
# be faster.
|
|
647
|
+
|
|
648
|
+
# method 1: write out solution. this is currently
|
|
649
|
+
# incorrect, because it ends up doing 0^0 in the sum,
|
|
650
|
+
# so I'll fix it and do timings soon.
|
|
651
|
+
# for s in range(self.weight()-two+1):
|
|
652
|
+
# coeff = sum([ binomial(i,t)*binomial(self.weight()-two-i,s-t)*
|
|
653
|
+
# x**t * y**(i-t) * z**(s-t) *
|
|
654
|
+
# w**(self.weight()-two-i-s+t) for t in range(0,s) ])
|
|
655
|
+
# m = coeff * self.manin_symbol((s, y, w), check=False)
|
|
656
|
+
# a += m
|
|
657
|
+
|
|
658
|
+
# method 2
|
|
659
|
+
p1 = x*X+y
|
|
660
|
+
p2 = z*X+w
|
|
661
|
+
if i == 0:
|
|
662
|
+
p1 = R(one)
|
|
663
|
+
if (self.weight()-2-i == 0):
|
|
664
|
+
p2 = R(one)
|
|
665
|
+
poly = (p1**i) * (p2**(self.weight()-2-i))
|
|
666
|
+
for s in range(self.weight()-1): # k-2+1 = k-1
|
|
667
|
+
a += poly[s] * self.manin_symbol((s, z, w), check=False)
|
|
668
|
+
else:
|
|
669
|
+
for k in range(1, len(c)):
|
|
670
|
+
u = c[k][1]
|
|
671
|
+
v = c[k-1][1]
|
|
672
|
+
if k % 2 == 0:
|
|
673
|
+
v = -v
|
|
674
|
+
x = self.manin_symbol((i, u, v), check=False)
|
|
675
|
+
a += x
|
|
676
|
+
return a
|
|
677
|
+
|
|
678
|
+
def modular_symbol(self, x, check=True):
|
|
679
|
+
r"""
|
|
680
|
+
Create a modular symbol in this space.
|
|
681
|
+
|
|
682
|
+
INPUT:
|
|
683
|
+
|
|
684
|
+
- ``x`` -- list of either 2 or 3 entries:
|
|
685
|
+
|
|
686
|
+
- 2 entries: `[\alpha, \beta]` where `\alpha` and `\beta`
|
|
687
|
+
are cusps;
|
|
688
|
+
|
|
689
|
+
- 3 entries: `[i, \alpha, \beta]` where `0\le i\le k-2`
|
|
690
|
+
and `\alpha` and `\beta` are cusps;
|
|
691
|
+
|
|
692
|
+
- ``check`` -- boolean (default: ``True``); flag that determines
|
|
693
|
+
whether the input ``x`` needs processing: use check=False
|
|
694
|
+
for efficiency if the input ``x`` is a list of length 3 whose
|
|
695
|
+
first entry is an Integer, and whose second and third
|
|
696
|
+
entries are Cusps (see examples).
|
|
697
|
+
|
|
698
|
+
OUTPUT:
|
|
699
|
+
|
|
700
|
+
(Modular Symbol) The modular symbol `Y^{k-2}\{\alpha,
|
|
701
|
+
\beta\}`. or `X^i Y^{k-2-i}\{\alpha,\beta\}`.
|
|
702
|
+
|
|
703
|
+
EXAMPLES::
|
|
704
|
+
|
|
705
|
+
sage: set_modsym_print_mode('modular')
|
|
706
|
+
sage: M = ModularSymbols(11)
|
|
707
|
+
sage: M.modular_symbol([2/11, oo])
|
|
708
|
+
-{-1/9, 0}
|
|
709
|
+
sage: M.1
|
|
710
|
+
{-1/8, 0}
|
|
711
|
+
sage: M.modular_symbol([-1/8, 0])
|
|
712
|
+
{-1/8, 0}
|
|
713
|
+
sage: M.modular_symbol([0, -1/8, 0])
|
|
714
|
+
{-1/8, 0}
|
|
715
|
+
sage: M.modular_symbol([10, -1/8, 0])
|
|
716
|
+
Traceback (most recent call last):
|
|
717
|
+
...
|
|
718
|
+
ValueError: The first entry of the tuple (=[10, -1/8, 0]) must be an integer between 0 and k-2 (=0).
|
|
719
|
+
|
|
720
|
+
::
|
|
721
|
+
|
|
722
|
+
sage: N = ModularSymbols(6,4)
|
|
723
|
+
sage: set_modsym_print_mode('manin')
|
|
724
|
+
sage: N([1,Cusp(-1/4),Cusp(0)])
|
|
725
|
+
17/2*[X^2,(2,3)] - 9/2*[X^2,(2,5)] + 15/2*[X^2,(3,1)] - 15/2*[X^2,(3,2)]
|
|
726
|
+
sage: N([1,Cusp(-1/2),Cusp(0)])
|
|
727
|
+
1/2*[X^2,(2,3)] + 3/2*[X^2,(2,5)] + 3/2*[X^2,(3,1)] - 3/2*[X^2,(3,2)]
|
|
728
|
+
|
|
729
|
+
Use check=False for efficiency if the input x is a list of length 3
|
|
730
|
+
whose first entry is an Integer, and whose second and third entries
|
|
731
|
+
are cusps::
|
|
732
|
+
|
|
733
|
+
sage: M.modular_symbol([0, Cusp(2/11), Cusp(oo)], check=False)
|
|
734
|
+
-(1,9)
|
|
735
|
+
|
|
736
|
+
::
|
|
737
|
+
|
|
738
|
+
sage: set_modsym_print_mode() # return to default.
|
|
739
|
+
"""
|
|
740
|
+
if check:
|
|
741
|
+
if len(x) == 2:
|
|
742
|
+
x = [0, x[0], x[1]]
|
|
743
|
+
elif len(x) == 3:
|
|
744
|
+
if x[0] < 0 or x[0] > self.weight()-2:
|
|
745
|
+
raise ValueError("The first entry of the tuple (=%s)\
|
|
746
|
+
must be an integer between 0 and k-2 (=%s)." % (
|
|
747
|
+
x, self.weight()-2))
|
|
748
|
+
else:
|
|
749
|
+
raise ValueError("x (=%s) must be of length 2 or 3" % x)
|
|
750
|
+
i = Integer(x[0])
|
|
751
|
+
alpha = Cusp(x[1])
|
|
752
|
+
beta = Cusp(x[2])
|
|
753
|
+
else:
|
|
754
|
+
i = x[0]
|
|
755
|
+
alpha = x[1]
|
|
756
|
+
beta = x[2]
|
|
757
|
+
|
|
758
|
+
# Compute {0,beta} - {0,alpha}
|
|
759
|
+
a = self._modular_symbol_0_to_alpha(alpha, i)
|
|
760
|
+
b = self._modular_symbol_0_to_alpha(beta, i)
|
|
761
|
+
return b - a
|
|
762
|
+
|
|
763
|
+
def modular_symbol_sum(self, x, check=True):
|
|
764
|
+
r"""
|
|
765
|
+
Construct a modular symbol sum.
|
|
766
|
+
|
|
767
|
+
INPUT:
|
|
768
|
+
|
|
769
|
+
- ``x`` -- list; `[f, \alpha, \beta]` where `f =
|
|
770
|
+
\sum_{i=0}^{k-2} a_i X^i Y^{k-2-i}` is a homogeneous
|
|
771
|
+
polynomial over `\ZZ` of degree `k` and `\alpha` and `\beta`
|
|
772
|
+
are cusps.
|
|
773
|
+
|
|
774
|
+
- ``check`` -- boolean (default: ``True``); if ``True`` check the
|
|
775
|
+
validity of the input tuple ``x``
|
|
776
|
+
|
|
777
|
+
OUTPUT:
|
|
778
|
+
|
|
779
|
+
The sum `\sum_{i=0}^{k-2} a_i [ i, \alpha, \beta ]` as an
|
|
780
|
+
element of this modular symbol space.
|
|
781
|
+
|
|
782
|
+
EXAMPLES::
|
|
783
|
+
|
|
784
|
+
sage: M = ModularSymbols(11,4)
|
|
785
|
+
sage: R.<X,Y>=QQ[]
|
|
786
|
+
sage: M.modular_symbol_sum([X*Y,Cusp(0),Cusp(Infinity)])
|
|
787
|
+
-3/14*[X^2,(1,6)] + 1/14*[X^2,(1,7)] - 1/14*[X^2,(1,8)] + 1/2*[X^2,(1,9)] - 2/7*[X^2,(1,10)]
|
|
788
|
+
"""
|
|
789
|
+
if check:
|
|
790
|
+
if len(x) != 3:
|
|
791
|
+
raise ValueError("%s must have length 3" % x)
|
|
792
|
+
f = x[0]
|
|
793
|
+
R = self.base_ring()['X', 'Y']
|
|
794
|
+
X = R.gen(0)
|
|
795
|
+
try:
|
|
796
|
+
f = R(f)
|
|
797
|
+
except TypeError:
|
|
798
|
+
raise ValueError("f must be coercible to a polynomial \
|
|
799
|
+
over %s" % self.base_ring())
|
|
800
|
+
if (not f.is_homogeneous()) or (f.degree() != self.weight()-2):
|
|
801
|
+
raise ValueError("f must be a homogeneous polynomial of degree k-2")
|
|
802
|
+
alpha = Cusp(x[1])
|
|
803
|
+
beta = Cusp(x[2])
|
|
804
|
+
else:
|
|
805
|
+
f = x[0]
|
|
806
|
+
R = self.base_ring()
|
|
807
|
+
X = R.gen(0)
|
|
808
|
+
alpha = x[1]
|
|
809
|
+
beta = x[2]
|
|
810
|
+
|
|
811
|
+
s = self(0)
|
|
812
|
+
|
|
813
|
+
for term in f.monomials():
|
|
814
|
+
deg = term.degree(X)
|
|
815
|
+
a = self._modular_symbol_0_to_alpha(alpha, deg)
|
|
816
|
+
b = self._modular_symbol_0_to_alpha(beta, deg)
|
|
817
|
+
s += f.monomial_coefficient(term) * (b - a)
|
|
818
|
+
|
|
819
|
+
return s
|
|
820
|
+
|
|
821
|
+
def _compute_dual_hecke_matrix(self, n):
|
|
822
|
+
r"""
|
|
823
|
+
Return the matrix of the dual Hecke operator `T(n)`.
|
|
824
|
+
|
|
825
|
+
INPUT:
|
|
826
|
+
|
|
827
|
+
- ``n`` -- positive integer
|
|
828
|
+
|
|
829
|
+
OUTPUT:
|
|
830
|
+
|
|
831
|
+
(matrix) The matrix of the dual of `T(n)`.
|
|
832
|
+
|
|
833
|
+
EXAMPLES::
|
|
834
|
+
|
|
835
|
+
sage: M = ModularSymbols(11,4,1)
|
|
836
|
+
sage: M._compute_dual_hecke_matrix(5)
|
|
837
|
+
[ 126 0 0 0]
|
|
838
|
+
[ 2 63 62 38]
|
|
839
|
+
[ 26/3 -20 -27 -4]
|
|
840
|
+
[-32/3 83 91 92]
|
|
841
|
+
"""
|
|
842
|
+
return self.hecke_matrix(n).transpose()
|
|
843
|
+
|
|
844
|
+
def _compute_hecke_matrix_prime(self, p, rows=None):
|
|
845
|
+
"""
|
|
846
|
+
Return the matrix of the Hecke operator `T(p)`.
|
|
847
|
+
|
|
848
|
+
INPUT:
|
|
849
|
+
|
|
850
|
+
- ``p`` -- integer; a prime number
|
|
851
|
+
|
|
852
|
+
- ``rows`` -- list or ``None`` (default); if not ``None``, a list of
|
|
853
|
+
the rows which should be computed, otherwise the complete
|
|
854
|
+
matrix will be computed
|
|
855
|
+
|
|
856
|
+
.. NOTE::
|
|
857
|
+
|
|
858
|
+
`p` does not have to be prime despite the function name.
|
|
859
|
+
|
|
860
|
+
OUTPUT:
|
|
861
|
+
|
|
862
|
+
(matrix) The matrix of the Hecke operator `T(p)` on this
|
|
863
|
+
space, with respect to its standard basis.
|
|
864
|
+
|
|
865
|
+
ALGORITHM:
|
|
866
|
+
|
|
867
|
+
Use Heilbronn-Cremona matrices if `p` is prime, else use
|
|
868
|
+
Heilbronn-Merel matrices.
|
|
869
|
+
|
|
870
|
+
EXAMPLES:
|
|
871
|
+
|
|
872
|
+
We first compute some examples for Gamma0(N)::
|
|
873
|
+
|
|
874
|
+
sage: m = ModularSymbols(2, weight=4)
|
|
875
|
+
sage: m._compute_hecke_matrix_prime(2).charpoly('x')
|
|
876
|
+
x^2 - 9*x + 8
|
|
877
|
+
|
|
878
|
+
::
|
|
879
|
+
|
|
880
|
+
sage: m = ModularSymbols(1,weight=12)
|
|
881
|
+
sage: m._compute_hecke_matrix_prime(2).charpoly('x')
|
|
882
|
+
x^3 - 2001*x^2 - 97776*x - 1180224
|
|
883
|
+
sage: m._compute_hecke_matrix_prime(13).charpoly('x')
|
|
884
|
+
x^3 - 1792159238562*x^2 - 2070797989680255444*x - 598189440899986203208472
|
|
885
|
+
|
|
886
|
+
::
|
|
887
|
+
|
|
888
|
+
sage: m = ModularSymbols(1,weight=12, sign=-1)
|
|
889
|
+
sage: m._compute_hecke_matrix_prime(5)
|
|
890
|
+
[4830]
|
|
891
|
+
sage: m._compute_hecke_matrix_prime(23)
|
|
892
|
+
[18643272]
|
|
893
|
+
|
|
894
|
+
::
|
|
895
|
+
|
|
896
|
+
sage: m = ModularSymbols(3,4)
|
|
897
|
+
sage: m._compute_hecke_matrix_prime(2).charpoly('x')
|
|
898
|
+
x^2 - 18*x + 81
|
|
899
|
+
|
|
900
|
+
::
|
|
901
|
+
|
|
902
|
+
sage: m = ModularSymbols(6,4)
|
|
903
|
+
sage: m._compute_hecke_matrix_prime(2).charpoly('x')
|
|
904
|
+
x^6 - 14*x^5 + 29*x^4 + 172*x^3 - 124*x^2 - 320*x + 256
|
|
905
|
+
sage: m._compute_hecke_matrix_prime(3).charpoly('x')
|
|
906
|
+
x^6 - 50*x^5 + 511*x^4 + 3012*x^3 - 801*x^2 - 9234*x + 6561
|
|
907
|
+
|
|
908
|
+
::
|
|
909
|
+
|
|
910
|
+
sage: m = ModularSymbols(15,4, sign=-1)
|
|
911
|
+
sage: m._compute_hecke_matrix_prime(3).charpoly('x')
|
|
912
|
+
x^4 - 2*x^3 + 18*x^2 + 18*x - 243
|
|
913
|
+
|
|
914
|
+
::
|
|
915
|
+
|
|
916
|
+
sage: m = ModularSymbols(6,4)
|
|
917
|
+
sage: m._compute_hecke_matrix_prime(7).charpoly('x')
|
|
918
|
+
x^6 - 1344*x^5 + 666240*x^4 - 140462080*x^3 + 8974602240*x^2 + 406424518656*x + 3584872677376
|
|
919
|
+
|
|
920
|
+
::
|
|
921
|
+
|
|
922
|
+
sage: m = ModularSymbols(4,4)
|
|
923
|
+
sage: m._compute_hecke_matrix_prime(3).charpoly('x')
|
|
924
|
+
x^3 - 84*x^2 + 2352*x - 21952
|
|
925
|
+
|
|
926
|
+
We now compute some examples for modular symbols on Gamma1(N)::
|
|
927
|
+
|
|
928
|
+
sage: m = ModularSymbols(Gamma1(13),2, sign=-1)
|
|
929
|
+
sage: m._compute_hecke_matrix_prime(2).charpoly('x')
|
|
930
|
+
x^2 + 3*x + 3
|
|
931
|
+
|
|
932
|
+
The following is an example with odd weight::
|
|
933
|
+
|
|
934
|
+
sage: m = ModularSymbols(Gamma1(5),3)
|
|
935
|
+
sage: m._compute_hecke_matrix_prime(2).charpoly('x')
|
|
936
|
+
x^4 - 10*x^3 + 50*x^2 - 170*x + 289
|
|
937
|
+
|
|
938
|
+
This example has composite conductor and weight2 dividing the
|
|
939
|
+
conductor and nontrivial sign::
|
|
940
|
+
|
|
941
|
+
sage: m = ModularSymbols(Gamma1(9),3, sign=1)
|
|
942
|
+
sage: m._compute_hecke_matrix_prime(3).charpoly('x')
|
|
943
|
+
x^6 + 3*x^4 - 19*x^3 + 24*x^2 - 9*x
|
|
944
|
+
|
|
945
|
+
In some situations we do not need all the rows of the result, and can thereby save time::
|
|
946
|
+
|
|
947
|
+
sage: m = ModularSymbols(1,weight=12)
|
|
948
|
+
sage: m._compute_hecke_matrix_prime(2)
|
|
949
|
+
[ -24 0 0]
|
|
950
|
+
[ 0 -24 0]
|
|
951
|
+
[4860 0 2049]
|
|
952
|
+
sage: m._compute_hecke_matrix_prime(2,rows=[0,1])
|
|
953
|
+
[-24 0 0]
|
|
954
|
+
[ 0 -24 0]
|
|
955
|
+
sage: m._compute_hecke_matrix_prime(2,rows=[1,2])
|
|
956
|
+
[ 0 -24 0]
|
|
957
|
+
[4860 0 2049]
|
|
958
|
+
"""
|
|
959
|
+
# note -- p doesn't have to be prime despite the function name
|
|
960
|
+
p = int(Integer(p)) # go through Integer so p = 2.5 gives an error.
|
|
961
|
+
if isinstance(rows, list):
|
|
962
|
+
rows = tuple(rows)
|
|
963
|
+
try:
|
|
964
|
+
return self._hecke_matrices[(p, rows)]
|
|
965
|
+
except AttributeError:
|
|
966
|
+
self._hecke_matrices = {}
|
|
967
|
+
except KeyError:
|
|
968
|
+
pass
|
|
969
|
+
tm = verbose("Computing Hecke operator T_%s" % p)
|
|
970
|
+
|
|
971
|
+
if is_prime(p):
|
|
972
|
+
H = heilbronn.HeilbronnCremona(p)
|
|
973
|
+
else:
|
|
974
|
+
H = heilbronn.HeilbronnMerel(p)
|
|
975
|
+
|
|
976
|
+
B = self.manin_basis()
|
|
977
|
+
if rows is not None:
|
|
978
|
+
B = [B[i] for i in rows]
|
|
979
|
+
mod2term = self._mod2term
|
|
980
|
+
R = self.manin_gens_to_basis()
|
|
981
|
+
K = self.base_ring()
|
|
982
|
+
W = R.new_matrix(nrows=len(B), ncols=R.nrows())
|
|
983
|
+
syms = self.manin_symbols()
|
|
984
|
+
j = 0
|
|
985
|
+
for i in B:
|
|
986
|
+
for h in H:
|
|
987
|
+
entries = syms.apply(i, h)
|
|
988
|
+
for k, x in entries:
|
|
989
|
+
f, s = mod2term[k]
|
|
990
|
+
if s:
|
|
991
|
+
# W[j,f] = W[j,f] + s*K(x)
|
|
992
|
+
W.add_to_entry(j, f, s * K(x))
|
|
993
|
+
j += 1
|
|
994
|
+
tm = verbose("start matrix multiply", tm)
|
|
995
|
+
if hasattr(W, '_matrix_times_matrix_dense'):
|
|
996
|
+
Tp = W._matrix_times_matrix_dense(R)
|
|
997
|
+
verbose("done matrix multiply and computing Hecke operator", tm)
|
|
998
|
+
else:
|
|
999
|
+
Tp = W * R
|
|
1000
|
+
tm = verbose("done matrix multiply", tm)
|
|
1001
|
+
Tp = Tp.dense_matrix()
|
|
1002
|
+
verbose("done making Hecke operator matrix dense", tm)
|
|
1003
|
+
self._hecke_matrices[(p, rows)] = Tp
|
|
1004
|
+
return Tp
|
|
1005
|
+
|
|
1006
|
+
def __heilbronn_operator(self, M, H, t=1):
|
|
1007
|
+
r"""
|
|
1008
|
+
Return the matrix function to the space `M` defined by `H`, `t`.
|
|
1009
|
+
|
|
1010
|
+
.. NOTE::
|
|
1011
|
+
|
|
1012
|
+
Users will instead use the simpler interface defined, for
|
|
1013
|
+
example, by ``hecke_matrix()`` (see examples).
|
|
1014
|
+
|
|
1015
|
+
INPUT:
|
|
1016
|
+
|
|
1017
|
+
- ``M`` -- ModularSymbols; codomain (a space of modular symbols)
|
|
1018
|
+
|
|
1019
|
+
- ``H`` -- list of matrices in `M_2(\ZZ)`
|
|
1020
|
+
|
|
1021
|
+
- ``t`` -- integer (default: 1)
|
|
1022
|
+
|
|
1023
|
+
OUTPUT:
|
|
1024
|
+
|
|
1025
|
+
(free module morphism) A function from the Modular Symbol
|
|
1026
|
+
space to the Modular Symbol space `M` defined by `t` and the
|
|
1027
|
+
matrices in `H`.
|
|
1028
|
+
|
|
1029
|
+
EXAMPLES::
|
|
1030
|
+
|
|
1031
|
+
sage: M = ModularSymbols(37,2)
|
|
1032
|
+
sage: M._ModularSymbolsAmbient__heilbronn_operator(M,HeilbronnCremona(3))
|
|
1033
|
+
Hecke module morphism Heilbronn operator(The Cremona-Heilbronn matrices of determinant 3,1) defined by the matrix
|
|
1034
|
+
[ 4 0 0 0 -1]
|
|
1035
|
+
[ 0 -1 2 2 -2]
|
|
1036
|
+
[ 0 2 -1 2 0]
|
|
1037
|
+
[ 0 0 0 -3 2]
|
|
1038
|
+
[ 0 0 0 0 1]
|
|
1039
|
+
Domain: Modular Symbols space of dimension 5 for Gamma_0(37) of weight ...
|
|
1040
|
+
Codomain: Modular Symbols space of dimension 5 for Gamma_0(37) of weight ...
|
|
1041
|
+
|
|
1042
|
+
sage: M.hecke_matrix(3)
|
|
1043
|
+
[ 4 0 0 0 -1]
|
|
1044
|
+
[ 0 -1 2 2 -2]
|
|
1045
|
+
[ 0 2 -1 2 0]
|
|
1046
|
+
[ 0 0 0 -3 2]
|
|
1047
|
+
[ 0 0 0 0 1]
|
|
1048
|
+
"""
|
|
1049
|
+
|
|
1050
|
+
MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
|
|
1051
|
+
hom = self.Hom(M)
|
|
1052
|
+
if self.dimension() == 0 or M.dimension() == 0:
|
|
1053
|
+
A = MS(0)
|
|
1054
|
+
return hom(A, "Heilbronn operator(%s,%s)" % (H, t))
|
|
1055
|
+
|
|
1056
|
+
rows = []
|
|
1057
|
+
B = self.manin_basis()
|
|
1058
|
+
syms = self.manin_symbols()
|
|
1059
|
+
k = self.weight()
|
|
1060
|
+
for n in B:
|
|
1061
|
+
z = M(0)
|
|
1062
|
+
i, u, v = syms[n].tuple()
|
|
1063
|
+
# We apply each Heilbronn matrix to the
|
|
1064
|
+
# Manin symbol [X^i*Y^(k-2-i), (u,v)]
|
|
1065
|
+
for h in H:
|
|
1066
|
+
# Apply h to the polynomial part
|
|
1067
|
+
a, b, c, d = tuple(h)
|
|
1068
|
+
# P gives the ordered coefficients of (a*X+b*Y)^i*(c*X+d*Y)^(j-i)
|
|
1069
|
+
P = apply_to_monomial(i, k-2, a, b, c, d)
|
|
1070
|
+
# Apply h to the (u,v) part of the Manin symbol
|
|
1071
|
+
(uu, vv) = (u*a+v*c, u*b+v*d)
|
|
1072
|
+
|
|
1073
|
+
# For the generalized Heilbronn operator, we through away any
|
|
1074
|
+
# symbols for which the (u,v) part of the symbol doesn't have
|
|
1075
|
+
# both entries divisible by t.
|
|
1076
|
+
if t != 1:
|
|
1077
|
+
if uu % t != 0 or vv % t != 0:
|
|
1078
|
+
continue
|
|
1079
|
+
uu = uu//t
|
|
1080
|
+
vv = vv//t
|
|
1081
|
+
|
|
1082
|
+
# Now coerce each Manin symbol
|
|
1083
|
+
#
|
|
1084
|
+
# P[m]*[X^m*Y^(k-2-m), (uu,vv)], for m=0,...,len(P)
|
|
1085
|
+
#
|
|
1086
|
+
# into the image space M and add that to z.
|
|
1087
|
+
# Note that we coerce in Manin symbols as tuples.
|
|
1088
|
+
for m in range(len(P)):
|
|
1089
|
+
x = M((m, uu, vv))
|
|
1090
|
+
z += x*P[m]
|
|
1091
|
+
|
|
1092
|
+
rows.append(z.element())
|
|
1093
|
+
|
|
1094
|
+
A = MS(rows)
|
|
1095
|
+
return hom(A, "Heilbronn operator(%s,%s)" % (H, t))
|
|
1096
|
+
|
|
1097
|
+
def _repr_(self):
|
|
1098
|
+
r"""
|
|
1099
|
+
String representation of this Modular Symbols space.
|
|
1100
|
+
|
|
1101
|
+
EXAMPLES::
|
|
1102
|
+
|
|
1103
|
+
sage: m = ModularSymbols(1,weight=12)
|
|
1104
|
+
sage: m # indirect doctest
|
|
1105
|
+
Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
|
|
1106
|
+
"""
|
|
1107
|
+
return "Modular Symbols space of dimension %s and weight %s for %s with sign %s and character %s over %s" % (
|
|
1108
|
+
self.dimension(), self.weight(), self.group(), self.sign(), self.character()._repr_short_(), self.base_ring())
|
|
1109
|
+
|
|
1110
|
+
def _latex_(self):
|
|
1111
|
+
r"""
|
|
1112
|
+
Latex representation of this Modular Symbols space.
|
|
1113
|
+
|
|
1114
|
+
EXAMPLES::
|
|
1115
|
+
|
|
1116
|
+
sage: m = ModularSymbols(11,weight=12)
|
|
1117
|
+
sage: latex(m) # indirect doctest
|
|
1118
|
+
\mathrm{ModSym}_{12}(\Gamma_0(11),\left[1\right];\Bold{Q})
|
|
1119
|
+
|
|
1120
|
+
sage: chi = DirichletGroup(7).0
|
|
1121
|
+
sage: m = ModularSymbols(chi)
|
|
1122
|
+
sage: latex(m)
|
|
1123
|
+
\mathrm{ModSym}_{2}(\Gamma_1(7),\left[\zeta_{6}\right];\Bold{Q}(\zeta_{6}))
|
|
1124
|
+
"""
|
|
1125
|
+
return "\\mathrm{ModSym}_{%s}(%s,%s;%s)" % (self.weight(),
|
|
1126
|
+
latex(self.group()),
|
|
1127
|
+
latex(list(self.character().values_on_gens())),
|
|
1128
|
+
latex(self.base_ring()))
|
|
1129
|
+
|
|
1130
|
+
def _matrix_of_operator_on_modular_symbols(self, codomain, R):
|
|
1131
|
+
r"""
|
|
1132
|
+
Return the matrix of a modular symbols operator.
|
|
1133
|
+
|
|
1134
|
+
.. NOTE::
|
|
1135
|
+
|
|
1136
|
+
Users will usually instead use the simpler interface
|
|
1137
|
+
defined, for example, by ``hecke_matrix()`` (see examples),
|
|
1138
|
+
though this function allows one to compute much more
|
|
1139
|
+
general operators.
|
|
1140
|
+
|
|
1141
|
+
INPUT:
|
|
1142
|
+
|
|
1143
|
+
- ``codomain`` -- space of modular symbols
|
|
1144
|
+
|
|
1145
|
+
- ``R`` -- list of lists `[a,b,c,d]` of length 4,
|
|
1146
|
+
which we view as elements of `GL_2(`QQ)`
|
|
1147
|
+
|
|
1148
|
+
OUTPUT:
|
|
1149
|
+
|
|
1150
|
+
The matrix of the operator
|
|
1151
|
+
|
|
1152
|
+
.. MATH::
|
|
1153
|
+
|
|
1154
|
+
x \mapsto \sum_{g in R} g.x,
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
where `g.x` is the formal linear fractional transformation on modular
|
|
1158
|
+
symbols, with respect to the standard basis.
|
|
1159
|
+
|
|
1160
|
+
EXAMPLES::
|
|
1161
|
+
|
|
1162
|
+
sage: M = ModularSymbols(37,2)
|
|
1163
|
+
sage: M._matrix_of_operator_on_modular_symbols(M,HeilbronnCremona(3))
|
|
1164
|
+
[ 4 0 0 0 0]
|
|
1165
|
+
[ 0 -3 1 1 0]
|
|
1166
|
+
[ 0 3 0 5 -2]
|
|
1167
|
+
[ 0 -3 1 -5 3]
|
|
1168
|
+
[ 0 0 2 3 -3]
|
|
1169
|
+
"""
|
|
1170
|
+
rows = []
|
|
1171
|
+
for b in self.basis():
|
|
1172
|
+
v = FormalSum(0, check=False)
|
|
1173
|
+
for c, x in b.modular_symbol_rep():
|
|
1174
|
+
for g in R:
|
|
1175
|
+
y = x.apply(g)
|
|
1176
|
+
v += y*c
|
|
1177
|
+
w = codomain(v).element()
|
|
1178
|
+
rows.append(w)
|
|
1179
|
+
M = MatrixSpace(self.base_ring(), len(rows), codomain.degree(), sparse=False)
|
|
1180
|
+
return M(rows)
|
|
1181
|
+
|
|
1182
|
+
def _compute_atkin_lehner_matrix(self, d):
|
|
1183
|
+
r"""
|
|
1184
|
+
Return the matrix of the Atkin-Lehner operator `W_d`.
|
|
1185
|
+
|
|
1186
|
+
INPUT:
|
|
1187
|
+
|
|
1188
|
+
- ``d`` -- integer that divides the level
|
|
1189
|
+
|
|
1190
|
+
OUTPUT: the matrix of the operator `W_d` with respect to the standard
|
|
1191
|
+
basis
|
|
1192
|
+
|
|
1193
|
+
EXAMPLES: An example at level 29::
|
|
1194
|
+
|
|
1195
|
+
sage: M = ModularSymbols((DirichletGroup(29,QQ).0), 2,1); M
|
|
1196
|
+
Modular Symbols space of dimension 4 and level 29, weight 2, character [-1], sign 1, over Rational Field
|
|
1197
|
+
sage: w = M._compute_atkin_lehner_matrix(29)
|
|
1198
|
+
sage: w^2 == 1
|
|
1199
|
+
True
|
|
1200
|
+
sage: w.fcp()
|
|
1201
|
+
(x - 1)^2 * (x + 1)^2
|
|
1202
|
+
|
|
1203
|
+
This doesn't work since the character is not trivial or quadratic::
|
|
1204
|
+
|
|
1205
|
+
sage: M = ModularSymbols((DirichletGroup(13).0), 2,1); M
|
|
1206
|
+
Modular Symbols space of dimension 0 and level 13, weight 2, character [zeta12], sign 1, over Cyclotomic Field of order 12 and degree 4
|
|
1207
|
+
sage: M._compute_atkin_lehner_matrix(13)
|
|
1208
|
+
Traceback (most recent call last):
|
|
1209
|
+
...
|
|
1210
|
+
ValueError: Atkin-Lehner W_d only defined when d-primary part of character is trivial or quadratic
|
|
1211
|
+
|
|
1212
|
+
Note that Atkin-Lehner does make sense on `\Gamma_1(13)`,
|
|
1213
|
+
but doesn't commute with the Hecke operators::
|
|
1214
|
+
|
|
1215
|
+
sage: M = ModularSymbols(Gamma1(13),2)
|
|
1216
|
+
sage: w = M.atkin_lehner_operator(13).matrix()
|
|
1217
|
+
sage: t = M.T(2).matrix()
|
|
1218
|
+
sage: t*w == w*t
|
|
1219
|
+
False
|
|
1220
|
+
sage: t * w * ~t * ~w == M.diamond_bracket_matrix(2)
|
|
1221
|
+
True
|
|
1222
|
+
sage: w^2 == 1
|
|
1223
|
+
True
|
|
1224
|
+
|
|
1225
|
+
For `\Gamma_1(N)` levels, when `d` is a proper factor of `N`, the
|
|
1226
|
+
square of the operator `W_d` is not a scalar any more::
|
|
1227
|
+
|
|
1228
|
+
sage: M = ModularSymbols(Gamma1(10), 2)
|
|
1229
|
+
sage: w = M.atkin_lehner_operator(2).matrix()
|
|
1230
|
+
sage: w^2 == M.diamond_bracket_matrix(7)
|
|
1231
|
+
True
|
|
1232
|
+
|
|
1233
|
+
In higher weights, the operator is defined, but its eigenvalues are no longer roots of unity::
|
|
1234
|
+
|
|
1235
|
+
sage: M = ModularSymbols(Gamma1(13), 3)
|
|
1236
|
+
sage: w = M.atkin_lehner_operator(13).matrix()
|
|
1237
|
+
sage: w**2 == -13
|
|
1238
|
+
True
|
|
1239
|
+
|
|
1240
|
+
TESTS:
|
|
1241
|
+
|
|
1242
|
+
Check that signed spaces are handled gracefully::
|
|
1243
|
+
|
|
1244
|
+
sage: M = ModularSymbols(Gamma1(18), 3, sign=1)
|
|
1245
|
+
sage: M.atkin_lehner_operator(2).matrix().fcp()
|
|
1246
|
+
(x^2 + 2)^3 * (x^4 - 2*x^2 + 4)^3
|
|
1247
|
+
sage: M.atkin_lehner_operator(9)
|
|
1248
|
+
Traceback (most recent call last):
|
|
1249
|
+
...
|
|
1250
|
+
ValueError: Atkin-Lehner operator not defined on signed space (use sign=0)
|
|
1251
|
+
|
|
1252
|
+
GammaH spaces work::
|
|
1253
|
+
|
|
1254
|
+
sage: G = GammaH(25, [6])
|
|
1255
|
+
sage: ModularSymbols(G, sign=0).atkin_lehner_operator().fcp()
|
|
1256
|
+
(x - 1)^5 * (x + 1)^6
|
|
1257
|
+
"""
|
|
1258
|
+
N = self.level()
|
|
1259
|
+
|
|
1260
|
+
chi = self.character()
|
|
1261
|
+
if chi is not None:
|
|
1262
|
+
dec = [u for u in chi.decomposition() if chi.modulus().divides(d)]
|
|
1263
|
+
if not all((u**2).is_trivial() for u in dec):
|
|
1264
|
+
raise ValueError("Atkin-Lehner W_d only defined when d-primary part of character is trivial or quadratic")
|
|
1265
|
+
|
|
1266
|
+
if self.sign() != 0:
|
|
1267
|
+
# AL operator problematic on signed spaces
|
|
1268
|
+
if self.diamond_bracket_matrix(crt(-1, 1, d, N/d)) != 1:
|
|
1269
|
+
raise ValueError("Atkin-Lehner operator not defined on signed space (use sign=0)")
|
|
1270
|
+
|
|
1271
|
+
W = self.group().atkin_lehner_matrix(d).list()
|
|
1272
|
+
return self._action_on_modular_symbols(W)
|
|
1273
|
+
|
|
1274
|
+
def boundary_map(self):
|
|
1275
|
+
r"""
|
|
1276
|
+
Return the boundary map to the corresponding space of boundary modular
|
|
1277
|
+
symbols.
|
|
1278
|
+
|
|
1279
|
+
EXAMPLES::
|
|
1280
|
+
|
|
1281
|
+
sage: ModularSymbols(20,2).boundary_map()
|
|
1282
|
+
Hecke module morphism boundary map defined by the matrix
|
|
1283
|
+
[ 1 -1 0 0 0 0]
|
|
1284
|
+
[ 0 1 -1 0 0 0]
|
|
1285
|
+
[ 0 1 0 -1 0 0]
|
|
1286
|
+
[ 0 0 0 -1 1 0]
|
|
1287
|
+
[ 0 1 0 -1 0 0]
|
|
1288
|
+
[ 0 0 1 -1 0 0]
|
|
1289
|
+
[ 0 1 0 0 0 -1]
|
|
1290
|
+
Domain: Modular Symbols space of dimension 7 for Gamma_0(20) of weight ...
|
|
1291
|
+
Codomain: Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(20) ...
|
|
1292
|
+
sage: type(ModularSymbols(20,2).boundary_map())
|
|
1293
|
+
<class 'sage.modular.hecke.morphism.HeckeModuleMorphism_matrix'>
|
|
1294
|
+
"""
|
|
1295
|
+
try:
|
|
1296
|
+
return self.__boundary_map
|
|
1297
|
+
except AttributeError:
|
|
1298
|
+
# compute boundary map
|
|
1299
|
+
B = self.boundary_space()
|
|
1300
|
+
I = [B(b) for b in self.basis()]
|
|
1301
|
+
W = MatrixSpace(self.base_ring(), len(I), B.rank(), sparse=True)
|
|
1302
|
+
|
|
1303
|
+
# Note -- the underlying elements have degree the number of distinct
|
|
1304
|
+
# cusps known when the element was computed. This isn't constant,
|
|
1305
|
+
# so we pad the elements.
|
|
1306
|
+
E = [x.element() for x in I]
|
|
1307
|
+
zero = self.base_ring()(0)
|
|
1308
|
+
n = int(B.dimension())
|
|
1309
|
+
E = sum([list(x) + [zero]*(n - len(x)) for x in E], [])
|
|
1310
|
+
|
|
1311
|
+
A = W(E)
|
|
1312
|
+
H = Hom(self, B)
|
|
1313
|
+
self.__boundary_map = H(A, "boundary map")
|
|
1314
|
+
return self.__boundary_map
|
|
1315
|
+
|
|
1316
|
+
def cusps(self):
|
|
1317
|
+
r"""
|
|
1318
|
+
Return the set of cusps for this modular symbols space.
|
|
1319
|
+
|
|
1320
|
+
EXAMPLES::
|
|
1321
|
+
|
|
1322
|
+
sage: ModularSymbols(20,2).cusps()
|
|
1323
|
+
[Infinity, 0, -1/4, 1/5, -1/2, 1/10]
|
|
1324
|
+
"""
|
|
1325
|
+
try:
|
|
1326
|
+
return self.__cusps
|
|
1327
|
+
except AttributeError:
|
|
1328
|
+
f = self.boundary_map()
|
|
1329
|
+
B = f.codomain()
|
|
1330
|
+
C = B._known_cusps()
|
|
1331
|
+
self.__cusps = C
|
|
1332
|
+
return C
|
|
1333
|
+
|
|
1334
|
+
def boundary_space(self):
|
|
1335
|
+
r"""
|
|
1336
|
+
Return the subspace of boundary modular symbols of this modular symbols ambient space.
|
|
1337
|
+
|
|
1338
|
+
EXAMPLES::
|
|
1339
|
+
|
|
1340
|
+
sage: M = ModularSymbols(20, 2)
|
|
1341
|
+
sage: B = M.boundary_space(); B
|
|
1342
|
+
Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(20) of weight 2 over Rational Field
|
|
1343
|
+
sage: M.cusps()
|
|
1344
|
+
[Infinity, 0, -1/4, 1/5, -1/2, 1/10]
|
|
1345
|
+
sage: M.dimension()
|
|
1346
|
+
7
|
|
1347
|
+
sage: B.dimension()
|
|
1348
|
+
6
|
|
1349
|
+
"""
|
|
1350
|
+
raise NotImplementedError
|
|
1351
|
+
|
|
1352
|
+
def cuspidal_submodule(self):
|
|
1353
|
+
"""
|
|
1354
|
+
The cuspidal submodule of this modular symbols ambient space.
|
|
1355
|
+
|
|
1356
|
+
EXAMPLES::
|
|
1357
|
+
|
|
1358
|
+
sage: M = ModularSymbols(12,2,0,GF(5)) ; M
|
|
1359
|
+
Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Finite Field of size 5
|
|
1360
|
+
sage: M.cuspidal_submodule()
|
|
1361
|
+
Modular Symbols subspace of dimension 0 of Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Finite Field of size 5
|
|
1362
|
+
sage: ModularSymbols(1,24,-1).cuspidal_submodule()
|
|
1363
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 2 for Gamma_0(1) of weight 24 with sign -1 over Rational Field
|
|
1364
|
+
|
|
1365
|
+
The cuspidal submodule of the cuspidal submodule is itself::
|
|
1366
|
+
|
|
1367
|
+
sage: M = ModularSymbols(389)
|
|
1368
|
+
sage: S = M.cuspidal_submodule()
|
|
1369
|
+
sage: S.cuspidal_submodule() is S
|
|
1370
|
+
True
|
|
1371
|
+
"""
|
|
1372
|
+
try:
|
|
1373
|
+
return self.__cuspidal_submodule
|
|
1374
|
+
except AttributeError:
|
|
1375
|
+
try:
|
|
1376
|
+
if self.__is_cuspidal:
|
|
1377
|
+
return self
|
|
1378
|
+
except AttributeError:
|
|
1379
|
+
pass
|
|
1380
|
+
S = self.boundary_map().kernel()
|
|
1381
|
+
S._set_is_cuspidal(True)
|
|
1382
|
+
S._is_full_hecke_module = True
|
|
1383
|
+
# We know the cuspidal subspace is stable, so
|
|
1384
|
+
# if it's one-dimensional, it must be simple
|
|
1385
|
+
if S.dimension() == 1:
|
|
1386
|
+
S._is_simple = True
|
|
1387
|
+
if self.base_ring().characteristic() == 0:
|
|
1388
|
+
d = self._cuspidal_submodule_dimension_formula()
|
|
1389
|
+
if d is not None:
|
|
1390
|
+
assert d == S.dimension(), "According to dimension formulas the cuspidal subspace of \"%s\" has dimension %s; however, computing it using modular symbols we obtained %s, so there is a bug (please report!)." % (self, d, S.dimension())
|
|
1391
|
+
self.__cuspidal_submodule = S
|
|
1392
|
+
return self.__cuspidal_submodule
|
|
1393
|
+
|
|
1394
|
+
def _degeneracy_raising_matrix(self, M, t):
|
|
1395
|
+
r"""
|
|
1396
|
+
Return the matrix of the level-raising degeneracy map from ``self`` to M,
|
|
1397
|
+
of index t. This is calculated by composing the level-raising matrix
|
|
1398
|
+
for `t = 1` with a Hecke operator.
|
|
1399
|
+
|
|
1400
|
+
INPUT:
|
|
1401
|
+
|
|
1402
|
+
- ``M`` -- integer; a space of modular symbols whose level is an
|
|
1403
|
+
integer multiple of the level of ``self``
|
|
1404
|
+
|
|
1405
|
+
- ``t`` -- positive integer dividing the quotient of the two levels
|
|
1406
|
+
|
|
1407
|
+
OUTPUT:
|
|
1408
|
+
|
|
1409
|
+
(matrix) The matrix of the degeneracy map of index `t` from this space
|
|
1410
|
+
of level `N` to the space `M` (of level a multiple of `N`). Here `t` is
|
|
1411
|
+
a divisor of the quotient.
|
|
1412
|
+
|
|
1413
|
+
EXAMPLES::
|
|
1414
|
+
|
|
1415
|
+
sage: A = ModularSymbols(11, 2); B = ModularSymbols(22, 2)
|
|
1416
|
+
sage: A._degeneracy_raising_matrix(B, 1)
|
|
1417
|
+
[ 1 0 0 0 0 -1 -1]
|
|
1418
|
+
[ 0 1 0 -3 1 1 -1]
|
|
1419
|
+
[ 0 1 1 -1 -1 0 0]
|
|
1420
|
+
sage: A._degeneracy_raising_matrix(B, 2)
|
|
1421
|
+
[ 2 0 0 0 1 0 -1]
|
|
1422
|
+
[ 0 0 -1 3 -1 -1 1]
|
|
1423
|
+
[ 0 -1 -1 1 0 1 -1]
|
|
1424
|
+
|
|
1425
|
+
Check that :issue:`13198` is fixed::
|
|
1426
|
+
|
|
1427
|
+
sage: M22 = ModularSymbols(Gamma1(22), sign=1)
|
|
1428
|
+
sage: M2 = ModularSymbols(Gamma1(2))
|
|
1429
|
+
sage: d1 = M2.degeneracy_map(M22,1)
|
|
1430
|
+
sage: d2 = M2.degeneracy_map(M22,11)
|
|
1431
|
+
sage: M22.hecke_matrix(17).restrict((d1.image() + d2.image()).free_module())
|
|
1432
|
+
[18 0]
|
|
1433
|
+
[ 0 18]
|
|
1434
|
+
sage: S = M22.cuspidal_submodule()
|
|
1435
|
+
sage: S.new_submodule().intersection(S.old_submodule()) == S.zero_submodule()
|
|
1436
|
+
True
|
|
1437
|
+
"""
|
|
1438
|
+
if t == 1:
|
|
1439
|
+
return self._degeneracy_raising_matrix_1(M)
|
|
1440
|
+
else:
|
|
1441
|
+
# use Hecke operator and t=1 case.
|
|
1442
|
+
d1 = self.degeneracy_map(M, 1).matrix()
|
|
1443
|
+
T = M.hecke_matrix(t)
|
|
1444
|
+
return (~self.base_ring()(t)) * d1 * T
|
|
1445
|
+
|
|
1446
|
+
def _degeneracy_raising_matrix_1(self, M):
|
|
1447
|
+
r"""
|
|
1448
|
+
Return the matrix of the degeneracy map to the given level
|
|
1449
|
+
(which must be a multiple of the level of self).
|
|
1450
|
+
|
|
1451
|
+
.. NOTE::
|
|
1452
|
+
|
|
1453
|
+
Not implemented in the base class, only in the derived classes.
|
|
1454
|
+
|
|
1455
|
+
EXAMPLES::
|
|
1456
|
+
|
|
1457
|
+
sage: M = ModularSymbols(37,4)
|
|
1458
|
+
sage: M._degeneracy_raising_matrix_1(ModularSymbols(74, 4))
|
|
1459
|
+
20 x 58 dense matrix over Rational Field (use the '.str()' method to see the entries)
|
|
1460
|
+
"""
|
|
1461
|
+
raise NotImplementedError
|
|
1462
|
+
|
|
1463
|
+
def _degeneracy_lowering_matrix(self, M, t):
|
|
1464
|
+
r"""
|
|
1465
|
+
Return the matrix of the level-lowering degeneracy map from ``self`` to M.
|
|
1466
|
+
|
|
1467
|
+
INPUT:
|
|
1468
|
+
|
|
1469
|
+
- ``M`` -- a modular symbols space whose level divides the level of
|
|
1470
|
+
``self``
|
|
1471
|
+
|
|
1472
|
+
- ``t`` -- integer; a positive integer dividing the quotient of the
|
|
1473
|
+
levels
|
|
1474
|
+
|
|
1475
|
+
OUTPUT:
|
|
1476
|
+
|
|
1477
|
+
The matrix of the degeneracy map from this space to the space
|
|
1478
|
+
`M` of index `t`, where `t` is a divisor of the quotient of the levels
|
|
1479
|
+
of ``self`` and `M`.
|
|
1480
|
+
|
|
1481
|
+
EXAMPLES::
|
|
1482
|
+
|
|
1483
|
+
sage: M = ModularSymbols(22,2)
|
|
1484
|
+
sage: M._degeneracy_lowering_matrix(ModularSymbols(11, 2), 2)
|
|
1485
|
+
[ 1 0 0]
|
|
1486
|
+
[ 0 1 -1]
|
|
1487
|
+
[ 0 0 -1]
|
|
1488
|
+
[ 0 1 0]
|
|
1489
|
+
[ 0 0 0]
|
|
1490
|
+
[-1 0 1]
|
|
1491
|
+
[-1 0 0]
|
|
1492
|
+
"""
|
|
1493
|
+
# Use Proposition 2.6.15 in Merel's 1585 paper (or Prop 15 in
|
|
1494
|
+
# electronic version of that paper).
|
|
1495
|
+
H = heilbronn.HeilbronnMerel(t)
|
|
1496
|
+
return self.__heilbronn_operator(M, H, t).matrix()
|
|
1497
|
+
|
|
1498
|
+
def rank(self):
|
|
1499
|
+
"""
|
|
1500
|
+
Return the rank of this modular symbols ambient space.
|
|
1501
|
+
|
|
1502
|
+
OUTPUT: integer; the rank of this space of modular symbols
|
|
1503
|
+
|
|
1504
|
+
EXAMPLES::
|
|
1505
|
+
|
|
1506
|
+
sage: M = ModularSymbols(389)
|
|
1507
|
+
sage: M.rank()
|
|
1508
|
+
65
|
|
1509
|
+
|
|
1510
|
+
::
|
|
1511
|
+
|
|
1512
|
+
sage: ModularSymbols(11,sign=0).rank()
|
|
1513
|
+
3
|
|
1514
|
+
sage: ModularSymbols(100,sign=0).rank()
|
|
1515
|
+
31
|
|
1516
|
+
sage: ModularSymbols(22,sign=1).rank()
|
|
1517
|
+
5
|
|
1518
|
+
sage: ModularSymbols(1,12).rank()
|
|
1519
|
+
3
|
|
1520
|
+
sage: ModularSymbols(3,4).rank()
|
|
1521
|
+
2
|
|
1522
|
+
sage: ModularSymbols(8,6,sign=-1).rank()
|
|
1523
|
+
3
|
|
1524
|
+
"""
|
|
1525
|
+
try:
|
|
1526
|
+
return self.__rank
|
|
1527
|
+
except AttributeError:
|
|
1528
|
+
self.__rank = len(self.manin_basis())
|
|
1529
|
+
return self.__rank
|
|
1530
|
+
|
|
1531
|
+
def eisenstein_submodule(self):
|
|
1532
|
+
"""
|
|
1533
|
+
Return the Eisenstein submodule of this space of modular symbols.
|
|
1534
|
+
|
|
1535
|
+
EXAMPLES::
|
|
1536
|
+
|
|
1537
|
+
sage: ModularSymbols(20,2).eisenstein_submodule()
|
|
1538
|
+
Modular Symbols subspace of dimension 5 of Modular Symbols space of dimension 7 for Gamma_0(20) of weight 2 with sign 0 over Rational Field
|
|
1539
|
+
"""
|
|
1540
|
+
try:
|
|
1541
|
+
return self.__eisenstein_submodule
|
|
1542
|
+
except AttributeError:
|
|
1543
|
+
self.__eisenstein_submodule = self.cuspidal_submodule().complement()
|
|
1544
|
+
return self.__eisenstein_submodule
|
|
1545
|
+
|
|
1546
|
+
def element(self, x):
|
|
1547
|
+
"""
|
|
1548
|
+
Create and return an element of ``self`` from a modular symbol, if
|
|
1549
|
+
possible.
|
|
1550
|
+
|
|
1551
|
+
INPUT:
|
|
1552
|
+
|
|
1553
|
+
- ``x`` -- an object of one of the following types:
|
|
1554
|
+
ModularSymbol, ManinSymbol
|
|
1555
|
+
|
|
1556
|
+
OUTPUT: ModularSymbol - a modular symbol with parent self
|
|
1557
|
+
|
|
1558
|
+
EXAMPLES::
|
|
1559
|
+
|
|
1560
|
+
sage: M = ModularSymbols(11,4,1)
|
|
1561
|
+
sage: M.T(3)
|
|
1562
|
+
Hecke operator T_3 on Modular Symbols space of dimension 4 for Gamma_0(11) of weight 4 with sign 1 over Rational Field
|
|
1563
|
+
sage: M.T(3)(M.0)
|
|
1564
|
+
28*[X^2,(0,1)] + 2*[X^2,(1,4)] + 2/3*[X^2,(1,6)] - 8/3*[X^2,(1,9)]
|
|
1565
|
+
sage: M.T(3)(M.0).element()
|
|
1566
|
+
(28, 2, 2/3, -8/3)
|
|
1567
|
+
"""
|
|
1568
|
+
if isinstance(x, ManinSymbol):
|
|
1569
|
+
if not x.parent().weight() == self.weight():
|
|
1570
|
+
raise ArithmeticError("incompatible weights: Manin symbol\
|
|
1571
|
+
has weight %s, but modular symbols space has weight %s" % (
|
|
1572
|
+
x.parent().weight(), self.weight()))
|
|
1573
|
+
t = self.manin_symbols().index(x.tuple())
|
|
1574
|
+
if isinstance(t, tuple):
|
|
1575
|
+
i, scalar = t
|
|
1576
|
+
v = self.manin_gens_to_basis().row(i) * scalar
|
|
1577
|
+
else:
|
|
1578
|
+
v = self.manin_gens_to_basis().row(t)
|
|
1579
|
+
return self.element_class(self, v)
|
|
1580
|
+
|
|
1581
|
+
elif isinstance(x, element.ModularSymbolsElement):
|
|
1582
|
+
M = x.parent()
|
|
1583
|
+
if M.ambient_hecke_module() != self:
|
|
1584
|
+
# TODO -- sometimes do something more sophisticated here.
|
|
1585
|
+
raise TypeError("Modular symbol (%s) does not lie in this space." % x)
|
|
1586
|
+
return self(x.element())
|
|
1587
|
+
|
|
1588
|
+
else:
|
|
1589
|
+
raise ValueError("Cannot create element of %s from %s." % (x, self))
|
|
1590
|
+
|
|
1591
|
+
def dual_star_involution_matrix(self):
|
|
1592
|
+
"""
|
|
1593
|
+
Return the matrix of the dual star involution, which is induced by
|
|
1594
|
+
complex conjugation on the linear dual of modular symbols.
|
|
1595
|
+
|
|
1596
|
+
EXAMPLES::
|
|
1597
|
+
|
|
1598
|
+
sage: ModularSymbols(20,2).dual_star_involution_matrix()
|
|
1599
|
+
[1 0 0 0 0 0 0]
|
|
1600
|
+
[0 1 0 0 0 0 0]
|
|
1601
|
+
[0 0 0 0 1 0 0]
|
|
1602
|
+
[0 0 0 1 0 0 0]
|
|
1603
|
+
[0 0 1 0 0 0 0]
|
|
1604
|
+
[0 0 0 0 0 1 0]
|
|
1605
|
+
[0 0 0 0 0 0 1]
|
|
1606
|
+
"""
|
|
1607
|
+
try:
|
|
1608
|
+
return self.__dual_star_involution_matrix
|
|
1609
|
+
except AttributeError:
|
|
1610
|
+
pass
|
|
1611
|
+
self.__dual_star_involution_matrix = self.star_involution().matrix().transpose()
|
|
1612
|
+
return self.__dual_star_involution_matrix
|
|
1613
|
+
|
|
1614
|
+
def factorization(self):
|
|
1615
|
+
r"""
|
|
1616
|
+
Return a list of pairs `(S,e)` where `S` is spaces
|
|
1617
|
+
of modular symbols and ``self`` is isomorphic to the direct sum of the
|
|
1618
|
+
`S^e` as a module over the *anemic* Hecke algebra adjoin
|
|
1619
|
+
the star involution. The cuspidal `S` are all simple, but
|
|
1620
|
+
the Eisenstein factors need not be simple.
|
|
1621
|
+
|
|
1622
|
+
EXAMPLES::
|
|
1623
|
+
|
|
1624
|
+
sage: ModularSymbols(Gamma0(22), 2).factorization()
|
|
1625
|
+
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field)^2 *
|
|
1626
|
+
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field)^2 *
|
|
1627
|
+
(Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field)
|
|
1628
|
+
|
|
1629
|
+
::
|
|
1630
|
+
|
|
1631
|
+
sage: ModularSymbols(1,6,0,GF(2)).factorization()
|
|
1632
|
+
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(1) of weight 6 with sign 0 over Finite Field of size 2) *
|
|
1633
|
+
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(1) of weight 6 with sign 0 over Finite Field of size 2)
|
|
1634
|
+
|
|
1635
|
+
::
|
|
1636
|
+
|
|
1637
|
+
sage: ModularSymbols(18,2).factorization()
|
|
1638
|
+
(Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 for Gamma_0(18) of weight 2 with sign 0 over Rational Field) *
|
|
1639
|
+
(Modular Symbols subspace of dimension 5 of Modular Symbols space of dimension 7 for Gamma_0(18) of weight 2 with sign 0 over Rational Field)
|
|
1640
|
+
|
|
1641
|
+
::
|
|
1642
|
+
|
|
1643
|
+
sage: M = ModularSymbols(DirichletGroup(38,CyclotomicField(3)).0^2, 2, +1); M
|
|
1644
|
+
Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2
|
|
1645
|
+
sage: M.factorization() # long time (about 8 seconds)
|
|
1646
|
+
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2) *
|
|
1647
|
+
(Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2) *
|
|
1648
|
+
(Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2) *
|
|
1649
|
+
(Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2)
|
|
1650
|
+
"""
|
|
1651
|
+
|
|
1652
|
+
# EXAMPLES::
|
|
1653
|
+
|
|
1654
|
+
# sage: M = ModularSymbols(Gamma0(22), 2); M
|
|
1655
|
+
# Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field
|
|
1656
|
+
# sage: M.factorization():
|
|
1657
|
+
# ... print b.dimension(), b.level(), e
|
|
1658
|
+
# 1 11 2
|
|
1659
|
+
# 1 11 2
|
|
1660
|
+
# 1 11 2
|
|
1661
|
+
# 1 22 1
|
|
1662
|
+
|
|
1663
|
+
# An example with sign 1::
|
|
1664
|
+
|
|
1665
|
+
# sage: M = ModularSymbols(Gamma0(22), 2, sign=1); M
|
|
1666
|
+
# Modular Symbols space of dimension 5 for Gamma_0(22) of weight 2 with sign 1 over Rational Field
|
|
1667
|
+
# sage: for b, e in M.factorization():
|
|
1668
|
+
# ... print b.dimension(), b.level(), e
|
|
1669
|
+
# 1 11 2
|
|
1670
|
+
# 1 11 2
|
|
1671
|
+
# 1 22 1
|
|
1672
|
+
|
|
1673
|
+
# An example for Gamma1::
|
|
1674
|
+
|
|
1675
|
+
# sage: M = ModularSymbols(Gamma1(26), 2, sign=1); M
|
|
1676
|
+
# Modular Symbols space of dimension 33 for Gamma_1(26) of weight 2 with sign 1 over Rational Field
|
|
1677
|
+
# sage: for b, e in M.factorization():
|
|
1678
|
+
# ... print b.dimension(), b.level(), e
|
|
1679
|
+
# 1 13 2
|
|
1680
|
+
# 1 13 2
|
|
1681
|
+
# 1 13 2
|
|
1682
|
+
# 2 13 2
|
|
1683
|
+
# 2 13 2
|
|
1684
|
+
# 2 13 2
|
|
1685
|
+
# 2 13 2
|
|
1686
|
+
# 2 13 2
|
|
1687
|
+
# 1 26 1
|
|
1688
|
+
# 1 26 1
|
|
1689
|
+
# 1 26 1
|
|
1690
|
+
# 2 26 1
|
|
1691
|
+
# 2 26 1
|
|
1692
|
+
|
|
1693
|
+
# An example with level divisible by a square::
|
|
1694
|
+
|
|
1695
|
+
# sage: M = ModularSymbols(Gamma0(2*9),2); M
|
|
1696
|
+
# ???
|
|
1697
|
+
# sage: for b, e in M.factorization():
|
|
1698
|
+
# ... print b.dimension(), b.level(), e
|
|
1699
|
+
# ???
|
|
1700
|
+
try:
|
|
1701
|
+
return self._factorization
|
|
1702
|
+
except AttributeError:
|
|
1703
|
+
pass
|
|
1704
|
+
|
|
1705
|
+
try:
|
|
1706
|
+
if self._is_simple:
|
|
1707
|
+
return [self]
|
|
1708
|
+
except AttributeError:
|
|
1709
|
+
pass
|
|
1710
|
+
|
|
1711
|
+
D = []
|
|
1712
|
+
|
|
1713
|
+
# Treat the cuspidal and eisenstein parts separately. The
|
|
1714
|
+
# cuspidal part is very straightforward because of
|
|
1715
|
+
# Atkin-Lehner-Li theory. The eisenstein part is trickier,
|
|
1716
|
+
# because of E2 and that the new and old Eisenstein subspaces
|
|
1717
|
+
# can intersect (e.g., they do for M_2(Gamma_0(6))), even
|
|
1718
|
+
# in a way that involves forms other than E_2 (i.e., twists
|
|
1719
|
+
# of E2).
|
|
1720
|
+
|
|
1721
|
+
# 1. Cuspidal part -- compute the factors and their multiplicities
|
|
1722
|
+
# using Atkin-Lehner-Li.
|
|
1723
|
+
|
|
1724
|
+
# 2. Eisenstein part -- just call normal decomposition.
|
|
1725
|
+
|
|
1726
|
+
# In the special case of weight 2 we have to do a bunch of
|
|
1727
|
+
# annoying extra work below to deal with the Eisenstein series E_2.
|
|
1728
|
+
|
|
1729
|
+
# If the characteristic of the base ring is 2,
|
|
1730
|
+
# the star involution is the identity, so we
|
|
1731
|
+
# want to avoid adding each cuspidal submodule
|
|
1732
|
+
# twice.
|
|
1733
|
+
if self.base_ring().characteristic() == 2:
|
|
1734
|
+
skip_minus = True
|
|
1735
|
+
else:
|
|
1736
|
+
skip_minus = False
|
|
1737
|
+
|
|
1738
|
+
# The cuspidal part
|
|
1739
|
+
# We only run through spaces of level a multiple of the conductor of the character, which
|
|
1740
|
+
# we compute below, or set to 1 in case of Gamma_H or Gamma_1
|
|
1741
|
+
chi = self.character()
|
|
1742
|
+
cond = 1 if chi is None else chi.conductor()
|
|
1743
|
+
# Now actually run through the divisor levels, taking only the ones with that are
|
|
1744
|
+
# a multiple of the conductor.
|
|
1745
|
+
for d in reversed(divisors(self.level())):
|
|
1746
|
+
if d % cond:
|
|
1747
|
+
continue
|
|
1748
|
+
n = number_of_divisors(self.level() // d)
|
|
1749
|
+
M = self.modular_symbols_of_level(d)
|
|
1750
|
+
N = M.new_submodule().cuspidal_submodule().decomposition()
|
|
1751
|
+
for A in N:
|
|
1752
|
+
if self.sign() == 0:
|
|
1753
|
+
V = A.plus_submodule()
|
|
1754
|
+
V._is_simple = True
|
|
1755
|
+
D.append((V, n))
|
|
1756
|
+
if skip_minus:
|
|
1757
|
+
continue
|
|
1758
|
+
V = A.minus_submodule()
|
|
1759
|
+
V._is_simple = True
|
|
1760
|
+
D.append((V, n))
|
|
1761
|
+
else:
|
|
1762
|
+
A._is_simple = True
|
|
1763
|
+
D.append((A, n))
|
|
1764
|
+
# The Eisenstein part
|
|
1765
|
+
D.extend((E, 1) for E in
|
|
1766
|
+
self.eisenstein_submodule().decomposition(anemic=True))
|
|
1767
|
+
|
|
1768
|
+
r = self.dimension()
|
|
1769
|
+
s = sum(A.rank() * mult for A, mult in D)
|
|
1770
|
+
D = Factorization(D, cr=True, sort=False)
|
|
1771
|
+
D.sort()
|
|
1772
|
+
assert r == s, "bug in factorization -- self has dimension %s, but sum of dimensions of factors is %s\n%s" % (r, s, D)
|
|
1773
|
+
self._factorization = D
|
|
1774
|
+
return self._factorization
|
|
1775
|
+
|
|
1776
|
+
factor = factorization
|
|
1777
|
+
|
|
1778
|
+
def is_cuspidal(self) -> bool:
|
|
1779
|
+
r"""
|
|
1780
|
+
Return ``True`` if this space is cuspidal, else ``False``.
|
|
1781
|
+
|
|
1782
|
+
EXAMPLES::
|
|
1783
|
+
|
|
1784
|
+
sage: M = ModularSymbols(20,2)
|
|
1785
|
+
sage: M.is_cuspidal()
|
|
1786
|
+
False
|
|
1787
|
+
sage: S = M.cuspidal_subspace()
|
|
1788
|
+
sage: S.is_cuspidal()
|
|
1789
|
+
True
|
|
1790
|
+
sage: S = M.eisenstein_subspace()
|
|
1791
|
+
sage: S.is_cuspidal()
|
|
1792
|
+
False
|
|
1793
|
+
"""
|
|
1794
|
+
try:
|
|
1795
|
+
return self.__is_cuspidal
|
|
1796
|
+
except AttributeError:
|
|
1797
|
+
S = self.ambient_hecke_module().cuspidal_submodule()
|
|
1798
|
+
self.__is_cuspidal = (S.dimension() == self.dimension())
|
|
1799
|
+
return self.__is_cuspidal
|
|
1800
|
+
|
|
1801
|
+
@cached_method
|
|
1802
|
+
def is_eisenstein(self) -> bool:
|
|
1803
|
+
r"""
|
|
1804
|
+
Return ``True`` if this space is Eisenstein, else ``False``.
|
|
1805
|
+
|
|
1806
|
+
EXAMPLES::
|
|
1807
|
+
|
|
1808
|
+
sage: M = ModularSymbols(20,2)
|
|
1809
|
+
sage: M.is_eisenstein()
|
|
1810
|
+
False
|
|
1811
|
+
sage: S = M.eisenstein_submodule()
|
|
1812
|
+
sage: S.is_eisenstein()
|
|
1813
|
+
True
|
|
1814
|
+
sage: S = M.cuspidal_subspace()
|
|
1815
|
+
sage: S.is_eisenstein()
|
|
1816
|
+
False
|
|
1817
|
+
"""
|
|
1818
|
+
S = self.ambient_hecke_module().eisenstein_submodule()
|
|
1819
|
+
return self.dimension() == S.dimension()
|
|
1820
|
+
|
|
1821
|
+
def manin_symbols_basis(self):
|
|
1822
|
+
"""
|
|
1823
|
+
A list of Manin symbols that form a basis for the ambient space
|
|
1824
|
+
``self``.
|
|
1825
|
+
|
|
1826
|
+
OUTPUT: list of 2-tuples (if the weight is 2) or 3-tuples, which
|
|
1827
|
+
represent the Manin symbols basis for ``self``
|
|
1828
|
+
|
|
1829
|
+
EXAMPLES::
|
|
1830
|
+
|
|
1831
|
+
sage: m = ModularSymbols(23)
|
|
1832
|
+
sage: m.manin_symbols_basis()
|
|
1833
|
+
[(1,0), (1,17), (1,19), (1,20), (1,21)]
|
|
1834
|
+
sage: m = ModularSymbols(6, weight=4, sign=-1)
|
|
1835
|
+
sage: m.manin_symbols_basis()
|
|
1836
|
+
[[X^2,(2,1)]]
|
|
1837
|
+
"""
|
|
1838
|
+
s = self.manin_symbols()
|
|
1839
|
+
return [s.manin_symbol(i) for i in self.manin_basis()]
|
|
1840
|
+
|
|
1841
|
+
def modular_symbols_of_level(self, G):
|
|
1842
|
+
"""
|
|
1843
|
+
Return a space of modular symbols with the same parameters as
|
|
1844
|
+
this space, except the congruence subgroup is changed to `G`.
|
|
1845
|
+
|
|
1846
|
+
INPUT:
|
|
1847
|
+
|
|
1848
|
+
- ``G`` -- either a congruence subgroup or an integer to use
|
|
1849
|
+
as the level of such a group. The given group must either
|
|
1850
|
+
contain or be contained in the group defining ``self``.
|
|
1851
|
+
|
|
1852
|
+
TESTS::
|
|
1853
|
+
|
|
1854
|
+
sage: M = ModularSymbols(11)
|
|
1855
|
+
sage: M.modular_symbols_of_level(22)
|
|
1856
|
+
Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field
|
|
1857
|
+
sage: M.modular_symbols_of_level(Gamma1(22))
|
|
1858
|
+
Modular Symbols space of dimension 31 for Gamma_1(22) of weight 2 with sign 0 over Rational Field
|
|
1859
|
+
|
|
1860
|
+
sage: M = ModularSymbols(Gamma1(6))
|
|
1861
|
+
sage: M.modular_symbols_of_level(12)
|
|
1862
|
+
Modular Symbols space of dimension 9 for Gamma_1(12) of weight 2 with sign 0 over Rational Field
|
|
1863
|
+
sage: M.modular_symbols_of_level(Gamma0(3))
|
|
1864
|
+
Modular Symbols space of dimension 1 for Gamma_0(3) of weight 2 with sign 0 over Rational Field
|
|
1865
|
+
sage: M.modular_symbols_of_level(Gamma0(12))
|
|
1866
|
+
Traceback (most recent call last):
|
|
1867
|
+
...
|
|
1868
|
+
ValueError: one subgroup must contain the other
|
|
1869
|
+
|
|
1870
|
+
sage: M = ModularSymbols(Gamma1(30),4); M
|
|
1871
|
+
Modular Symbols space of dimension 144 for Gamma_1(30) of weight 4 with sign 0 over Rational Field
|
|
1872
|
+
sage: M.modular_symbols_of_level(22)
|
|
1873
|
+
Traceback (most recent call last):
|
|
1874
|
+
...
|
|
1875
|
+
ValueError: one level must divide the other
|
|
1876
|
+
|
|
1877
|
+
sage: M = ModularSymbols(GammaH(15,[7]),6)
|
|
1878
|
+
sage: M.modular_symbols_of_level(5)
|
|
1879
|
+
Modular Symbols space of dimension 4 for Gamma_0(5) of weight 6 with sign 0 over Rational Field
|
|
1880
|
+
sage: M.modular_symbols_of_level(30)
|
|
1881
|
+
Modular Symbols space of dimension 60 for Congruence Subgroup Gamma_H(30) with H generated by [7] of weight 6 with sign 0 over Rational Field
|
|
1882
|
+
sage: M.modular_symbols_of_level(73)
|
|
1883
|
+
Traceback (most recent call last):
|
|
1884
|
+
...
|
|
1885
|
+
ValueError: one level must divide the other
|
|
1886
|
+
"""
|
|
1887
|
+
if G in ZZ:
|
|
1888
|
+
G = self.group()._new_group_from_level(G)
|
|
1889
|
+
elif not (self.group().is_subgroup(G) or G.is_subgroup(self.group())):
|
|
1890
|
+
raise ValueError('one subgroup must contain the other')
|
|
1891
|
+
return modsym.ModularSymbols(G, self.weight(), self.sign(), self.base_ring())
|
|
1892
|
+
|
|
1893
|
+
def modular_symbols_of_sign(self, sign):
|
|
1894
|
+
r"""
|
|
1895
|
+
Return a space of modular symbols with the same defining
|
|
1896
|
+
properties (weight, level, etc.) as this space except with given
|
|
1897
|
+
sign.
|
|
1898
|
+
|
|
1899
|
+
INPUT:
|
|
1900
|
+
|
|
1901
|
+
- ``sign`` -- integer; a sign (`+1`, `-1` or `0`)
|
|
1902
|
+
|
|
1903
|
+
OUTPUT:
|
|
1904
|
+
|
|
1905
|
+
(ModularSymbolsAmbient) A space of modular symbols with the
|
|
1906
|
+
same defining properties (weight, level, etc.) as this space
|
|
1907
|
+
except with given sign.
|
|
1908
|
+
|
|
1909
|
+
EXAMPLES::
|
|
1910
|
+
|
|
1911
|
+
sage: M = ModularSymbols(Gamma0(11),2,sign=0)
|
|
1912
|
+
sage: M
|
|
1913
|
+
Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
|
|
1914
|
+
sage: M.modular_symbols_of_sign(-1)
|
|
1915
|
+
Modular Symbols space of dimension 1 for Gamma_0(11) of weight 2 with sign -1 over Rational Field
|
|
1916
|
+
sage: M = ModularSymbols(Gamma1(11),2,sign=0)
|
|
1917
|
+
sage: M.modular_symbols_of_sign(-1)
|
|
1918
|
+
Modular Symbols space of dimension 1 for Gamma_1(11) of weight 2 with sign -1 over Rational Field
|
|
1919
|
+
"""
|
|
1920
|
+
if sign == self.sign():
|
|
1921
|
+
return self
|
|
1922
|
+
return modsym.ModularSymbols(self.group(), self.weight(), sign=sign, base_ring=self.base_ring())
|
|
1923
|
+
|
|
1924
|
+
def modular_symbols_of_weight(self, k):
|
|
1925
|
+
r"""
|
|
1926
|
+
Return a space of modular symbols with the same defining
|
|
1927
|
+
properties (weight, sign, etc.) as this space except with weight
|
|
1928
|
+
`k`.
|
|
1929
|
+
|
|
1930
|
+
INPUT:
|
|
1931
|
+
|
|
1932
|
+
- ``k`` -- positive integer
|
|
1933
|
+
|
|
1934
|
+
OUTPUT:
|
|
1935
|
+
|
|
1936
|
+
(ModularSymbolsAmbient) A space of modular symbols with the
|
|
1937
|
+
same defining properties (level, sign) as this space
|
|
1938
|
+
except with given weight.
|
|
1939
|
+
|
|
1940
|
+
EXAMPLES::
|
|
1941
|
+
|
|
1942
|
+
sage: M = ModularSymbols(Gamma1(6),2,sign=0)
|
|
1943
|
+
sage: M.modular_symbols_of_weight(3)
|
|
1944
|
+
Modular Symbols space of dimension 4 for Gamma_1(6) of weight 3 with sign 0 over Rational Field
|
|
1945
|
+
"""
|
|
1946
|
+
if k == self.weight():
|
|
1947
|
+
return self
|
|
1948
|
+
return modsym.ModularSymbols(self.group(), weight=k, sign=self.sign(), base_ring=self.base_ring())
|
|
1949
|
+
|
|
1950
|
+
def _compute_sign_submodule(self, sign, compute_dual=True):
|
|
1951
|
+
r"""
|
|
1952
|
+
Return the subspace of ``self`` that is fixed under the star
|
|
1953
|
+
involution.
|
|
1954
|
+
|
|
1955
|
+
INPUT:
|
|
1956
|
+
|
|
1957
|
+
- ``sign`` -- integer (either -1 or +1)
|
|
1958
|
+
|
|
1959
|
+
- ``compute_dual`` -- boolean (default: ``True``); also
|
|
1960
|
+
compute dual subspace. This is useful for many algorithms.
|
|
1961
|
+
|
|
1962
|
+
OUTPUT: a subspace of modular symbols
|
|
1963
|
+
|
|
1964
|
+
EXAMPLES::
|
|
1965
|
+
|
|
1966
|
+
sage: ModularSymbols(1,12,0,GF(5)).minus_submodule() # indirect doctest
|
|
1967
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Finite Field of size 5
|
|
1968
|
+
"""
|
|
1969
|
+
S = self.star_involution().matrix() - self.base_ring()(sign)
|
|
1970
|
+
V = S.kernel()
|
|
1971
|
+
if compute_dual:
|
|
1972
|
+
Vdual = S.transpose().kernel()
|
|
1973
|
+
M = self.submodule(V, Vdual, check=False)
|
|
1974
|
+
else:
|
|
1975
|
+
M = self.submodule(V, check=False)
|
|
1976
|
+
M._set_sign(sign)
|
|
1977
|
+
return M
|
|
1978
|
+
|
|
1979
|
+
def star_involution(self):
|
|
1980
|
+
r"""
|
|
1981
|
+
Return the star involution on this modular symbols space.
|
|
1982
|
+
|
|
1983
|
+
OUTPUT:
|
|
1984
|
+
|
|
1985
|
+
(matrix) The matrix of the star involution on this space,
|
|
1986
|
+
which is induced by complex conjugation on modular symbols,
|
|
1987
|
+
with respect to the standard basis.
|
|
1988
|
+
|
|
1989
|
+
EXAMPLES::
|
|
1990
|
+
|
|
1991
|
+
sage: ModularSymbols(20,2).star_involution()
|
|
1992
|
+
Hecke module morphism Star involution on Modular Symbols space of dimension 7 for Gamma_0(20) of weight 2 with sign 0 over Rational Field defined by the matrix
|
|
1993
|
+
[1 0 0 0 0 0 0]
|
|
1994
|
+
[0 1 0 0 0 0 0]
|
|
1995
|
+
[0 0 0 0 1 0 0]
|
|
1996
|
+
[0 0 0 1 0 0 0]
|
|
1997
|
+
[0 0 1 0 0 0 0]
|
|
1998
|
+
[0 0 0 0 0 1 0]
|
|
1999
|
+
[0 0 0 0 0 0 1]
|
|
2000
|
+
Domain: Modular Symbols space of dimension 7 for Gamma_0(20) of weight ...
|
|
2001
|
+
Codomain: Modular Symbols space of dimension 7 for Gamma_0(20) of weight ...
|
|
2002
|
+
"""
|
|
2003
|
+
try:
|
|
2004
|
+
return self.__star_involution
|
|
2005
|
+
except AttributeError:
|
|
2006
|
+
pass
|
|
2007
|
+
S = self.__heilbronn_operator(self, [[-1, 0, 0, 1]], 1)
|
|
2008
|
+
S.name("Star involution on %s" % self)
|
|
2009
|
+
self.__star_involution = S
|
|
2010
|
+
return self.__star_involution
|
|
2011
|
+
|
|
2012
|
+
def _compute_diamond_matrix(self, d):
|
|
2013
|
+
r"""
|
|
2014
|
+
Return the diamond bracket d operator on this modular symbols space.
|
|
2015
|
+
|
|
2016
|
+
INPUT:
|
|
2017
|
+
|
|
2018
|
+
- ``d`` -- integer
|
|
2019
|
+
|
|
2020
|
+
OUTPUT: the matrix of the diamond bracket operator on this space
|
|
2021
|
+
|
|
2022
|
+
EXAMPLES::
|
|
2023
|
+
|
|
2024
|
+
sage: e = kronecker_character(7)
|
|
2025
|
+
sage: M = ModularSymbols(e,2,sign=1)
|
|
2026
|
+
sage: D = M.diamond_bracket_operator(5); D
|
|
2027
|
+
Diamond bracket operator <5> on Modular Symbols space ...
|
|
2028
|
+
sage: D.matrix() # indirect doctest
|
|
2029
|
+
[-1 0 0 0]
|
|
2030
|
+
[ 0 -1 0 0]
|
|
2031
|
+
[ 0 0 -1 0]
|
|
2032
|
+
[ 0 0 0 -1]
|
|
2033
|
+
sage: [M.diamond_bracket_operator(d).matrix()[0,0] for d in [0..6]]
|
|
2034
|
+
[0, 1, 0, 1, 0, -1, 0]
|
|
2035
|
+
sage: [e(d) for d in [0..6]]
|
|
2036
|
+
[0, 1, 0, 1, 0, -1, 0]
|
|
2037
|
+
|
|
2038
|
+
We test that the sign issue at :issue:`8620` is fixed::
|
|
2039
|
+
|
|
2040
|
+
sage: M = Newforms(Gamma1(13),names = 'a')[0].modular_symbols(sign=0)
|
|
2041
|
+
sage: M.diamond_bracket_operator(4).matrix()
|
|
2042
|
+
[-1 1 1 -1]
|
|
2043
|
+
[-1 0 1 0]
|
|
2044
|
+
[ 0 0 0 -1]
|
|
2045
|
+
[ 0 0 1 -1]
|
|
2046
|
+
|
|
2047
|
+
We check that the result is correctly normalised for weight > 2::
|
|
2048
|
+
|
|
2049
|
+
sage: ModularSymbols(Gamma1(13), 5).diamond_bracket_operator(6).charpoly().factor()
|
|
2050
|
+
(x^2 + 1)^8 * (x^4 - x^2 + 1)^10
|
|
2051
|
+
"""
|
|
2052
|
+
return self.__heilbronn_operator(self, [[d, 0, 0, d]], 1).matrix() * d**(2 - self.weight())
|
|
2053
|
+
|
|
2054
|
+
def submodule(self, M, dual_free_module=None, check=True):
|
|
2055
|
+
r"""
|
|
2056
|
+
Return the submodule with given generators or free module `M`.
|
|
2057
|
+
|
|
2058
|
+
INPUT:
|
|
2059
|
+
|
|
2060
|
+
- ``M`` -- either a submodule of this ambient free module, or
|
|
2061
|
+
generators for a submodule
|
|
2062
|
+
|
|
2063
|
+
- ``dual_free_module`` -- boolean (default: ``None``); this may be
|
|
2064
|
+
useful to speed up certain calculations; it is the corresponding
|
|
2065
|
+
submodule of the ambient dual module;
|
|
2066
|
+
|
|
2067
|
+
- ``check`` -- boolean (default: ``True``); if ``True``, check that `M`
|
|
2068
|
+
is a submodule, i.e. is invariant under all Hecke operators
|
|
2069
|
+
|
|
2070
|
+
OUTPUT: a subspace of this modular symbol space
|
|
2071
|
+
|
|
2072
|
+
EXAMPLES::
|
|
2073
|
+
|
|
2074
|
+
sage: M = ModularSymbols(11)
|
|
2075
|
+
sage: M.submodule([M.0])
|
|
2076
|
+
Traceback (most recent call last):
|
|
2077
|
+
...
|
|
2078
|
+
ValueError: The submodule must be invariant under all Hecke operators.
|
|
2079
|
+
sage: M.eisenstein_submodule().basis()
|
|
2080
|
+
((1,0) - 1/5*(1,9),)
|
|
2081
|
+
sage: M.basis()
|
|
2082
|
+
((1,0), (1,8), (1,9))
|
|
2083
|
+
sage: M.submodule([M.0 - 1/5*M.2])
|
|
2084
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
|
|
2085
|
+
|
|
2086
|
+
.. NOTE::
|
|
2087
|
+
|
|
2088
|
+
It would make more sense to only check that `M` is invariant
|
|
2089
|
+
under the Hecke operators with index coprime to the level.
|
|
2090
|
+
Unfortunately, I do not know a reasonable algorithm for
|
|
2091
|
+
determining whether a module is invariant under just the
|
|
2092
|
+
anemic Hecke algebra, since I do not know an analogue of
|
|
2093
|
+
the Sturm bound for the anemic Hecke algebra. - William
|
|
2094
|
+
Stein, 2007-07-27
|
|
2095
|
+
"""
|
|
2096
|
+
if check:
|
|
2097
|
+
if not isinstance(M, FreeModule_generic):
|
|
2098
|
+
V = self.free_module()
|
|
2099
|
+
if not isinstance(M, (list, tuple)):
|
|
2100
|
+
M = M.gens()
|
|
2101
|
+
M = V.span([V(x.element()) for x in M])
|
|
2102
|
+
return subspace.ModularSymbolsSubspace(self, M, dual_free_module=dual_free_module, check=check)
|
|
2103
|
+
|
|
2104
|
+
def twisted_winding_element(self, i, eps):
|
|
2105
|
+
r"""
|
|
2106
|
+
Return the twisted winding element of given degree and character.
|
|
2107
|
+
|
|
2108
|
+
INPUT:
|
|
2109
|
+
|
|
2110
|
+
- ``i`` -- integer; `0\le i\le k-2` where `k` is the weight
|
|
2111
|
+
|
|
2112
|
+
- ``eps`` -- character; a Dirichlet character
|
|
2113
|
+
|
|
2114
|
+
OUTPUT:
|
|
2115
|
+
|
|
2116
|
+
(modular symbol) The so-called 'twisted winding element':
|
|
2117
|
+
|
|
2118
|
+
.. MATH::
|
|
2119
|
+
|
|
2120
|
+
\sum_{a \in (\ZZ/m\ZZ)^\times} \varepsilon(a) * [ i, 0, a/m ].
|
|
2121
|
+
|
|
2122
|
+
.. NOTE::
|
|
2123
|
+
|
|
2124
|
+
This will only work if the base ring of the modular symbol
|
|
2125
|
+
space contains the character values.
|
|
2126
|
+
|
|
2127
|
+
EXAMPLES::
|
|
2128
|
+
|
|
2129
|
+
sage: eps = DirichletGroup(5)[2]
|
|
2130
|
+
sage: K = eps.base_ring()
|
|
2131
|
+
sage: M = ModularSymbols(37,2,0,K)
|
|
2132
|
+
sage: M.twisted_winding_element(0,eps)
|
|
2133
|
+
2*(1,23) - 2*(1,32) + 2*(1,34)
|
|
2134
|
+
"""
|
|
2135
|
+
if not isinstance(eps, DirichletCharacter):
|
|
2136
|
+
raise TypeError("eps must be a Dirichlet character.")
|
|
2137
|
+
if (i < 0) or (i > self.weight() - 2):
|
|
2138
|
+
raise ValueError("i must be between 0 and k-2.")
|
|
2139
|
+
|
|
2140
|
+
m = eps.modulus()
|
|
2141
|
+
return self.sum(eps(a) * self.modular_symbol([i, Cusp(0), Cusp(a / m)])
|
|
2142
|
+
for a in m.coprime_integers(m))
|
|
2143
|
+
|
|
2144
|
+
######################################################################
|
|
2145
|
+
# Z-module of integral modular symbols.
|
|
2146
|
+
#######################################################################
|
|
2147
|
+
def integral_structure(self, algorithm='default'):
|
|
2148
|
+
r"""
|
|
2149
|
+
Return the `\ZZ`-structure of this modular symbols
|
|
2150
|
+
space, generated by all integral modular symbols.
|
|
2151
|
+
|
|
2152
|
+
INPUT:
|
|
2153
|
+
|
|
2154
|
+
- ``algorithm`` -- string (default: ``'default'``, choose
|
|
2155
|
+
heuristically)
|
|
2156
|
+
|
|
2157
|
+
- ``'pari'`` -- use pari for the HNF computation
|
|
2158
|
+
|
|
2159
|
+
- ``'padic'`` -- use `p`-adic algorithm (only good for
|
|
2160
|
+
dense case)
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
ALGORITHM: It suffices to consider lattice generated by the free
|
|
2164
|
+
generating symbols `X^iY^{k-2-i}.(u,v)` after quotienting
|
|
2165
|
+
out by the `S` (and `I`) relations, since the
|
|
2166
|
+
quotient by these relations is the same over any ring.
|
|
2167
|
+
|
|
2168
|
+
EXAMPLES: In weight 2 the rational basis is often integral.
|
|
2169
|
+
|
|
2170
|
+
::
|
|
2171
|
+
|
|
2172
|
+
sage: M = ModularSymbols(11,2)
|
|
2173
|
+
sage: M.integral_structure()
|
|
2174
|
+
Free module of degree 3 and rank 3 over Integer Ring
|
|
2175
|
+
Echelon basis matrix:
|
|
2176
|
+
[1 0 0]
|
|
2177
|
+
[0 1 0]
|
|
2178
|
+
[0 0 1]
|
|
2179
|
+
|
|
2180
|
+
This is rarely the case in higher weight::
|
|
2181
|
+
|
|
2182
|
+
sage: M = ModularSymbols(6,4)
|
|
2183
|
+
sage: M.integral_structure()
|
|
2184
|
+
Free module of degree 6 and rank 6 over Integer Ring
|
|
2185
|
+
Echelon basis matrix:
|
|
2186
|
+
[ 1 0 0 0 0 0]
|
|
2187
|
+
[ 0 1 0 0 0 0]
|
|
2188
|
+
[ 0 0 1/2 1/2 1/2 1/2]
|
|
2189
|
+
[ 0 0 0 1 0 0]
|
|
2190
|
+
[ 0 0 0 0 1 0]
|
|
2191
|
+
[ 0 0 0 0 0 1]
|
|
2192
|
+
|
|
2193
|
+
Here is an example involving `\Gamma_1(N)`.
|
|
2194
|
+
|
|
2195
|
+
::
|
|
2196
|
+
|
|
2197
|
+
sage: M = ModularSymbols(Gamma1(5),6)
|
|
2198
|
+
sage: M.integral_structure()
|
|
2199
|
+
Free module of degree 10 and rank 10 over Integer Ring
|
|
2200
|
+
Echelon basis matrix:
|
|
2201
|
+
[ 1 0 0 0 0 0 0 0 0 0]
|
|
2202
|
+
[ 0 1 0 0 0 0 0 0 0 0]
|
|
2203
|
+
[ 0 0 1/96 1/32 23/24 0 1/96 0 7/24 67/96]
|
|
2204
|
+
[ 0 0 0 1/24 23/24 0 0 1/24 1/4 17/24]
|
|
2205
|
+
[ 0 0 0 0 1 0 0 0 0 0]
|
|
2206
|
+
[ 0 0 0 0 0 1/6 0 1/48 23/48 1/3]
|
|
2207
|
+
[ 0 0 0 0 0 0 1/24 1/24 11/24 11/24]
|
|
2208
|
+
[ 0 0 0 0 0 0 0 1/16 7/16 1/2]
|
|
2209
|
+
[ 0 0 0 0 0 0 0 0 1/2 1/2]
|
|
2210
|
+
[ 0 0 0 0 0 0 0 0 0 1]
|
|
2211
|
+
"""
|
|
2212
|
+
if not self.base_ring() == QQ:
|
|
2213
|
+
raise NotImplementedError
|
|
2214
|
+
|
|
2215
|
+
try:
|
|
2216
|
+
return self.__integral_structure
|
|
2217
|
+
except AttributeError:
|
|
2218
|
+
pass
|
|
2219
|
+
|
|
2220
|
+
# The attribute _mod2term is set by self.compute_presentation().
|
|
2221
|
+
# It is a list of pairs (n, c), such that the ith element of the list
|
|
2222
|
+
# is equivalent to c times the n-th basis Manin symbol.
|
|
2223
|
+
G = {i for i, _ in self._mod2term}
|
|
2224
|
+
|
|
2225
|
+
# Now G is a set of integer i such that these integers gives
|
|
2226
|
+
# indices of Manin symbols that together generate the integral
|
|
2227
|
+
# structure. We next obtain the corresponding list of elements
|
|
2228
|
+
# by passing to the quotient by the remaining relations
|
|
2229
|
+
# via the _manin_gens_to_basis attribute.
|
|
2230
|
+
|
|
2231
|
+
# Next we take each element of X, which gives a linear combination
|
|
2232
|
+
# of the basis of the underlying vector space of self, and compute
|
|
2233
|
+
# the Z-module they span.
|
|
2234
|
+
|
|
2235
|
+
G = sorted(G)
|
|
2236
|
+
B = self._manin_gens_to_basis.matrix_from_rows(list(G)).dense_matrix()
|
|
2237
|
+
B, d = B._clear_denom()
|
|
2238
|
+
if algorithm == 'default':
|
|
2239
|
+
# pari is much better in the weight 2 case when the input
|
|
2240
|
+
# matrix is extremely sparse; the p-adic algorithm is
|
|
2241
|
+
# terrible in the sparse case.
|
|
2242
|
+
if self.weight() == 2:
|
|
2243
|
+
algorithm = 'pari'
|
|
2244
|
+
else:
|
|
2245
|
+
algorithm = 'padic'
|
|
2246
|
+
if algorithm == 'pari':
|
|
2247
|
+
B = B.echelon_form(algorithm='pari', include_zero_rows=False)
|
|
2248
|
+
elif algorithm == 'padic':
|
|
2249
|
+
B = B.echelon_form(algorithm='padic', include_zero_rows=False)
|
|
2250
|
+
else:
|
|
2251
|
+
raise ValueError("unknown algorithm '%s'" % algorithm)
|
|
2252
|
+
W = B.row_module()
|
|
2253
|
+
if d != 1:
|
|
2254
|
+
W = W.scale(1/d)
|
|
2255
|
+
self.__integral_structure = W
|
|
2256
|
+
assert W.rank() == self.rank(), "there is a bug in computing integral structure on modular symbols"
|
|
2257
|
+
return self.__integral_structure
|
|
2258
|
+
|
|
2259
|
+
######################################################################
|
|
2260
|
+
# Eigenvalues
|
|
2261
|
+
#######################################################################
|
|
2262
|
+
def compact_newform_eigenvalues(self, v, names='alpha'):
|
|
2263
|
+
r"""
|
|
2264
|
+
Return compact systems of eigenvalues for each Galois conjugacy
|
|
2265
|
+
class of cuspidal newforms in this ambient space.
|
|
2266
|
+
|
|
2267
|
+
INPUT:
|
|
2268
|
+
|
|
2269
|
+
- ``v`` -- list of positive integers
|
|
2270
|
+
|
|
2271
|
+
OUTPUT:
|
|
2272
|
+
|
|
2273
|
+
List of pairs (E, x), where ``E*x`` is a vector with entries the
|
|
2274
|
+
eigenvalues `a_n` for `n \in v`.
|
|
2275
|
+
|
|
2276
|
+
EXAMPLES::
|
|
2277
|
+
|
|
2278
|
+
sage: M = ModularSymbols(43,2,1)
|
|
2279
|
+
sage: X = M.compact_newform_eigenvalues(prime_range(10))
|
|
2280
|
+
sage: X[0][0] * X[0][1]
|
|
2281
|
+
(-2, -2, -4, 0)
|
|
2282
|
+
sage: X[1][0] * X[1][1]
|
|
2283
|
+
(alpha1, -alpha1, -alpha1 + 2, alpha1 - 2)
|
|
2284
|
+
|
|
2285
|
+
::
|
|
2286
|
+
|
|
2287
|
+
sage: M = ModularSymbols(DirichletGroup(24,QQ).1,2,sign=1)
|
|
2288
|
+
sage: M.compact_newform_eigenvalues(prime_range(10),'a')
|
|
2289
|
+
[(
|
|
2290
|
+
[-1/2 -1/2]
|
|
2291
|
+
[ 1/2 -1/2]
|
|
2292
|
+
[ -1 1]
|
|
2293
|
+
[ -2 0], (1, -2*a0 - 1)
|
|
2294
|
+
)]
|
|
2295
|
+
sage: a = M.compact_newform_eigenvalues([1..10],'a')[0]
|
|
2296
|
+
sage: a[0]*a[1]
|
|
2297
|
+
(1, a0, a0 + 1, -2*a0 - 2, -2*a0 - 2, -a0 - 2, -2, 2*a0 + 4, -1, 2*a0 + 4)
|
|
2298
|
+
sage: M = ModularSymbols(DirichletGroup(13).0^2,2,sign=1)
|
|
2299
|
+
sage: M.compact_newform_eigenvalues(prime_range(10),'a')
|
|
2300
|
+
[(
|
|
2301
|
+
[ -zeta6 - 1]
|
|
2302
|
+
[ 2*zeta6 - 2]
|
|
2303
|
+
[-2*zeta6 + 1]
|
|
2304
|
+
[ 0], (1)
|
|
2305
|
+
)]
|
|
2306
|
+
sage: a = M.compact_newform_eigenvalues([1..10],'a')[0]
|
|
2307
|
+
sage: a[0]*a[1]
|
|
2308
|
+
(1, -zeta6 - 1, 2*zeta6 - 2, zeta6, -2*zeta6 + 1, -2*zeta6 + 4, 0, 2*zeta6 - 1, -zeta6, 3*zeta6 - 3)
|
|
2309
|
+
"""
|
|
2310
|
+
if self.sign() == 0:
|
|
2311
|
+
raise ValueError("sign must be nonzero")
|
|
2312
|
+
v = list(v)
|
|
2313
|
+
|
|
2314
|
+
# Get decomposition of this space
|
|
2315
|
+
D = self.cuspidal_submodule().new_subspace().decomposition()
|
|
2316
|
+
for A in D:
|
|
2317
|
+
# since sign is zero and we're on the new cuspidal subspace
|
|
2318
|
+
# each factor is definitely simple.
|
|
2319
|
+
A._is_simple = True
|
|
2320
|
+
B = [A.dual_free_module().basis_matrix().transpose() for A in D]
|
|
2321
|
+
|
|
2322
|
+
# Normalize the names strings.
|
|
2323
|
+
names = ['%s%s' % (names, i) for i in range(len(B))]
|
|
2324
|
+
|
|
2325
|
+
# Find an integer i such that the i-th columns of the basis for the
|
|
2326
|
+
# dual modules corresponding to the factors in D are all nonzero.
|
|
2327
|
+
nz = None
|
|
2328
|
+
for i in range(self.dimension()):
|
|
2329
|
+
# Decide if this i works, i.e., ith row of every element of B is nonzero.
|
|
2330
|
+
bad = False
|
|
2331
|
+
for C in B:
|
|
2332
|
+
if C.row(i) == 0:
|
|
2333
|
+
# i is bad.
|
|
2334
|
+
bad = True
|
|
2335
|
+
continue
|
|
2336
|
+
if bad:
|
|
2337
|
+
continue
|
|
2338
|
+
# It turns out that i is not bad.
|
|
2339
|
+
nz = i
|
|
2340
|
+
break
|
|
2341
|
+
|
|
2342
|
+
if nz is not None:
|
|
2343
|
+
R = self.hecke_images(nz, v)
|
|
2344
|
+
return [(R * m, D[i].dual_eigenvector(names=names[i],
|
|
2345
|
+
lift=False, nz=nz))
|
|
2346
|
+
for i, m in enumerate(B)]
|
|
2347
|
+
|
|
2348
|
+
# No single i works, so we do something less uniform.
|
|
2349
|
+
ans = []
|
|
2350
|
+
cache = {}
|
|
2351
|
+
for i in range(len(D)):
|
|
2352
|
+
nz = D[i]._eigen_nonzero()
|
|
2353
|
+
if nz in cache:
|
|
2354
|
+
R = cache[nz]
|
|
2355
|
+
else:
|
|
2356
|
+
R = self.hecke_images(nz, v)
|
|
2357
|
+
cache[nz] = R
|
|
2358
|
+
ans.append((R * B[i], D[i].dual_eigenvector(names=names[i],
|
|
2359
|
+
lift=False, nz=nz)))
|
|
2360
|
+
return ans
|
|
2361
|
+
|
|
2362
|
+
def __pari__(self):
|
|
2363
|
+
"""
|
|
2364
|
+
Return a PARI object corresponding to ``self``.
|
|
2365
|
+
|
|
2366
|
+
TESTS::
|
|
2367
|
+
|
|
2368
|
+
sage: ModularSymbols(Gamma1(5), 2).__pari__()
|
|
2369
|
+
Traceback (most recent call last):
|
|
2370
|
+
...
|
|
2371
|
+
NotImplementedError: PARI modular symbols are only implemented for Gamma0(n)
|
|
2372
|
+
"""
|
|
2373
|
+
raise NotImplementedError('PARI modular symbols are only implemented for Gamma0(n)')
|
|
2374
|
+
|
|
2375
|
+
def _pari_pairing(self):
|
|
2376
|
+
r"""
|
|
2377
|
+
Return the matrix of the canonical pairing between this space and
|
|
2378
|
+
the corresponding space of modular symbols in PARI.
|
|
2379
|
+
|
|
2380
|
+
Let `M` be an ambient space of modular symbols over a field `K`
|
|
2381
|
+
of characteristic 0. The corresponding space `P` in PARI is
|
|
2382
|
+
canonically dual to `M`, giving rise to a `K`-bilinear map
|
|
2383
|
+
|
|
2384
|
+
.. MATH::
|
|
2385
|
+
|
|
2386
|
+
E\colon M \times P \to K.
|
|
2387
|
+
|
|
2388
|
+
OUTPUT: the matrix of the bilinear map `E`
|
|
2389
|
+
|
|
2390
|
+
This is currently only implemented for spaces of modular
|
|
2391
|
+
symbols of trivial character.
|
|
2392
|
+
|
|
2393
|
+
EXAMPLES::
|
|
2394
|
+
|
|
2395
|
+
sage: M = ModularSymbols(Gamma0(5), 6)
|
|
2396
|
+
sage: P = M.__pari__()
|
|
2397
|
+
sage: E = M._pari_pairing(); E
|
|
2398
|
+
[ 0 -1 0 0]
|
|
2399
|
+
[ 0 0 8 -27]
|
|
2400
|
+
[ 8 0 0 13]
|
|
2401
|
+
[ 24 0 8 37]
|
|
2402
|
+
|
|
2403
|
+
The duality is compatible with (for example) Hecke operators
|
|
2404
|
+
and the star involution::
|
|
2405
|
+
|
|
2406
|
+
sage: M.hecke_matrix(5) * E == E * P.mshecke(5)
|
|
2407
|
+
True
|
|
2408
|
+
sage: M.star_involution().matrix() * E == E * P.msstar()
|
|
2409
|
+
True
|
|
2410
|
+
"""
|
|
2411
|
+
if self.weight() == 2:
|
|
2412
|
+
return self._pari_tensor().inverse()
|
|
2413
|
+
from sage.matrix.constructor import matrix
|
|
2414
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
2415
|
+
P = self.__pari__()
|
|
2416
|
+
I = matrix.identity(self.rank()).__pari__()
|
|
2417
|
+
m = Integer(self.weight() - 2)
|
|
2418
|
+
R = PolynomialRing(QQ, 'x')
|
|
2419
|
+
x = R.gen()
|
|
2420
|
+
|
|
2421
|
+
def ev(s):
|
|
2422
|
+
# The Manin symbol s = X^i (c, d) corresponds to the
|
|
2423
|
+
# modular symbol (dX - bY)^i (-cX + aY)^(m - i) {b/d, a/c}.
|
|
2424
|
+
# The code below computes the canonical pairing of this
|
|
2425
|
+
# modular symbol with the distinguished basis of P.
|
|
2426
|
+
i = s.i
|
|
2427
|
+
a, b, c, d = s.lift_to_sl2z()
|
|
2428
|
+
e = [R(p) for p in P.mseval(I, matrix(2, 2, [b, a, d, c]))]
|
|
2429
|
+
g = (d * x - b)**i * (-c * x + a)**(m - i)
|
|
2430
|
+
return [sum(f[j] * g[m - j] / m.binomial(j) for j in range(m + 1))
|
|
2431
|
+
for f in e]
|
|
2432
|
+
return matrix([ev(s) for s in self.manin_symbols_basis()])
|
|
2433
|
+
|
|
2434
|
+
def _pari_tensor(self):
|
|
2435
|
+
r"""
|
|
2436
|
+
Return a matrix expressing the duality between this space and the
|
|
2437
|
+
corresponding space of modular symbols in PARI.
|
|
2438
|
+
|
|
2439
|
+
Let `M` be an ambient space of modular symbols over a field `K`
|
|
2440
|
+
of characteristic 0. The corresponding space `P` in PARI is
|
|
2441
|
+
canonically dual to `M`, giving rise to an element
|
|
2442
|
+
|
|
2443
|
+
.. MATH::
|
|
2444
|
+
|
|
2445
|
+
T \in P \otimes_K M.
|
|
2446
|
+
|
|
2447
|
+
OUTPUT: the matrix of the element `T \in P \otimes_K M`.
|
|
2448
|
+
This is the inverse of the matrix returned by
|
|
2449
|
+
:meth:`_pari_pairing`.
|
|
2450
|
+
|
|
2451
|
+
This is currently only implemented for spaces of modular
|
|
2452
|
+
symbols of trivial character.
|
|
2453
|
+
|
|
2454
|
+
EXAMPLES::
|
|
2455
|
+
|
|
2456
|
+
sage: M = ModularSymbols(Gamma0(37), 2)
|
|
2457
|
+
sage: P = M.__pari__()
|
|
2458
|
+
sage: T = M._pari_tensor(); T
|
|
2459
|
+
[ 1 0 0 0 0]
|
|
2460
|
+
[ 0 0 -1 0 0]
|
|
2461
|
+
[ 0 0 1 -1 0]
|
|
2462
|
+
[ 0 -1 0 -1 1]
|
|
2463
|
+
[ 0 0 0 1 -1]
|
|
2464
|
+
|
|
2465
|
+
The duality is compatible with (for example) Hecke operators
|
|
2466
|
+
and the star involution::
|
|
2467
|
+
|
|
2468
|
+
sage: T * M.hecke_matrix(3) == P.mshecke(3) * T
|
|
2469
|
+
True
|
|
2470
|
+
sage: T * M.star_involution().matrix() == P.msstar() * T
|
|
2471
|
+
True
|
|
2472
|
+
"""
|
|
2473
|
+
if self.weight() != 2:
|
|
2474
|
+
return self._pari_pairing().inverse()
|
|
2475
|
+
from sage.matrix.constructor import matrix
|
|
2476
|
+
gens = self.__pari__().mspathgens()[0][:self.rank()].sage()
|
|
2477
|
+
# gens is a basis for the space of modular symbols of weight 2
|
|
2478
|
+
# (in the sense of Sage), and the distinguished basis of the
|
|
2479
|
+
# corresponding PARI space of modular symbols is dual to this.
|
|
2480
|
+
return matrix([self.modular_symbol(g).element() for g in gens])
|
|
2481
|
+
|
|
2482
|
+
|
|
2483
|
+
class ModularSymbolsAmbient_wtk_g0(ModularSymbolsAmbient):
|
|
2484
|
+
r"""
|
|
2485
|
+
Modular symbols for `\Gamma_0(N)` of integer weight
|
|
2486
|
+
`k > 2` over the field `F`.
|
|
2487
|
+
|
|
2488
|
+
For weight `2`, it is faster to use ``ModularSymbols_wt2_g0``.
|
|
2489
|
+
|
|
2490
|
+
INPUT:
|
|
2491
|
+
|
|
2492
|
+
- ``N`` -- integer; the level
|
|
2493
|
+
|
|
2494
|
+
- ``k`` -- integer; weight = 2
|
|
2495
|
+
|
|
2496
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
2497
|
+
|
|
2498
|
+
- ``F`` -- field
|
|
2499
|
+
|
|
2500
|
+
EXAMPLES::
|
|
2501
|
+
|
|
2502
|
+
sage: ModularSymbols(1,12)
|
|
2503
|
+
Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
|
|
2504
|
+
sage: ModularSymbols(1,12, sign=1).dimension()
|
|
2505
|
+
2
|
|
2506
|
+
sage: ModularSymbols(15,4, sign=-1).dimension()
|
|
2507
|
+
4
|
|
2508
|
+
sage: ModularSymbols(6,6).dimension()
|
|
2509
|
+
10
|
|
2510
|
+
sage: ModularSymbols(36,4).dimension()
|
|
2511
|
+
36
|
|
2512
|
+
"""
|
|
2513
|
+
def __init__(self, N, k, sign, F, custom_init=None, category=None):
|
|
2514
|
+
r"""
|
|
2515
|
+
Initialize a space of modular symbols of weight `k` for
|
|
2516
|
+
`\Gamma_0(N)`, over `\QQ`.
|
|
2517
|
+
|
|
2518
|
+
For weight `2`, it is faster to use
|
|
2519
|
+
``ModularSymbols_wt2_g0``.
|
|
2520
|
+
|
|
2521
|
+
INPUT:
|
|
2522
|
+
|
|
2523
|
+
- ``N`` -- integer; the level
|
|
2524
|
+
|
|
2525
|
+
- ``k`` -- integer; weight = 2
|
|
2526
|
+
|
|
2527
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
2528
|
+
|
|
2529
|
+
- ``F`` -- field
|
|
2530
|
+
|
|
2531
|
+
EXAMPLES::
|
|
2532
|
+
|
|
2533
|
+
sage: ModularSymbols(1,12)
|
|
2534
|
+
Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
|
|
2535
|
+
sage: ModularSymbols(1,12, sign=1).dimension()
|
|
2536
|
+
2
|
|
2537
|
+
sage: ModularSymbols(15,4, sign=-1).dimension()
|
|
2538
|
+
4
|
|
2539
|
+
sage: ModularSymbols(6,6).dimension()
|
|
2540
|
+
10
|
|
2541
|
+
sage: ModularSymbols(36,4).dimension()
|
|
2542
|
+
36
|
|
2543
|
+
"""
|
|
2544
|
+
N = int(N)
|
|
2545
|
+
k = int(k)
|
|
2546
|
+
sign = int(sign)
|
|
2547
|
+
if sign not in [-1, 0, 1]:
|
|
2548
|
+
raise TypeError("sign must be an int in [-1,0,1]")
|
|
2549
|
+
|
|
2550
|
+
ModularSymbolsAmbient.__init__(self, weight=k, group=arithgroup.Gamma0(N),
|
|
2551
|
+
sign=sign, base_ring=F,
|
|
2552
|
+
custom_init=custom_init, category=category)
|
|
2553
|
+
|
|
2554
|
+
def _dimension_formula(self):
|
|
2555
|
+
r"""
|
|
2556
|
+
Return the dimension of this space using the formula.
|
|
2557
|
+
|
|
2558
|
+
EXAMPLES::
|
|
2559
|
+
|
|
2560
|
+
sage: M = ModularSymbols(37,6)
|
|
2561
|
+
sage: M.dimension()
|
|
2562
|
+
32
|
|
2563
|
+
sage: M._dimension_formula()
|
|
2564
|
+
32
|
|
2565
|
+
"""
|
|
2566
|
+
if self.base_ring().characteristic() == 0:
|
|
2567
|
+
k, sign = self.weight(), self.sign()
|
|
2568
|
+
if sign != 0:
|
|
2569
|
+
return None
|
|
2570
|
+
if k % 2:
|
|
2571
|
+
return 0
|
|
2572
|
+
elif k > 2:
|
|
2573
|
+
return 2 * self.group().dimension_cusp_forms(k) + self.group().ncusps()
|
|
2574
|
+
else:
|
|
2575
|
+
return 2*self.group().dimension_cusp_forms(k) + self.group().ncusps() - 1
|
|
2576
|
+
else:
|
|
2577
|
+
raise NotImplementedError
|
|
2578
|
+
|
|
2579
|
+
def _repr_(self):
|
|
2580
|
+
r"""
|
|
2581
|
+
Return the string representation of this Modular Symbols space.
|
|
2582
|
+
|
|
2583
|
+
EXAMPLES::
|
|
2584
|
+
|
|
2585
|
+
sage: M = ModularSymbols(37,6)
|
|
2586
|
+
sage: M # indirect doctest
|
|
2587
|
+
Modular Symbols space of dimension 32 for Gamma_0(37) of weight 6 with sign 0 over Rational Field
|
|
2588
|
+
"""
|
|
2589
|
+
return ("Modular Symbols space of dimension %s for Gamma_0(%s) of weight %s with sign %s " +
|
|
2590
|
+
"over %s") % (self.dimension(), self.level(), self.weight(), self.sign(),
|
|
2591
|
+
self.base_ring())
|
|
2592
|
+
|
|
2593
|
+
def _cuspidal_submodule_dimension_formula(self):
|
|
2594
|
+
r"""
|
|
2595
|
+
Return the dimension of the cuspidal subspace, using the formula.
|
|
2596
|
+
|
|
2597
|
+
EXAMPLES::
|
|
2598
|
+
|
|
2599
|
+
sage: M = ModularSymbols(37,4)
|
|
2600
|
+
sage: M.cuspidal_subspace().dimension()
|
|
2601
|
+
18
|
|
2602
|
+
sage: M._cuspidal_submodule_dimension_formula()
|
|
2603
|
+
18
|
|
2604
|
+
"""
|
|
2605
|
+
if self.base_ring().characteristic() == 0:
|
|
2606
|
+
k, sign = self.weight(), self.sign()
|
|
2607
|
+
if sign == 0:
|
|
2608
|
+
m = 2
|
|
2609
|
+
else:
|
|
2610
|
+
m = 1
|
|
2611
|
+
return m * self.group().dimension_cusp_forms(k)
|
|
2612
|
+
else:
|
|
2613
|
+
raise NotImplementedError
|
|
2614
|
+
|
|
2615
|
+
def _degeneracy_raising_matrix_1(self, M):
|
|
2616
|
+
r"""
|
|
2617
|
+
Return the matrix of the degeneracy map (with t = 1) to level
|
|
2618
|
+
`N`, where `N` is a multiple of the level.
|
|
2619
|
+
|
|
2620
|
+
INPUT:
|
|
2621
|
+
|
|
2622
|
+
- ``M`` -- a space of Gamma0 modular symbols of the same weight as
|
|
2623
|
+
``self``, with level an integer multiple of the level of ``self``
|
|
2624
|
+
|
|
2625
|
+
OUTPUT: the matrix of the degeneracy raising map to `M`
|
|
2626
|
+
|
|
2627
|
+
EXAMPLES::
|
|
2628
|
+
|
|
2629
|
+
sage: M = ModularSymbols(37,4)
|
|
2630
|
+
sage: M._degeneracy_raising_matrix_1(ModularSymbols(74, 4))
|
|
2631
|
+
20 x 58 dense matrix over Rational Field (use the '.str()' method to see the entries)
|
|
2632
|
+
sage: M.dimension()
|
|
2633
|
+
20
|
|
2634
|
+
sage: ModularSymbols(74,4).dimension()
|
|
2635
|
+
58
|
|
2636
|
+
"""
|
|
2637
|
+
level = int(M.level())
|
|
2638
|
+
N = self.level()
|
|
2639
|
+
|
|
2640
|
+
# 1. Find coset representatives H for Gamma_0(M.level()) \ Gamma_0(self.level())
|
|
2641
|
+
# (need to be careful in some small levels, cf. #13198)
|
|
2642
|
+
|
|
2643
|
+
if isinstance(M.group(), arithgroup.Gamma0_class):
|
|
2644
|
+
H = arithgroup.degeneracy_coset_representatives_gamma0(level, N, 1)
|
|
2645
|
+
elif isinstance(M.group(), arithgroup.Gamma1_class):
|
|
2646
|
+
H = arithgroup.degeneracy_coset_representatives_gamma1(level, N, 1)
|
|
2647
|
+
else:
|
|
2648
|
+
raise NotImplementedError("Degeneracy raising maps not implemented for GammaH levels")
|
|
2649
|
+
|
|
2650
|
+
# 2. The map is
|
|
2651
|
+
# [P,pi(g)] |--> sum_{h in H} [P, pi(h*g)]
|
|
2652
|
+
#
|
|
2653
|
+
MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
|
|
2654
|
+
if self.dimension() == 0 or M.dimension() == 0:
|
|
2655
|
+
return MS(0)
|
|
2656
|
+
rows = []
|
|
2657
|
+
B = self.manin_basis()
|
|
2658
|
+
syms = self.manin_symbols()
|
|
2659
|
+
H = [M2Z(h) for h in H]
|
|
2660
|
+
for n in B:
|
|
2661
|
+
z = M(0)
|
|
2662
|
+
s = syms.manin_symbol(n)
|
|
2663
|
+
g = M2Z(list(s.lift_to_sl2z(N)))
|
|
2664
|
+
i = s.i
|
|
2665
|
+
# We apply each matrix in H according to the above formula
|
|
2666
|
+
for h in H:
|
|
2667
|
+
hg = h*g
|
|
2668
|
+
z += M((i, hg[1, 0], hg[1, 1]))
|
|
2669
|
+
rows.append(z.element())
|
|
2670
|
+
|
|
2671
|
+
return MS(rows)
|
|
2672
|
+
|
|
2673
|
+
def _cuspidal_new_submodule_dimension_formula(self):
|
|
2674
|
+
r"""
|
|
2675
|
+
Return the dimension of the new cuspidal subspace, via the formula.
|
|
2676
|
+
|
|
2677
|
+
EXAMPLES::
|
|
2678
|
+
|
|
2679
|
+
sage: M = ModularSymbols(100,2)
|
|
2680
|
+
sage: M._cuspidal_new_submodule_dimension_formula()
|
|
2681
|
+
2
|
|
2682
|
+
sage: M.cuspidal_subspace().new_subspace().dimension()
|
|
2683
|
+
2
|
|
2684
|
+
"""
|
|
2685
|
+
if self.base_ring().characteristic() == 0:
|
|
2686
|
+
k, sign = self.weight(), self.sign()
|
|
2687
|
+
if sign == 0:
|
|
2688
|
+
m = 2
|
|
2689
|
+
else:
|
|
2690
|
+
m = 1
|
|
2691
|
+
return m * self.group().dimension_new_cusp_forms(k)
|
|
2692
|
+
else:
|
|
2693
|
+
raise NotImplementedError
|
|
2694
|
+
|
|
2695
|
+
def boundary_space(self):
|
|
2696
|
+
r"""
|
|
2697
|
+
Return the space of boundary modular symbols for this space.
|
|
2698
|
+
|
|
2699
|
+
EXAMPLES::
|
|
2700
|
+
|
|
2701
|
+
sage: M = ModularSymbols(100,2)
|
|
2702
|
+
sage: M.boundary_space()
|
|
2703
|
+
Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(100) of weight 2 over Rational Field
|
|
2704
|
+
"""
|
|
2705
|
+
try:
|
|
2706
|
+
return self.__boundary_space
|
|
2707
|
+
except AttributeError:
|
|
2708
|
+
pass
|
|
2709
|
+
self.__boundary_space = boundary.BoundarySpace_wtk_g0(
|
|
2710
|
+
self.level(), self.weight(), self.sign(), self.base_ring())
|
|
2711
|
+
return self.__boundary_space
|
|
2712
|
+
|
|
2713
|
+
def manin_symbols(self):
|
|
2714
|
+
r"""
|
|
2715
|
+
Return the Manin symbol list of this modular symbol space.
|
|
2716
|
+
|
|
2717
|
+
EXAMPLES::
|
|
2718
|
+
|
|
2719
|
+
sage: M = ModularSymbols(100,4)
|
|
2720
|
+
sage: M.manin_symbols()
|
|
2721
|
+
Manin Symbol List of weight 4 for Gamma0(100)
|
|
2722
|
+
sage: len(M.manin_symbols())
|
|
2723
|
+
540
|
|
2724
|
+
"""
|
|
2725
|
+
try:
|
|
2726
|
+
return self.__manin_symbols
|
|
2727
|
+
except AttributeError:
|
|
2728
|
+
self.__manin_symbols = ManinSymbolList_gamma0(
|
|
2729
|
+
level=self.level(), weight=self.weight())
|
|
2730
|
+
return self.__manin_symbols
|
|
2731
|
+
|
|
2732
|
+
def _hecke_images(self, i, v):
|
|
2733
|
+
"""
|
|
2734
|
+
Return matrix whose rows are the images of the `i`-th
|
|
2735
|
+
standard basis vector under the Hecke operators `T_p` for
|
|
2736
|
+
all integers in `v`.
|
|
2737
|
+
|
|
2738
|
+
INPUT:
|
|
2739
|
+
|
|
2740
|
+
- ``i`` -- nonnegative integer
|
|
2741
|
+
|
|
2742
|
+
- ``v`` -- list of positive integer
|
|
2743
|
+
|
|
2744
|
+
OUTPUT: ``matrix`` -- whose rows are the Hecke images
|
|
2745
|
+
|
|
2746
|
+
EXAMPLES::
|
|
2747
|
+
|
|
2748
|
+
sage: M = ModularSymbols(11,4,1)
|
|
2749
|
+
sage: mat = M._hecke_images(0,[1,2,3,4])
|
|
2750
|
+
sage: M.T(1)(M.0).element() == mat[0]
|
|
2751
|
+
True
|
|
2752
|
+
sage: M.T(2)(M.0).element() == mat[1]
|
|
2753
|
+
True
|
|
2754
|
+
sage: M.T(3)(M.0).element() == mat[2]
|
|
2755
|
+
True
|
|
2756
|
+
sage: M.T(4)(M.0).element() == mat[3]
|
|
2757
|
+
True
|
|
2758
|
+
|
|
2759
|
+
sage: M = ModularSymbols(12,4)
|
|
2760
|
+
sage: mat = M._hecke_images(0,[1,2,3,4])
|
|
2761
|
+
sage: M.T(1)(M.0).element() == mat[0]
|
|
2762
|
+
True
|
|
2763
|
+
sage: M.T(2)(M.0).element() == mat[1]
|
|
2764
|
+
True
|
|
2765
|
+
sage: M.T(3)(M.0).element() == mat[2]
|
|
2766
|
+
True
|
|
2767
|
+
sage: M.T(4)(M.0).element() == mat[3]
|
|
2768
|
+
True
|
|
2769
|
+
"""
|
|
2770
|
+
# Find basis vector for ambient space such that it is not in
|
|
2771
|
+
# the kernel of the dual space corresponding to self.
|
|
2772
|
+
c = self.manin_generators()[self.manin_basis()[i]]
|
|
2773
|
+
N = self.level()
|
|
2774
|
+
return heilbronn.hecke_images_gamma0_weight_k(c.u, c.v, c.i, N, self.weight(),
|
|
2775
|
+
v, self.manin_gens_to_basis())
|
|
2776
|
+
|
|
2777
|
+
@cached_method
|
|
2778
|
+
def __pari__(self):
|
|
2779
|
+
"""
|
|
2780
|
+
Return a PARI object corresponding to ``self``.
|
|
2781
|
+
|
|
2782
|
+
EXAMPLES::
|
|
2783
|
+
|
|
2784
|
+
sage: ModularSymbols(Gamma0(1), 2).__pari__()
|
|
2785
|
+
[[[[Vecsmall([0, 1])], [0], 1, [Vecsmall([]), Vecsmall([])],
|
|
2786
|
+
Vecsmall([1]), Vecsmall([]), Vecsmall([])],
|
|
2787
|
+
0, 0, 0, Vecsmall([1]), 0, 0, [[1, 1; [0, 1; -1, 0], 1]],
|
|
2788
|
+
[[1, 1; [0, -1; 1, -1], 1; [-1, 1; -1, 0], 1]], 0,
|
|
2789
|
+
Vecsmall([0, 0, 1, 1, 2]), [[Vecsmall([1, 0]), Vecsmall([0, 1])]],
|
|
2790
|
+
0, 0, 0, [Vecsmall([1, 1]), [Vecsmall([0, 1]), 0], [Vecsmall([1, 0])]]],
|
|
2791
|
+
[0, [;], [[;], [;], 1, Vecsmall([])]],
|
|
2792
|
+
[[], Vecsmall([2, 0]), Vecsmall([0, 0]), 0, [[;], [;], 1, Vecsmall([])]]]
|
|
2793
|
+
|
|
2794
|
+
.. NOTE::
|
|
2795
|
+
|
|
2796
|
+
Spaces of modular symbols as implemented in PARI are
|
|
2797
|
+
canonically dual to those implemented in Sage. See
|
|
2798
|
+
:meth:`ModularSymbolsAmbient._pari_pairing` and
|
|
2799
|
+
:meth:`ModularSymbolsAmbient._pari_tensor` for how to use
|
|
2800
|
+
this duality.
|
|
2801
|
+
"""
|
|
2802
|
+
return self.level().__pari__().msinit(self.weight(), self.sign())
|
|
2803
|
+
|
|
2804
|
+
|
|
2805
|
+
class ModularSymbolsAmbient_wt2_g0(ModularSymbolsAmbient_wtk_g0):
|
|
2806
|
+
r"""
|
|
2807
|
+
Modular symbols for `\Gamma_0(N)` of integer weight `2` over the field
|
|
2808
|
+
`F`.
|
|
2809
|
+
|
|
2810
|
+
INPUT:
|
|
2811
|
+
|
|
2812
|
+
- ``N`` -- integer; the level
|
|
2813
|
+
|
|
2814
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
2815
|
+
|
|
2816
|
+
OUTPUT:
|
|
2817
|
+
|
|
2818
|
+
The space of modular symbols of weight `2`, trivial character, level
|
|
2819
|
+
`N` and given sign.
|
|
2820
|
+
|
|
2821
|
+
EXAMPLES::
|
|
2822
|
+
|
|
2823
|
+
sage: ModularSymbols(Gamma0(12),2)
|
|
2824
|
+
Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Rational Field
|
|
2825
|
+
"""
|
|
2826
|
+
def __init__(self, N, sign, F, custom_init=None, category=None):
|
|
2827
|
+
"""
|
|
2828
|
+
Initialize a space of modular symbols.
|
|
2829
|
+
|
|
2830
|
+
INPUT:
|
|
2831
|
+
|
|
2832
|
+
- ``N`` -- integer; the level
|
|
2833
|
+
|
|
2834
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
2835
|
+
|
|
2836
|
+
OUTPUT:
|
|
2837
|
+
|
|
2838
|
+
The space of modular symbols of weight 2, trivial character,
|
|
2839
|
+
level N and given sign.
|
|
2840
|
+
|
|
2841
|
+
EXAMPLES::
|
|
2842
|
+
|
|
2843
|
+
sage: M = ModularSymbols(Gamma0(12),2)
|
|
2844
|
+
"""
|
|
2845
|
+
ModularSymbolsAmbient_wtk_g0.__init__(self, N=N, k=2, sign=sign, F=F,
|
|
2846
|
+
custom_init=custom_init, category=category)
|
|
2847
|
+
|
|
2848
|
+
def _dimension_formula(self):
|
|
2849
|
+
r"""
|
|
2850
|
+
Return the dimension of this space using the formula.
|
|
2851
|
+
|
|
2852
|
+
EXAMPLES::
|
|
2853
|
+
|
|
2854
|
+
sage: M = ModularSymbols(37,6)
|
|
2855
|
+
sage: M.dimension()
|
|
2856
|
+
32
|
|
2857
|
+
sage: M._dimension_formula()
|
|
2858
|
+
32
|
|
2859
|
+
"""
|
|
2860
|
+
if self.base_ring().characteristic() == 0:
|
|
2861
|
+
if self.sign() != 0:
|
|
2862
|
+
return None
|
|
2863
|
+
return 2*self.group().dimension_cusp_forms(2) + self.group().ncusps() - 1
|
|
2864
|
+
else:
|
|
2865
|
+
raise NotImplementedError
|
|
2866
|
+
|
|
2867
|
+
def _cuspidal_submodule_dimension_formula(self):
|
|
2868
|
+
r"""
|
|
2869
|
+
Return the dimension of the cuspidal subspace, using the formula.
|
|
2870
|
+
|
|
2871
|
+
EXAMPLES::
|
|
2872
|
+
|
|
2873
|
+
sage: M = ModularSymbols(37,4)
|
|
2874
|
+
sage: M.cuspidal_subspace().dimension()
|
|
2875
|
+
18
|
|
2876
|
+
sage: M._cuspidal_submodule_dimension_formula()
|
|
2877
|
+
18
|
|
2878
|
+
"""
|
|
2879
|
+
if self.base_ring().characteristic() == 0:
|
|
2880
|
+
if self.sign() == 0:
|
|
2881
|
+
m = 2
|
|
2882
|
+
else:
|
|
2883
|
+
m = 1
|
|
2884
|
+
return m * self.group().dimension_cusp_forms(2)
|
|
2885
|
+
else:
|
|
2886
|
+
raise NotImplementedError
|
|
2887
|
+
|
|
2888
|
+
def _cuspidal_new_submodule_dimension_formula(self):
|
|
2889
|
+
r"""
|
|
2890
|
+
Return the dimension of the new cuspidal subspace, via the formula.
|
|
2891
|
+
|
|
2892
|
+
EXAMPLES::
|
|
2893
|
+
|
|
2894
|
+
sage: M = ModularSymbols(100,2)
|
|
2895
|
+
sage: M._cuspidal_new_submodule_dimension_formula()
|
|
2896
|
+
2
|
|
2897
|
+
sage: M.cuspidal_subspace().new_subspace().dimension()
|
|
2898
|
+
2
|
|
2899
|
+
"""
|
|
2900
|
+
if self.base_ring().characteristic() == 0:
|
|
2901
|
+
if self.sign() == 0:
|
|
2902
|
+
m = 2
|
|
2903
|
+
else:
|
|
2904
|
+
m = 1
|
|
2905
|
+
return m * self.group().dimension_new_cusp_forms(2)
|
|
2906
|
+
else:
|
|
2907
|
+
raise NotImplementedError
|
|
2908
|
+
|
|
2909
|
+
def _compute_hecke_matrix_prime(self, p, rows=None):
|
|
2910
|
+
r"""
|
|
2911
|
+
Compute and return the matrix of the `p`-th Hecke operator.
|
|
2912
|
+
|
|
2913
|
+
EXAMPLES::
|
|
2914
|
+
|
|
2915
|
+
sage: m = ModularSymbols(37,2)
|
|
2916
|
+
sage: m._compute_hecke_matrix_prime(2).charpoly('x')
|
|
2917
|
+
x^5 + x^4 - 8*x^3 - 12*x^2
|
|
2918
|
+
"""
|
|
2919
|
+
# note -- p doesn't have to be prime.
|
|
2920
|
+
if isinstance(rows, list):
|
|
2921
|
+
rows = tuple(rows)
|
|
2922
|
+
try:
|
|
2923
|
+
return self._hecke_matrices[(p, rows)]
|
|
2924
|
+
except AttributeError:
|
|
2925
|
+
self._hecke_matrices = {}
|
|
2926
|
+
except KeyError:
|
|
2927
|
+
pass
|
|
2928
|
+
tm = verbose(f"Computing Hecke operator T_{p}")
|
|
2929
|
+
|
|
2930
|
+
H = heilbronn.HeilbronnCremona(p)
|
|
2931
|
+
# H = heilbronn.HeilbronnMerel(p)
|
|
2932
|
+
B = self.manin_basis()
|
|
2933
|
+
if rows is not None:
|
|
2934
|
+
B = [B[i] for i in rows]
|
|
2935
|
+
|
|
2936
|
+
N = self.level()
|
|
2937
|
+
P1 = self.p1list()
|
|
2938
|
+
mod2term = self._mod2term
|
|
2939
|
+
R = self.manin_gens_to_basis()
|
|
2940
|
+
W = R.new_matrix(nrows=len(B), ncols=R.nrows()) # the 0 with given number of rows and cols.
|
|
2941
|
+
j = 0
|
|
2942
|
+
tm = verbose("Matrix non-reduced", tm)
|
|
2943
|
+
for i in B:
|
|
2944
|
+
# The following step is where most of the time is spent.
|
|
2945
|
+
c, d = P1[i]
|
|
2946
|
+
v = H.apply(c, d, N)
|
|
2947
|
+
|
|
2948
|
+
# v is now a list of pairs ((c,d),m), where m is the
|
|
2949
|
+
# number of times that (c,d) appears in the image of x
|
|
2950
|
+
# under the matrices in H. Also, the pairs (c,d) are
|
|
2951
|
+
# normalized.
|
|
2952
|
+
# Let ind(c,d) denote the index of the normalized pair
|
|
2953
|
+
# (c,d) in the fixed ordered list of elements of
|
|
2954
|
+
# P1(Z/NZ). Then the list of pairs (ind(c,d), m)
|
|
2955
|
+
# obtained from the above list defines a sparse vector
|
|
2956
|
+
# s, and the image of x under T_p is the product
|
|
2957
|
+
# of s with the matrix R defined above.
|
|
2958
|
+
for z, m in v:
|
|
2959
|
+
k = P1.index_of_normalized_pair(z[0], z[1])
|
|
2960
|
+
if k != -1:
|
|
2961
|
+
f, s = mod2term[k]
|
|
2962
|
+
if s != 0:
|
|
2963
|
+
W[j, f] = W[j, f] + s*m
|
|
2964
|
+
j += 1
|
|
2965
|
+
tm = verbose("done making non-reduced matrix", tm)
|
|
2966
|
+
verbose("start matrix-matrix (%s x %s) times (%s x %s) multiply to get Tp" % (W.nrows(), W.ncols(),
|
|
2967
|
+
R.nrows(), R.ncols()))
|
|
2968
|
+
if hasattr(W, '_matrix_times_matrix_dense'):
|
|
2969
|
+
Tp = W._matrix_times_matrix_dense(R)
|
|
2970
|
+
verbose("done matrix multiply and computing Hecke operator", tm)
|
|
2971
|
+
else:
|
|
2972
|
+
Tp = W * R
|
|
2973
|
+
tm = verbose("done multiplying", tm)
|
|
2974
|
+
Tp = Tp.dense_matrix()
|
|
2975
|
+
verbose("done making Hecke operator dense", tm)
|
|
2976
|
+
if rows is None:
|
|
2977
|
+
self._hecke_matrices[(p, rows)] = Tp
|
|
2978
|
+
return Tp
|
|
2979
|
+
|
|
2980
|
+
def boundary_space(self):
|
|
2981
|
+
r"""
|
|
2982
|
+
Return the space of boundary modular symbols for this space.
|
|
2983
|
+
|
|
2984
|
+
EXAMPLES::
|
|
2985
|
+
|
|
2986
|
+
sage: M = ModularSymbols(100,2)
|
|
2987
|
+
sage: M.boundary_space()
|
|
2988
|
+
Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(100) of weight 2 over Rational Field
|
|
2989
|
+
"""
|
|
2990
|
+
try:
|
|
2991
|
+
return self.__boundary_space
|
|
2992
|
+
except AttributeError:
|
|
2993
|
+
pass
|
|
2994
|
+
self.__boundary_space = boundary.BoundarySpace_wtk_g0(
|
|
2995
|
+
self.level(), self.weight(), self.sign(), self.base_ring())
|
|
2996
|
+
return self.__boundary_space
|
|
2997
|
+
|
|
2998
|
+
def _hecke_image_of_ith_basis_vector(self, n, i):
|
|
2999
|
+
"""
|
|
3000
|
+
Return `T_n(e_i)`, where `e_i` is the
|
|
3001
|
+
`i` th basis vector of this ambient space.
|
|
3002
|
+
|
|
3003
|
+
INPUT:
|
|
3004
|
+
|
|
3005
|
+
- ``n`` -- integer which should be prime
|
|
3006
|
+
|
|
3007
|
+
OUTPUT: ``modular symbol`` -- element of this ambient space
|
|
3008
|
+
|
|
3009
|
+
EXAMPLES::
|
|
3010
|
+
|
|
3011
|
+
sage: M = ModularSymbols(43,2,1)
|
|
3012
|
+
sage: M._hecke_image_of_ith_basis_vector(2, 0)
|
|
3013
|
+
3*(1,0) - 2*(1,33)
|
|
3014
|
+
sage: M.hecke_operator(2)(M.0)
|
|
3015
|
+
3*(1,0) - 2*(1,33)
|
|
3016
|
+
sage: M._hecke_image_of_ith_basis_vector(6, 1)
|
|
3017
|
+
4*(1,31) - 3*(1,33) + 3*(1,39)
|
|
3018
|
+
sage: M.hecke_operator(6)(M.1)
|
|
3019
|
+
4*(1,31) - 3*(1,33) + 3*(1,39)
|
|
3020
|
+
"""
|
|
3021
|
+
c = self.manin_generators()[self.manin_basis()[i]]
|
|
3022
|
+
N = self.level()
|
|
3023
|
+
I = heilbronn.hecke_images_gamma0_weight2(c.u, c.v, N, [n],
|
|
3024
|
+
self.manin_gens_to_basis())
|
|
3025
|
+
return self(I[0])
|
|
3026
|
+
|
|
3027
|
+
def _hecke_images(self, i, v):
|
|
3028
|
+
"""
|
|
3029
|
+
Return images of the `i`-th standard basis vector under the
|
|
3030
|
+
Hecke operators `T_p` for all integers in `v`.
|
|
3031
|
+
|
|
3032
|
+
INPUT:
|
|
3033
|
+
|
|
3034
|
+
- ``i`` -- nonnegative integer
|
|
3035
|
+
|
|
3036
|
+
- ``v`` -- list of positive integer
|
|
3037
|
+
|
|
3038
|
+
OUTPUT: matrix whose rows are the Hecke images
|
|
3039
|
+
|
|
3040
|
+
EXAMPLES::
|
|
3041
|
+
|
|
3042
|
+
sage: M = ModularSymbols(46,2,-1)
|
|
3043
|
+
sage: mat = M._hecke_images(1,[3,4,5,6])
|
|
3044
|
+
sage: v = M.basis()[1]
|
|
3045
|
+
sage: M.T(3)(v).element() == mat[0]
|
|
3046
|
+
True
|
|
3047
|
+
sage: M.T(4)(v).element() == mat[1]
|
|
3048
|
+
True
|
|
3049
|
+
sage: M.T(5)(v).element() == mat[2]
|
|
3050
|
+
True
|
|
3051
|
+
sage: M.T(6)(v).element() == mat[3]
|
|
3052
|
+
True
|
|
3053
|
+
"""
|
|
3054
|
+
# Find basis vector for ambient space such that it is not in
|
|
3055
|
+
# the kernel of the dual space corresponding to self.
|
|
3056
|
+
c = self.manin_generators()[self.manin_basis()[i]]
|
|
3057
|
+
N = self.level()
|
|
3058
|
+
return heilbronn.hecke_images_gamma0_weight2(c.u, c.v, N, v,
|
|
3059
|
+
self.manin_gens_to_basis())
|
|
3060
|
+
|
|
3061
|
+
|
|
3062
|
+
class ModularSymbolsAmbient_wtk_g1(ModularSymbolsAmbient):
|
|
3063
|
+
r"""
|
|
3064
|
+
INPUT:
|
|
3065
|
+
|
|
3066
|
+
- ``level`` -- integer; the level
|
|
3067
|
+
|
|
3068
|
+
- ``weight`` -- integer; the weight = 2
|
|
3069
|
+
|
|
3070
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
3071
|
+
|
|
3072
|
+
- ``F`` -- field
|
|
3073
|
+
|
|
3074
|
+
EXAMPLES::
|
|
3075
|
+
|
|
3076
|
+
sage: ModularSymbols(Gamma1(17),2)
|
|
3077
|
+
Modular Symbols space of dimension 25 for Gamma_1(17) of weight 2 with sign 0 over Rational Field
|
|
3078
|
+
sage: [ModularSymbols(Gamma1(7),k).dimension() for k in [2,3,4,5]]
|
|
3079
|
+
[5, 8, 12, 16]
|
|
3080
|
+
|
|
3081
|
+
::
|
|
3082
|
+
|
|
3083
|
+
sage: ModularSymbols(Gamma1(7),3)
|
|
3084
|
+
Modular Symbols space of dimension 8 for Gamma_1(7) of weight 3 with sign 0 over Rational Field
|
|
3085
|
+
"""
|
|
3086
|
+
|
|
3087
|
+
def __init__(self, level, weight, sign, F, custom_init=None, category=None):
|
|
3088
|
+
r"""
|
|
3089
|
+
Initialize a space of modular symbols for Gamma1(N).
|
|
3090
|
+
|
|
3091
|
+
INPUT:
|
|
3092
|
+
|
|
3093
|
+
- ``level`` -- integer; the level
|
|
3094
|
+
|
|
3095
|
+
- ``weight`` -- integer; the weight = 2
|
|
3096
|
+
|
|
3097
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
3098
|
+
|
|
3099
|
+
- ``F`` -- field
|
|
3100
|
+
|
|
3101
|
+
EXAMPLES::
|
|
3102
|
+
|
|
3103
|
+
sage: ModularSymbols(Gamma1(17),2)
|
|
3104
|
+
Modular Symbols space of dimension 25 for Gamma_1(17) of weight 2 with sign 0 over Rational Field
|
|
3105
|
+
sage: [ModularSymbols(Gamma1(7),k).dimension() for k in [2,3,4,5]]
|
|
3106
|
+
[5, 8, 12, 16]
|
|
3107
|
+
|
|
3108
|
+
::
|
|
3109
|
+
|
|
3110
|
+
sage: M = ModularSymbols(Gamma1(7),3)
|
|
3111
|
+
"""
|
|
3112
|
+
ModularSymbolsAmbient.__init__(self,
|
|
3113
|
+
weight=weight,
|
|
3114
|
+
group=arithgroup.Gamma1(level),
|
|
3115
|
+
sign=sign,
|
|
3116
|
+
base_ring=F,
|
|
3117
|
+
custom_init=custom_init,
|
|
3118
|
+
category=category)
|
|
3119
|
+
|
|
3120
|
+
def _dimension_formula(self):
|
|
3121
|
+
r"""
|
|
3122
|
+
Return the dimension of this space using the formula.
|
|
3123
|
+
|
|
3124
|
+
EXAMPLES::
|
|
3125
|
+
|
|
3126
|
+
sage: M = ModularSymbols(Gamma1(7),6)
|
|
3127
|
+
sage: M.dimension()
|
|
3128
|
+
20
|
|
3129
|
+
sage: M._dimension_formula()
|
|
3130
|
+
20
|
|
3131
|
+
"""
|
|
3132
|
+
if self.base_ring().characteristic() != 0:
|
|
3133
|
+
raise NotImplementedError
|
|
3134
|
+
level, weight, sign = self.level(), self.weight(), self.sign()
|
|
3135
|
+
if sign != 0:
|
|
3136
|
+
return None
|
|
3137
|
+
d = 2*self.group().dimension_cusp_forms(weight) + self.group().ncusps()
|
|
3138
|
+
if level == 1 and weight % 2:
|
|
3139
|
+
return 0
|
|
3140
|
+
if weight == 2:
|
|
3141
|
+
return d - 1
|
|
3142
|
+
if weight % 2 == 0:
|
|
3143
|
+
return d
|
|
3144
|
+
|
|
3145
|
+
# TODO: I don't know a formula for dim ModSym_k(Gamma_1(N)) for odd k!!!
|
|
3146
|
+
|
|
3147
|
+
return None
|
|
3148
|
+
|
|
3149
|
+
def _repr_(self):
|
|
3150
|
+
r"""
|
|
3151
|
+
Return a string representation of this space.
|
|
3152
|
+
|
|
3153
|
+
EXAMPLES::
|
|
3154
|
+
|
|
3155
|
+
sage: M = ModularSymbols(Gamma1(7),3)
|
|
3156
|
+
sage: M # indirect doctest
|
|
3157
|
+
Modular Symbols space of dimension 8 for Gamma_1(7) of weight 3 with sign 0 over Rational Field
|
|
3158
|
+
"""
|
|
3159
|
+
return ("Modular Symbols space of dimension %s for Gamma_1(%s) of weight %s with sign %s over %s"
|
|
3160
|
+
% (self.dimension(), self.level(), self.weight(), self.sign(), self.base_ring()))
|
|
3161
|
+
|
|
3162
|
+
def _cuspidal_submodule_dimension_formula(self):
|
|
3163
|
+
r"""
|
|
3164
|
+
Return the dimension of the cuspidal subspace, using the formula.
|
|
3165
|
+
|
|
3166
|
+
EXAMPLES::
|
|
3167
|
+
|
|
3168
|
+
sage: M = ModularSymbols(Gamma1(11),4)
|
|
3169
|
+
sage: M.cuspidal_subspace().dimension()
|
|
3170
|
+
20
|
|
3171
|
+
sage: M._cuspidal_submodule_dimension_formula()
|
|
3172
|
+
20
|
|
3173
|
+
"""
|
|
3174
|
+
if self.sign() == 0:
|
|
3175
|
+
m = 2
|
|
3176
|
+
else:
|
|
3177
|
+
m = 1
|
|
3178
|
+
return m * self.group().dimension_cusp_forms(self.weight())
|
|
3179
|
+
|
|
3180
|
+
def _cuspidal_new_submodule_dimension_formula(self):
|
|
3181
|
+
r"""
|
|
3182
|
+
Return the dimension of the new cuspidal subspace, via the formula.
|
|
3183
|
+
|
|
3184
|
+
EXAMPLES::
|
|
3185
|
+
|
|
3186
|
+
sage: M = ModularSymbols(Gamma1(22),2)
|
|
3187
|
+
sage: M._cuspidal_new_submodule_dimension_formula()
|
|
3188
|
+
8
|
|
3189
|
+
sage: M.cuspidal_subspace().new_subspace().dimension()
|
|
3190
|
+
8
|
|
3191
|
+
"""
|
|
3192
|
+
if self.sign() == 0:
|
|
3193
|
+
m = 2
|
|
3194
|
+
else:
|
|
3195
|
+
m = 1
|
|
3196
|
+
return m * self.group().dimension_new_cusp_forms(self.weight())
|
|
3197
|
+
|
|
3198
|
+
def _compute_hecke_matrix_prime_power(self, p, r):
|
|
3199
|
+
r"""
|
|
3200
|
+
Compute and return the matrix of the Hecke operator `T(p^r)`.
|
|
3201
|
+
|
|
3202
|
+
EXAMPLES::
|
|
3203
|
+
|
|
3204
|
+
sage: m = ModularSymbols(Gamma1(11),2)
|
|
3205
|
+
sage: m._compute_hecke_matrix_prime_power(3,4).charpoly('x')
|
|
3206
|
+
x^11 - 291*x^10 + 30555*x^9 - 1636145*x^8 + 59637480*x^7 + 1983040928*x^6 - 401988683888*x^5 - 14142158875680*x^4 + 3243232720819520*x^3 - 103658398669404480*x^2 + 197645665452381696*x - 97215957397309696
|
|
3207
|
+
"""
|
|
3208
|
+
return self._compute_hecke_matrix_prime(p**r)
|
|
3209
|
+
|
|
3210
|
+
def _degeneracy_raising_matrix_1(self, M):
|
|
3211
|
+
r"""
|
|
3212
|
+
Return the matrix of the degeneracy raising map to `M`.
|
|
3213
|
+
|
|
3214
|
+
INPUT:
|
|
3215
|
+
|
|
3216
|
+
- ``M`` -- an ambient space of Gamma1 modular symbols, of level a
|
|
3217
|
+
multiple of the level of self
|
|
3218
|
+
|
|
3219
|
+
OUTPUT:
|
|
3220
|
+
|
|
3221
|
+
(matrix) The matrix of the degeneracy raising matrix to the higher level.
|
|
3222
|
+
|
|
3223
|
+
EXAMPLES::
|
|
3224
|
+
|
|
3225
|
+
sage: M = ModularSymbols(Gamma1(7),3)
|
|
3226
|
+
sage: N = ModularSymbols(Gamma1(21), 3)
|
|
3227
|
+
sage: M._degeneracy_raising_matrix_1(N)
|
|
3228
|
+
8 x 64 dense matrix over Rational Field (use the '.str()' method to see the entries)
|
|
3229
|
+
sage: M.dimension()
|
|
3230
|
+
8
|
|
3231
|
+
sage: N.dimension()
|
|
3232
|
+
64
|
|
3233
|
+
"""
|
|
3234
|
+
N = self.level()
|
|
3235
|
+
|
|
3236
|
+
# 1. Find coset representatives H for Gamma_1(M.level()) \ Gamma_1(self.level())
|
|
3237
|
+
H = arithgroup.degeneracy_coset_representatives_gamma1(M.level(), N, 1)
|
|
3238
|
+
# 2. The map is
|
|
3239
|
+
# [P,pi(g)] |--> sum_{h in H} [P, pi(h*g)]
|
|
3240
|
+
#
|
|
3241
|
+
MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
|
|
3242
|
+
if self.dimension() == 0 or M.dimension() == 0:
|
|
3243
|
+
return MS(0)
|
|
3244
|
+
rows = []
|
|
3245
|
+
B = self.manin_basis()
|
|
3246
|
+
syms = self.manin_symbols()
|
|
3247
|
+
G = MatrixSpace(ZZ, 2)
|
|
3248
|
+
H = [G(h) for h in H]
|
|
3249
|
+
for n in B:
|
|
3250
|
+
z = M(0)
|
|
3251
|
+
s = syms.manin_symbol(n)
|
|
3252
|
+
g = G(list(s.lift_to_sl2z(N)))
|
|
3253
|
+
i = s.i
|
|
3254
|
+
# We apply each matrix in H according to the above formula
|
|
3255
|
+
for h in H:
|
|
3256
|
+
hg = h*g
|
|
3257
|
+
z += M((i, hg[1, 0], hg[1, 1]))
|
|
3258
|
+
rows.append(z.element())
|
|
3259
|
+
|
|
3260
|
+
return MS(rows)
|
|
3261
|
+
|
|
3262
|
+
def boundary_space(self):
|
|
3263
|
+
r"""
|
|
3264
|
+
Return the space of boundary modular symbols for this space.
|
|
3265
|
+
|
|
3266
|
+
EXAMPLES::
|
|
3267
|
+
|
|
3268
|
+
sage: M = ModularSymbols(100,2)
|
|
3269
|
+
sage: M.boundary_space()
|
|
3270
|
+
Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(100) of weight 2 over Rational Field
|
|
3271
|
+
"""
|
|
3272
|
+
try:
|
|
3273
|
+
return self.__boundary_space
|
|
3274
|
+
except AttributeError:
|
|
3275
|
+
pass
|
|
3276
|
+
self.__boundary_space = boundary.BoundarySpace_wtk_g1(
|
|
3277
|
+
self.level(), self.weight(), self.sign(), self.base_ring())
|
|
3278
|
+
return self.__boundary_space
|
|
3279
|
+
|
|
3280
|
+
def manin_symbols(self):
|
|
3281
|
+
r"""
|
|
3282
|
+
Return the Manin symbol list of this modular symbol space.
|
|
3283
|
+
|
|
3284
|
+
EXAMPLES::
|
|
3285
|
+
|
|
3286
|
+
sage: M = ModularSymbols(Gamma1(30),4)
|
|
3287
|
+
sage: M.manin_symbols()
|
|
3288
|
+
Manin Symbol List of weight 4 for Gamma1(30)
|
|
3289
|
+
sage: len(M.manin_symbols())
|
|
3290
|
+
1728
|
|
3291
|
+
"""
|
|
3292
|
+
try:
|
|
3293
|
+
return self.__manin_symbols
|
|
3294
|
+
except AttributeError:
|
|
3295
|
+
self.__manin_symbols = ManinSymbolList_gamma1(
|
|
3296
|
+
level=self.level(), weight=self.weight())
|
|
3297
|
+
return self.__manin_symbols
|
|
3298
|
+
|
|
3299
|
+
|
|
3300
|
+
class ModularSymbolsAmbient_wtk_gamma_h(ModularSymbolsAmbient):
|
|
3301
|
+
def __init__(self, group, weight, sign, F, custom_init=None, category=None):
|
|
3302
|
+
r"""
|
|
3303
|
+
Initialize a space of modular symbols for `\Gamma_H(N)`.
|
|
3304
|
+
|
|
3305
|
+
INPUT:
|
|
3306
|
+
|
|
3307
|
+
- ``group`` -- a congruence subgroup `\Gamma_H(N)`
|
|
3308
|
+
|
|
3309
|
+
- ``weight`` -- integer; the weight = 2
|
|
3310
|
+
|
|
3311
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
3312
|
+
|
|
3313
|
+
- ``F`` -- field
|
|
3314
|
+
|
|
3315
|
+
EXAMPLES::
|
|
3316
|
+
|
|
3317
|
+
sage: ModularSymbols(GammaH(15,[4]),2)
|
|
3318
|
+
Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 with sign 0 over Rational Field
|
|
3319
|
+
"""
|
|
3320
|
+
ModularSymbolsAmbient.__init__(self,
|
|
3321
|
+
weight=weight, group=group,
|
|
3322
|
+
sign=sign, base_ring=F,
|
|
3323
|
+
custom_init=custom_init,
|
|
3324
|
+
category=category)
|
|
3325
|
+
|
|
3326
|
+
def _dimension_formula(self):
|
|
3327
|
+
r"""
|
|
3328
|
+
Return None: we have no dimension formulas for `\Gamma_H(N)` spaces.
|
|
3329
|
+
|
|
3330
|
+
EXAMPLES::
|
|
3331
|
+
|
|
3332
|
+
sage: M = ModularSymbols(GammaH(15,[4]),2)
|
|
3333
|
+
sage: M.dimension()
|
|
3334
|
+
9
|
|
3335
|
+
sage: M._dimension_formula()
|
|
3336
|
+
"""
|
|
3337
|
+
return
|
|
3338
|
+
|
|
3339
|
+
def _repr_(self):
|
|
3340
|
+
r"""
|
|
3341
|
+
Return a string representation of this space.
|
|
3342
|
+
|
|
3343
|
+
EXAMPLES::
|
|
3344
|
+
|
|
3345
|
+
sage: M = ModularSymbols(GammaH(15,[4]),2)
|
|
3346
|
+
sage: M # indirect doctest
|
|
3347
|
+
Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 with sign 0 over Rational Field
|
|
3348
|
+
"""
|
|
3349
|
+
return ("Modular Symbols space of dimension %s for %s of weight %s with sign %s over %s"
|
|
3350
|
+
% (self.dimension(), self.group(), self.weight(), self.sign(), self.base_ring()))
|
|
3351
|
+
|
|
3352
|
+
def _cuspidal_submodule_dimension_formula(self):
|
|
3353
|
+
r"""
|
|
3354
|
+
Return None: we have no dimension formulas for `\Gamma_H(N)` spaces.
|
|
3355
|
+
|
|
3356
|
+
EXAMPLES::
|
|
3357
|
+
|
|
3358
|
+
sage: ModularSymbols(GammaH(15,[4]),2)._cuspidal_submodule_dimension_formula() is None
|
|
3359
|
+
True
|
|
3360
|
+
"""
|
|
3361
|
+
return
|
|
3362
|
+
|
|
3363
|
+
def _cuspidal_new_submodule_dimension_formula(self):
|
|
3364
|
+
r"""
|
|
3365
|
+
Return None: we have no dimension formulas for `\Gamma_H(N)` spaces.
|
|
3366
|
+
|
|
3367
|
+
EXAMPLES::
|
|
3368
|
+
|
|
3369
|
+
sage: ModularSymbols(GammaH(15,[4]),2)._cuspidal_new_submodule_dimension_formula() is None
|
|
3370
|
+
True
|
|
3371
|
+
"""
|
|
3372
|
+
return
|
|
3373
|
+
|
|
3374
|
+
def _compute_hecke_matrix_prime_power(self, p, r):
|
|
3375
|
+
r"""
|
|
3376
|
+
Return matrix of a prime-power Hecke operator.
|
|
3377
|
+
|
|
3378
|
+
EXAMPLES::
|
|
3379
|
+
|
|
3380
|
+
sage: M = ModularSymbols(GammaH(15,[4]),2)
|
|
3381
|
+
sage: M._compute_hecke_matrix_prime_power(2, 3)
|
|
3382
|
+
[10 0 5 1 0 0 0 4 0]
|
|
3383
|
+
[ 0 10 0 4 10 -5 -5 -4 5]
|
|
3384
|
+
[ 5 0 10 -4 0 0 0 -1 0]
|
|
3385
|
+
[ 0 0 0 -1 0 0 0 -4 0]
|
|
3386
|
+
[ 0 0 0 -7 5 0 10 -3 6]
|
|
3387
|
+
[ 0 -5 0 -6 0 10 5 -4 -1]
|
|
3388
|
+
[ 0 0 0 -3 10 0 5 -7 6]
|
|
3389
|
+
[ 0 0 0 -4 0 0 0 -1 0]
|
|
3390
|
+
[ 0 0 0 0 0 0 0 0 3]
|
|
3391
|
+
sage: M.hecke_matrix(7)^2 == M.hecke_matrix(49) + 7 * M.diamond_bracket_operator(7).matrix() # indirect doctest
|
|
3392
|
+
True
|
|
3393
|
+
"""
|
|
3394
|
+
return self._compute_hecke_matrix_prime(p**r)
|
|
3395
|
+
|
|
3396
|
+
def _degeneracy_raising_matrix_1(self, level):
|
|
3397
|
+
r"""
|
|
3398
|
+
Return matrix of a degeneracy raising map.
|
|
3399
|
+
|
|
3400
|
+
EXAMPLES::
|
|
3401
|
+
|
|
3402
|
+
sage: ModularSymbols(GammaH(15,[4]),2)._degeneracy_raising_matrix_1(ModularSymbols(GammaH(30, [19]), 2))
|
|
3403
|
+
Traceback (most recent call last):
|
|
3404
|
+
...
|
|
3405
|
+
NotImplementedError
|
|
3406
|
+
"""
|
|
3407
|
+
raise NotImplementedError
|
|
3408
|
+
|
|
3409
|
+
def boundary_space(self):
|
|
3410
|
+
r"""
|
|
3411
|
+
Return the space of boundary modular symbols for this space.
|
|
3412
|
+
|
|
3413
|
+
EXAMPLES::
|
|
3414
|
+
|
|
3415
|
+
sage: M = ModularSymbols(GammaH(15,[4]),2)
|
|
3416
|
+
sage: M.boundary_space()
|
|
3417
|
+
Boundary Modular Symbols space for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 over Rational Field
|
|
3418
|
+
"""
|
|
3419
|
+
try:
|
|
3420
|
+
return self.__boundary_space
|
|
3421
|
+
except AttributeError:
|
|
3422
|
+
pass
|
|
3423
|
+
self.__boundary_space = boundary.BoundarySpace_wtk_gamma_h(
|
|
3424
|
+
self.group(), self.weight(), self.sign(), self.base_ring())
|
|
3425
|
+
return self.__boundary_space
|
|
3426
|
+
|
|
3427
|
+
def manin_symbols(self):
|
|
3428
|
+
r"""
|
|
3429
|
+
Return the Manin symbol list of this modular symbol space.
|
|
3430
|
+
|
|
3431
|
+
EXAMPLES::
|
|
3432
|
+
|
|
3433
|
+
sage: M = ModularSymbols(GammaH(15,[4]),2)
|
|
3434
|
+
sage: M.manin_symbols()
|
|
3435
|
+
Manin Symbol List of weight 2 for Congruence Subgroup Gamma_H(15) with H generated by [4]
|
|
3436
|
+
sage: len(M.manin_symbols())
|
|
3437
|
+
96
|
|
3438
|
+
"""
|
|
3439
|
+
try:
|
|
3440
|
+
return self.__manin_symbols
|
|
3441
|
+
except AttributeError:
|
|
3442
|
+
self.__manin_symbols = ManinSymbolList_gamma_h(
|
|
3443
|
+
group=self.group(), weight=self.weight())
|
|
3444
|
+
return self.__manin_symbols
|
|
3445
|
+
|
|
3446
|
+
|
|
3447
|
+
class ModularSymbolsAmbient_wtk_eps(ModularSymbolsAmbient):
|
|
3448
|
+
def __init__(self, eps, weight, sign, base_ring, custom_init=None, category=None):
|
|
3449
|
+
"""
|
|
3450
|
+
Space of modular symbols with given weight, character, base ring and
|
|
3451
|
+
sign.
|
|
3452
|
+
|
|
3453
|
+
INPUT:
|
|
3454
|
+
|
|
3455
|
+
- ``eps`` -- dirichlet.DirichletCharacter, the
|
|
3456
|
+
"Nebentypus" character
|
|
3457
|
+
|
|
3458
|
+
- ``weight`` -- integer; the weight = 2
|
|
3459
|
+
|
|
3460
|
+
- ``sign`` -- integer; either -1, 0, or 1
|
|
3461
|
+
|
|
3462
|
+
- ``base_ring`` -- the base ring; it must be possible to change the ring
|
|
3463
|
+
of the character to this base ring (not always canonically)
|
|
3464
|
+
|
|
3465
|
+
EXAMPLES::
|
|
3466
|
+
|
|
3467
|
+
sage: eps = DirichletGroup(4).gen(0)
|
|
3468
|
+
sage: eps.order()
|
|
3469
|
+
2
|
|
3470
|
+
sage: ModularSymbols(eps, 2)
|
|
3471
|
+
Modular Symbols space of dimension 0 and level 4, weight 2, character [-1], sign 0, over Rational Field
|
|
3472
|
+
sage: ModularSymbols(eps, 3)
|
|
3473
|
+
Modular Symbols space of dimension 2 and level 4, weight 3, character [-1], sign 0, over Rational Field
|
|
3474
|
+
|
|
3475
|
+
We next create a space with character of order bigger than 2.
|
|
3476
|
+
|
|
3477
|
+
::
|
|
3478
|
+
|
|
3479
|
+
sage: eps = DirichletGroup(5).gen(0)
|
|
3480
|
+
sage: eps # has order 4
|
|
3481
|
+
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4
|
|
3482
|
+
sage: ModularSymbols(eps, 2).dimension()
|
|
3483
|
+
0
|
|
3484
|
+
sage: ModularSymbols(eps, 3).dimension()
|
|
3485
|
+
2
|
|
3486
|
+
|
|
3487
|
+
Here is another example::
|
|
3488
|
+
|
|
3489
|
+
sage: G.<e> = DirichletGroup(5)
|
|
3490
|
+
sage: M = ModularSymbols(e,3)
|
|
3491
|
+
sage: loads(M.dumps()) == M
|
|
3492
|
+
True
|
|
3493
|
+
"""
|
|
3494
|
+
level = eps.modulus()
|
|
3495
|
+
ModularSymbolsAmbient.__init__(self,
|
|
3496
|
+
weight=weight,
|
|
3497
|
+
group=arithgroup.Gamma1(level),
|
|
3498
|
+
sign=sign,
|
|
3499
|
+
base_ring=base_ring,
|
|
3500
|
+
character=eps.change_ring(base_ring),
|
|
3501
|
+
custom_init=custom_init,
|
|
3502
|
+
category=category)
|
|
3503
|
+
|
|
3504
|
+
def _repr_(self):
|
|
3505
|
+
r"""
|
|
3506
|
+
Return a string representation of this space.
|
|
3507
|
+
|
|
3508
|
+
EXAMPLES::
|
|
3509
|
+
|
|
3510
|
+
sage: G.<e> = DirichletGroup(5)
|
|
3511
|
+
sage: M = ModularSymbols(e,3)
|
|
3512
|
+
sage: M # indirect doctest
|
|
3513
|
+
Modular Symbols space of dimension 2 and level 5, weight 3, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
|
|
3514
|
+
"""
|
|
3515
|
+
return ("Modular Symbols space of dimension %s and level %s, weight %s, character %s, sign %s, " +
|
|
3516
|
+
"over %s") % (self.dimension(), self.level(), self.weight(),
|
|
3517
|
+
self.character()._repr_short_(), self.sign(),
|
|
3518
|
+
self.base_ring())
|
|
3519
|
+
|
|
3520
|
+
def _cuspidal_submodule_dimension_formula(self):
|
|
3521
|
+
r"""
|
|
3522
|
+
Return the dimension for the cuspidal subspace of this space, given by the formula.
|
|
3523
|
+
|
|
3524
|
+
EXAMPLES::
|
|
3525
|
+
|
|
3526
|
+
sage: G.<e> = DirichletGroup(50)
|
|
3527
|
+
sage: M = ModularSymbols(e^2,2)
|
|
3528
|
+
sage: M.dimension()
|
|
3529
|
+
16
|
|
3530
|
+
sage: M._cuspidal_submodule_dimension_formula()
|
|
3531
|
+
12
|
|
3532
|
+
"""
|
|
3533
|
+
if self.base_ring().characteristic() != 0:
|
|
3534
|
+
raise NotImplementedError
|
|
3535
|
+
if self.sign() == 0:
|
|
3536
|
+
m = 2
|
|
3537
|
+
else:
|
|
3538
|
+
m = 1
|
|
3539
|
+
return m * self.group().dimension_cusp_forms(self.weight(), eps=self.character())
|
|
3540
|
+
|
|
3541
|
+
def _cuspidal_new_submodule_dimension_formula(self):
|
|
3542
|
+
r"""
|
|
3543
|
+
Return the dimension for the new cuspidal subspace of this space, given by the formula.
|
|
3544
|
+
|
|
3545
|
+
EXAMPLES::
|
|
3546
|
+
|
|
3547
|
+
sage: G.<e> = DirichletGroup(50)
|
|
3548
|
+
sage: M = ModularSymbols(e,3)
|
|
3549
|
+
sage: M.dimension()
|
|
3550
|
+
30
|
|
3551
|
+
sage: M._cuspidal_new_submodule_dimension_formula()
|
|
3552
|
+
10
|
|
3553
|
+
"""
|
|
3554
|
+
if self.base_ring().characteristic() != 0:
|
|
3555
|
+
raise NotImplementedError
|
|
3556
|
+
if self.sign() == 0:
|
|
3557
|
+
m = 2
|
|
3558
|
+
else:
|
|
3559
|
+
m = 1
|
|
3560
|
+
return m * self.group().dimension_new_cusp_forms(self.weight(), eps=self.character())
|
|
3561
|
+
|
|
3562
|
+
def _matrix_of_operator_on_modular_symbols(self, codomain, R, character_twist=False):
|
|
3563
|
+
r"""
|
|
3564
|
+
INPUT:
|
|
3565
|
+
|
|
3566
|
+
- ``self`` -- this space of modular symbols
|
|
3567
|
+
|
|
3568
|
+
- ``codomain`` -- space of modular symbols
|
|
3569
|
+
|
|
3570
|
+
- ``R`` -- list of lists [a,b,c,d] of length 4, which
|
|
3571
|
+
we view as elements of GL_2(Q)
|
|
3572
|
+
|
|
3573
|
+
OUTPUT: a matrix, which represents the operator
|
|
3574
|
+
|
|
3575
|
+
.. MATH::
|
|
3576
|
+
|
|
3577
|
+
x \mapsto \sum_{g in R} g.x,
|
|
3578
|
+
|
|
3579
|
+
|
|
3580
|
+
where g.x is the formal linear fractional transformation on modular
|
|
3581
|
+
symbols.
|
|
3582
|
+
|
|
3583
|
+
EXAMPLES::
|
|
3584
|
+
|
|
3585
|
+
sage: G.<e> = DirichletGroup(5)
|
|
3586
|
+
sage: M = ModularSymbols(e,3)
|
|
3587
|
+
sage: M.dimension()
|
|
3588
|
+
2
|
|
3589
|
+
sage: M._matrix_of_operator_on_modular_symbols(M,HeilbronnCremona(3))
|
|
3590
|
+
[ 6 6]
|
|
3591
|
+
[ 0 10]
|
|
3592
|
+
"""
|
|
3593
|
+
eps = self.character()
|
|
3594
|
+
rows = []
|
|
3595
|
+
for b in self.basis():
|
|
3596
|
+
v = FormalSum(0, check=False)
|
|
3597
|
+
for c, x in b.modular_symbol_rep():
|
|
3598
|
+
for g in R:
|
|
3599
|
+
y = x.apply(g)
|
|
3600
|
+
if character_twist:
|
|
3601
|
+
v += y*c*eps(g[0])
|
|
3602
|
+
else:
|
|
3603
|
+
v += y*c
|
|
3604
|
+
w = codomain(v).element()
|
|
3605
|
+
rows.append(w)
|
|
3606
|
+
M = MatrixSpace(self.base_ring(), len(rows), codomain.degree(), sparse=False)
|
|
3607
|
+
return M(rows)
|
|
3608
|
+
|
|
3609
|
+
def _degeneracy_raising_matrix_1(self, M):
|
|
3610
|
+
r"""
|
|
3611
|
+
Return the matrix of the degeneracy raising map to ``M``, which should
|
|
3612
|
+
be a space of modular symbols with level a multiple of the level of
|
|
3613
|
+
``self`` and with compatible character.
|
|
3614
|
+
|
|
3615
|
+
INPUT:
|
|
3616
|
+
|
|
3617
|
+
- ``M`` -- a space of modular symbols with character, whose level
|
|
3618
|
+
should be an integer multiple of the level of ``self``, and whose
|
|
3619
|
+
character should be the Dirichlet character at that level obtained by
|
|
3620
|
+
extending the character of ``self``.
|
|
3621
|
+
|
|
3622
|
+
The input is *not* sanity-checked in any way -- use with care!
|
|
3623
|
+
|
|
3624
|
+
OUTPUT:
|
|
3625
|
+
|
|
3626
|
+
(matrix) The matrix of the degeneracy raising matrix to the higher level.
|
|
3627
|
+
|
|
3628
|
+
EXAMPLES::
|
|
3629
|
+
|
|
3630
|
+
sage: eps = DirichletGroup(4).gen(0)
|
|
3631
|
+
sage: M = ModularSymbols(eps, 3); M
|
|
3632
|
+
Modular Symbols space of dimension 2 and level 4, weight 3, character [-1], sign 0, over Rational Field
|
|
3633
|
+
sage: M._degeneracy_raising_matrix_1(ModularSymbols(eps.extend(20), 3))
|
|
3634
|
+
[ 1 0 0 0 -1 -1 3 1 0 2 -3 0]
|
|
3635
|
+
[ 0 5 1 -2 -3 3 0 4 -1 5 -7 -1]
|
|
3636
|
+
"""
|
|
3637
|
+
N = self.level()
|
|
3638
|
+
|
|
3639
|
+
# 1. Find coset representatives H for Gamma_0(M.level()) \ Gamma_0(self.level())
|
|
3640
|
+
H = arithgroup.degeneracy_coset_representatives_gamma0(M.level(), N, 1)
|
|
3641
|
+
# 2. The map is
|
|
3642
|
+
# [P,pi(g)] |--> sum_{h in H} [P, pi(h*g)]
|
|
3643
|
+
#
|
|
3644
|
+
MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
|
|
3645
|
+
if self.dimension() == 0 or M.dimension() == 0:
|
|
3646
|
+
return MS(0)
|
|
3647
|
+
rows = []
|
|
3648
|
+
B = self.manin_basis()
|
|
3649
|
+
syms = self.manin_symbols()
|
|
3650
|
+
G = MatrixSpace(ZZ, 2)
|
|
3651
|
+
H = [G(h) for h in H]
|
|
3652
|
+
eps = self.character()
|
|
3653
|
+
# note: in my thesis I twisted by eps^(-1), which is definitely a mistake
|
|
3654
|
+
# since twisting by eps gives the right answer and by eps^(-1) does not.
|
|
3655
|
+
|
|
3656
|
+
for n in B:
|
|
3657
|
+
z = M(0)
|
|
3658
|
+
s = syms.manin_symbol(n)
|
|
3659
|
+
g = G(list(s.lift_to_sl2z(N)))
|
|
3660
|
+
i = s.i
|
|
3661
|
+
# We apply each matrix in H according to the above formula
|
|
3662
|
+
for h in H:
|
|
3663
|
+
hg = h * g
|
|
3664
|
+
z += eps(h[0, 0]) * M((i, hg[1, 0], hg[1, 1]))
|
|
3665
|
+
rows.append(z.element())
|
|
3666
|
+
return MS(rows)
|
|
3667
|
+
|
|
3668
|
+
def _dimension_formula(self):
|
|
3669
|
+
r"""
|
|
3670
|
+
Return None: we have no dimension formula for `\Gamma_H(N)` spaces.
|
|
3671
|
+
|
|
3672
|
+
EXAMPLES::
|
|
3673
|
+
|
|
3674
|
+
sage: eps = DirichletGroup(5).gen(0)
|
|
3675
|
+
sage: M = ModularSymbols(eps, 2)
|
|
3676
|
+
sage: M.dimension()
|
|
3677
|
+
0
|
|
3678
|
+
sage: M._dimension_formula()
|
|
3679
|
+
"""
|
|
3680
|
+
return
|
|
3681
|
+
|
|
3682
|
+
def boundary_space(self):
|
|
3683
|
+
r"""
|
|
3684
|
+
Return the space of boundary modular symbols for this space.
|
|
3685
|
+
|
|
3686
|
+
EXAMPLES::
|
|
3687
|
+
|
|
3688
|
+
sage: eps = DirichletGroup(5).gen(0)
|
|
3689
|
+
sage: M = ModularSymbols(eps, 2)
|
|
3690
|
+
sage: M.boundary_space()
|
|
3691
|
+
Boundary Modular Symbols space of level 5, weight 2, character [zeta4] and dimension 0 over Cyclotomic Field of order 4 and degree 2
|
|
3692
|
+
"""
|
|
3693
|
+
try:
|
|
3694
|
+
return self.__boundary_space
|
|
3695
|
+
except AttributeError:
|
|
3696
|
+
pass
|
|
3697
|
+
self.__boundary_space = boundary.BoundarySpace_wtk_eps(
|
|
3698
|
+
self.character(), self.weight(), self.sign())
|
|
3699
|
+
return self.__boundary_space
|
|
3700
|
+
|
|
3701
|
+
def manin_symbols(self):
|
|
3702
|
+
r"""
|
|
3703
|
+
Return the Manin symbol list of this modular symbol space.
|
|
3704
|
+
|
|
3705
|
+
EXAMPLES::
|
|
3706
|
+
|
|
3707
|
+
sage: eps = DirichletGroup(5).gen(0)
|
|
3708
|
+
sage: M = ModularSymbols(eps, 2)
|
|
3709
|
+
sage: M.manin_symbols()
|
|
3710
|
+
Manin Symbol List of weight 2 for Gamma1(5) with character [zeta4]
|
|
3711
|
+
sage: len(M.manin_symbols())
|
|
3712
|
+
6
|
|
3713
|
+
"""
|
|
3714
|
+
try:
|
|
3715
|
+
return self.__manin_symbols
|
|
3716
|
+
except AttributeError:
|
|
3717
|
+
self.__manin_symbols = ManinSymbolList_character(
|
|
3718
|
+
character=self.character(), weight=self.weight())
|
|
3719
|
+
return self.__manin_symbols
|
|
3720
|
+
|
|
3721
|
+
def modular_symbols_of_level(self, N):
|
|
3722
|
+
r"""
|
|
3723
|
+
Return a space of modular symbols with the same parameters as
|
|
3724
|
+
this space except with level `N`.
|
|
3725
|
+
|
|
3726
|
+
INPUT:
|
|
3727
|
+
|
|
3728
|
+
- ``N`` -- positive integer
|
|
3729
|
+
|
|
3730
|
+
OUTPUT:
|
|
3731
|
+
|
|
3732
|
+
(Modular Symbol space) A space of modular symbols with the
|
|
3733
|
+
same defining properties (weight, sign, etc.) as this space
|
|
3734
|
+
except with level `N`.
|
|
3735
|
+
|
|
3736
|
+
EXAMPLES::
|
|
3737
|
+
|
|
3738
|
+
sage: eps = DirichletGroup(5).gen(0)
|
|
3739
|
+
sage: M = ModularSymbols(eps, 2); M
|
|
3740
|
+
Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
|
|
3741
|
+
sage: M.modular_symbols_of_level(15)
|
|
3742
|
+
Modular Symbols space of dimension 0 and level 15, weight 2, character [1, zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
|
|
3743
|
+
"""
|
|
3744
|
+
if self.level() % N == 0:
|
|
3745
|
+
eps = self.character().restrict(N)
|
|
3746
|
+
elif N % self.level() == 0:
|
|
3747
|
+
eps = self.character().extend(N)
|
|
3748
|
+
else:
|
|
3749
|
+
raise ValueError("The level N (=%s) must be a divisor or multiple of the modulus of the character (=%s)" % (N, self.level()))
|
|
3750
|
+
return modsym.ModularSymbols(eps, self.weight(), self.sign(), self.base_ring())
|
|
3751
|
+
|
|
3752
|
+
def modular_symbols_of_sign(self, sign):
|
|
3753
|
+
r"""
|
|
3754
|
+
Return a space of modular symbols with the same defining
|
|
3755
|
+
properties (weight, level, etc.) as this space except with given
|
|
3756
|
+
sign.
|
|
3757
|
+
|
|
3758
|
+
INPUT:
|
|
3759
|
+
|
|
3760
|
+
- ``sign`` -- integer; a sign (`+1`, `-1` or `0`)
|
|
3761
|
+
|
|
3762
|
+
OUTPUT:
|
|
3763
|
+
|
|
3764
|
+
(ModularSymbolsAmbient) A space of modular symbols with the
|
|
3765
|
+
same defining properties (weight, level, etc.) as this space
|
|
3766
|
+
except with given sign.
|
|
3767
|
+
|
|
3768
|
+
EXAMPLES::
|
|
3769
|
+
|
|
3770
|
+
sage: eps = DirichletGroup(5).gen(0)
|
|
3771
|
+
sage: M = ModularSymbols(eps, 2); M
|
|
3772
|
+
Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
|
|
3773
|
+
sage: M.modular_symbols_of_sign(0) == M
|
|
3774
|
+
True
|
|
3775
|
+
sage: M.modular_symbols_of_sign(+1)
|
|
3776
|
+
Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 1, over Cyclotomic Field of order 4 and degree 2
|
|
3777
|
+
sage: M.modular_symbols_of_sign(-1)
|
|
3778
|
+
Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign -1, over Cyclotomic Field of order 4 and degree 2
|
|
3779
|
+
"""
|
|
3780
|
+
return modsym.ModularSymbols(self.character(), self.weight(), sign, self.base_ring())
|
|
3781
|
+
|
|
3782
|
+
def modular_symbols_of_weight(self, k):
|
|
3783
|
+
r"""
|
|
3784
|
+
Return a space of modular symbols with the same defining
|
|
3785
|
+
properties (weight, sign, etc.) as this space except with weight
|
|
3786
|
+
`k`.
|
|
3787
|
+
|
|
3788
|
+
INPUT:
|
|
3789
|
+
|
|
3790
|
+
- ``k`` -- positive integer
|
|
3791
|
+
|
|
3792
|
+
OUTPUT:
|
|
3793
|
+
|
|
3794
|
+
(ModularSymbolsAmbient) A space of modular symbols with the
|
|
3795
|
+
same defining properties (level, sign) as this space
|
|
3796
|
+
except with given weight.
|
|
3797
|
+
|
|
3798
|
+
EXAMPLES::
|
|
3799
|
+
|
|
3800
|
+
sage: eps = DirichletGroup(5).gen(0)
|
|
3801
|
+
sage: M = ModularSymbols(eps, 2); M
|
|
3802
|
+
Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
|
|
3803
|
+
sage: M.modular_symbols_of_weight(3)
|
|
3804
|
+
Modular Symbols space of dimension 2 and level 5, weight 3, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
|
|
3805
|
+
sage: M.modular_symbols_of_weight(2) == M
|
|
3806
|
+
True
|
|
3807
|
+
"""
|
|
3808
|
+
return modsym.ModularSymbols(self.character(), k, self.sign(), self.base_ring())
|
|
3809
|
+
|
|
3810
|
+
def _hecke_images(self, i, v):
|
|
3811
|
+
"""
|
|
3812
|
+
Return images of the `i`-th standard basis vector under the
|
|
3813
|
+
Hecke operators `T_p` for all integers in `v`.
|
|
3814
|
+
|
|
3815
|
+
INPUT:
|
|
3816
|
+
|
|
3817
|
+
- ``i`` -- nonnegative integer
|
|
3818
|
+
|
|
3819
|
+
- ``v`` -- list of positive integer
|
|
3820
|
+
|
|
3821
|
+
OUTPUT: ``matrix`` -- whose rows are the Hecke images
|
|
3822
|
+
|
|
3823
|
+
EXAMPLES::
|
|
3824
|
+
|
|
3825
|
+
sage: G.<e> = DirichletGroup(50,QQ)
|
|
3826
|
+
sage: M = ModularSymbols(e^2,2)
|
|
3827
|
+
sage: M.dimension()
|
|
3828
|
+
15
|
|
3829
|
+
sage: M._hecke_images(8,list(range(1,5)))
|
|
3830
|
+
[ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
|
|
3831
|
+
[ 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0]
|
|
3832
|
+
[ 0 1 0 2 0 -1 1 1 0 0 0 0 0 0 0]
|
|
3833
|
+
[ 0 1 1 -1 -1 0 -1 1 1 0 1 2 0 -2 2]
|
|
3834
|
+
"""
|
|
3835
|
+
if self.weight() != 2:
|
|
3836
|
+
raise NotImplementedError("Hecke images only implemented when the weight is 2")
|
|
3837
|
+
chi = self.character()
|
|
3838
|
+
# Find basis vector for ambient space such that it is not in
|
|
3839
|
+
# the kernel of the dual space corresponding to self.
|
|
3840
|
+
c = self.manin_generators()[self.manin_basis()[i]]
|
|
3841
|
+
N = self.level()
|
|
3842
|
+
if chi.order() > 2:
|
|
3843
|
+
return heilbronn.hecke_images_nonquad_character_weight2(c.u, c.v, N,
|
|
3844
|
+
v, chi, self.manin_gens_to_basis())
|
|
3845
|
+
return heilbronn.hecke_images_quad_character_weight2(c.u, c.v, N,
|
|
3846
|
+
v, chi, self.manin_gens_to_basis())
|