passagemath-schemes 10.6.40__cp314-cp314-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.

Potentially problematic release.


This version of passagemath-schemes might be problematic. Click here for more details.

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