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,4220 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.rings.number_field
3
+ r"""
4
+ Elliptic curves over number fields
5
+
6
+ An elliptic curve `E` over a number field `K` can be given
7
+ by a Weierstrass equation whose coefficients lie in `K` or by
8
+ using ``base_extend`` on an elliptic curve defined over a subfield.
9
+
10
+ One major difference to elliptic curves over `\QQ` is that there
11
+ might not exist a global minimal equation over `K`, when `K` does
12
+ not have class number one.
13
+ Another difference is the lack of understanding of modularity for
14
+ general elliptic curves over general number fields.
15
+
16
+ Currently Sage can obtain local information about `E/K_v` for finite places
17
+ `v`, it has an interface to Denis Simon's script for 2-descent, it can compute
18
+ the torsion subgroup of the Mordell-Weil group `E(K)`, and it can work with
19
+ isogenies defined over `K`.
20
+
21
+ EXAMPLES::
22
+
23
+ sage: x = polygen(QQ)
24
+ sage: K.<i> = NumberField(x^2 + 1)
25
+ sage: E = EllipticCurve([0, 4+i])
26
+ sage: E.discriminant()
27
+ -3456*i - 6480
28
+ sage: P= E([i,2])
29
+ sage: P+P
30
+ (-2*i + 9/16 : -9/4*i - 101/64 : 1)
31
+
32
+ ::
33
+
34
+ sage: E.has_good_reduction(2 + i)
35
+ True
36
+ sage: E.local_data(4+i)
37
+ Local data at Fractional ideal (i + 4):
38
+ Reduction type: bad additive
39
+ Local minimal model: Elliptic Curve defined by y^2 = x^3 + (i+4)
40
+ over Number Field in i with defining polynomial x^2 + 1
41
+ Minimal discriminant valuation: 2
42
+ Conductor exponent: 2
43
+ Kodaira Symbol: II
44
+ Tamagawa Number: 1
45
+ sage: E.tamagawa_product_bsd()
46
+ 1
47
+
48
+ ::
49
+
50
+ sage: E.simon_two_descent()
51
+ (1, 1, [(i : 2 : 1)])
52
+
53
+ ::
54
+
55
+ sage: E.torsion_order()
56
+ 1
57
+
58
+ ::
59
+
60
+ sage: E.isogenies_prime_degree(3)
61
+ [Isogeny of degree 3
62
+ from Elliptic Curve defined by y^2 = x^3 + (i+4)
63
+ over Number Field in i with defining polynomial x^2 + 1
64
+ to Elliptic Curve defined by y^2 = x^3 + (-27*i-108)
65
+ over Number Field in i with defining polynomial x^2 + 1]
66
+
67
+ AUTHORS:
68
+
69
+ - Robert Bradshaw 2007
70
+
71
+ - John Cremona
72
+
73
+ - Chris Wuthrich
74
+
75
+ REFERENCE:
76
+
77
+ - [Sil] Silverman, Joseph H. The arithmetic of elliptic curves. Second edition. Graduate Texts in
78
+ Mathematics, 106. Springer, 2009.
79
+
80
+ - [Sil2] Silverman, Joseph H. Advanced topics in the arithmetic of elliptic curves. Graduate Texts in
81
+ Mathematics, 151. Springer, 1994.
82
+ """
83
+
84
+ # ****************************************************************************
85
+ # Copyright (C) 2007 Robert Bradshaw <robertwb@math.washington.edu>
86
+ # William Stein <wstein@gmail.com>
87
+ #
88
+ # This program is free software: you can redistribute it and/or modify
89
+ # it under the terms of the GNU General Public License as published by
90
+ # the Free Software Foundation, either version 2 of the License, or
91
+ # (at your option) any later version.
92
+ # https://www.gnu.org/licenses/
93
+ # ****************************************************************************
94
+
95
+ import sage.rings.abc
96
+ from .ell_field import EllipticCurve_field
97
+ from .ell_generic import EllipticCurve_generic
98
+ from .ell_point import EllipticCurvePoint_number_field
99
+ from .constructor import EllipticCurve
100
+ from sage.rings.integer_ring import ZZ
101
+ from sage.rings.rational_field import QQ
102
+ from sage.rings.real_mpfr import RealField
103
+ from sage.rings.integer import Integer
104
+ from sage.misc.cachefunc import cached_method
105
+ from sage.misc.misc_c import prod
106
+
107
+
108
+ class EllipticCurve_number_field(EllipticCurve_field):
109
+ r"""
110
+ Elliptic curve over a number field.
111
+
112
+ EXAMPLES::
113
+
114
+ sage: x = polygen(QQ)
115
+ sage: K.<i> = NumberField(x^2 + 1)
116
+ sage: EllipticCurve([i, i - 1, i + 1, 24*i + 15, 14*i + 35])
117
+ Elliptic Curve defined by
118
+ y^2 + i*x*y + (i+1)*y = x^3 + (i-1)*x^2 + (24*i+15)*x + (14*i+35)
119
+ over Number Field in i with defining polynomial x^2 + 1
120
+ """
121
+ def __init__(self, K, ainvs):
122
+ r"""
123
+ EXAMPLES:
124
+
125
+ A curve from the database of curves over `\QQ`, but over a larger field::
126
+
127
+ sage: x = polygen(QQ)
128
+ sage: K.<i> = NumberField(x^2 + 1)
129
+ sage: EllipticCurve(K,'389a1')
130
+ Elliptic Curve defined by y^2 + y = x^3 + x^2 + (-2)*x
131
+ over Number Field in i with defining polynomial x^2 + 1
132
+
133
+ Making the field of definition explicitly larger::
134
+
135
+ sage: EllipticCurve(K,[0,-1,1,0,0])
136
+ Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2
137
+ over Number Field in i with defining polynomial x^2 + 1
138
+ """
139
+ self._known_points = []
140
+ EllipticCurve_field.__init__(self, K, ainvs)
141
+
142
+ _point = EllipticCurvePoint_number_field
143
+
144
+ def base_extend(self, R):
145
+ """
146
+ Return the base extension of ``self`` to `R`.
147
+
148
+ EXAMPLES::
149
+
150
+ sage: E = EllipticCurve('11a3')
151
+ sage: K = QuadraticField(-5, 'a')
152
+ sage: E.base_extend(K)
153
+ Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 over Number Field in a
154
+ with defining polynomial x^2 + 5 with a = 2.236067977499790?*I
155
+
156
+ Check that non-torsion points are remembered when extending
157
+ the base field (see :issue:`16034`)::
158
+
159
+ sage: E = EllipticCurve([1, 0, 1, -1751, -31352])
160
+ sage: K.<d> = QuadraticField(5)
161
+ sage: E.gens() # needs eclib
162
+ [(52 : 111 : 1)]
163
+ sage: EK = E.base_extend(K)
164
+ sage: EK.gens() # needs eclib
165
+ ((52 : 111 : 1),)
166
+ """
167
+ E = super().base_extend(R)
168
+ if isinstance(E, EllipticCurve_number_field):
169
+ E._known_points = [E([R(_) for _ in P.xy()]) for P in self._known_points if not P.is_zero()]
170
+ return E
171
+
172
+ def simon_two_descent(self, verbose=0, lim1=2, lim3=4, limtriv=2,
173
+ maxprob=20, limbigprime=30, known_points=None):
174
+ r"""
175
+ Return lower and upper bounds on the rank of the Mordell-Weil
176
+ group `E(K)` and a list of points.
177
+
178
+ This method is used internally by the :meth:`~rank`,
179
+ :meth:`~rank_bounds` and :meth:`~gens` methods.
180
+
181
+ INPUT:
182
+
183
+ - ``self`` -- an elliptic curve `E` over a number field `K`
184
+
185
+ - ``verbose`` -- 0, 1, 2, or 3 (default: 0); the verbosity level
186
+
187
+ - ``lim1`` -- (default: 2) limit on trivial points on quartics
188
+
189
+ - ``lim3`` -- (default: 4) limit on points on ELS quartics
190
+
191
+ - ``limtriv`` -- (default: 2) limit on trivial points on `E`
192
+
193
+ - ``maxprob`` -- (default: 20)
194
+
195
+ - ``limbigprime`` -- (default: 30) to distinguish between
196
+ small and large prime numbers. Use probabilistic tests for
197
+ large primes. If 0, do not use probabilistic tests.
198
+
199
+ - ``known_points`` -- (default: ``None``) list of known points on
200
+ the curve
201
+
202
+ OUTPUT: a triple ``(lower, upper, list)`` consisting of
203
+
204
+ - ``lower`` -- integer; lower bound on the rank
205
+
206
+ - ``upper`` -- integer; upper bound on the rank
207
+
208
+ - ``list`` -- list of points in `E(K)`
209
+
210
+ The integer ``upper`` is in fact an upper bound on the
211
+ dimension of the 2-Selmer group, hence on the dimension of
212
+ `E(K)/2E(K)`. It is equal to the dimension of the 2-Selmer
213
+ group except possibly if `E(K)[2]` has dimension 1. In that
214
+ case, ``upper`` may exceed the dimension of the 2-Selmer group
215
+ by an even number, due to the fact that the algorithm does not
216
+ perform a second descent.
217
+
218
+ .. NOTE::
219
+
220
+ For non-quadratic number fields, this code does return, but
221
+ it takes a long time.
222
+
223
+ ALGORITHM:
224
+
225
+ Uses Denis Simon's PARI/GP scripts from
226
+ https://simond.users.lmno.cnrs.fr/.
227
+
228
+ EXAMPLES::
229
+
230
+ sage: x = polygen(ZZ, 'x')
231
+ sage: K.<a> = NumberField(x^2 + 23, 'a')
232
+ sage: E = EllipticCurve(K, '37')
233
+ sage: E == loads(dumps(E))
234
+ True
235
+ sage: E.simon_two_descent()
236
+ (2, 2, [(0 : 0 : 1), (1/8*a + 5/8 : -3/16*a - 7/16 : 1)])
237
+ sage: E.simon_two_descent(lim1=5, lim3=5, limtriv=10, maxprob=7, limbigprime=10)
238
+ (2, 2, [(-1 : 0 : 1), (1/2*a - 5/2 : -1/2*a - 13/2 : 1)])
239
+
240
+ ::
241
+
242
+ sage: K.<a> = NumberField(x^2 + 7, 'a')
243
+ sage: E = EllipticCurve(K, [0,0,0,1,a]); E
244
+ Elliptic Curve defined by y^2 = x^3 + x + a
245
+ over Number Field in a with defining polynomial x^2 + 7
246
+
247
+ sage: v = E.simon_two_descent(verbose=1); v
248
+ elliptic curve: Y^2 = x^3 + Mod(1, y^2 + 7)*x + Mod(y, y^2 + 7)
249
+ Trivial points on the curve = [[1, 1, 0], [Mod(1/2*y + 3/2, y^2 + 7), Mod(-y - 2, y^2 + 7), 1]]
250
+ #S(E/K)[2] = 2
251
+ #E(K)/2E(K) = 2
252
+ #III(E/K)[2] = 1
253
+ rank(E/K) = 1
254
+ listpoints = [[Mod(1/2*y + 3/2, y^2 + 7), Mod(-y - 2, y^2 + 7), 1]]
255
+ (1, 1, [(1/2*a + 3/2 : -a - 2 : 1)])
256
+
257
+ A curve with 2-torsion::
258
+
259
+ sage: K.<a> = NumberField(x^2 + 7)
260
+ sage: E = EllipticCurve(K, '15a')
261
+ sage: E.simon_two_descent() # long time (3s on sage.math, 2013), points can vary
262
+ (1, 3, [...])
263
+
264
+ Check that the bug reported in :issue:`15483` is fixed::
265
+
266
+ sage: K.<s> = QuadraticField(229)
267
+ sage: c4 = 2173 - 235*(1 - s)/2
268
+ sage: c6 = -124369 + 15988*(1 - s)/2
269
+ sage: E = EllipticCurve([-c4/48, -c6/864])
270
+ sage: E.simon_two_descent()
271
+ (0, 0, [])
272
+
273
+ sage: R.<t> = QQ[]
274
+ sage: L.<g> = NumberField(t^3 - 9*t^2 + 13*t - 4)
275
+ sage: E1 = EllipticCurve(L, [1-g*(g-1), -g^2*(g-1), -g^2*(g-1), 0, 0])
276
+ sage: E1.rank() # long time (about 5 s)
277
+ 0
278
+
279
+ sage: K = CyclotomicField(43).subfields(3)[0][0]
280
+ sage: E = EllipticCurve(K, '37')
281
+ sage: E.simon_two_descent() # long time (4s on sage.math, 2013)
282
+ (3,
283
+ 3,
284
+ [(-1/2*zeta43_0^2 - 1/2*zeta43_0 + 7 : -3/2*zeta43_0^2 - 5/2*zeta43_0 + 18 : 1),
285
+ (0 : 0 : 1)])
286
+ """
287
+ verbose = int(verbose)
288
+ if known_points is None:
289
+ known_points = self._known_points
290
+ known_points = [self(P) for P in known_points]
291
+
292
+ # We deliberately do not use known_points as a key in the
293
+ # following caching code, so that calling E.gens() a second
294
+ # time (when known_points may have increased) will not cause
295
+ # another execution of simon_two_descent.
296
+ try:
297
+ result = self._simon_two_descent_data[lim1, lim3, limtriv,
298
+ maxprob, limbigprime]
299
+ if verbose == 0:
300
+ return result
301
+ except AttributeError:
302
+ self._simon_two_descent_data = {}
303
+ except KeyError:
304
+ pass
305
+
306
+ from .gp_simon import simon_two_descent
307
+ t = simon_two_descent(self, verbose=verbose,
308
+ lim1=lim1, lim3=lim3, limtriv=limtriv,
309
+ maxprob=maxprob, limbigprime=limbigprime,
310
+ known_points=known_points)
311
+ self._simon_two_descent_data[lim1,lim3,limtriv,maxprob,limbigprime] = t
312
+ self._known_points.extend([P for P in t[2]
313
+ if P not in self._known_points])
314
+ return t
315
+
316
+ def height_pairing_matrix(self, points=None, precision=None, normalised=True):
317
+ r"""
318
+ Return the height pairing matrix of the given points.
319
+
320
+ INPUT:
321
+
322
+ - ``points`` -- list or ``None`` (default); list of points
323
+ on this curve, or ``None``, in which case ``self.gens()`` will
324
+ be used
325
+
326
+ - ``precision`` -- integer or ``None`` (default); number of bits
327
+ of precision of result, or ``None``, for default RealField precision
328
+
329
+ - ``normalised`` -- boolean (default: ``True``); if ``True``, use
330
+ normalised heights which are independent of base change.
331
+ Otherwise use the non-normalised Néron-Tate height, as
332
+ required for the regulator in the BSD conjecture.
333
+
334
+ EXAMPLES::
335
+
336
+ sage: E = EllipticCurve([0, 0, 1, -1, 0])
337
+ sage: E.height_pairing_matrix() # needs eclib
338
+ [0.0511114082399688]
339
+
340
+ For rank 0 curves, the result is a valid 0x0 matrix::
341
+
342
+ sage: # needs eclib
343
+ sage: EllipticCurve('11a').height_pairing_matrix()
344
+ []
345
+ sage: E = EllipticCurve('5077a1')
346
+ sage: E.height_pairing_matrix([E.lift_x(x) for x in [-2,-7/4,1]], precision=100)
347
+ [ 1.3685725053539301120518194471 -1.3095767070865761992624519454 -0.63486715783715592064475542573]
348
+ [ -1.3095767070865761992624519454 2.7173593928122930896610589220 1.0998184305667292139777571432]
349
+ [-0.63486715783715592064475542573 1.0998184305667292139777571432 0.66820516565192793503314205089]
350
+
351
+ sage: E = EllipticCurve('389a1')
352
+ sage: E = EllipticCurve('389a1')
353
+ sage: P, Q = E.point([-1,1,1]), E.point([0,-1,1])
354
+ sage: E.height_pairing_matrix([P,Q]) # needs eclib
355
+ [0.686667083305587 0.268478098806726]
356
+ [0.268478098806726 0.327000773651605]
357
+
358
+ Over a number field::
359
+
360
+ sage: x = polygen(QQ)
361
+ sage: K.<t> = NumberField(x^2 + 47)
362
+ sage: EK = E.base_extend(K)
363
+ sage: EK.height_pairing_matrix([EK(P),EK(Q)]) # needs eclib
364
+ [0.686667083305587 0.268478098806726]
365
+ [0.268478098806726 0.327000773651605]
366
+
367
+ ::
368
+
369
+ sage: K.<i> = QuadraticField(-1)
370
+ sage: E = EllipticCurve([0,0,0,i,i])
371
+ sage: P = E(-9+4*i, -18-25*i)
372
+ sage: Q = E(i,-i)
373
+ sage: E.height_pairing_matrix([P,Q]) # needs eclib
374
+ [ 2.16941934493768 -0.870059380421505]
375
+ [-0.870059380421505 0.424585837470709]
376
+ sage: E.regulator_of_points([P,Q]) # needs eclib
377
+ 0.164101403936070
378
+
379
+ When the parameter ``normalised`` is set to ``False``, each
380
+ height is multiplied by the degree `d` of the base field, and
381
+ the regulator of `r` points is multiplied by `d^r`::
382
+
383
+ sage: E.height_pairing_matrix([P,Q], normalised=False)
384
+ [ 4.33883868987537 -1.74011876084301]
385
+ [-1.74011876084301 0.849171674941418]
386
+ sage: E.regulator_of_points([P,Q], normalised=False)
387
+ 0.656405615744281
388
+ """
389
+ if points is None:
390
+ points = self.gens()
391
+ else:
392
+ for P in points:
393
+ assert P.curve() == self
394
+
395
+ r = len(points)
396
+ if precision is None:
397
+ RR = RealField()
398
+ else:
399
+ RR = RealField(precision)
400
+ from sage.matrix.matrix_space import MatrixSpace
401
+ M = MatrixSpace(RR, r)
402
+ mat = M()
403
+ for j in range(r):
404
+ mat[j, j] = points[j].height(precision=precision, normalised=normalised)
405
+ for j in range(r):
406
+ for k in range(j + 1, r):
407
+ mat[j, k] = ((points[j] + points[k]).height(precision=precision, normalised=normalised) - mat[j, j] - mat[k, k]) / 2
408
+ mat[k, j] = mat[j, k]
409
+ return mat
410
+
411
+ def regulator_of_points(self, points=[], precision=None, normalised=True):
412
+ """Return the regulator of the given points on this curve.
413
+
414
+ INPUT:
415
+
416
+ - ``points`` -- (default: empty list) a list of points on this curve
417
+
418
+ - ``precision`` -- integer or ``None`` (default); the
419
+ precision in bits of the result (default: real precision if ``None``)
420
+
421
+ - ``normalised`` -- boolean (default: ``True``); if ``True``, use
422
+ normalised heights which are independent of base change.
423
+ Otherwise use the non-normalised Néron-Tate height, as
424
+ required for the regulator in the BSD conjecture
425
+
426
+ EXAMPLES::
427
+
428
+ sage: E = EllipticCurve('37a1')
429
+ sage: P = E(0,0)
430
+ sage: Q = E(1,0)
431
+ sage: E.regulator_of_points([P,Q])
432
+ 0.000000000000000
433
+ sage: 2*P == Q
434
+ True
435
+
436
+ ::
437
+
438
+ sage: E = EllipticCurve('5077a1')
439
+ sage: points = [E.lift_x(x) for x in [-2,-7/4,1]]
440
+ sage: E.regulator_of_points(points)
441
+ 0.417143558758384
442
+ sage: E.regulator_of_points(points, precision=100)
443
+ 0.41714355875838396981711954462
444
+
445
+ ::
446
+
447
+ sage: E = EllipticCurve('389a')
448
+ sage: E.regulator_of_points()
449
+ 1.00000000000000
450
+ sage: points = [P,Q] = [E(-1,1), E(0,-1)]
451
+ sage: E.regulator_of_points(points)
452
+ 0.152460177943144
453
+ sage: E.regulator_of_points(points, precision=100)
454
+ 0.15246017794314375162432475705
455
+ sage: E.regulator_of_points(points, precision=200)
456
+ 0.15246017794314375162432475704945582324372707748663081784028
457
+ sage: E.regulator_of_points(points, precision=300)
458
+ 0.152460177943143751624324757049455823243727077486630817840280980046053225683562463604114816
459
+
460
+ Examples over number fields::
461
+
462
+ sage: K.<a> = QuadraticField(97)
463
+ sage: E = EllipticCurve(K, [1,1])
464
+ sage: P = E(0,1)
465
+ sage: P.height()
466
+ 0.476223106404866
467
+ sage: E.regulator_of_points([P])
468
+ 0.476223106404866
469
+
470
+ When the parameter ``normalised`` is set to ``False``, each
471
+ height is multiplied by the degree `d` of the base field, and
472
+ the regulator of `r` points is multiplied by `d^r`::
473
+
474
+ sage: P.height(normalised=False)
475
+ 0.952446212809731
476
+ sage: E.regulator_of_points([P], normalised=False)
477
+ 0.952446212809731
478
+
479
+ ::
480
+
481
+ sage: E = EllipticCurve('11a1')
482
+ sage: x = polygen(QQ)
483
+ sage: K.<t> = NumberField(x^2 + 47)
484
+ sage: EK = E.base_extend(K)
485
+ sage: T = EK(5, 5)
486
+ sage: T.order()
487
+ 5
488
+ sage: P = EK(-2, -1/2*t - 1/2)
489
+ sage: P.order()
490
+ +Infinity
491
+ sage: EK.regulator_of_points([P,T]) # random very small output
492
+ -1.23259516440783e-32
493
+ sage: EK.regulator_of_points([P,T]).abs() < 1e-30
494
+ True
495
+
496
+ ::
497
+
498
+ sage: # needs eclib
499
+ sage: E = EllipticCurve('389a1')
500
+ sage: P,Q = E.gens()
501
+ sage: E.regulator_of_points([P,Q])
502
+ 0.152460177943144
503
+ sage: K.<t> = NumberField(x^2 + 47)
504
+ sage: EK = E.base_extend(K)
505
+ sage: EK.regulator_of_points([EK(P),EK(Q)])
506
+ 0.152460177943144
507
+
508
+ ::
509
+
510
+ sage: K.<i> = QuadraticField(-1)
511
+ sage: E = EllipticCurve([0,0,0,i,i])
512
+ sage: P = E(-9+4*i, -18-25*i)
513
+ sage: Q = E(i, -i)
514
+ sage: E.height_pairing_matrix([P,Q])
515
+ [ 2.16941934493768 -0.870059380421505]
516
+ [-0.870059380421505 0.424585837470709]
517
+ sage: E.regulator_of_points([P,Q])
518
+ 0.164101403936070
519
+ """
520
+ if points is None:
521
+ points = []
522
+ mat = self.height_pairing_matrix(points=points, precision=precision, normalised=normalised)
523
+ return mat.det(algorithm='hessenberg')
524
+
525
+ def is_local_integral_model(self, *P):
526
+ r"""
527
+ Test if ``self`` is integral at the prime ideal `P`, or at all the
528
+ primes if `P` is a list or tuple.
529
+
530
+ INPUT:
531
+
532
+ - ``*P`` -- a prime ideal, or a list or tuple of primes
533
+
534
+ EXAMPLES::
535
+
536
+ sage: x = polygen(QQ)
537
+ sage: K.<i> = NumberField(x^2 + 1)
538
+ sage: P1, P2 = K.primes_above(5)
539
+ sage: E = EllipticCurve([i/5,i/5,i/5,i/5,i/5])
540
+ sage: E.is_local_integral_model(P1, P2)
541
+ False
542
+ sage: Emin = E.local_integral_model(P1, P2)
543
+ sage: Emin.is_local_integral_model(P1, P2)
544
+ True
545
+ """
546
+ if len(P) == 1:
547
+ P = P[0]
548
+ if isinstance(P, (tuple, list)):
549
+ return all(self.is_local_integral_model(x) for x in P)
550
+ return all(x.valuation(P) >= 0 for x in self.ainvs())
551
+
552
+ def local_integral_model(self, *P):
553
+ r"""
554
+ Return a model of ``self`` which is integral at the prime ideal `P`.
555
+
556
+ .. NOTE::
557
+
558
+ The integrality at other primes is not affected, even if
559
+ `P` is non-principal.
560
+
561
+ INPUT:
562
+
563
+ - ``*P`` -- a prime ideal, or a list or tuple of primes
564
+
565
+ EXAMPLES::
566
+
567
+ sage: x = polygen(QQ)
568
+ sage: K.<i> = NumberField(x^2 + 1)
569
+ sage: P1, P2 = K.primes_above(5)
570
+ sage: E = EllipticCurve([i/5,i/5,i/5,i/5,i/5])
571
+ sage: E.local_integral_model((P1,P2))
572
+ Elliptic Curve defined by
573
+ y^2 + (-i)*x*y + (-25*i)*y = x^3 + 5*i*x^2 + 125*i*x + 3125*i
574
+ over Number Field in i with defining polynomial x^2 + 1
575
+ """
576
+ if len(P) == 1:
577
+ P = P[0]
578
+ if isinstance(P, (tuple, list)):
579
+ E = self
580
+ for Pi in P:
581
+ E = E.local_integral_model(Pi)
582
+ return E
583
+ ai = self.a_invariants()
584
+ e = min((ai[i].valuation(P) / [1, 2, 3, 4, 6][i])
585
+ for i in range(5)).floor()
586
+ pi = self.base_field().uniformizer(P, 'negative')
587
+ return EllipticCurve([ai[i]/pi**(e*[1,2,3,4,6][i]) for i in range(5)])
588
+
589
+ def is_global_integral_model(self):
590
+ r"""
591
+ Return whether ``self`` is integral at all primes.
592
+
593
+ EXAMPLES::
594
+
595
+ sage: x = polygen(QQ)
596
+ sage: K.<i> = NumberField(x^2 + 1)
597
+ sage: E = EllipticCurve([i/5,i/5,i/5,i/5,i/5])
598
+ sage: P1, P2 = K.primes_above(5)
599
+ sage: Emin = E.global_integral_model()
600
+ sage: Emin.is_global_integral_model()
601
+ True
602
+ """
603
+ return all(x.is_integral() for x in self.a_invariants())
604
+
605
+ def global_integral_model(self):
606
+ r"""
607
+ Return a model of ``self`` which is integral at all primes.
608
+
609
+ EXAMPLES::
610
+
611
+ sage: x = polygen(QQ)
612
+ sage: K.<i> = NumberField(x^2 + 1)
613
+ sage: E = EllipticCurve([i/5,i/5,i/5,i/5,i/5])
614
+ sage: P1, P2 = K.primes_above(5)
615
+ sage: E.global_integral_model()
616
+ Elliptic Curve defined by
617
+ y^2 + (-i)*x*y + (-25*i)*y = x^3 + 5*i*x^2 + 125*i*x + 3125*i
618
+ over Number Field in i with defining polynomial x^2 + 1
619
+
620
+ :issue:`7935`::
621
+
622
+ sage: x = polygen(QQ)
623
+ sage: K.<a> = NumberField(x^2 - 38)
624
+ sage: E = EllipticCurve([a,1/2])
625
+ sage: E.global_integral_model()
626
+ Elliptic Curve defined by y^2 = x^3 + 1444*a*x + 27436
627
+ over Number Field in a with defining polynomial x^2 - 38
628
+
629
+ :issue:`9266`::
630
+
631
+ sage: x = polygen(QQ)
632
+ sage: K.<s> = NumberField(x^2 - 5)
633
+ sage: w = (1+s)/2
634
+ sage: E = EllipticCurve(K, [2,w])
635
+ sage: E.global_integral_model()
636
+ Elliptic Curve defined by y^2 = x^3 + 2*x + (1/2*s+1/2)
637
+ over Number Field in s with defining polynomial x^2 - 5
638
+
639
+ :issue:`12151`::
640
+
641
+ sage: x = polygen(QQ)
642
+ sage: K.<v> = NumberField(x^2 + 161*x - 150)
643
+ sage: E = EllipticCurve([25105/216*v - 3839/36, 634768555/7776*v - 98002625/1296, 634768555/7776*v - 98002625/1296, 0, 0])
644
+ sage: M = E.global_integral_model(); M # choice varies, not tested
645
+ Elliptic Curve defined by
646
+ y^2 + (2094779518028859*v-1940492905300351)*x*y + (477997268472544193101178234454165304071127500*v-442791377441346852919930773849502871958097500)*y = x^3 + (26519784690047674853185542622500*v-24566525306469707225840460652500)*x^2
647
+ over Number Field in v with defining polynomial x^2 + 161*x - 150
648
+
649
+ :issue:`14476`::
650
+
651
+ sage: R.<t> = QQ[]
652
+ sage: K.<g> = NumberField(t^4 - t^3 - 3*t^2 - t + 1)
653
+ sage: E = EllipticCurve([ -43/625*g^3 + 14/625*g^2 - 4/625*g + 706/625, -4862/78125*g^3 - 4074/78125*g^2 - 711/78125*g + 10304/78125, -4862/78125*g^3 - 4074/78125*g^2 - 711/78125*g + 10304/78125, 0,0])
654
+ sage: E.global_integral_model()
655
+ Elliptic Curve defined by
656
+ y^2 + (15*g^3-48*g-42)*x*y + (-111510*g^3-162162*g^2-44145*g+37638)*y = x^3 + (-954*g^3-1134*g^2+81*g+576)*x^2
657
+ over Number Field in g with defining polynomial t^4 - t^3 - 3*t^2 - t + 1
658
+
659
+ TESTS:
660
+
661
+ Check the skipped test from above::
662
+
663
+ sage: x = polygen(QQ)
664
+ sage: K.<v> = NumberField(x^2 + 161*x - 150)
665
+ sage: E = EllipticCurve([25105/216*v - 3839/36, 634768555/7776*v - 98002625/1296, 634768555/7776*v - 98002625/1296, 0, 0])
666
+ sage: M = E.global_integral_model()
667
+ sage: b = M.ainvs()
668
+ sage: b[0] in (2094779518028859*v-1940492905300351, 33872485050625*v - 31078224284250)
669
+ True
670
+ sage: b[1] in (26519784690047674853185542622500*v - 24566525306469707225840460652500,
671
+ ....: 6933305282258321342920781250*v - 6422644400723486559914062500)
672
+ True
673
+ sage: b[2] in (477997268472544193101178234454165304071127500*v -442791377441346852919930773849502871958097500,
674
+ ....: 2020602604156076340058146664245468750000*v - 1871778534673615560803175189398437500000)
675
+ True
676
+ sage: b[3:]
677
+ (0, 0)
678
+ """
679
+ K = self.base_field()
680
+ ai = self.a_invariants()
681
+ Ps = {ff[0] for a in ai if not a.is_integral()
682
+ for ff in a.denominator_ideal().factor()}
683
+ for P in Ps:
684
+ pi = K.uniformizer(P, 'positive')
685
+ e = min((ai[i].valuation(P)/[1,2,3,4,6][i])
686
+ for i in range(5)).floor()
687
+ if e < 0:
688
+ ai = [ai[i]/pi**(e*[1,2,3,4,6][i]) for i in range(5)]
689
+ if all(a.is_integral() for a in ai):
690
+ break
691
+ for z in ai:
692
+ assert z.is_integral(), "bug in global_integral_model: %s" % list(ai)
693
+ return EllipticCurve(list(ai))
694
+
695
+ integral_model = global_integral_model
696
+
697
+ def _reduce_model(self):
698
+ r"""
699
+ Return a reduced model for this elliptic curve.
700
+
701
+ Transforms the elliptic curve to a model which is optimally scaled
702
+ with respect to units and in which `a_1`, `a_2`, `a_3` are
703
+ reduced modulo 2, 3, 2 respectively.
704
+
705
+ .. NOTE::
706
+
707
+ This only works on integral models, i.e. it requires that
708
+ `a_1`, `a_2` and `a_3` lie in the ring of integers of the base
709
+ field.
710
+
711
+ EXAMPLES::
712
+
713
+ sage: x = polygen(ZZ, 'x')
714
+ sage: K.<a> = NumberField(x^2 - 38)
715
+ sage: E = EllipticCurve([a, -5*a + 19, -39*a + 237, 368258520200522046806318224*a - 2270097978636731786720858047, 8456608930180227786550494643437985949781*a - 52130038506835491453281450568107193773505])
716
+ sage: E.ainvs()
717
+ (a,
718
+ -5*a + 19,
719
+ -39*a + 237,
720
+ 368258520200522046806318224*a - 2270097978636731786720858047,
721
+ 8456608930180227786550494643437985949781*a - 52130038506835491453281450568107193773505)
722
+ sage: E._reduce_model().ainvs()
723
+ (a,
724
+ a + 1,
725
+ a + 1,
726
+ 368258520200522046806318444*a - 2270097978636731786720859345,
727
+ 8456608930173478039472018047583706316424*a - 52130038506793883217874390501829588391299)
728
+ sage: EllipticCurve([101,202,303,404,505])._reduce_model().ainvs()
729
+ (1, 1, 0, -2509254, 1528863051)
730
+ sage: EllipticCurve([-101,-202,-303,-404,-505])._reduce_model().ainvs()
731
+ (1, -1, 0, -1823195, 947995262)
732
+
733
+ sage: E = EllipticCurve([a/4, 1])
734
+ sage: E._reduce_model()
735
+ Traceback (most recent call last):
736
+ ...
737
+ TypeError: _reduce_model() requires an integral model.
738
+ """
739
+ K = self.base_ring()
740
+ ZK = K.maximal_order()
741
+ try:
742
+ a1, a2, a3, a4, a6 = (ZK(a) for a in self.a_invariants())
743
+ except TypeError:
744
+ raise TypeError("_reduce_model() requires an integral model.")
745
+
746
+ # N.B. Must define s, r, t in the right order.
747
+ if ZK.absolute_degree() == 1:
748
+ s = ((-a1) / 2).round('up')
749
+ r = ((-a2 + s * a1 + s * s) / 3).round()
750
+ t = ((-a3 - r * a1) / 2).round('up')
751
+ else:
752
+ pariK = K.__pari__()
753
+ s = K(pariK.nfeltdiveuc(-a1, 2))
754
+ r = K(pariK.nfeltdiveuc(-a2 + s * a1 + s * s, 3))
755
+ t = K(pariK.nfeltdiveuc(-a3 - r * a1, 2))
756
+
757
+ return self.rst_transform(r, s, t)
758
+
759
+ def _scale_by_units(self):
760
+ r"""
761
+ Return a model reduced with respect to scaling by units.
762
+
763
+ OUTPUT:
764
+
765
+ A model for this elliptic curve, optimally scaled with respect
766
+ to scaling by units, with respect to the logarithmic embedding
767
+ of `|c4|^(1/4)+|c6|^(1/6)`. No scaling by roots of unity is
768
+ carried out, so there is no change when the unit rank is 0.
769
+
770
+ EXAMPLES::
771
+
772
+ sage: x = polygen(ZZ, 'x')
773
+ sage: K.<a> = NumberField(x^2 - 10)
774
+ sage: u = a + 3
775
+ sage: u.is_unit()
776
+ True
777
+ sage: E = EllipticCurve([0, 0, 0, 4536*a + 14148, -163728*a - 474336])
778
+ sage: E1 = E.scale_curve(u^5)
779
+ sage: E1.ainvs()
780
+ (0,
781
+ 0,
782
+ 0,
783
+ 28087920796764302856*a + 88821804456186580548,
784
+ -77225139016967233228487820912*a - 244207331916752959911655344864)
785
+ sage: E1._scale_by_units().ainvs()
786
+ (0, 0, 0, 4536*a + 14148, -163728*a - 474336)
787
+
788
+ A totally real cubic example::
789
+
790
+ sage: K.<a> = NumberField(x^3-x^2-6*x+5)
791
+ sage: E = EllipticCurve([a + 1, a^2 + a - 1, a + 1, 44*a^2 + a - 258, -215*a^2 + 53*a + 1340])
792
+ sage: u1, u2 = K.units()
793
+ sage: u = u1^2/u2^3
794
+ sage: E1 = E.scale_curve(u)
795
+ sage: E1._scale_by_units().ainvs() == E.ainvs()
796
+ True
797
+
798
+ A complex quartic example::
799
+
800
+ sage: K.<a> = CyclotomicField(5)
801
+ sage: E = EllipticCurve([a + 1, a^2 + a - 1, a + 1, 44*a^2 + a - 258, -215*a^2 + 53*a + 1340])
802
+ sage: u = K.units()[0]
803
+ sage: E1 = E.scale_curve(u^5)
804
+ sage: E1._scale_by_units().ainvs() == E.ainvs()
805
+ True
806
+
807
+ TESTS:
808
+
809
+ See :issue:`34174`. This used to raise an error due to insufficient precision::
810
+
811
+ sage: K.<a> = QuadraticField(4569)
812
+ sage: j = 46969655/32768
813
+ sage: E = EllipticCurve(j=K(j))
814
+ sage: C = E.isogeny_class() # long time (9.5s)
815
+ """
816
+ K = self.base_field()
817
+ r1, r2 = K.signature()
818
+ if r1 + r2 == 1: # unit rank is 0
819
+ return self
820
+
821
+ degs = [1]*r1 + [2]*r2
822
+ fu = K.units()
823
+ c4, c6 = self.c_invariants()
824
+
825
+ from sage.matrix.constructor import Matrix
826
+ from sage.modules.free_module_element import vector
827
+
828
+ prec = 1000 # initial value, will be increased if necessary
829
+ ok = False
830
+ while not ok:
831
+ embs = K.places(prec=prec)
832
+ c4s = [e(c4) for e in embs]
833
+ c6s = [e(c6) for e in embs]
834
+
835
+ U = Matrix([[e(u).abs().log()*d for d,e in zip(degs,embs)] for u in fu])
836
+ v = vector([(x4.abs().nth_root(4)+x6.abs().nth_root(6)).log()*d for x4,x6,d in zip(c4s,c6s,degs)])
837
+ w = -(U*U.transpose()).inverse()*U*v
838
+ try:
839
+ es = [e.round() for e in w]
840
+ ok = True
841
+ except ValueError:
842
+ prec *= 2
843
+
844
+ u = prod([uj**ej for uj,ej in zip(fu,es)])
845
+ return self.scale_curve(u)
846
+
847
+ def local_data(self, P=None, proof=None, algorithm='pari', globally=False):
848
+ r"""
849
+ Local data for this elliptic curve at the prime `P`.
850
+
851
+ INPUT:
852
+
853
+ - ``P`` -- either ``None``, a prime ideal of the base field of ``self``,
854
+ or an element of the base field that generates a prime ideal
855
+
856
+ - ``proof`` -- whether to only use provably correct methods
857
+ (default controlled by global proof module). Note that the
858
+ proof module is number_field, not elliptic_curves, since the
859
+ functions that actually need the flag are in number fields.
860
+
861
+ - ``algorithm`` -- string (default: ``'pari'``); ignored unless the
862
+ base field is `\QQ`. If ``'pari'``, use the PARI C-library
863
+ :pari:`ellglobalred` implementation of Tate's algorithm over
864
+ `\QQ`. If ``'generic'``, use the general number field
865
+ implementation.
866
+
867
+ - ``globally`` -- whether the local algorithm uses global generators
868
+ for the prime ideals. Default is False, which will not require any
869
+ information about the class group. If ``True``, a generator for `P`
870
+ will be used if `P` is principal. Otherwise, or if ``globally``
871
+ is False, the minimal model returned will preserve integrality
872
+ at other primes, but not minimality.
873
+
874
+ OUTPUT:
875
+
876
+ If `P` is specified, returns the ``EllipticCurveLocalData``
877
+ object associated to the prime `P` for this curve. Otherwise,
878
+ returns a list of such objects, one for each prime `P` in the
879
+ support of the discriminant of this model.
880
+
881
+ .. NOTE::
882
+
883
+ The model is not required to be integral on input.
884
+
885
+ EXAMPLES::
886
+
887
+ sage: x = polygen(QQ)
888
+ sage: K.<i> = NumberField(x^2 + 1)
889
+ sage: E = EllipticCurve([1 + i, 0, 1, 0, 0])
890
+ sage: E.local_data()
891
+ [Local data at Fractional ideal (-2*i - 1):
892
+ Reduction type: bad non-split multiplicative
893
+ Local minimal model: Elliptic Curve defined by y^2 + (i+1)*x*y + y = x^3
894
+ over Number Field in i with defining polynomial x^2 + 1
895
+ Minimal discriminant valuation: 1
896
+ Conductor exponent: 1
897
+ Kodaira Symbol: I1
898
+ Tamagawa Number: 1,
899
+ Local data at Fractional ideal (3*i + 2):
900
+ Reduction type: bad split multiplicative
901
+ Local minimal model: Elliptic Curve defined by y^2 + (i+1)*x*y + y = x^3
902
+ over Number Field in i with defining polynomial x^2 + 1
903
+ Minimal discriminant valuation: 2
904
+ Conductor exponent: 1
905
+ Kodaira Symbol: I2
906
+ Tamagawa Number: 2]
907
+ sage: E.local_data(K.ideal(3))
908
+ Local data at Fractional ideal (3):
909
+ Reduction type: good
910
+ Local minimal model: Elliptic Curve defined by y^2 + (i+1)*x*y + y = x^3
911
+ over Number Field in i with defining polynomial x^2 + 1
912
+ Minimal discriminant valuation: 0
913
+ Conductor exponent: 0
914
+ Kodaira Symbol: I0
915
+ Tamagawa Number: 1
916
+ sage: E.local_data(2*i + 1)
917
+ Local data at Fractional ideal (-2*i - 1):
918
+ Reduction type: bad non-split multiplicative
919
+ Local minimal model: Elliptic Curve defined by y^2 + (i+1)*x*y + y = x^3
920
+ over Number Field in i with defining polynomial x^2 + 1
921
+ Minimal discriminant valuation: 1
922
+ Conductor exponent: 1
923
+ Kodaira Symbol: I1
924
+ Tamagawa Number: 1
925
+
926
+ An example raised in :issue:`3897`::
927
+
928
+ sage: E = EllipticCurve([1,1])
929
+ sage: E.local_data(3)
930
+ Local data at Principal ideal (3) of Integer Ring:
931
+ Reduction type: good
932
+ Local minimal model: Elliptic Curve defined by y^2 = x^3 + x + 1
933
+ over Rational Field
934
+ Minimal discriminant valuation: 0
935
+ Conductor exponent: 0
936
+ Kodaira Symbol: I0
937
+ Tamagawa Number: 1
938
+ """
939
+ if proof is None:
940
+ import sage.structure.proof.proof
941
+ # We use the "number_field" flag because the actual proof dependence is in PARI's number field functions.
942
+ proof = sage.structure.proof.proof.get_flag(None, "number_field")
943
+
944
+ if P is None:
945
+ primes = self.base_ring()(self.integral_model().discriminant()).support()
946
+ return [self._get_local_data(pr, proof) for pr in primes]
947
+
948
+ from sage.schemes.elliptic_curves.ell_local_data import check_prime
949
+ P = check_prime(self.base_field(),P)
950
+
951
+ return self._get_local_data(P,proof,algorithm,globally)
952
+
953
+ def _get_local_data(self, P, proof, algorithm='pari', globally=False):
954
+ r"""
955
+ Internal function to create data for this elliptic curve at the prime `P`.
956
+
957
+ This function handles the caching of local data. It is called
958
+ by local_data() which is the user interface and which parses
959
+ the input parameters `P` and proof.
960
+
961
+ INPUT:
962
+
963
+ - ``P`` -- either ``None`` or a prime ideal of the base field of ``self``
964
+
965
+ - ``proof`` -- whether to only use provably correct methods
966
+ (default controlled by global proof module). Note that the
967
+ proof module is number_field, not elliptic_curves, since the
968
+ functions that actually need the flag are in number fields.
969
+
970
+ - ``algorithm`` -- string (default: ``'pari'``); ignored unless the
971
+ base field is `\QQ`. If ``'pari'``, use the PARI C-library
972
+ :pari:`ellglobalred` implementation of Tate's algorithm over
973
+ `\QQ`. If ``'generic'``, use the general number field
974
+ implementation.
975
+
976
+ - ``globally`` -- whether the local algorithm uses global generators
977
+ for the prime ideals. Default is False, which will not require any
978
+ information about the class group. If ``True``, a generator for `P`
979
+ will be used if `P` is principal. Otherwise, or if ``globally``
980
+ is False, the minimal model returned will preserve integrality
981
+ at other primes, but not minimality.
982
+
983
+ EXAMPLES::
984
+
985
+ sage: x = polygen(QQ)
986
+ sage: K.<i> = NumberField(x^2 + 1)
987
+ sage: E = EllipticCurve(K, [0,1,0,-160,308])
988
+ sage: p = K.ideal(i + 1)
989
+ sage: E._get_local_data(p, False)
990
+ Local data at Fractional ideal (i + 1):
991
+ Reduction type: good
992
+ Local minimal model: Elliptic Curve defined by
993
+ y^2 + x*y + y = x^3 + x^2 + (-10)*x + (-10)
994
+ over Number Field in i with defining polynomial x^2 + 1
995
+ Minimal discriminant valuation: 0
996
+ Conductor exponent: 0
997
+ Kodaira Symbol: I0
998
+ Tamagawa Number: 1
999
+
1000
+ Verify that we cache based on the proof value and the algorithm choice::
1001
+
1002
+ sage: E._get_local_data(p, False) is E._get_local_data(p, True)
1003
+ False
1004
+
1005
+ sage: E._get_local_data(p, None, "pari") is E._get_local_data(p, None, "generic")
1006
+ False
1007
+ """
1008
+ try:
1009
+ return self._local_data[P, proof, algorithm, globally]
1010
+ except AttributeError:
1011
+ self._local_data = {}
1012
+ except KeyError:
1013
+ pass
1014
+ from sage.schemes.elliptic_curves.ell_local_data import EllipticCurveLocalData
1015
+ self._local_data[P, proof, algorithm, globally] = EllipticCurveLocalData(self, P, proof, algorithm, globally)
1016
+ return self._local_data[P, proof, algorithm, globally]
1017
+
1018
+ def local_minimal_model(self, P, proof=None, algorithm='pari'):
1019
+ r"""
1020
+ Return a model which is integral at all primes and minimal at `P`.
1021
+
1022
+ INPUT:
1023
+
1024
+ - ``P`` -- either ``None`` or a prime ideal of the base field of ``self``
1025
+
1026
+ - ``proof`` -- whether to only use provably correct methods
1027
+ (default controlled by global proof module). Note that the
1028
+ proof module is number_field, not elliptic_curves, since the
1029
+ functions that actually need the flag are in number fields.
1030
+
1031
+ - ``algorithm`` -- string (default: ``'pari'``); ignored unless the
1032
+ base field is `\QQ`. If ``'pari'``, use the PARI C-library
1033
+ :pari:`ellglobalred` implementation of Tate's algorithm over
1034
+ `\QQ`. If ``'generic'``, use the general number field
1035
+ implementation.
1036
+
1037
+ OUTPUT:
1038
+
1039
+ A model of the curve which is minimal (and integral) at `P`.
1040
+
1041
+ .. NOTE::
1042
+
1043
+ The model is not required to be integral on input.
1044
+
1045
+ For principal `P`, a generator is used as a uniformizer,
1046
+ and integrality or minimality at other primes is not
1047
+ affected. For non-principal `P`, the minimal model
1048
+ returned will preserve integrality at other primes, but not
1049
+ minimality.
1050
+
1051
+ EXAMPLES::
1052
+
1053
+ sage: x = polygen(QQ)
1054
+ sage: K.<a> = NumberField(x^2 - 5)
1055
+ sage: E = EllipticCurve([20, 225, 750, 1250*a + 6250, 62500*a + 15625])
1056
+ sage: P = K.ideal(a)
1057
+ sage: E.local_minimal_model(P).ainvs()
1058
+ (0, 1, 0, 2*a - 34, -4*a + 66)
1059
+ """
1060
+ if proof is None:
1061
+ import sage.structure.proof.proof
1062
+ # We use the "number_field" flag because the actual proof dependence is in PARI's number field functions.
1063
+ proof = sage.structure.proof.proof.get_flag(None, "number_field")
1064
+
1065
+ return self.local_data(P, proof, algorithm).minimal_model()
1066
+
1067
+ def has_good_reduction(self, P) -> bool:
1068
+ r"""
1069
+ Return ``True`` if this elliptic curve has good reduction at the prime `P`.
1070
+
1071
+ INPUT:
1072
+
1073
+ - ``P`` -- a prime ideal of the base field of ``self``, or a field
1074
+ element generating such an ideal
1075
+
1076
+ OUTPUT:
1077
+
1078
+ boolean; ``True`` if the curve has good reduction at `P`, else ``False``.
1079
+
1080
+ .. NOTE::
1081
+
1082
+ This requires determining a local integral minimal model;
1083
+ we do not just check that the discriminant of the current
1084
+ model has valuation zero.
1085
+
1086
+ EXAMPLES::
1087
+
1088
+ sage: E = EllipticCurve('14a1')
1089
+ sage: [(p, E.has_good_reduction(p)) for p in prime_range(15)]
1090
+ [(2, False), (3, True), (5, True), (7, False), (11, True), (13, True)]
1091
+
1092
+ sage: x = polygen(QQ)
1093
+ sage: K.<a> = NumberField(x^3 - 2)
1094
+ sage: P17a, P17b = [P for P,e in K.factor(17)]
1095
+ sage: E = EllipticCurve([0,0,0,0,2*a+1])
1096
+ sage: [(p, E.has_good_reduction(p)) for p in [P17a,P17b]]
1097
+ [(Fractional ideal (4*a^2 - 2*a + 1), True),
1098
+ (Fractional ideal (2*a + 1), False)]
1099
+ """
1100
+ return self.local_data(P).has_good_reduction()
1101
+
1102
+ def has_bad_reduction(self, P) -> bool:
1103
+ r"""
1104
+ Return ``True`` if this elliptic curve has bad reduction at the prime `P`.
1105
+
1106
+ INPUT:
1107
+
1108
+ - ``P`` -- a prime ideal of the base field of ``self``, or a field
1109
+ element generating such an ideal
1110
+
1111
+ OUTPUT:
1112
+
1113
+ boolean; ``True`` if the curve has bad reduction at `P`, else ``False``.
1114
+
1115
+ .. NOTE::
1116
+
1117
+ This requires determining a local integral minimal model;
1118
+ we do not just check that the discriminant of the current
1119
+ model has valuation zero.
1120
+
1121
+ EXAMPLES::
1122
+
1123
+ sage: E = EllipticCurve('14a1')
1124
+ sage: [(p, E.has_bad_reduction(p)) for p in prime_range(15)]
1125
+ [(2, True), (3, False), (5, False), (7, True), (11, False), (13, False)]
1126
+
1127
+ sage: x = polygen(QQ)
1128
+ sage: K.<a> = NumberField(x^3 - 2)
1129
+ sage: P17a, P17b = [P for P,e in K.factor(17)]
1130
+ sage: E = EllipticCurve([0,0,0,0,2*a+1])
1131
+ sage: [(p, E.has_bad_reduction(p)) for p in [P17a,P17b]]
1132
+ [(Fractional ideal (4*a^2 - 2*a + 1), False),
1133
+ (Fractional ideal (2*a + 1), True)]
1134
+ """
1135
+ return self.local_data(P).has_bad_reduction()
1136
+
1137
+ def has_multiplicative_reduction(self, P) -> bool:
1138
+ r"""
1139
+ Return ``True`` if this elliptic curve has (bad) multiplicative
1140
+ reduction at the prime `P`.
1141
+
1142
+ .. NOTE::
1143
+
1144
+ See also ``has_split_multiplicative_reduction()`` and
1145
+ ``has_nonsplit_multiplicative_reduction()``.
1146
+
1147
+ INPUT:
1148
+
1149
+ - ``P`` -- a prime ideal of the base field of ``self``, or a field
1150
+ element generating such an ideal
1151
+
1152
+ OUTPUT:
1153
+
1154
+ boolean; ``True`` if the curve has multiplicative reduction at `P`,
1155
+ else ``False``.
1156
+
1157
+ EXAMPLES::
1158
+
1159
+ sage: E = EllipticCurve('14a1')
1160
+ sage: [(p, E.has_multiplicative_reduction(p)) for p in prime_range(15)]
1161
+ [(2, True), (3, False), (5, False), (7, True), (11, False), (13, False)]
1162
+
1163
+ sage: x = polygen(QQ)
1164
+ sage: K.<a> = NumberField(x^3 - 2)
1165
+ sage: P17a, P17b = [P for P,e in K.factor(17)]
1166
+ sage: E = EllipticCurve([0,0,0,0,2*a+1])
1167
+ sage: [(p, E.has_multiplicative_reduction(p)) for p in [P17a,P17b]]
1168
+ [(Fractional ideal (4*a^2 - 2*a + 1), False),
1169
+ (Fractional ideal (2*a + 1), False)]
1170
+ """
1171
+ return self.local_data(P).has_multiplicative_reduction()
1172
+
1173
+ def has_split_multiplicative_reduction(self, P) -> bool:
1174
+ r"""
1175
+ Return ``True`` if this elliptic curve has (bad) split multiplicative reduction at the prime `P`.
1176
+
1177
+ INPUT:
1178
+
1179
+ - ``P`` -- a prime ideal of the base field of ``self``, or a field
1180
+ element generating such an ideal
1181
+
1182
+ OUTPUT:
1183
+
1184
+ boolean; ``True`` if the curve has split multiplicative reduction at
1185
+ `P`, else ``False``.
1186
+
1187
+ EXAMPLES::
1188
+
1189
+ sage: E = EllipticCurve('14a1')
1190
+ sage: [(p, E.has_split_multiplicative_reduction(p)) for p in prime_range(15)]
1191
+ [(2, False), (3, False), (5, False), (7, True), (11, False), (13, False)]
1192
+
1193
+ sage: x = polygen(QQ)
1194
+ sage: K.<a> = NumberField(x^3 - 2)
1195
+ sage: P17a, P17b = [P for P,e in K.factor(17)]
1196
+ sage: E = EllipticCurve([0,0,0,0,2*a+1])
1197
+ sage: [(p, E.has_split_multiplicative_reduction(p)) for p in [P17a,P17b]]
1198
+ [(Fractional ideal (4*a^2 - 2*a + 1), False),
1199
+ (Fractional ideal (2*a + 1), False)]
1200
+ """
1201
+ return self.local_data(P).has_split_multiplicative_reduction()
1202
+
1203
+ def has_nonsplit_multiplicative_reduction(self, P) -> bool:
1204
+ r"""
1205
+ Return ``True`` if this elliptic curve has (bad) non-split
1206
+ multiplicative reduction at the prime `P`.
1207
+
1208
+ INPUT:
1209
+
1210
+ - ``P`` -- a prime ideal of the base field of ``self``, or a field
1211
+ element generating such an ideal
1212
+
1213
+ OUTPUT:
1214
+
1215
+ boolean; ``True`` if the curve has non-split multiplicative
1216
+ reduction at `P`, else ``False``.
1217
+
1218
+ EXAMPLES::
1219
+
1220
+ sage: E = EllipticCurve('14a1')
1221
+ sage: [(p, E.has_nonsplit_multiplicative_reduction(p)) for p in prime_range(15)]
1222
+ [(2, True), (3, False), (5, False), (7, False), (11, False), (13, False)]
1223
+
1224
+ sage: x = polygen(QQ)
1225
+ sage: K.<a> = NumberField(x^3 - 2)
1226
+ sage: P17a, P17b = [P for P,e in K.factor(17)]
1227
+ sage: E = EllipticCurve([0,0,0,0,2*a+1])
1228
+ sage: [(p, E.has_nonsplit_multiplicative_reduction(p)) for p in [P17a,P17b]]
1229
+ [(Fractional ideal (4*a^2 - 2*a + 1), False),
1230
+ (Fractional ideal (2*a + 1), False)]
1231
+ """
1232
+ return self.local_data(P).has_nonsplit_multiplicative_reduction()
1233
+
1234
+ def has_additive_reduction(self, P) -> bool:
1235
+ r"""
1236
+ Return ``True`` if this elliptic curve has (bad) additive reduction at
1237
+ the prime `P`.
1238
+
1239
+ INPUT:
1240
+
1241
+ - ``P`` -- a prime ideal of the base field of ``self``, or a field
1242
+ element generating such an ideal
1243
+
1244
+ OUTPUT:
1245
+
1246
+ boolean; ``True`` if the curve has additive reduction at `P`, else
1247
+ ``False``.
1248
+
1249
+ EXAMPLES::
1250
+
1251
+ sage: E = EllipticCurve('27a1')
1252
+ sage: [(p, E.has_additive_reduction(p)) for p in prime_range(15)]
1253
+ [(2, False), (3, True), (5, False), (7, False), (11, False), (13, False)]
1254
+
1255
+ sage: x = polygen(QQ)
1256
+ sage: K.<a> = NumberField(x^3 - 2)
1257
+ sage: P17a, P17b = [P for P,e in K.factor(17)]
1258
+ sage: E = EllipticCurve([0,0,0,0,2*a+1])
1259
+ sage: [(p, E.has_additive_reduction(p)) for p in [P17a,P17b]]
1260
+ [(Fractional ideal (4*a^2 - 2*a + 1), False),
1261
+ (Fractional ideal (2*a + 1), True)]
1262
+ """
1263
+ return self.local_data(P).has_additive_reduction()
1264
+
1265
+ def tamagawa_number(self, P, proof=None):
1266
+ r"""
1267
+ Return the Tamagawa number of this elliptic curve at the prime `P`.
1268
+
1269
+ INPUT:
1270
+
1271
+ - ``P`` -- either ``None`` or a prime ideal of the base field of ``self``
1272
+
1273
+ - ``proof`` -- whether to only use provably correct methods
1274
+ (default controlled by global proof module). Note that the
1275
+ proof module is number_field, not elliptic_curves, since the
1276
+ functions that actually need the flag are in number fields.
1277
+
1278
+ OUTPUT: positive integer; the Tamagawa number of the curve at `P`
1279
+
1280
+ EXAMPLES::
1281
+
1282
+ sage: x = polygen(ZZ, 'x')
1283
+ sage: K.<a> = NumberField(x^2 - 5)
1284
+ sage: E = EllipticCurve([20, 225, 750, 625*a + 6875, 31250*a + 46875])
1285
+ sage: [E.tamagawa_number(P) for P in E.discriminant().support()]
1286
+ [1, 1, 1, 1]
1287
+ sage: K.<a> = QuadraticField(-11)
1288
+ sage: E = EllipticCurve('11a1').change_ring(K)
1289
+ sage: [E.tamagawa_number(P) for P in K(11).support()]
1290
+ [10]
1291
+ """
1292
+ if proof is None:
1293
+ import sage.structure.proof.proof
1294
+ # We use the "number_field" flag because the actual proof dependence is in PARI's number field functions.
1295
+ proof = sage.structure.proof.proof.get_flag(None, "number_field")
1296
+
1297
+ return self.local_data(P, proof).tamagawa_number()
1298
+
1299
+ def tamagawa_numbers(self) -> list:
1300
+ """
1301
+ Return a list of all Tamagawa numbers for all prime divisors of the
1302
+ conductor (in order).
1303
+
1304
+ EXAMPLES::
1305
+
1306
+ sage: e = EllipticCurve('30a1')
1307
+ sage: e.tamagawa_numbers()
1308
+ [2, 3, 1]
1309
+ sage: vector(e.tamagawa_numbers())
1310
+ (2, 3, 1)
1311
+ sage: x = polygen(QQ)
1312
+ sage: K.<a> = NumberField(x^2 + 3)
1313
+ sage: eK = e.base_extend(K)
1314
+ sage: eK.tamagawa_numbers()
1315
+ [4, 6, 1]
1316
+ """
1317
+ return [self.tamagawa_number(p)
1318
+ for p in self.conductor().prime_factors()]
1319
+
1320
+ def tamagawa_exponent(self, P, proof=None):
1321
+ r"""
1322
+ Return the Tamagawa index of this elliptic curve at the prime `P`.
1323
+
1324
+ INPUT:
1325
+
1326
+ - ``P`` -- either ``None`` or a prime ideal of the base field of ``self``
1327
+
1328
+ - ``proof`` -- whether to only use provably correct methods
1329
+ (default controlled by global proof module). Note that the
1330
+ proof module is number_field, not elliptic_curves, since the
1331
+ functions that actually need the flag are in number fields.
1332
+
1333
+ OUTPUT: positive integer; the Tamagawa index of the curve at P
1334
+
1335
+ EXAMPLES::
1336
+
1337
+ sage: x = polygen(QQ)
1338
+ sage: K.<a> = NumberField(x^2 - 5)
1339
+ sage: E = EllipticCurve([20, 225, 750, 625*a + 6875, 31250*a + 46875])
1340
+ sage: [E.tamagawa_exponent(P) for P in E.discriminant().support()]
1341
+ [1, 1, 1, 1]
1342
+ sage: K.<a> = QuadraticField(-11)
1343
+ sage: E = EllipticCurve('11a1').change_ring(K)
1344
+ sage: [E.tamagawa_exponent(P) for P in K(11).support()]
1345
+ [10]
1346
+ """
1347
+ if proof is None:
1348
+ import sage.structure.proof.proof
1349
+ # We use the "number_field" flag because the actual proof dependence is in PARI's number field functions.
1350
+ proof = sage.structure.proof.proof.get_flag(None, "number_field")
1351
+
1352
+ return self.local_data(P, proof).tamagawa_exponent()
1353
+
1354
+ def tamagawa_product(self):
1355
+ r"""Return the product of the Tamagawa numbers `c_v` where `v` runs
1356
+ over all prime ideals of `K`.
1357
+
1358
+ .. NOTE::
1359
+
1360
+ See also tamagawa_product_bsd(), which includes an
1361
+ additional factor when the model is not globally minimal,
1362
+ as required by the BSD formula.
1363
+
1364
+ OUTPUT: a positive integer
1365
+
1366
+ EXAMPLES::
1367
+
1368
+ sage: x = polygen(QQ)
1369
+ sage: K.<i> = NumberField(x^2 + 1)
1370
+ sage: E = EllipticCurve([0, 2+i])
1371
+ sage: E.tamagawa_product()
1372
+ 1
1373
+
1374
+ sage: E = EllipticCurve([(2*i+1)^2, i*(2*i+1)^7])
1375
+ sage: E.tamagawa_product()
1376
+ 4
1377
+
1378
+ An example over `\QQ`::
1379
+
1380
+ sage: E = EllipticCurve('30a')
1381
+ sage: E.tamagawa_product()
1382
+ 6
1383
+
1384
+ An example with everywhere good reduction, where the product
1385
+ is empty::
1386
+
1387
+ sage: x = polygen(QQ)
1388
+ sage: K.<a> = NumberField(x^2 - 38)
1389
+ sage: E = EllipticCurve( [a, -a + 1, a + 1, -5*a + 15, -5*a + 21])
1390
+ sage: E.tamagawa_numbers()
1391
+ []
1392
+ sage: E.tamagawa_product()
1393
+ 1
1394
+ """
1395
+ return prod([ld.tamagawa_number() for ld in self.local_data()], Integer(1))
1396
+
1397
+ def tamagawa_product_bsd(self):
1398
+ r"""Given an elliptic curve `E` over a number field `K`, this function
1399
+ returns the integer `C(E/K)` that appears in the Birch and
1400
+ Swinnerton-Dyer conjecture accounting for the local
1401
+ information at finite places. If the model is a global minimal
1402
+ model then `C(E/K)` is simply the product of the Tamagawa
1403
+ numbers `c_v` where `v` runs over all prime ideals of
1404
+ `K`. Otherwise, if the model has to be changed at a place `v`
1405
+ a correction factor appears. The definition is such that
1406
+ `C(E/K)` times the periods at the infinite places is invariant
1407
+ under change of the Weierstrass model. See [Tate1966]_ and
1408
+ [DD2010]_ for details.
1409
+
1410
+ .. NOTE::
1411
+
1412
+ This definition differs from the definition of
1413
+ ``tamagawa_product`` for curves defined over `\QQ`. Over
1414
+ the rational number it is always defined to be the product
1415
+ of the Tamagawa numbers, so the two definitions only agree
1416
+ when the model is global minimal.
1417
+
1418
+ OUTPUT: a rational number
1419
+
1420
+ EXAMPLES::
1421
+
1422
+ sage: x = polygen(QQ)
1423
+ sage: K.<i> = NumberField(x^2 + 1)
1424
+ sage: E = EllipticCurve([0, 2+i])
1425
+ sage: E.tamagawa_product_bsd()
1426
+ 1
1427
+
1428
+ sage: E = EllipticCurve([(2*i+1)^2, i*(2*i+1)^7])
1429
+ sage: E.tamagawa_product_bsd()
1430
+ 4
1431
+
1432
+ An example where the Neron model changes over K::
1433
+
1434
+ sage: K.<t> = NumberField(x^5 - 10*x^3 + 5*x^2 + 10*x + 1)
1435
+ sage: E = EllipticCurve(K, '75a1')
1436
+ sage: E.tamagawa_product_bsd()
1437
+ 5
1438
+ sage: da = E.local_data()
1439
+ sage: [dav.tamagawa_number() for dav in da]
1440
+ [1, 1]
1441
+
1442
+ An example over `\QQ` (:issue:`9413`)::
1443
+
1444
+ sage: E = EllipticCurve('30a')
1445
+ sage: E.tamagawa_product_bsd()
1446
+ 6
1447
+ """
1448
+ pr = QQ(1)
1449
+ for v in self.local_data():
1450
+ pp = v.prime()
1451
+ cv = v.tamagawa_number()
1452
+ # uu is the quotient of the Neron differential at pp divided by
1453
+ # the differential associated to this particular model of E
1454
+ uu = self.isomorphism_to(v.minimal_model()).u
1455
+ if self.base_field().absolute_degree() == 1:
1456
+ p = pp.gens_reduced()[0]
1457
+ f = 1
1458
+ v = ZZ(uu).valuation(p)
1459
+ else:
1460
+ p = pp.smallest_integer()
1461
+ f = pp.residue_class_degree()
1462
+ v = uu.valuation(pp)
1463
+ uu_abs_val = p**(f*v)
1464
+ pr *= cv * uu_abs_val
1465
+ return pr
1466
+
1467
+ def kodaira_symbol(self, P, proof=None):
1468
+ r"""
1469
+ Return the Kodaira Symbol of this elliptic curve at the prime `P`.
1470
+
1471
+ INPUT:
1472
+
1473
+ - ``P`` -- either ``None`` or a prime ideal of the base field of ``self``
1474
+
1475
+ - ``proof`` -- whether to only use provably correct methods
1476
+ (default controlled by global proof module). Note that the
1477
+ proof module is number_field, not elliptic_curves, since the
1478
+ functions that actually need the flag are in number fields.
1479
+
1480
+ OUTPUT: the Kodaira Symbol of the curve at ``P``, represented as a string
1481
+
1482
+ EXAMPLES::
1483
+
1484
+ sage: x = polygen(QQ)
1485
+ sage: K.<a> = NumberField(x^2 - 5)
1486
+ sage: E = EllipticCurve([20, 225, 750, 625*a + 6875, 31250*a + 46875])
1487
+ sage: bad_primes = E.discriminant().support(); bad_primes
1488
+ [Fractional ideal (-a),
1489
+ Fractional ideal (-7/2*a + 81/2),
1490
+ Fractional ideal (-a - 52),
1491
+ Fractional ideal (2)]
1492
+ sage: [E.kodaira_symbol(P) for P in bad_primes]
1493
+ [I0, I1, I1, II]
1494
+ sage: K.<a> = QuadraticField(-11)
1495
+ sage: E = EllipticCurve('11a1').change_ring(K)
1496
+ sage: [E.kodaira_symbol(P) for P in K(11).support()]
1497
+ [I10]
1498
+ """
1499
+ if proof is None:
1500
+ import sage.structure.proof.proof
1501
+ # We use the "number_field" flag because the actual proof dependence is in PARI's number field functions.
1502
+ proof = sage.structure.proof.proof.get_flag(None, "number_field")
1503
+
1504
+ return self.local_data(P, proof).kodaira_symbol()
1505
+
1506
+ def conductor(self):
1507
+ r"""
1508
+ Return the conductor of this elliptic curve as a fractional
1509
+ ideal of the base field.
1510
+
1511
+ OUTPUT: fractional ideal; the conductor of the curve
1512
+
1513
+ EXAMPLES::
1514
+
1515
+ sage: x = polygen(QQ)
1516
+ sage: K.<i> = NumberField(x^2 + 1)
1517
+ sage: EllipticCurve([i, i - 1, i + 1, 24*i + 15, 14*i + 35]).conductor()
1518
+ Fractional ideal (3*i + 21)
1519
+ sage: K.<a> = NumberField(x^2 - x + 3)
1520
+ sage: EllipticCurve([1 + a, -1 + a, 1 + a, -11 + a, 5 - 9*a]).conductor()
1521
+ Fractional ideal (6*a)
1522
+
1523
+ A not so well known curve with everywhere good reduction::
1524
+
1525
+ sage: x = polygen(QQ)
1526
+ sage: K.<a> = NumberField(x^2 - 38)
1527
+ sage: E = EllipticCurve([0,0,0, 21796814856932765568243810*a - 134364590724198567128296995, 121774567239345229314269094644186997594*a - 750668847495706904791115375024037711300])
1528
+ sage: E.conductor()
1529
+ Fractional ideal (1)
1530
+
1531
+ An example which used to fail (see :issue:`5307`)::
1532
+
1533
+ sage: x = polygen(QQ)
1534
+ sage: K.<w> = NumberField(x^2 + x + 6)
1535
+ sage: E = EllipticCurve([w, -1, 0, -w-6, 0])
1536
+ sage: E.conductor()
1537
+ Fractional ideal (86304, w + 5898)
1538
+
1539
+ An example raised in :issue:`11346`::
1540
+
1541
+ sage: x = polygen(QQ)
1542
+ sage: K.<g> = NumberField(x^2 - x - 1)
1543
+ sage: E1 = EllipticCurve(K, [0, 0, 0, -1/48, -161/864])
1544
+ sage: [(p.smallest_integer(), e) for p,e in E1.conductor().factor()]
1545
+ [(2, 4), (3, 1), (5, 1)]
1546
+ """
1547
+ try:
1548
+ return self._conductor
1549
+ except AttributeError:
1550
+ pass
1551
+
1552
+ # Note: for number fields other than QQ we could initialize
1553
+ # N=K.ideal(1) or N=OK.ideal(1), which are the same, but for
1554
+ # K == QQ it has to be ZZ.ideal(1).
1555
+ K = self.base_field()
1556
+ N = ZZ.ideal(1) if K is QQ else K.fractional_ideal(1)
1557
+ self._conductor = prod([d.prime()**d.conductor_valuation()
1558
+ for d in self.local_data()],
1559
+ N)
1560
+ return self._conductor
1561
+
1562
+ def minimal_discriminant_ideal(self):
1563
+ r"""
1564
+ Return the minimal discriminant ideal of this elliptic curve.
1565
+
1566
+ OUTPUT:
1567
+
1568
+ The integral ideal `D` whose valuation at every prime `P` is
1569
+ that of the local minimal model for `E` at `P`. If `E` has a
1570
+ global minimal model, this will be the principal ideal
1571
+ generated by the discriminant of any such model, but otherwise
1572
+ it can be a proper divisor of the discriminant of any model.
1573
+
1574
+ EXAMPLES::
1575
+
1576
+ sage: x = polygen(QQ)
1577
+ sage: K.<a> = NumberField(x^2 - x - 57)
1578
+ sage: K.class_number()
1579
+ 3
1580
+ sage: E = EllipticCurve([a, -a, a, -5692-820*a, -259213-36720*a])
1581
+ sage: K.ideal(E.discriminant())
1582
+ Fractional ideal (90118662980*a + 636812084644)
1583
+ sage: K.ideal(E.discriminant()).factor()
1584
+ (Fractional ideal (2))^2 * (Fractional ideal (3, a + 2))^12
1585
+
1586
+ Here the minimal discriminant ideal is principal but there is
1587
+ no global minimal model since the quotient is the 12th power
1588
+ of a non-principal ideal::
1589
+
1590
+ sage: E.minimal_discriminant_ideal()
1591
+ Fractional ideal (4)
1592
+ sage: E.minimal_discriminant_ideal().factor()
1593
+ (Fractional ideal (2))^2
1594
+
1595
+ If (and only if) the curve has everywhere good reduction the
1596
+ result is the unit ideal::
1597
+
1598
+ sage: x = polygen(QQ)
1599
+ sage: K.<a> = NumberField(x^2 - 26)
1600
+ sage: E = EllipticCurve([a, a-1, a+1, 4*a+10, 2*a+6])
1601
+ sage: E.conductor()
1602
+ Fractional ideal (1)
1603
+ sage: E.discriminant()
1604
+ -104030*a - 530451
1605
+ sage: E.minimal_discriminant_ideal()
1606
+ Fractional ideal (1)
1607
+
1608
+ Over `\QQ`, the result returned is an ideal of `\ZZ` rather
1609
+ than a fractional ideal of `\QQ`::
1610
+
1611
+ sage: E = EllipticCurve([1,2,3,4,5])
1612
+ sage: E.minimal_discriminant_ideal()
1613
+ Principal ideal (10351) of Integer Ring
1614
+ """
1615
+ dat = self.local_data()
1616
+ # we treat separately the case where there are no bad primes,
1617
+ # which cannot happen over QQ, since ideals of QQ behave
1618
+ # differently to (fractional) ideals of other number fields.
1619
+ if not dat:
1620
+ return self.base_field().ideal(1)
1621
+ return prod([d.prime()**d.discriminant_valuation() for d in dat])
1622
+
1623
+ def non_minimal_primes(self):
1624
+ r"""
1625
+ Return a list of primes at which this elliptic curve is not minimal.
1626
+
1627
+ OUTPUT:
1628
+
1629
+ A list of prime ideals (or prime numbers when the base field
1630
+ is `\QQ`, empty if this is a global minimal model.
1631
+
1632
+ EXAMPLES::
1633
+
1634
+ sage: x = polygen(QQ)
1635
+ sage: K.<a> = NumberField(x^2 - 10)
1636
+ sage: E = EllipticCurve([0, 0, 0, -22500, 750000*a])
1637
+ sage: E.non_minimal_primes()
1638
+ [Fractional ideal (2, a), Fractional ideal (5, a)]
1639
+ sage: K.ideal(E.discriminant()).factor()
1640
+ (Fractional ideal (2, a))^24 * (Fractional ideal (3, a + 1))^5 * (Fractional ideal (3, a + 2))^5 * (Fractional ideal (5, a))^24 * (Fractional ideal (7))
1641
+ sage: E.minimal_discriminant_ideal().factor()
1642
+ (Fractional ideal (2, a))^12 * (Fractional ideal (3, a + 1))^5 * (Fractional ideal (3, a + 2))^5 * (Fractional ideal (7))
1643
+
1644
+ Over `\QQ`, the primes returned are integers, not ideals::
1645
+
1646
+ sage: E = EllipticCurve([0, 0, 0, -3024, 46224])
1647
+ sage: E.non_minimal_primes()
1648
+ [2, 3]
1649
+ sage: Emin = E.global_minimal_model()
1650
+ sage: Emin.non_minimal_primes()
1651
+ []
1652
+
1653
+ If the model is not globally integral, a :exc:`ValueError` is
1654
+ raised::
1655
+
1656
+ sage: E = EllipticCurve([0, 0, 0, 1/2, 1/3])
1657
+ sage: E.non_minimal_primes()
1658
+ Traceback (most recent call last):
1659
+ ...
1660
+ ValueError: non_minimal_primes only defined for integral models
1661
+ """
1662
+ if not self.is_global_integral_model():
1663
+ raise ValueError("non_minimal_primes only defined for integral models")
1664
+ dat = self.local_data()
1665
+ D = self.discriminant()
1666
+ primes = [d.prime() for d in dat]
1667
+ if self.base_field() is QQ:
1668
+ primes = [P.gen() for P in primes]
1669
+ vals = [d.discriminant_valuation() for d in dat]
1670
+ return [P for P,v in zip(primes,vals) if D.valuation(P) > v]
1671
+
1672
+ def is_global_minimal_model(self):
1673
+ r"""
1674
+ Return whether this elliptic curve is a global minimal model.
1675
+
1676
+ OUTPUT:
1677
+
1678
+ Boolean, False if E is not integral, or if E is non-minimal at
1679
+ some prime, else True.
1680
+
1681
+ EXAMPLES::
1682
+
1683
+ sage: x = polygen(QQ)
1684
+ sage: K.<a> = NumberField(x^2 - 10)
1685
+ sage: E = EllipticCurve([0, 0, 0, -22500, 750000*a])
1686
+ sage: E.is_global_minimal_model()
1687
+ False
1688
+ sage: E.non_minimal_primes()
1689
+ [Fractional ideal (2, a), Fractional ideal (5, a)]
1690
+
1691
+ sage: E = EllipticCurve([0, 0, 0, -3024, 46224])
1692
+ sage: E.is_global_minimal_model()
1693
+ False
1694
+ sage: E.non_minimal_primes()
1695
+ [2, 3]
1696
+ sage: Emin = E.global_minimal_model()
1697
+ sage: Emin.is_global_minimal_model()
1698
+ True
1699
+
1700
+ A necessary condition to be a global minimal model is that the
1701
+ model must be globally integral::
1702
+
1703
+ sage: E = EllipticCurve([0,0,0,1/2,1/3])
1704
+ sage: E.is_global_minimal_model()
1705
+ False
1706
+ sage: Emin.is_global_minimal_model()
1707
+ True
1708
+ sage: Emin.ainvs()
1709
+ (0, 1, 1, -2, 0)
1710
+ """
1711
+ if not self.is_global_integral_model():
1712
+ return False
1713
+ return self.non_minimal_primes() == []
1714
+
1715
+ def global_minimality_class(self):
1716
+ r"""
1717
+ Return the obstruction to this curve having a global minimal model.
1718
+
1719
+ OUTPUT:
1720
+
1721
+ An ideal class of the base number field, which is trivial if
1722
+ and only if the elliptic curve has a global minimal model, and
1723
+ which can be used to find global and semi-global minimal
1724
+ models.
1725
+
1726
+ EXAMPLES:
1727
+
1728
+ A curve defined over a field of class number 2 with no global
1729
+ minimal model was a nontrivial minimality class::
1730
+
1731
+ sage: x = polygen(QQ)
1732
+ sage: K.<a> = NumberField(x^2 - 10)
1733
+ sage: K.class_number()
1734
+ 2
1735
+ sage: E = EllipticCurve([0, 0, 0, -22500, 750000*a])
1736
+ sage: E.global_minimality_class()
1737
+ Fractional ideal class (10, 5*a)
1738
+ sage: E.global_minimality_class().order()
1739
+ 2
1740
+
1741
+ Over the same field, a curve defined by a non-minimal model
1742
+ has trivial class, showing that a global minimal model does
1743
+ exist::
1744
+
1745
+ sage: K.<a> = NumberField(x^2 - 10)
1746
+ sage: E = EllipticCurve([0, 0, 0, 4536*a+14148, -163728*a-474336])
1747
+ sage: E.is_global_minimal_model()
1748
+ False
1749
+ sage: E.global_minimality_class()
1750
+ Trivial principal fractional ideal class
1751
+
1752
+ Over a field of class number 1 the result is always the
1753
+ trivial class::
1754
+
1755
+ sage: K.<a> = NumberField(x^2 - 5)
1756
+ sage: E = EllipticCurve([0, 0, 0, K(16), K(64)])
1757
+ sage: E.global_minimality_class()
1758
+ Trivial principal fractional ideal class
1759
+
1760
+ sage: E = EllipticCurve([0, 0, 0, 16, 64])
1761
+ sage: E.base_field()
1762
+ Rational Field
1763
+ sage: E.global_minimality_class()
1764
+ 1
1765
+ """
1766
+ K = self.base_field()
1767
+ Cl = K.class_group()
1768
+ if K.class_number() == 1:
1769
+ return Cl(1)
1770
+ D = self.discriminant()
1771
+ dat = self.local_data()
1772
+ primes = [d.prime() for d in dat]
1773
+ vals = [d.discriminant_valuation() for d in dat]
1774
+ I = prod([P**((D.valuation(P)-v)//12) for P,v in zip(primes,vals)],
1775
+ K.ideal(1))
1776
+ return Cl(I)
1777
+
1778
+ def has_global_minimal_model(self) -> bool:
1779
+ r"""
1780
+ Return whether this elliptic curve has a global minimal model.
1781
+
1782
+ OUTPUT:
1783
+
1784
+ boolean; ``True`` iff a global minimal model exists, i.e. an
1785
+ integral model which is minimal at every prime.
1786
+
1787
+ EXAMPLES::
1788
+
1789
+ sage: x = polygen(QQ)
1790
+ sage: K.<a> = NumberField(x^2 - 10)
1791
+ sage: E = EllipticCurve([0, 0, 0, 4536*a+14148, -163728*a-474336])
1792
+ sage: E.is_global_minimal_model()
1793
+ False
1794
+ sage: E.has_global_minimal_model()
1795
+ True
1796
+ """
1797
+ return self.global_minimality_class().is_one()
1798
+
1799
+ def global_minimal_model(self, proof=None, semi_global=False):
1800
+ r"""
1801
+ Return a model of ``self`` that is integral, and minimal.
1802
+
1803
+ .. NOTE::
1804
+
1805
+ Over fields of class number greater than 1, a global
1806
+ minimal model may not exist. If it does not, set the
1807
+ parameter ``semi_global`` to ``True`` to obtain a model
1808
+ minimal at all but one prime.
1809
+
1810
+ INPUT:
1811
+
1812
+ - ``proof`` -- whether to only use provably correct methods
1813
+ (default controlled by global proof module). Note that the
1814
+ proof module is number_field, not elliptic_curves, since the
1815
+ functions that actually need the flag are in number fields.
1816
+
1817
+ - ``semi_global``-- boolean (default: ``False``); if there is no
1818
+ global minimal mode, return a semi-global minimal model
1819
+ (minimal at all but one prime) instead, if True; raise an
1820
+ error if False. No effect if a global minimal model exists.
1821
+
1822
+ OUTPUT:
1823
+
1824
+ A global integral and minimal model, or an integral model
1825
+ minimal at all but one prime of there is no global minimal
1826
+ model and the flag ``semi_global`` is True.
1827
+
1828
+ EXAMPLES::
1829
+
1830
+ sage: x = polygen(QQ)
1831
+ sage: K.<a> = NumberField(x^2 - 38)
1832
+ sage: E = EllipticCurve([0,0,0, 21796814856932765568243810*a - 134364590724198567128296995, 121774567239345229314269094644186997594*a - 750668847495706904791115375024037711300])
1833
+ sage: E2 = E.global_minimal_model()
1834
+ sage: E2
1835
+ Elliptic Curve defined by
1836
+ y^2 + a*x*y + (a+1)*y = x^3 + (a+1)*x^2 + (4*a+15)*x + (4*a+21)
1837
+ over Number Field in a with defining polynomial x^2 - 38
1838
+ sage: E2.local_data()
1839
+ []
1840
+
1841
+ See :issue:`11347`::
1842
+
1843
+ sage: x = polygen(QQ)
1844
+ sage: K.<g> = NumberField(x^2 - x - 1)
1845
+ sage: E = EllipticCurve(K, [0, 0, 0, -1/48, 161/864])
1846
+ sage: E2 = E.integral_model().global_minimal_model(); E2
1847
+ Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2
1848
+ over Number Field in g with defining polynomial x^2 - x - 1
1849
+ sage: [(p.norm(), e) for p, e in E2.conductor().factor()]
1850
+ [(9, 1), (5, 1)]
1851
+ sage: [(p.norm(), e) for p, e in E2.discriminant().factor()]
1852
+ [(-5, 2), (9, 1)]
1853
+
1854
+ See :issue:`14472`, this used not to work over a relative extension::
1855
+
1856
+ sage: x = polygen(QQ)
1857
+ sage: K1.<w> = NumberField(x^2 + x + 1)
1858
+ sage: m = polygen(K1)
1859
+ sage: K2.<v> = K1.extension(m^2 - w + 1)
1860
+ sage: E = EllipticCurve([0*v, -432])
1861
+ sage: E.global_minimal_model()
1862
+ Elliptic Curve defined by y^2 + y = x^3
1863
+ over Number Field in v with defining polynomial x^2 - w + 1 over its base field
1864
+
1865
+ See :issue:`18662`: for fields of class number greater than 1,
1866
+ even when global minimal models did exist, their computation
1867
+ was not implemented. Now it is::
1868
+
1869
+ sage: x = polygen(QQ)
1870
+ sage: K.<a> = NumberField(x^2 - 10)
1871
+ sage: K.class_number()
1872
+ 2
1873
+ sage: E = EllipticCurve([0, 0, 0, -186408*a - 589491, 78055704*a + 246833838])
1874
+ sage: E.discriminant().norm()
1875
+ 16375845905239507992576
1876
+ sage: E.discriminant().norm().factor()
1877
+ 2^31 * 3^27
1878
+ sage: E.has_global_minimal_model()
1879
+ True
1880
+ sage: Emin = E.global_minimal_model(); Emin
1881
+ Elliptic Curve defined by
1882
+ y^2 + (a+1)*x*y + (a+1)*y = x^3 + (-a)*x^2 + (a-12)*x + (-2*a+2)
1883
+ over Number Field in a with defining polynomial x^2 - 10
1884
+ sage: Emin.discriminant().norm()
1885
+ 3456
1886
+ sage: Emin.discriminant().norm().factor()
1887
+ 2^7 * 3^3
1888
+
1889
+ If there is no global minimal model, this method will raise an
1890
+ error unless you set the parameter ``semi_global`` to ``True``::
1891
+
1892
+ sage: K.<a> = NumberField(x^2 - 10)
1893
+ sage: K.class_number()
1894
+ 2
1895
+ sage: E = EllipticCurve([a, a, 0, 3*a+8, 4*a+3])
1896
+ sage: E.has_global_minimal_model()
1897
+ False
1898
+ sage: E.global_minimal_model()
1899
+ Traceback (most recent call last):
1900
+ ...
1901
+ ValueError: Elliptic Curve defined by
1902
+ y^2 + a*x*y = x^3 + a*x^2 + (3*a+8)*x + (4*a+3) over Number Field
1903
+ in a with defining polynomial x^2 - 10 has no global minimal model!
1904
+ For a semi-global minimal model use semi_global=True
1905
+ sage: E.global_minimal_model(semi_global=True) # needs sage.symbolic
1906
+ Elliptic Curve defined by
1907
+ y^2 + a*x*y = x^3 + a*x^2 + (3*a+8)*x + (4*a+3) over Number Field in a
1908
+ with defining polynomial x^2 - 10
1909
+
1910
+ An example of a curve with everywhere good reduction but which
1911
+ has no model with unit discriminant::
1912
+
1913
+ sage: # needs sage.symbolic
1914
+ sage: x = polygen(QQ)
1915
+ sage: K.<a> = NumberField(x^2 - x - 16)
1916
+ sage: K.class_number()
1917
+ 2
1918
+ sage: E = EllipticCurve([0,0,0,-15221331*a - 53748576, -79617688290*a - 281140318368])
1919
+ sage: Emin = E.global_minimal_model(semi_global=True)
1920
+ sage: Emin.ainvs()
1921
+ (a, a - 1, a, 605*a - 2728, 15887*a - 71972)
1922
+ sage: Emin.discriminant()
1923
+ -17*a - 16
1924
+ sage: Emin.discriminant().norm()
1925
+ -4096
1926
+ sage: Emin.minimal_discriminant_ideal()
1927
+ Fractional ideal (1)
1928
+ sage: E.conductor()
1929
+ Fractional ideal (1)
1930
+ """
1931
+ if proof is None:
1932
+ import sage.structure.proof.proof
1933
+ # We use the "number_field" flag because the actual proof dependence is in PARI's number field functions.
1934
+ proof = sage.structure.proof.proof.get_flag(None, "number_field")
1935
+
1936
+ if self.has_global_minimal_model() or semi_global:
1937
+ if self.base_ring().class_number() == 1:
1938
+ E = self.global_integral_model()
1939
+ for P in E.base_ring()(E.discriminant()).support():
1940
+ E = E.local_data(P,proof, globally=True).minimal_model()
1941
+ else:
1942
+ from .kraus import semi_global_minimal_model
1943
+ E, P = semi_global_minimal_model(self)
1944
+ return E._scale_by_units()._reduce_model()
1945
+
1946
+ raise ValueError("%s has no global minimal model! For a semi-global minimal model use semi_global=True" % self)
1947
+
1948
+ def reduction(self, place):
1949
+ r"""
1950
+ Return the reduction of the elliptic curve at a place of good reduction.
1951
+
1952
+ INPUT:
1953
+
1954
+ - ``place`` -- a prime ideal in the base field of the curve
1955
+
1956
+ OUTPUT: an elliptic curve over a finite field, the residue field of the place
1957
+
1958
+ EXAMPLES::
1959
+
1960
+ sage: K.<i> = QuadraticField(-1)
1961
+ sage: EK = EllipticCurve([0, 0, 0, i, i+3])
1962
+ sage: v = K.fractional_ideal(2*i+3)
1963
+ sage: EK.reduction(v)
1964
+ Elliptic Curve defined by y^2 = x^3 + 5*x + 8
1965
+ over Residue field of Fractional ideal (2*i + 3)
1966
+ sage: EK.reduction(K.ideal(1+i))
1967
+ Traceback (most recent call last):
1968
+ ...
1969
+ ValueError: The curve must have good reduction at the place.
1970
+ sage: EK.reduction(K.ideal(2))
1971
+ Traceback (most recent call last):
1972
+ ...
1973
+ ValueError: The ideal must be prime.
1974
+
1975
+ sage: x = polygen(QQ)
1976
+ sage: K = QQ.extension(x^2 + x + 1, "a")
1977
+ sage: E = EllipticCurve([1024*K.0, 1024*K.0])
1978
+ sage: E.reduction(2*K)
1979
+ Elliptic Curve defined by y^2 + (abar+1)*y = x^3
1980
+ over Residue field in abar of Fractional ideal (2)
1981
+ """
1982
+ K = self.base_field()
1983
+ OK = K.ring_of_integers()
1984
+ try:
1985
+ place = K.ideal(place)
1986
+ except TypeError:
1987
+ raise TypeError("The parameter must be an ideal of the base field of the elliptic curve")
1988
+ if not place.is_prime():
1989
+ raise ValueError("The ideal must be prime.")
1990
+ disc = self.discriminant()
1991
+ if not K.ideal(disc).valuation(place) == 0:
1992
+ local_data = self.local_data(place)
1993
+ if local_data.has_good_reduction():
1994
+ Fv = OK.residue_field(place)
1995
+ return local_data.minimal_model().change_ring(Fv)
1996
+ raise ValueError("The curve must have good reduction at the place.")
1997
+ Fv = OK.residue_field(place)
1998
+ return self.change_ring(Fv)
1999
+
2000
+ @cached_method
2001
+ def torsion_subgroup(self):
2002
+ r"""
2003
+ Return the torsion subgroup of this elliptic curve.
2004
+
2005
+ OUTPUT: the :class:`EllipticCurveTorsionSubgroup` associated to this elliptic
2006
+ curve.
2007
+
2008
+ EXAMPLES::
2009
+
2010
+ sage: E = EllipticCurve('11a1')
2011
+ sage: x = polygen(ZZ, 'x')
2012
+ sage: K.<t> = NumberField(x^4 + x^3 + 11*x^2 + 41*x + 101)
2013
+ sage: EK = E.base_extend(K)
2014
+ sage: tor = EK.torsion_subgroup() # long time (2s on sage.math, 2014)
2015
+ sage: tor # long time
2016
+ Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve
2017
+ defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Number Field
2018
+ in t with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101
2019
+ sage: tor.gens() # long time
2020
+ ((16 : 60 : 1), (t : 1/11*t^3 + 6/11*t^2 + 19/11*t + 48/11 : 1))
2021
+
2022
+ ::
2023
+
2024
+ sage: E = EllipticCurve('15a1')
2025
+ sage: K.<t> = NumberField(x^2 + 2*x + 10)
2026
+ sage: EK = E.base_extend(K)
2027
+ sage: EK.torsion_subgroup()
2028
+ Torsion Subgroup isomorphic to Z/4 + Z/4 associated to the
2029
+ Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + (-10)*x + (-10)
2030
+ over Number Field in t with defining polynomial x^2 + 2*x + 10
2031
+
2032
+ ::
2033
+
2034
+ sage: E = EllipticCurve('19a1')
2035
+ sage: K.<t> = NumberField(x^9-3*x^8-4*x^7+16*x^6-3*x^5-21*x^4+5*x^3+7*x^2-7*x+1)
2036
+ sage: EK = E.base_extend(K)
2037
+ sage: EK.torsion_subgroup()
2038
+ Torsion Subgroup isomorphic to Z/9 associated to the Elliptic Curve defined
2039
+ by y^2 + y = x^3 + x^2 + (-9)*x + (-15) over Number Field in t with defining
2040
+ polynomial x^9 - 3*x^8 - 4*x^7 + 16*x^6 - 3*x^5 - 21*x^4 + 5*x^3 + 7*x^2 - 7*x + 1
2041
+
2042
+ ::
2043
+
2044
+ sage: K.<i> = QuadraticField(-1)
2045
+ sage: EK = EllipticCurve([0, 0, 0, i, i+3])
2046
+ sage: EK.torsion_subgroup ()
2047
+ Torsion Subgroup isomorphic to Trivial group associated to the
2048
+ Elliptic Curve defined by y^2 = x^3 + i*x + (i+3)
2049
+ over Number Field in i with defining polynomial x^2 + 1 with i = 1*I
2050
+
2051
+ .. SEEALSO::
2052
+
2053
+ Use :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.division_field`
2054
+ to determine the field of definition of the `\ell`-torsion subgroup.
2055
+ """
2056
+ from .ell_torsion import EllipticCurveTorsionSubgroup
2057
+ return EllipticCurveTorsionSubgroup(self)
2058
+
2059
+ @cached_method
2060
+ def torsion_order(self):
2061
+ r"""
2062
+ Return the order of the torsion subgroup of this elliptic curve.
2063
+
2064
+ OUTPUT: integer
2065
+
2066
+ EXAMPLES::
2067
+
2068
+ sage: E = EllipticCurve('11a1')
2069
+ sage: x = polygen(ZZ, 'x')
2070
+ sage: K.<t> = NumberField(x^4 + x^3 + 11*x^2 + 41*x + 101)
2071
+ sage: EK = E.base_extend(K)
2072
+ sage: EK.torsion_order() # long time (2s on sage.math, 2014)
2073
+ 25
2074
+
2075
+ ::
2076
+
2077
+ sage: E = EllipticCurve('15a1')
2078
+ sage: K.<t> = NumberField(x^2 + 2*x + 10)
2079
+ sage: EK = E.base_extend(K)
2080
+ sage: EK.torsion_order()
2081
+ 16
2082
+
2083
+ ::
2084
+
2085
+ sage: E = EllipticCurve('19a1')
2086
+ sage: K.<t> = NumberField(x^9 - 3*x^8 - 4*x^7 + 16*x^6 - 3*x^5 - 21*x^4 + 5*x^3 + 7*x^2 - 7*x + 1)
2087
+ sage: EK = E.base_extend(K)
2088
+ sage: EK.torsion_order()
2089
+ 9
2090
+
2091
+ ::
2092
+
2093
+ sage: K.<i> = QuadraticField(-1)
2094
+ sage: EK = EllipticCurve([0, 0, 0, i, i + 3])
2095
+ sage: EK.torsion_order()
2096
+ 1
2097
+ """
2098
+ return self.torsion_subgroup().order()
2099
+
2100
+ def torsion_points(self):
2101
+ r"""
2102
+ Return a list of the torsion points of this elliptic curve.
2103
+
2104
+ OUTPUT: sorted list of the torsion points
2105
+
2106
+ EXAMPLES::
2107
+
2108
+ sage: E = EllipticCurve('11a1')
2109
+ sage: E.torsion_points()
2110
+ [(0 : 1 : 0), (5 : -6 : 1), (5 : 5 : 1), (16 : -61 : 1), (16 : 60 : 1)]
2111
+ sage: x = polygen(ZZ, 'x')
2112
+ sage: K.<t> = NumberField(x^4 + x^3 + 11*x^2 + 41*x + 101)
2113
+ sage: EK = E.base_extend(K)
2114
+ sage: EK.torsion_points() # long time (1s on sage.math, 2014)
2115
+ [(0 : 1 : 0),
2116
+ (t : 1/11*t^3 + 6/11*t^2 + 19/11*t + 48/11 : 1),
2117
+ (1/11*t^3 - 5/11*t^2 + 19/11*t - 40/11 : -6/11*t^3 - 3/11*t^2 - 26/11*t - 321/11 : 1),
2118
+ (1/11*t^3 - 5/11*t^2 + 19/11*t - 40/11 : 6/11*t^3 + 3/11*t^2 + 26/11*t + 310/11 : 1),
2119
+ (t : -1/11*t^3 - 6/11*t^2 - 19/11*t - 59/11 : 1),
2120
+ (16 : 60 : 1),
2121
+ (-3/55*t^3 - 7/55*t^2 - 2/55*t - 133/55 : 6/55*t^3 + 3/55*t^2 + 25/11*t + 156/55 : 1),
2122
+ (14/121*t^3 - 15/121*t^2 + 90/121*t + 232/121 : 16/121*t^3 - 69/121*t^2 + 293/121*t - 46/121 : 1),
2123
+ (-26/121*t^3 + 20/121*t^2 - 219/121*t - 995/121 : -15/121*t^3 - 156/121*t^2 + 232/121*t - 2887/121 : 1),
2124
+ (10/121*t^3 + 49/121*t^2 + 168/121*t + 73/121 : -32/121*t^3 - 60/121*t^2 + 261/121*t + 686/121 : 1),
2125
+ (5 : 5 : 1),
2126
+ (-9/121*t^3 - 21/121*t^2 - 127/121*t - 377/121 : -7/121*t^3 + 24/121*t^2 + 197/121*t + 16/121 : 1),
2127
+ (3/55*t^3 + 7/55*t^2 + 2/55*t + 78/55 : 7/55*t^3 - 24/55*t^2 + 9/11*t + 17/55 : 1),
2128
+ (-5/121*t^3 + 36/121*t^2 - 84/121*t + 24/121 : -34/121*t^3 + 27/121*t^2 - 305/121*t - 829/121 : 1),
2129
+ (5/121*t^3 - 14/121*t^2 - 158/121*t - 453/121 : 49/121*t^3 + 129/121*t^2 + 315/121*t + 86/121 : 1),
2130
+ (5 : -6 : 1),
2131
+ (5/121*t^3 - 14/121*t^2 - 158/121*t - 453/121 : -49/121*t^3 - 129/121*t^2 - 315/121*t - 207/121 : 1),
2132
+ (-5/121*t^3 + 36/121*t^2 - 84/121*t + 24/121 : 34/121*t^3 - 27/121*t^2 + 305/121*t + 708/121 : 1),
2133
+ (3/55*t^3 + 7/55*t^2 + 2/55*t + 78/55 : -7/55*t^3 + 24/55*t^2 - 9/11*t - 72/55 : 1),
2134
+ (-9/121*t^3 - 21/121*t^2 - 127/121*t - 377/121 : 7/121*t^3 - 24/121*t^2 - 197/121*t - 137/121 : 1),
2135
+ (16 : -61 : 1),
2136
+ (10/121*t^3 + 49/121*t^2 + 168/121*t + 73/121 : 32/121*t^3 + 60/121*t^2 - 261/121*t - 807/121 : 1),
2137
+ (-26/121*t^3 + 20/121*t^2 - 219/121*t - 995/121 : 15/121*t^3 + 156/121*t^2 - 232/121*t + 2766/121 : 1),
2138
+ (14/121*t^3 - 15/121*t^2 + 90/121*t + 232/121 : -16/121*t^3 + 69/121*t^2 - 293/121*t - 75/121 : 1),
2139
+ (-3/55*t^3 - 7/55*t^2 - 2/55*t - 133/55 : -6/55*t^3 - 3/55*t^2 - 25/11*t - 211/55 : 1)]
2140
+
2141
+ ::
2142
+
2143
+ sage: E = EllipticCurve('15a1')
2144
+ sage: K.<t> = NumberField(x^2 + 2*x + 10)
2145
+ sage: EK = E.base_extend(K)
2146
+ sage: EK.torsion_points()
2147
+ [(0 : 1 : 0),
2148
+ (-7 : -5*t - 2 : 1),
2149
+ (-7 : 5*t + 8 : 1),
2150
+ (-13/4 : 9/8 : 1),
2151
+ (-2 : -2 : 1),
2152
+ (-2 : 3 : 1),
2153
+ (-t - 2 : -t - 7 : 1),
2154
+ (-t - 2 : 2*t + 8 : 1),
2155
+ (-1 : 0 : 1),
2156
+ (t : t - 5 : 1),
2157
+ (t : -2*t + 4 : 1),
2158
+ (1/2 : -5/4*t - 2 : 1),
2159
+ (1/2 : 5/4*t + 1/2 : 1),
2160
+ (3 : -2 : 1),
2161
+ (8 : -27 : 1),
2162
+ (8 : 18 : 1)]
2163
+
2164
+ ::
2165
+
2166
+ sage: K.<i> = QuadraticField(-1)
2167
+ sage: EK = EllipticCurve(K, [0,0,0,0,-1])
2168
+ sage: EK.torsion_points()
2169
+ [(0 : 1 : 0),
2170
+ (-2 : -3*i : 1),
2171
+ (-2 : 3*i : 1),
2172
+ (0 : -i : 1),
2173
+ (0 : i : 1),
2174
+ (1 : 0 : 1)]
2175
+ """
2176
+ T = self.torsion_subgroup() # cached
2177
+ return sorted(T.points()) # these are also cached in T
2178
+
2179
+ def rank_bounds(self, **kwds):
2180
+ r"""
2181
+ Return the lower and upper bounds using :meth:`~simon_two_descent`.
2182
+ The results of :meth:`~simon_two_descent` are cached.
2183
+
2184
+ .. NOTE::
2185
+
2186
+ The optional parameters control the Simon two descent algorithm;
2187
+ see the documentation of :meth:`~simon_two_descent` for more
2188
+ details.
2189
+
2190
+ INPUT:
2191
+
2192
+ - ``verbose`` -- 0, 1, 2, or 3 (default: 0); the verbosity level
2193
+
2194
+ - ``lim1`` -- (default: 2) limit on trivial points on quartics
2195
+
2196
+ - ``lim3`` -- (default: 4) limit on points on ELS quartics
2197
+
2198
+ - ``limtriv`` -- (default: 2) limit on trivial points on elliptic curve
2199
+
2200
+ - ``maxprob`` -- (default: 20)
2201
+
2202
+ - ``limbigprime`` -- (default: 30) to distinguish between
2203
+ small and large prime numbers. Use probabilistic tests for
2204
+ large primes. If 0, do not use probabilistic tests.
2205
+
2206
+ - ``known_points`` -- (default: ``None``) list of known points on
2207
+ the curve
2208
+
2209
+ OUTPUT: lower and upper bounds for the rank of the Mordell-Weil group
2210
+
2211
+ .. NOTE::
2212
+
2213
+ For non-quadratic number fields, this code does
2214
+ return, but it takes a long time.
2215
+
2216
+ EXAMPLES::
2217
+
2218
+ sage: x = polygen(ZZ, 'x')
2219
+ sage: K.<a> = NumberField(x^2 + 23, 'a')
2220
+ sage: E = EllipticCurve(K, '37')
2221
+ sage: E == loads(dumps(E))
2222
+ True
2223
+ sage: E.rank_bounds()
2224
+ (2, 2)
2225
+
2226
+ Here is a curve with two-torsion, again the bounds coincide::
2227
+
2228
+ sage: Qrt5.<rt5> = NumberField(x^2 - 5)
2229
+ sage: E = EllipticCurve([0, 5-rt5, 0, rt5, 0])
2230
+ sage: E.rank_bounds()
2231
+ (1, 1)
2232
+
2233
+ Finally an example with non-trivial 2-torsion in Sha. So the
2234
+ 2-descent will not be able to determine the rank, but can only
2235
+ give bounds::
2236
+
2237
+ sage: E = EllipticCurve("15a5")
2238
+ sage: K.<t> = NumberField(x^2 - 6)
2239
+ sage: EK = E.base_extend(K)
2240
+ sage: EK.rank_bounds(lim1=1, lim3=1, limtriv=1)
2241
+ (0, 2)
2242
+
2243
+ IMPLEMENTATION:
2244
+
2245
+ Uses Denis Simon's PARI/GP scripts from
2246
+ http://www.math.unicaen.fr/~simon/.
2247
+ """
2248
+ lower, upper, gens = self.simon_two_descent(**kwds)
2249
+ # this was corrected in trac 13593. upper is the dimension
2250
+ # of the 2-selmer group, so we can certainly remove the
2251
+ # 2-torsion of the Mordell-Weil group.
2252
+ upper -= self.two_torsion_rank()
2253
+ return lower, upper
2254
+
2255
+ def rank(self, **kwds):
2256
+ r"""
2257
+ Return the rank of this elliptic curve, if it can be determined.
2258
+
2259
+ .. NOTE::
2260
+
2261
+ The optional parameters control the Simon two descent algorithm;
2262
+ see the documentation of :meth:`~simon_two_descent` for more
2263
+ details.
2264
+
2265
+ INPUT:
2266
+
2267
+ - ``verbose`` -- 0, 1, 2, or 3 (default: 0); the verbosity level
2268
+
2269
+ - ``lim1`` -- (default: 2) limit on trivial points on quartics
2270
+
2271
+ - ``lim3`` -- (default: 4) limit on points on ELS quartics
2272
+
2273
+ - ``limtriv`` -- (default: 2) limit on trivial points on elliptic curve
2274
+
2275
+ - ``maxprob`` -- (default: 20)
2276
+
2277
+ - ``limbigprime`` -- (default: 30) to distinguish between
2278
+ small and large prime numbers. Use probabilistic tests for
2279
+ large primes. If 0, do not use probabilistic tests.
2280
+
2281
+ - ``known_points`` -- (default: ``None``) list of known points on
2282
+ the curve
2283
+
2284
+ OUTPUT:
2285
+
2286
+ If the upper and lower bounds given by Simon two-descent are
2287
+ the same, then the rank has been uniquely identified and we
2288
+ return this. Otherwise, we raise a :exc:`ValueError` with an error
2289
+ message specifying the upper and lower bounds.
2290
+
2291
+ .. NOTE::
2292
+
2293
+ For non-quadratic number fields, this code does return, but it takes
2294
+ a long time.
2295
+
2296
+ EXAMPLES::
2297
+
2298
+ sage: x = polygen(ZZ, 'x')
2299
+ sage: K.<a> = NumberField(x^2 + 23, 'a')
2300
+ sage: E = EllipticCurve(K, '37')
2301
+ sage: E == loads(dumps(E))
2302
+ True
2303
+ sage: E.rank()
2304
+ 2
2305
+
2306
+ Here is a curve with two-torsion in the Tate-Shafarevich group,
2307
+ so here the bounds given by the algorithm do not uniquely
2308
+ determine the rank::
2309
+
2310
+ sage: E = EllipticCurve("15a5")
2311
+ sage: K.<t> = NumberField(x^2 - 6)
2312
+ sage: EK = E.base_extend(K)
2313
+ sage: EK.rank(lim1=1, lim3=1, limtriv=1)
2314
+ Traceback (most recent call last):
2315
+ ...
2316
+ ValueError: There is insufficient data to determine the rank -
2317
+ 2-descent gave lower bound 0 and upper bound 2
2318
+
2319
+ IMPLEMENTATION:
2320
+
2321
+ Uses Denis Simon's PARI/GP scripts from
2322
+ http://www.math.unicaen.fr/~simon/.
2323
+ """
2324
+ lower, upper = self.rank_bounds(**kwds)
2325
+ if lower == upper:
2326
+ return lower
2327
+ else:
2328
+ raise ValueError('There is insufficient data to determine the rank - 2-descent gave lower bound %s and upper bound %s' % (lower, upper))
2329
+
2330
+ def gens(self, **kwds):
2331
+ r"""
2332
+ Return some points of infinite order on this elliptic curve.
2333
+
2334
+ Contrary to what the name of this method suggests, the points
2335
+ it returns do not always generate a subgroup of full rank in
2336
+ the Mordell-Weil group, nor are they necessarily linearly
2337
+ independent. Moreover, the number of points can be smaller or
2338
+ larger than what one could expect after calling :meth:`~rank`
2339
+ or :meth:`~rank_bounds`.
2340
+
2341
+ .. NOTE::
2342
+
2343
+ The optional parameters control the Simon two descent algorithm;
2344
+ see the documentation of :meth:`~simon_two_descent` for more
2345
+ details.
2346
+
2347
+ INPUT:
2348
+
2349
+ - ``verbose`` -- 0, 1, 2, or 3 (default: 0); the verbosity level
2350
+
2351
+ - ``lim1`` -- (default: 2) limit on trivial points on quartics
2352
+
2353
+ - ``lim3`` -- (default: 4) limit on points on ELS quartics
2354
+
2355
+ - ``limtriv`` -- (default: 2) limit on trivial points on elliptic curve
2356
+
2357
+ - ``maxprob`` -- (default: 20)
2358
+
2359
+ - ``limbigprime`` -- (default: 30) to distinguish between
2360
+ small and large prime numbers. Use probabilistic tests for
2361
+ large primes. If 0, do not use probabilistic tests.
2362
+
2363
+ - ``known_points`` -- (default: ``None``) list of known points on
2364
+ the curve
2365
+
2366
+ OUTPUT: a set of points of infinite order given by the Simon two-descent
2367
+
2368
+ .. NOTE::
2369
+
2370
+ For non-quadratic number fields, this code does return, but it takes
2371
+ a long time.
2372
+
2373
+ EXAMPLES::
2374
+
2375
+ sage: x = polygen(ZZ, 'x')
2376
+ sage: K.<a> = NumberField(x^2 + 23, 'a')
2377
+ sage: E = EllipticCurve(K,[0,0,0,101,0])
2378
+ sage: E.gens() # needs eclib
2379
+ ((23831509/8669448*a - 2867471/8669448 : 76507317707/18049790736*a - 424166479633/18049790736 : 1),
2380
+ (-2031032029/969232392*a + 58813561/969232392 : -15575984630401/21336681877488*a + 451041199309/21336681877488 : 1),
2381
+ (-186948623/4656964 : 549438861195/10049728312*a : 1))
2382
+
2383
+ It can happen that no points are found if the height bounds
2384
+ used in the search are too small (see :issue:`10745`)::
2385
+
2386
+ sage: # needs eclib
2387
+ sage: K.<t> = NumberField(x^4 + x^2 - 7)
2388
+ sage: E = EllipticCurve(K, [1, 0, 5*t^2 + 16, 0, 0])
2389
+ sage: E.gens(lim1=1, lim3=1)
2390
+ ()
2391
+ sage: E.rank()
2392
+ 1
2393
+ sage: gg = E.gens(lim3=13); gg # long time (about 4s)
2394
+ ((... : 1),)
2395
+
2396
+ Check that the point found has infinite order, and that it is on the curve::
2397
+
2398
+ sage: # needs eclib
2399
+ sage: P = gg[0]; P.order() # long time
2400
+ +Infinity
2401
+ sage: E.defining_polynomial()(*P) # long time
2402
+ 0
2403
+
2404
+ Here is a curve of rank 2::
2405
+
2406
+ sage: K.<t> = NumberField(x^2 - 17)
2407
+ sage: E = EllipticCurve(K, [-4, 0])
2408
+ sage: E.gens() # needs eclib
2409
+ ((-1/2*t + 1/2 : -1/2*t + 1/2 : 1), (-t + 3 : -2*t + 10 : 1))
2410
+ sage: E.rank()
2411
+ 2
2412
+
2413
+ Test that points of finite order are not included (see :issue:`13593`)::
2414
+
2415
+ sage: E = EllipticCurve("17a3")
2416
+ sage: K.<t> = NumberField(x^2 + 3)
2417
+ sage: EK = E.base_extend(K)
2418
+ sage: EK.rank()
2419
+ 0
2420
+ sage: EK.gens() # needs eclib
2421
+ ()
2422
+
2423
+ IMPLEMENTATION:
2424
+
2425
+ For curves over quadratic fields which are base-changes from
2426
+ `\QQ`, we delegate the work to :meth:`gens_quadratic` where
2427
+ methods over `\QQ` suffice. Otherwise, we use Denis Simon's
2428
+ PARI/GP scripts from http://www.math.unicaen.fr/~simon/.
2429
+ """
2430
+ try:
2431
+ return tuple(self.gens_quadratic(**kwds))
2432
+ except ValueError:
2433
+ self.simon_two_descent(**kwds)
2434
+ return tuple(self._known_points)
2435
+
2436
+ def period_lattice(self, embedding):
2437
+ r"""
2438
+ Return the period lattice of the elliptic curve for the given
2439
+ embedding of its base field with respect to the differential
2440
+ `dx/(2y + a_1x + a_3)`.
2441
+
2442
+ INPUT:
2443
+
2444
+ - ``embedding`` -- an embedding of the base number field into `\RR` or `\CC`
2445
+
2446
+ .. NOTE::
2447
+
2448
+ The precision of the embedding is ignored: we only use the
2449
+ given embedding to determine which embedding into ``QQbar``
2450
+ to use. Once the lattice has been initialized, periods can
2451
+ be computed to arbitrary precision.
2452
+
2453
+ EXAMPLES:
2454
+
2455
+ First define a field with two real embeddings::
2456
+
2457
+ sage: x = polygen(QQ)
2458
+ sage: K.<a> = NumberField(x^3 - 2)
2459
+ sage: E = EllipticCurve([0,0,0,a,2])
2460
+ sage: embs = K.embeddings(CC); len(embs)
2461
+ 3
2462
+
2463
+ For each embedding we have a different period lattice::
2464
+
2465
+ sage: E.period_lattice(embs[0])
2466
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + a*x + 2
2467
+ over Number Field in a with defining polynomial x^3 - 2
2468
+ with respect to the embedding Ring morphism:
2469
+ From: Number Field in a with defining polynomial x^3 - 2
2470
+ To: Algebraic Field
2471
+ Defn: a |--> -0.6299605249474365? - 1.091123635971722?*I
2472
+
2473
+ sage: E.period_lattice(embs[1])
2474
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + a*x + 2
2475
+ over Number Field in a with defining polynomial x^3 - 2
2476
+ with respect to the embedding Ring morphism:
2477
+ From: Number Field in a with defining polynomial x^3 - 2
2478
+ To: Algebraic Field
2479
+ Defn: a |--> -0.6299605249474365? + 1.091123635971722?*I
2480
+
2481
+ sage: E.period_lattice(embs[2])
2482
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + a*x + 2
2483
+ over Number Field in a with defining polynomial x^3 - 2
2484
+ with respect to the embedding Ring morphism:
2485
+ From: Number Field in a with defining polynomial x^3 - 2
2486
+ To: Algebraic Field
2487
+ Defn: a |--> 1.259921049894873?
2488
+
2489
+ Although the original embeddings have only the default
2490
+ precision, we can obtain the basis with higher precision
2491
+ later::
2492
+
2493
+ sage: L = E.period_lattice(embs[0])
2494
+ sage: L.basis()
2495
+ (1.86405007647981 - 0.903761485143226*I, -0.149344633143919 - 2.06619546272945*I)
2496
+
2497
+ sage: L.basis(prec=100)
2498
+ (1.8640500764798108425920506200 - 0.90376148514322594749786960975*I,
2499
+ -0.14934463314391922099120107422 - 2.0661954627294548995621225062*I)
2500
+ """
2501
+ from sage.schemes.elliptic_curves.period_lattice import PeriodLattice_ell
2502
+ return PeriodLattice_ell(self, embedding)
2503
+
2504
+ def real_components(self, embedding):
2505
+ """
2506
+ Return the number of real components with respect to a real embedding of the base field.
2507
+
2508
+ EXAMPLES::
2509
+
2510
+ sage: K.<a> = QuadraticField(5)
2511
+ sage: embs = K.real_embeddings()
2512
+ sage: E = EllipticCurve([0,1,1,a,a])
2513
+ sage: [e(E.discriminant()) > 0 for e in embs]
2514
+ [True, False]
2515
+ sage: [E.real_components(e) for e in embs]
2516
+ [2, 1]
2517
+
2518
+ TESTS::
2519
+
2520
+ sage: K.<a> = QuadraticField(-1)
2521
+ sage: e = K.complex_embeddings()[0]
2522
+ sage: E = EllipticCurve([0,1,1,a,a])
2523
+ sage: E.real_components(e)
2524
+ Traceback (most recent call last):
2525
+ ...
2526
+ ValueError: invalid embedding specified: should be real
2527
+
2528
+ sage: E.real_components('banana')
2529
+ Traceback (most recent call last):
2530
+ ...
2531
+ ValueError: invalid embedding
2532
+
2533
+ sage: K.<a> = QuadraticField(-1)
2534
+ sage: E = EllipticCurve([0,1,1,a,a])
2535
+ sage: K1.<a> = QuadraticField(5)
2536
+ sage: e = K1.real_embeddings()[0]
2537
+ sage: E.real_components(e)
2538
+ Traceback (most recent call last):
2539
+ ...
2540
+ ValueError: invalid embedding specified: should have domain ...
2541
+ """
2542
+ try:
2543
+ if embedding.domain() is not self.base_field():
2544
+ raise ValueError("invalid embedding specified: should have domain {}".format(self.base_field()))
2545
+ if not isinstance(embedding.codomain(), sage.rings.abc.RealField):
2546
+ raise ValueError("invalid embedding specified: should be real")
2547
+ except AttributeError:
2548
+ raise ValueError("invalid embedding")
2549
+
2550
+ from sage.rings.number_field.number_field import refine_embedding
2551
+ from sage.rings.infinity import Infinity
2552
+ e = refine_embedding(embedding,Infinity)
2553
+
2554
+ return 2 if e(self.discriminant()) > 0 else 1
2555
+
2556
+ def height_function(self):
2557
+ """
2558
+ Return the canonical height function attached to ``self``.
2559
+
2560
+ EXAMPLES::
2561
+
2562
+ sage: x = polygen(ZZ, 'x')
2563
+ sage: K.<a> = NumberField(x^2 - 5)
2564
+ sage: E = EllipticCurve(K, '11a3')
2565
+ sage: E.height_function()
2566
+ EllipticCurveCanonicalHeight object associated to
2567
+ Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2
2568
+ over Number Field in a with defining polynomial x^2 - 5
2569
+ """
2570
+ if not hasattr(self, '_height_function'):
2571
+ from sage.schemes.elliptic_curves.height import EllipticCurveCanonicalHeight
2572
+ self._height_function = EllipticCurveCanonicalHeight(self)
2573
+ return self._height_function
2574
+
2575
+ ##########################################################
2576
+ # Isogeny class
2577
+ ##########################################################
2578
+ def isogeny_class(self, reducible_primes=None, algorithm='Billerey', minimal_models=True):
2579
+ r"""
2580
+ Return the isogeny class of this elliptic curve.
2581
+
2582
+ INPUT:
2583
+
2584
+ - ``reducible_primes`` -- list of integers or ``None`` (default)); if
2585
+ not ``None`` then this should be a list of primes; in computing
2586
+ the isogeny class, only composites isogenies of these
2587
+ degrees will be used.
2588
+
2589
+ - ``algorithm`` -- string (default: ``'Billerey'``); the algorithm
2590
+ to use to compute the reducible primes. Ignored for CM
2591
+ curves or if ``reducible_primes`` is provided. Values are
2592
+ ``'Billerey'`` (default), ``'Larson'``, and ``'heuristic'``.
2593
+
2594
+ - ``minimal_models`` -- boolean (default: ``True``); if ``True``,
2595
+ all curves in the class will be minimal or semi-minimal
2596
+ models. Over fields of larger degree it can be expensive to
2597
+ compute these so set to ``False``.
2598
+
2599
+ OUTPUT:
2600
+
2601
+ An instance of the class
2602
+ :class:`sage.schemes.elliptic_curves.isogeny_class.IsogenyClass_EC_NumberField`.
2603
+ From this object may be obtained a list of curves in the
2604
+ class, a matrix of the degrees of the isogenies between them,
2605
+ and the isogenies themselves.
2606
+
2607
+ .. NOTE::
2608
+
2609
+ If using the algorithm ``'heuristic'`` for non-CM curves, the
2610
+ result is not guaranteed to be the complete isogeny class,
2611
+ since only reducible primes up to the default bound in
2612
+ :meth:`reducible_primes_naive` (currently 1000) are
2613
+ tested. However, no examples of non-CM elliptic curves
2614
+ with reducible primes greater than 100 have yet been
2615
+ computed so the output is likely to be correct.
2616
+
2617
+ .. NOTE::
2618
+
2619
+ By default, the curves in the isogeny class will all be
2620
+ minimal models if these exist (for example, when the class
2621
+ number is `1`); otherwise they will be minimal at all but
2622
+ one prime. This behaviour can be switched off if desired,
2623
+ for example over fields where the computation of the class
2624
+ group would be too expensive.
2625
+
2626
+ EXAMPLES::
2627
+
2628
+ sage: K.<i> = QuadraticField(-1)
2629
+ sage: E = EllipticCurve(K, [0,0,0,0,1])
2630
+ sage: C = E.isogeny_class(); C
2631
+ Isogeny class of Elliptic Curve defined by y^2 = x^3 + 1
2632
+ over Number Field in i with defining polynomial x^2 + 1 with i = 1*I
2633
+
2634
+ The curves in the class (sorted)::
2635
+
2636
+ sage: [E1.ainvs() for E1 in C]
2637
+ [(0, 0, 0, 0, -27),
2638
+ (0, 0, 0, 0, 1),
2639
+ (i + 1, i, 0, 3, -i),
2640
+ (i + 1, i, 0, 33, 91*i)]
2641
+
2642
+ The matrix of degrees of cyclic isogenies between curves::
2643
+
2644
+ sage: C.matrix()
2645
+ [1 3 6 2]
2646
+ [3 1 2 6]
2647
+ [6 2 1 3]
2648
+ [2 6 3 1]
2649
+
2650
+ The array of isogenies themselves is not filled out but only
2651
+ contains those used to construct the class, the other entries
2652
+ containing the integer 0. This will be changed when the
2653
+ class :class:`EllipticCurveIsogeny` allowed composition. In
2654
+ this case we used `2`-isogenies to go from 0 to 2 and from 1
2655
+ to 3, and `3`-isogenies to go from 0 to 1 and from 2 to 3::
2656
+
2657
+ sage: isogs = C.isogenies()
2658
+ sage: [((i,j), isogs[i][j].degree())
2659
+ ....: for i in range(4) for j in range(4) if isogs[i][j] != 0]
2660
+ [((0, 1), 3),
2661
+ ((0, 3), 2),
2662
+ ((1, 0), 3),
2663
+ ((1, 2), 2),
2664
+ ((2, 1), 2),
2665
+ ((2, 3), 3),
2666
+ ((3, 0), 2),
2667
+ ((3, 2), 3)]
2668
+ sage: [((i,j), isogs[i][j].x_rational_map())
2669
+ ....: for i in range(4) for j in range(4) if isogs[i][j] != 0]
2670
+ [((0, 1), (1/9*x^3 - 12)/x^2),
2671
+ ((0, 3), (1/2*i*x^2 - 2*i*x + 15*i)/(x - 3)),
2672
+ ((1, 0), (x^3 + 4)/x^2),
2673
+ ((1, 2), (1/2*i*x^2 + i)/(x + 1)),
2674
+ ((2, 1), (-1/2*i*x^2 - 1/2*i)/(x - 1/2*i)),
2675
+ ((2, 3), (x^3 - 2*i*x^2 - 7*x + 4*i)/(x^2 - 2*i*x - 1)),
2676
+ ((3, 0), (-1/2*i*x^2 + 2*x - 5/2*i)/(x + 7/2*i)),
2677
+ ((3, 2), (1/9*x^3 + 2/3*i*x^2 - 13/3*x - 116/9*i)/(x^2 + 10*i*x - 25))]
2678
+
2679
+ The isogeny class may be visualized by obtaining its graph and
2680
+ plotting it::
2681
+
2682
+ sage: G = C.graph() # needs sage.graphs
2683
+ sage: G.show(edge_labels=True) # long time # needs sage.graphs
2684
+
2685
+ sage: K.<i> = QuadraticField(-1)
2686
+ sage: E = EllipticCurve([1+i, -i, i, 1, 0])
2687
+ sage: C = E.isogeny_class(); C # long time
2688
+ Isogeny class of
2689
+ Elliptic Curve defined by y^2 + (i+1)*x*y + i*y = x^3 + (-i)*x^2 + x
2690
+ over Number Field in i with defining polynomial x^2 + 1 with i = 1*I
2691
+ sage: len(C) # long time
2692
+ 6
2693
+ sage: C.matrix() # long time
2694
+ [ 1 3 9 18 6 2]
2695
+ [ 3 1 3 6 2 6]
2696
+ [ 9 3 1 2 6 18]
2697
+ [18 6 2 1 3 9]
2698
+ [ 6 2 6 3 1 3]
2699
+ [ 2 6 18 9 3 1]
2700
+ sage: [E1.ainvs() for E1 in C] # long time
2701
+ [(i + 1, i - 1, i, -i - 1, -i + 1),
2702
+ (i + 1, i - 1, i, 14*i + 4, 7*i + 14),
2703
+ (i + 1, i - 1, i, 59*i + 99, 372*i - 410),
2704
+ (i + 1, -i, i, -240*i - 399, 2869*i + 2627),
2705
+ (i + 1, -i, i, -5*i - 4, 2*i + 5),
2706
+ (i + 1, -i, i, 1, 0)]
2707
+
2708
+ An example with CM by `\sqrt{-5}`::
2709
+
2710
+ sage: pol = PolynomialRing(QQ,'x')([1,0,3,0,1])
2711
+ sage: K.<c> = NumberField(pol)
2712
+ sage: j = 1480640 + 565760*c^2
2713
+ sage: E = EllipticCurve(j=j)
2714
+ sage: E.has_cm()
2715
+ True
2716
+ sage: E.has_rational_cm()
2717
+ True
2718
+ sage: E.cm_discriminant()
2719
+ -20
2720
+ sage: C = E.isogeny_class()
2721
+ sage: len(C)
2722
+ 2
2723
+ sage: C.matrix()
2724
+ [1 2]
2725
+ [2 1]
2726
+ sage: [E.ainvs() for E in C]
2727
+ [(0, 0, 0, 83490*c^2 - 147015, -64739840*c^2 - 84465260),
2728
+ (0, 0, 0, -161535*c^2 + 70785, -62264180*c^3 + 6229080*c)]
2729
+ sage: C.isogenies()[0][1]
2730
+ Isogeny of degree 2
2731
+ from Elliptic Curve defined by
2732
+ y^2 = x^3 + (83490*c^2-147015)*x + (-64739840*c^2-84465260)
2733
+ over Number Field in c with defining polynomial x^4 + 3*x^2 + 1
2734
+ to Elliptic Curve defined by
2735
+ y^2 = x^3 + (-161535*c^2+70785)*x + (-62264180*c^3+6229080*c)
2736
+ over Number Field in c with defining polynomial x^4 + 3*x^2 + 1
2737
+
2738
+ An example with CM by `\sqrt{-23}` (class number `3`)::
2739
+
2740
+ sage: pol = PolynomialRing(QQ,'x')([1,-3,5,-5,5,-3,1])
2741
+ sage: L.<a> = NumberField(pol)
2742
+ sage: js = hilbert_class_polynomial(-23).roots(L,multiplicities=False); len(js)
2743
+ 3
2744
+ sage: E = EllipticCurve(j=js[0])
2745
+ sage: E.has_rational_cm()
2746
+ True
2747
+ sage: len(E.isogenies_prime_degree()) # long time
2748
+ 3
2749
+ sage: C = E.isogeny_class(); len(C) # long time
2750
+ 6
2751
+
2752
+ The reason for the isogeny class having size six while the
2753
+ class number is only `3` is that the class also contains three
2754
+ curves with CM by the order of discriminant `-92=4\cdot(-23)`,
2755
+ which also has class number `3`. The curves in the class are
2756
+ sorted first by CM discriminant (then lexicographically using
2757
+ a-invariants)::
2758
+
2759
+ sage: [F.cm_discriminant() for F in C] # long time
2760
+ [-23, -23, -23, -92, -92, -92]
2761
+
2762
+ `2` splits in the order with discriminant `-23`, into two
2763
+ primes of order `3` in the class group, each of which induces
2764
+ a `2`-isogeny to a curve with the same endomorphism ring; the
2765
+ third `2`-isogeny is to a curve with the smaller endomorphism
2766
+ ring::
2767
+
2768
+ sage: [phi.codomain().cm_discriminant() for phi in E.isogenies_prime_degree()] # long time
2769
+ [-92, -23, -23]
2770
+
2771
+ sage: C.matrix() # long time # random
2772
+ [1 2 2 4 4 2]
2773
+ [2 1 2 4 2 4]
2774
+ [2 2 1 2 4 4]
2775
+ [4 4 2 1 3 3]
2776
+ [4 2 4 3 1 3]
2777
+ [2 4 4 3 3 1]
2778
+
2779
+ The graph of this isogeny class has a shape which does not
2780
+ occur over `\QQ`: a triangular prism. Note that for curves
2781
+ without CM, the graph has an edge between two curves if and
2782
+ only if they are connected by an isogeny of prime degree, and
2783
+ this degree is uniquely determined by the two curves, but in
2784
+ the CM case this property does not hold, since for pairs of
2785
+ curves in the class with the same endomorphism ring `O`, the
2786
+ set of degrees of isogenies between them is the set of
2787
+ integers represented by a primitive integral binary quadratic
2788
+ form of discriminant `\text{disc}(O)`, and this form
2789
+ represents infinitely many primes. In the matrix we give a
2790
+ small prime represented by the appropriate form. In this
2791
+ example, the matrix is formed by four `3\times3` blocks. The
2792
+ isogenies of degree `2` indicated by the upper left `3\times3`
2793
+ block of the matrix could be replaced by isogenies of any
2794
+ degree represented by the quadratic form `2x^2+xy+3y^2` of
2795
+ discriminant `-23`. Similarly in the lower right block, the
2796
+ entries of `3` could be represented by any integers
2797
+ represented by the quadratic form `3x^2+2xy+8y^2` of
2798
+ discriminant `-92`. In the top right block and lower left
2799
+ blocks, by contrast, the prime entries `2` are unique
2800
+ determined::
2801
+
2802
+ sage: # needs sage.graphs
2803
+ sage: G = C.graph() # long time
2804
+ sage: G.adjacency_matrix() # long time # random
2805
+ [0 1 1 0 0 1]
2806
+ [1 0 1 0 1 0]
2807
+ [1 1 0 1 0 0]
2808
+ [0 0 1 0 1 1]
2809
+ [0 1 0 1 0 1]
2810
+ [1 0 0 1 1 0]
2811
+ sage: Graph(polytopes.simplex(2).prism().adjacency_matrix()).is_isomorphic(G) # long time
2812
+ True
2813
+
2814
+ To display the graph without any edge labels::
2815
+
2816
+ sage: G.show() # not tested # needs sage.graphs
2817
+
2818
+ To display the graph with edge labels: by default, for curves
2819
+ with rational CM, the labels are the coefficients of the
2820
+ associated quadratic forms::
2821
+
2822
+ sage: G.show(edge_labels=True) # not tested # needs sage.graphs
2823
+
2824
+ For an alternative view, first relabel the edges using only 2
2825
+ labels to distinguish between isogenies between curves with
2826
+ the same endomorphism ring and isogenies between curves with
2827
+ different endomorphism rings, then use a 3-dimensional plot
2828
+ which can be rotated::
2829
+
2830
+ sage: for i, j, l in G.edge_iterator(): # long time # needs sage.graphs
2831
+ ....: G.set_edge_label(i, j, l.count(','))
2832
+ sage: G.show3d(color_by_label=True) # long time # needs sage.graphs sage.plot
2833
+
2834
+ A class number `6` example. First we set up the fields: ``pol``
2835
+ defines the same field as ``pol26`` but is simpler::
2836
+
2837
+ sage: pol26 = hilbert_class_polynomial(-4*26)
2838
+ sage: x = polygen(QQ, 'x')
2839
+ sage: pol = x^6 - x^5 + 2*x^4 + x^3 - 2*x^2 - x - 1
2840
+ sage: K.<a> = NumberField(pol)
2841
+ sage: L.<b> = K.extension(x^2 + 26)
2842
+
2843
+ Only `2` of the `j`-invariants with discriminant -104 are in
2844
+ `K`, though all are in `L`::
2845
+
2846
+ sage: len(pol26.roots(K))
2847
+ 2
2848
+ sage: len(pol26.roots(L))
2849
+ 6
2850
+
2851
+ We create an elliptic curve defined over `K` with one of the
2852
+ `j`-invariants in `K`::
2853
+
2854
+ sage: j1 = pol26.roots(K)[0][0]
2855
+ sage: E = EllipticCurve(j=j1)
2856
+ sage: E.has_cm()
2857
+ True
2858
+ sage: E.has_rational_cm()
2859
+ False
2860
+ sage: E.has_rational_cm(L)
2861
+ True
2862
+
2863
+ Over `K` the isogeny class has size `4`, with `2` curves for
2864
+ each of the `2` `K`-rational `j`-invariants::
2865
+
2866
+ sage: C = E.isogeny_class(); len(C) # long time (~11s)
2867
+ 4
2868
+ sage: C.matrix() # long time
2869
+ [ 1 13 2 26]
2870
+ [13 1 26 2]
2871
+ [ 2 26 1 13]
2872
+ [26 2 13 1]
2873
+ sage: len(Set([EE.j_invariant() for EE in C.curves])) # long time
2874
+ 2
2875
+
2876
+ Over `L`, the isogeny class grows to size `6` (the class
2877
+ number)::
2878
+
2879
+ sage: EL = E.change_ring(L)
2880
+ sage: CL = EL.isogeny_class(minimal_models=False) # long time
2881
+ sage: len(CL) # long time
2882
+ 6
2883
+ sage: s1 = Set([EE.j_invariant() for EE in CL.curves]) # long time
2884
+ sage: s2 = Set(pol26.roots(L, multiplicities=False)) # long time
2885
+ sage: s1 == s2 # long time
2886
+ True
2887
+
2888
+ In each position in the matrix of degrees, we see primes (or
2889
+ `1`). In fact the set of degrees of cyclic isogenies from
2890
+ curve `i` to curve `j` is infinite, and is the set of all
2891
+ integers represented by one of the primitive binary quadratic
2892
+ forms of discriminant `-104`, from which we have selected a
2893
+ small prime::
2894
+
2895
+ sage: CL.matrix() # long time # random (see :issue:`19229`)
2896
+ [1 2 3 3 5 5]
2897
+ [2 1 5 5 3 3]
2898
+ [3 5 1 3 2 5]
2899
+ [3 5 3 1 5 2]
2900
+ [5 3 2 5 1 3]
2901
+ [5 3 5 2 3 1]
2902
+
2903
+ To see the array of binary quadratic forms::
2904
+
2905
+ sage: CL.qf_matrix() # long time # random (see :issue:`19229`)
2906
+ [[[1], [2, 0, 13], [3, -2, 9], [3, -2, 9], [5, -4, 6], [5, -4, 6]],
2907
+ [[2, 0, 13], [1], [5, -4, 6], [5, -4, 6], [3, -2, 9], [3, -2, 9]],
2908
+ [[3, -2, 9], [5, -4, 6], [1], [3, -2, 9], [2, 0, 13], [5, -4, 6]],
2909
+ [[3, -2, 9], [5, -4, 6], [3, -2, 9], [1], [5, -4, 6], [2, 0, 13]],
2910
+ [[5, -4, 6], [3, -2, 9], [2, 0, 13], [5, -4, 6], [1], [3, -2, 9]],
2911
+ [[5, -4, 6], [3, -2, 9], [5, -4, 6], [2, 0, 13], [3, -2, 9], [1]]]
2912
+
2913
+ As in the non-CM case, the isogeny class may be visualized by
2914
+ obtaining its graph and plotting it. Since there are more
2915
+ edges than in the non-CM case, it may be preferable to omit
2916
+ the edge_labels::
2917
+
2918
+ sage: G = C.graph() # needs sage.graphs
2919
+ sage: G.show(edge_labels=False) # long time # needs sage.graphs sage.plot
2920
+
2921
+ It is possible to display a 3-dimensional plot, with colours
2922
+ to represent the different edge labels, in a form which can be
2923
+ rotated!::
2924
+
2925
+ sage: G.show3d(color_by_label=True) # long time # needs sage.graphs sage.plot
2926
+
2927
+ Over larger number fields several options make computations
2928
+ tractable. Here we use algorithm 'heuristic' which avoids a
2929
+ rigorous computation of the reducible primes, only testing
2930
+ those less than 1000, and setting ``minimal_models`` to
2931
+ ``False`` avoid having to compute the class group of `K`. To
2932
+ obtain minimal models set proof.number_field(False); the class
2933
+ group computation takes an additional 10s::
2934
+
2935
+ sage: K.<z> = CyclotomicField(53)
2936
+ sage: E = EllipticCurve(K,[0,6,0,2,0])
2937
+ sage: C = E.isogeny_class(algorithm='heuristic', minimal_models=False); C # long time (10s)
2938
+ Isogeny class of Elliptic Curve defined by y^2 = x^3 + 6*x^2 + 2*x
2939
+ over Cyclotomic Field of order 53 and degree 52
2940
+ sage: C.curves # long time
2941
+ [Elliptic Curve defined by y^2 = x^3 + 6*x^2 + (-8)*x + (-48)
2942
+ over Cyclotomic Field of order 53 and degree 52,
2943
+ Elliptic Curve defined by y^2 = x^3 + 6*x^2 + 2*x
2944
+ over Cyclotomic Field of order 53 and degree 52]
2945
+
2946
+ TESTS:
2947
+
2948
+ An example which failed until fixed at :issue:`19229`::
2949
+
2950
+ sage: K.<a> = NumberField(x^2 - x + 1)
2951
+ sage: E = EllipticCurve([a+1, 1, 1, 0, 0])
2952
+ sage: C = E.isogeny_class(); len(C) # long time
2953
+ 4
2954
+
2955
+ Check that :issue:`36780` is fixed::
2956
+
2957
+ sage: L5.<r5> = NumberField(x^2-5)
2958
+ sage: F = EllipticCurve(L5,[0,-4325477943600 *r5-4195572876000])
2959
+ sage: F.isogeny_class().matrix()
2960
+ [ 1 25 75 3 5 15]
2961
+ [25 1 3 75 5 15]
2962
+ [75 3 1 25 15 5]
2963
+ [ 3 75 25 1 15 5]
2964
+ [ 5 5 15 15 1 3]
2965
+ [15 15 5 5 3 1]
2966
+ """
2967
+ try:
2968
+ return self._isoclass
2969
+ except AttributeError:
2970
+ from sage.schemes.elliptic_curves.isogeny_class import IsogenyClass_EC_NumberField
2971
+ self._isoclass = IsogenyClass_EC_NumberField(self, reducible_primes=reducible_primes, algorithm=algorithm, minimal_models=minimal_models)
2972
+ return self._isoclass
2973
+
2974
+ def isogenies_prime_degree(self, l=None, algorithm='Billerey', minimal_models=True):
2975
+ r"""
2976
+ Return a list of `\ell`-isogenies from ``self``, where `\ell` is a
2977
+ prime.
2978
+
2979
+ INPUT:
2980
+
2981
+ - ``l`` -- either ``None`` or a prime or a list of primes
2982
+
2983
+ - ``algorithm`` -- string (default: ``'Billerey'``); the algorithm
2984
+ to use to compute the reducible primes when ``l`` is ``None``.
2985
+ Ignored for CM curves or if ``l`` is provided. Values are
2986
+ 'Billerey' (default), 'Larson', and 'heuristic'.
2987
+
2988
+ - ``minimal_models`` -- boolean (default: ``True``); if ``True``,
2989
+ all curves computed will be minimal or semi-minimal models.
2990
+ Over fields of larger degree it can be expensive to compute
2991
+ these so set to ``False``.
2992
+
2993
+ OUTPUT: list; `\ell`-isogenies for the given `\ell` or if `\ell` is
2994
+ ``None``, all isogenies of prime degree (see below for the CM case)
2995
+
2996
+ .. NOTE::
2997
+
2998
+ Over `\QQ`, the codomains of the isogenies returned are
2999
+ standard minimal models. Over other number fields they are
3000
+ global minimal models if these exist, otherwise models
3001
+ which are minimal at all but one prime.
3002
+
3003
+ .. NOTE::
3004
+
3005
+ For curves with rational CM, isogenies of primes degree
3006
+ exist for infinitely many primes `\ell`, though there are
3007
+ only finitely many isogenous curves up to isomorphism. The
3008
+ list returned only includes one isogeny of prime degree for
3009
+ each codomain.
3010
+
3011
+ EXAMPLES::
3012
+
3013
+ sage: K.<i> = QuadraticField(-1)
3014
+ sage: E = EllipticCurve(K, [0,0,0,0,1])
3015
+ sage: isogs = E.isogenies_prime_degree()
3016
+ sage: [phi.degree() for phi in isogs]
3017
+ [2, 3]
3018
+
3019
+ sage: pol = PolynomialRing(QQ,'x')([1,-3,5,-5,5,-3,1])
3020
+ sage: L.<a> = NumberField(pol)
3021
+ sage: js = hilbert_class_polynomial(-23).roots(L, multiplicities=False); len(js)
3022
+ 3
3023
+ sage: E = EllipticCurve(j=js[0])
3024
+ sage: len(E.isogenies_prime_degree()) # long time
3025
+ 3
3026
+
3027
+ Set ``minimal_models`` to False to avoid computing minimal
3028
+ models of the isogenous curves, since that can be
3029
+ time-consuming since it requires computation of the class
3030
+ group::
3031
+
3032
+ sage: proof.number_field(False)
3033
+ sage: K.<z> = CyclotomicField(53)
3034
+ sage: E = EllipticCurve(K, [0,6,0,2,0])
3035
+ sage: E.isogenies_prime_degree(2, minimal_models=False)
3036
+ [Isogeny of degree 2
3037
+ from Elliptic Curve defined by y^2 = x^3 + 6*x^2 + 2*x
3038
+ over Cyclotomic Field of order 53 and degree 52
3039
+ to Elliptic Curve defined by y^2 = x^3 + 6*x^2 + (-8)*x + (-48)
3040
+ over Cyclotomic Field of order 53 and degree 52]
3041
+ sage: E.isogenies_prime_degree(2, minimal_models=True) # not tested (10s)
3042
+ [Isogeny of degree 2
3043
+ from Elliptic Curve defined by y^2 = x^3 + 6*x^2 + 2*x
3044
+ over Cyclotomic Field of order 53 and degree 52
3045
+ to Elliptic Curve defined by y^2 = x^3 + (-20)*x + (-16)
3046
+ over Cyclotomic Field of order 53 and degree 52]
3047
+
3048
+ TESTS::
3049
+
3050
+ sage: E.isogenies_prime_degree(4)
3051
+ Traceback (most recent call last):
3052
+ ...
3053
+ ValueError: 4 is not prime.
3054
+ """
3055
+ from .isogeny_small_degree import isogenies_prime_degree
3056
+
3057
+ if l is not None and not isinstance(l, list):
3058
+ try:
3059
+ l = ZZ(l)
3060
+ except TypeError:
3061
+ raise ValueError("%s is not a prime integer" % l)
3062
+ try:
3063
+ if l.is_prime(proof=False):
3064
+ return isogenies_prime_degree(self, l, minimal_models=minimal_models)
3065
+ else:
3066
+ raise ValueError("%s is not prime." % l)
3067
+ except AttributeError:
3068
+ raise ValueError("%s is not prime." % l)
3069
+
3070
+ if l is None:
3071
+ from .isogeny_class import possible_isogeny_degrees
3072
+ L = possible_isogeny_degrees(self)
3073
+ return self.isogenies_prime_degree(L, minimal_models=minimal_models)
3074
+
3075
+ isogs = sum([self.isogenies_prime_degree(p, minimal_models=minimal_models) for p in l],
3076
+ [])
3077
+
3078
+ if self.has_rational_cm():
3079
+ # eliminate any endomorphisms and repeated codomains
3080
+ isogs = [phi for phi in isogs if not self.is_isomorphic(phi.codomain())]
3081
+ codoms = [phi.codomain() for phi in isogs]
3082
+ isogs = [phi for i, phi in enumerate(isogs)
3083
+ if not any(E.is_isomorphic(codoms[i])
3084
+ for E in codoms[:i])]
3085
+ return isogs
3086
+
3087
+ def is_isogenous(self, other, proof=True, maxnorm=100):
3088
+ """
3089
+ Return whether or not ``self`` is isogenous to ``other``.
3090
+
3091
+ INPUT:
3092
+
3093
+ - ``other`` -- another elliptic curve
3094
+
3095
+ - ``proof`` -- boolean (default: ``True``); if ``False``, the function
3096
+ will return ``True`` whenever the two curves have the same
3097
+ conductor and are isogenous modulo `p` for all primes `p` of
3098
+ norm up to ``maxnorm``. If ``True``, the function returns
3099
+ False when the previous condition does not hold, and if it
3100
+ does hold we compute the complete isogeny class to see if
3101
+ the curves are indeed isogenous.
3102
+
3103
+ - ``maxnorm`` -- integer (default: 100); the maximum norm of
3104
+ primes `p` for which isogeny modulo `p` will be checked
3105
+
3106
+ OUTPUT:
3107
+
3108
+ boolean; ``True`` if there is an isogeny from curve ``self`` to
3109
+ curve ``other``.
3110
+
3111
+ EXAMPLES::
3112
+
3113
+ sage: x = polygen(QQ, 'x')
3114
+ sage: F = NumberField(x^2 - 2, 's'); F
3115
+ Number Field in s with defining polynomial x^2 - 2
3116
+ sage: E1 = EllipticCurve(F, [7,8])
3117
+ sage: E2 = EllipticCurve(F, [0,5,0,1,0])
3118
+ sage: E3 = EllipticCurve(F, [0,-10,0,21,0])
3119
+ sage: E1.is_isogenous(E2)
3120
+ False
3121
+ sage: E1.is_isogenous(E1)
3122
+ True
3123
+ sage: E2.is_isogenous(E2)
3124
+ True
3125
+ sage: E2.is_isogenous(E1)
3126
+ False
3127
+ sage: E2.is_isogenous(E3)
3128
+ True
3129
+
3130
+ ::
3131
+
3132
+ sage: x = polygen(QQ, 'x')
3133
+ sage: F = NumberField(x^2 - 2, 's'); F
3134
+ Number Field in s with defining polynomial x^2 - 2
3135
+ sage: E = EllipticCurve('14a1')
3136
+ sage: EE = EllipticCurve('14a2')
3137
+ sage: E1 = E.change_ring(F)
3138
+ sage: E2 = EE.change_ring(F)
3139
+ sage: E1.is_isogenous(E2)
3140
+ True
3141
+
3142
+ ::
3143
+
3144
+ sage: x = polygen(QQ, 'x')
3145
+ sage: F = NumberField(x^2 - 2, 's'); F
3146
+ Number Field in s with defining polynomial x^2 - 2
3147
+ sage: k.<a> = NumberField(x^3 + 7)
3148
+ sage: E = EllipticCurve(F, [7,8])
3149
+ sage: EE = EllipticCurve(k, [2, 2])
3150
+ sage: E.is_isogenous(EE)
3151
+ Traceback (most recent call last):
3152
+ ...
3153
+ ValueError: Second argument must be defined over the same number field.
3154
+
3155
+ Some examples from Cremona's 1981 tables::
3156
+
3157
+ sage: K.<i> = QuadraticField(-1)
3158
+ sage: E1 = EllipticCurve([i + 1, 0, 1, -240*i - 400, -2869*i - 2627])
3159
+ sage: E1.conductor()
3160
+ Fractional ideal (4*i + 7)
3161
+ sage: E2 = EllipticCurve([1+i,0,1,0,0])
3162
+ sage: E2.conductor()
3163
+ Fractional ideal (4*i + 7)
3164
+ sage: E1.is_isogenous(E2) # long time
3165
+ True
3166
+ sage: E1.is_isogenous(E2, proof=False) # faster (~170ms)
3167
+ True
3168
+
3169
+ In this case E1 and E2 are in fact 9-isogenous, as may be
3170
+ deduced from the following::
3171
+
3172
+ sage: E3 = EllipticCurve([i + 1, 0, 1, -5*i - 5, -2*i - 5])
3173
+ sage: E3.is_isogenous(E1)
3174
+ True
3175
+ sage: E3.is_isogenous(E2)
3176
+ True
3177
+ sage: E1.isogeny_degree(E2) # long time
3178
+ 9
3179
+
3180
+ TESTS:
3181
+
3182
+ Check that :issue:`15890` is fixed::
3183
+
3184
+ sage: K.<s> = QuadraticField(229)
3185
+ sage: c4 = 2173 - 235*(1 - s)/2
3186
+ sage: c6 = -124369 + 15988*(1 - s)/2
3187
+ sage: c4c = 2173 - 235*(1 + s)/2
3188
+ sage: c6c = -124369 + 15988*(1 + s)/2
3189
+ sage: E = EllipticCurve_from_c4c6(c4, c6)
3190
+ sage: Ec = EllipticCurve_from_c4c6(c4c, c6c)
3191
+ sage: E.is_isogenous(Ec) # needs sage.symbolic
3192
+ True
3193
+
3194
+ Check that :issue:`17295` is fixed::
3195
+
3196
+ sage: k.<s> = QuadraticField(2)
3197
+ sage: K.<b> = k.extension(x^2 - 3)
3198
+ sage: E = EllipticCurve(k, [-3*s*(4 + 5*s), 2*s*(2 + 14*s + 11*s^2)])
3199
+ sage: Ec = EllipticCurve(k, [3*s*(4 - 5*s), -2*s*(2 - 14*s + 11*s^2)])
3200
+ sage: EK = E.base_extend(K)
3201
+ sage: EcK = Ec.base_extend(K)
3202
+ sage: EK.is_isogenous(EcK) # long time (about 3.5 s) # needs sage.symbolic
3203
+ True
3204
+ """
3205
+ if not isinstance(other, EllipticCurve_generic):
3206
+ raise ValueError("Second argument is not an Elliptic Curve.")
3207
+ if self.is_isomorphic(other):
3208
+ return True
3209
+ K = self.base_field()
3210
+ if K != other.base_field():
3211
+ raise ValueError("Second argument must be defined over the same number field.")
3212
+
3213
+ E1 = self.integral_model()
3214
+ E2 = other.integral_model()
3215
+ N = E1.conductor()
3216
+ if N != E2.conductor():
3217
+ return False
3218
+
3219
+ PI = K.primes_of_degree_one_iter()
3220
+ while True:
3221
+ P = next(PI)
3222
+ if P.absolute_norm() > maxnorm:
3223
+ break
3224
+ if not P.divides(N):
3225
+ if E1.reduction(P).cardinality() != E2.reduction(P).cardinality():
3226
+ return False
3227
+
3228
+ if not proof:
3229
+ return True
3230
+
3231
+ # We first try the easiest cases: primes for which X_0(l) has genus 0:
3232
+
3233
+ for l in [2, 3, 5, 7, 13]:
3234
+ if any(E2.is_isomorphic(f.codomain())
3235
+ for f in E1.isogenies_prime_degree(l)):
3236
+ return True
3237
+
3238
+ # Next we try the primes for which X_0^+(l) has genus 0 for
3239
+ # which isogeny-finding is faster than in general:
3240
+
3241
+ from .isogeny_small_degree import hyperelliptic_primes
3242
+ for l in hyperelliptic_primes:
3243
+ if any(E2.is_isomorphic(f.codomain())
3244
+ for f in E1.isogenies_prime_degree(l)):
3245
+ return True
3246
+
3247
+ # Next we try looking modulo some more primes:
3248
+
3249
+ while True:
3250
+ if P.absolute_norm() > 10 * maxnorm:
3251
+ break
3252
+ if not P.divides(N):
3253
+ OP = K.residue_field(P)
3254
+ if E1.change_ring(OP).cardinality() != E2.change_ring(OP).cardinality():
3255
+ return False
3256
+ P = next(PI)
3257
+
3258
+ # Finally we compute the full isogeny class of E1 and check if
3259
+ # E2 is isomorphic to any curve in the class:
3260
+
3261
+ return any(E2.is_isomorphic(E3) for E3 in E1.isogeny_class().curves)
3262
+
3263
+ raise NotImplementedError("Curves appear to be isogenous (same conductor, isogenous modulo all primes of norm up to %s), but no isogeny has been constructed." % (10*maxnorm))
3264
+
3265
+ def isogeny_degree(self, other):
3266
+ """
3267
+ Return the minimal degree of an isogeny between ``self`` and
3268
+ ``other``, or 0 if no isogeny exists.
3269
+
3270
+ INPUT:
3271
+
3272
+ - ``other`` -- another elliptic curve
3273
+
3274
+ OUTPUT: integer; the degree of an isogeny from ``self`` to ``other``, or 0
3275
+
3276
+ EXAMPLES::
3277
+
3278
+ sage: x = QQ['x'].0
3279
+ sage: F = NumberField(x^2 - 2, 's'); F
3280
+ Number Field in s with defining polynomial x^2 - 2
3281
+ sage: E = EllipticCurve('14a1')
3282
+ sage: EE = EllipticCurve('14a2')
3283
+ sage: E1 = E.change_ring(F)
3284
+ sage: E2 = EE.change_ring(F)
3285
+ sage: E1.isogeny_degree(E2) # long time
3286
+ 2
3287
+ sage: E2.isogeny_degree(E2)
3288
+ 1
3289
+ sage: E5 = EllipticCurve('14a5').change_ring(F)
3290
+ sage: E1.isogeny_degree(E5) # long time
3291
+ 6
3292
+
3293
+ sage: E = EllipticCurve('11a1')
3294
+ sage: [E2.label() for E2 in cremona_curves([11..20]) if E.isogeny_degree(E2)]
3295
+ ['11a1', '11a2', '11a3']
3296
+
3297
+ sage: K.<i> = QuadraticField(-1)
3298
+ sage: E = EllipticCurve([1+i, -i, i, 1, 0])
3299
+ sage: C = E.isogeny_class() # long time
3300
+ sage: [E.isogeny_degree(F) for F in C] # long time
3301
+ [2, 6, 18, 9, 3, 1]
3302
+ """
3303
+ # First deal with some easy cases:
3304
+ if self.conductor() != other.conductor():
3305
+ return ZZ.zero()
3306
+
3307
+ if self.is_isomorphic(other):
3308
+ return ZZ.one()
3309
+
3310
+ C = self.isogeny_class()
3311
+ i = C.index(self) # may not be 0 since curves are sorted
3312
+ try:
3313
+ return C.matrix()[i][C.index(other)]
3314
+ except ValueError:
3315
+ return ZZ.zero()
3316
+
3317
+ def reducible_primes(self, algorithm='Billerey', max_l=None,
3318
+ num_l=None, verbose=False):
3319
+ r"""
3320
+ Return a finite set of primes `\ell` for which `E` has a
3321
+ K-rational `\ell`-isogeny.
3322
+
3323
+ For curves without CM the list returned is exactly the finite
3324
+ set of primes `\ell` for which the mod-`\ell` Galois
3325
+ representation is reducible. For curves with CM this set is
3326
+ infinite; we return a (not necessarily minimal) finite list
3327
+ of primes `\ell` such that every curve isogenous to this curve
3328
+ can be obtained by a finite sequence of isogenies of degree one
3329
+ of the primes in the list.
3330
+
3331
+ INPUT:
3332
+
3333
+ - ``algorithm`` -- string; only relevant for non-CM curves
3334
+ Either 'Billerey", to use the methods of [Bil2011]_,
3335
+ 'Larson' to use Larson's implementation using Galois
3336
+ representations, or 'heuristic' (see below).
3337
+
3338
+ - ``max_l`` -- integer or ``None``; only relevant for non-CM
3339
+ curves and algorithms 'Billerey' and 'heuristic. Controls
3340
+ the maximum prime used in either algorithm. If ``None``,
3341
+ use the default for that algorithm.
3342
+
3343
+ - ``num_l`` -- integer or ``None``; only relevant for non-CM
3344
+ curves and algorithm 'Billerey'. Controls the maximum
3345
+ number of primes used in the algorithm. If ``None``, use
3346
+ the default for that algorithm.
3347
+
3348
+ .. NOTE::
3349
+
3350
+ The 'heuristic' algorithm only checks primes up to the
3351
+ bound ``max_l``. This is faster but not guaranteed to be
3352
+ complete. Both the Billerey and Larson algorithms are
3353
+ rigorous.
3354
+
3355
+ EXAMPLES::
3356
+
3357
+ sage: x = polygen(ZZ, 'x')
3358
+ sage: K = NumberField(x**2 - 29, 'a'); a = K.gen()
3359
+ sage: E = EllipticCurve([1, 0, ((5 + a)/2)**2, 0, 0])
3360
+ sage: rho = E.galois_representation()
3361
+ sage: rho.reducible_primes() # long time
3362
+ [3, 5]
3363
+ sage: E.reducible_primes() # long time
3364
+ [3, 5]
3365
+ sage: K = NumberField(x**2 + 1, 'a')
3366
+ sage: E = EllipticCurve_from_j(K(1728)) # CM over K
3367
+ sage: rho = E.galois_representation()
3368
+ sage: rho.reducible_primes() # CM curves always return [0]
3369
+ [0]
3370
+ sage: E.reducible_primes()
3371
+ [2, 5]
3372
+ sage: E = EllipticCurve_from_j(K(0)) # CM but NOT over K
3373
+ sage: rho = E.galois_representation()
3374
+ sage: rho.reducible_primes() # long time
3375
+ [2, 3]
3376
+ sage: E.reducible_primes()
3377
+ [2, 3]
3378
+ sage: E = EllipticCurve_from_j(K(2268945/128)).global_minimal_model() # c.f. [Sut2012]
3379
+ sage: rho = E.galois_representation()
3380
+ sage: rho.isogeny_bound() # ..but there is no 7-isogeny, long time
3381
+ [7]
3382
+ sage: rho.reducible_primes() # long time
3383
+ []
3384
+ sage: E.reducible_primes() # long time
3385
+ []
3386
+ """
3387
+ from sage.schemes.elliptic_curves.isogeny_class import possible_isogeny_degrees
3388
+ return possible_isogeny_degrees(self, max_l=max_l, num_l=num_l, exact=True, verbose=verbose)
3389
+
3390
+ def lll_reduce(self, points, height_matrix=None, precision=None):
3391
+ r"""
3392
+ Return an LLL-reduced basis from a given basis, with transform
3393
+ matrix.
3394
+
3395
+ INPUT:
3396
+
3397
+ - ``points`` -- list of points on this elliptic
3398
+ curve, which should be independent
3399
+
3400
+ - ``height_matrix`` -- the height-pairing matrix of
3401
+ the points, or ``None``. If ``None``, it will be computed.
3402
+
3403
+ - ``precision`` -- number of bits of precision of intermediate
3404
+ computations (default: ``None``, for default RealField
3405
+ precision; ignored if ``height_matrix`` is supplied)
3406
+
3407
+ OUTPUT: a tuple (newpoints, U) where U is a unimodular integer
3408
+ matrix, new_points is the transform of points by U, such that
3409
+ new_points has LLL-reduced height pairing matrix
3410
+
3411
+ .. NOTE::
3412
+
3413
+ If the input points are not independent, the output
3414
+ depends on the undocumented behaviour of PARI's
3415
+ :pari:`qflllgram` function when applied to a Gram matrix which
3416
+ is not positive definite.
3417
+
3418
+ EXAMPLES:
3419
+
3420
+ Some examples over `\QQ`::
3421
+
3422
+ sage: # needs eclib
3423
+ sage: E = EllipticCurve([0, 1, 1, -2, 42])
3424
+ sage: Pi = E.gens(); Pi
3425
+ [(-4 : 1 : 1), (-3 : 5 : 1), (-11/4 : 43/8 : 1), (-2 : 6 : 1)]
3426
+ sage: Qi, U = E.lll_reduce(Pi)
3427
+ sage: all(sum(U[i,j]*Pi[i] for i in range(4)) == Qi[j] for j in range(4))
3428
+ True
3429
+ sage: sorted(Qi)
3430
+ [(-4 : 1 : 1), (-3 : 5 : 1), (-2 : 6 : 1), (0 : 6 : 1)]
3431
+ sage: U.det()
3432
+ 1
3433
+ sage: E.regulator_of_points(Pi)
3434
+ 4.59088036960573
3435
+ sage: E.regulator_of_points(Qi)
3436
+ 4.59088036960574
3437
+
3438
+ ::
3439
+
3440
+ sage: E = EllipticCurve([1,0,1,-120039822036992245303534619191166796374,504224992484910670010801799168082726759443756222911415116])
3441
+ sage: xi = [2005024558054813068,
3442
+ ....: -4690836759490453344,
3443
+ ....: 4700156326649806635,
3444
+ ....: 6785546256295273860,
3445
+ ....: 6823803569166584943,
3446
+ ....: 7788809602110240789,
3447
+ ....: 27385442304350994620556,
3448
+ ....: 54284682060285253719/4,
3449
+ ....: -94200235260395075139/25,
3450
+ ....: -3463661055331841724647/576,
3451
+ ....: -6684065934033506970637/676,
3452
+ ....: -956077386192640344198/2209,
3453
+ ....: -27067471797013364392578/2809,
3454
+ ....: -25538866857137199063309/3721,
3455
+ ....: -1026325011760259051894331/108241,
3456
+ ....: 9351361230729481250627334/1366561,
3457
+ ....: 10100878635879432897339615/1423249,
3458
+ ....: 11499655868211022625340735/17522596,
3459
+ ....: 110352253665081002517811734/21353641,
3460
+ ....: 414280096426033094143668538257/285204544,
3461
+ ....: 36101712290699828042930087436/4098432361,
3462
+ ....: 45442463408503524215460183165/5424617104,
3463
+ ....: 983886013344700707678587482584/141566320009,
3464
+ ....: 1124614335716851053281176544216033/152487126016]
3465
+ sage: points = [E.lift_x(x) for x in xi]
3466
+ sage: newpoints, U = E.lll_reduce(points) # long time (35s on sage.math, 2011)
3467
+ sage: [P[0] for P in newpoints] # long time
3468
+ [6823803569166584943, 5949539878899294213, 2005024558054813068, 5864879778877955778, 23955263915878682727/4, 5922188321411938518, 5286988283823825378, 11465667352242779838, -11451575907286171572, 3502708072571012181, 1500143935183238709184/225, 27180522378120223419/4, -5811874164190604461581/625, 26807786527159569093, 7041412654828066743, 475656155255883588, 265757454726766017891/49, 7272142121019825303, 50628679173833693415/4, 6951643522366348968, 6842515151518070703, 111593750389650846885/16, 2607467890531740394315/9, -1829928525835506297]
3469
+
3470
+ An example to show the explicit use of the height pairing matrix::
3471
+
3472
+ sage: # needs eclib
3473
+ sage: E = EllipticCurve([0, 1, 1, -2, 42])
3474
+ sage: Pi = E.gens()
3475
+ sage: H = E.height_pairing_matrix(Pi,3)
3476
+ sage: E.lll_reduce(Pi,height_matrix=H)
3477
+ (
3478
+ [1 0 0 1]
3479
+ [0 1 0 1]
3480
+ [0 0 0 1]
3481
+ [(-4 : 1 : 1), (-3 : 5 : 1), (-2 : 6 : 1), (1 : -7 : 1)], [0 0 1 1]
3482
+ )
3483
+
3484
+ Some examples over number fields (see :issue:`9411`)::
3485
+
3486
+ sage: K.<a> = QuadraticField(-23, 'a')
3487
+ sage: E = EllipticCurve(K, [0,0,1,-1,0])
3488
+ sage: P = E(-2, -(a+1)/2)
3489
+ sage: Q = E(0,-1)
3490
+ sage: E.lll_reduce([P,Q])
3491
+ (
3492
+ [ 0 -1]
3493
+ [(0 : -1 : 1), (-2 : 1/2*a - 1/2 : 1)], [ 1 0]
3494
+ )
3495
+
3496
+ ::
3497
+
3498
+ sage: K.<a> = QuadraticField(-5)
3499
+ sage: E = EllipticCurve(K, [0,a])
3500
+ sage: points = [E.point([-211/841*a - 6044/841,-209584/24389*a + 53634/24389]),
3501
+ ....: E.point([-17/18*a - 1/9, -109/108*a - 277/108])]
3502
+ sage: E.lll_reduce(points)
3503
+ (
3504
+ [(-a + 4 : -3*a + 7 : 1), (-17/18*a - 1/9 : -109/108*a - 277/108 : 1)],
3505
+ <BLANKLINE>
3506
+ [1 0]
3507
+ [1 1]
3508
+ )
3509
+ """
3510
+ r = len(points)
3511
+ if height_matrix is None:
3512
+ height_matrix = self.height_pairing_matrix(points, precision)
3513
+ U = height_matrix.__pari__().lllgram().sage()
3514
+ new_points = [sum([U[j, i]*points[j] for j in range(r)])
3515
+ for i in range(r)]
3516
+ return new_points, U
3517
+
3518
+ def galois_representation(self):
3519
+ r"""
3520
+ The compatible family of the Galois representation
3521
+ attached to this elliptic curve.
3522
+
3523
+ Given an elliptic curve `E` over a number field `K`
3524
+ and a rational prime number `p`, the `p^n`-torsion
3525
+ `E[p^n]` points of `E` is a representation of the
3526
+ absolute Galois group of `K`. As `n` varies
3527
+ we obtain the Tate module `T_p E` which is a
3528
+ a representation of `G_K` on a free `\ZZ_p`-module
3529
+ of rank `2`. As `p` varies the representations
3530
+ are compatible.
3531
+
3532
+ EXAMPLES::
3533
+
3534
+ sage: x = polygen(ZZ, 'x')
3535
+ sage: K = NumberField(x**2 + 1, 'a')
3536
+ sage: E = EllipticCurve('11a1').change_ring(K)
3537
+ sage: rho = E.galois_representation()
3538
+ sage: rho
3539
+ Compatible family of Galois representations associated to the
3540
+ Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20)
3541
+ over Number Field in a with defining polynomial x^2 + 1
3542
+ sage: rho.is_surjective(3)
3543
+ True
3544
+ sage: rho.is_surjective(5) # long time (4s on sage.math, 2014)
3545
+ False
3546
+ sage: rho.non_surjective()
3547
+ [5]
3548
+ """
3549
+ from .gal_reps_number_field import GaloisRepresentation
3550
+ return GaloisRepresentation(self)
3551
+
3552
+ @cached_method
3553
+ def cm_discriminant(self):
3554
+ """
3555
+ Return the CM discriminant of the `j`-invariant of this curve, or 0.
3556
+
3557
+ OUTPUT:
3558
+
3559
+ An integer `D` which is either `0` if this curve `E` does not
3560
+ have Complex Multiplication) (CM), or an imaginary quadratic
3561
+ discriminant if `j(E)` is the `j`-invariant of the order with
3562
+ discriminant `D`.
3563
+
3564
+ .. NOTE::
3565
+
3566
+ If `E` has CM but the discriminant `D` is not a square in
3567
+ the base field `K` then the extra endomorphisms will not be
3568
+ defined over `K`. See also :meth:`has_rational_cm`.
3569
+
3570
+ EXAMPLES::
3571
+
3572
+ sage: EllipticCurve(j=0).cm_discriminant()
3573
+ -3
3574
+ sage: EllipticCurve(j=1).cm_discriminant()
3575
+ Traceback (most recent call last):
3576
+ ...
3577
+ ValueError: Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455
3578
+ over Rational Field does not have CM
3579
+ sage: EllipticCurve(j=1728).cm_discriminant()
3580
+ -4
3581
+ sage: EllipticCurve(j=8000).cm_discriminant() # needs database_cremona_mini_ellcurve
3582
+ -8
3583
+ sage: K.<a> = QuadraticField(5)
3584
+ sage: EllipticCurve(j=282880*a + 632000).cm_discriminant()
3585
+ -20
3586
+ sage: x = polygen(ZZ, 'x')
3587
+ sage: K.<a> = NumberField(x^3 - 2)
3588
+ sage: EllipticCurve(j=31710790944000*a^2 + 39953093016000*a + 50337742902000).cm_discriminant()
3589
+ -108
3590
+ """
3591
+ from sage.schemes.elliptic_curves.cm import is_cm_j_invariant
3592
+ flag, df = is_cm_j_invariant(self.j_invariant())
3593
+ if flag:
3594
+ d, f = df
3595
+ return d*f**2
3596
+ else: # no CM
3597
+ return ZZ.zero()
3598
+
3599
+ @cached_method
3600
+ def has_cm(self) -> bool:
3601
+ """
3602
+ Return whether or not this curve has a CM `j`-invariant.
3603
+
3604
+ OUTPUT:
3605
+
3606
+ ``True`` if this curve has CM over the algebraic closure
3607
+ of the base field, otherwise ``False``. See also
3608
+ :meth:`cm_discriminant` and :meth:`has_rational_cm`.
3609
+
3610
+ .. NOTE::
3611
+
3612
+ Even if `E` has CM in this sense (that its `j`-invariant is
3613
+ a CM `j`-invariant), if the associated negative
3614
+ discriminant `D` is not a square in the base field `K`, the
3615
+ extra endomorphisms will not be defined over `K`. See also
3616
+ the method :meth:`has_rational_cm` which tests whether `E`
3617
+ has extra endomorphisms defined over `K` or a given
3618
+ extension of `K`.
3619
+
3620
+ EXAMPLES::
3621
+
3622
+ sage: EllipticCurve(j=0).has_cm()
3623
+ True
3624
+ sage: EllipticCurve(j=1).has_cm()
3625
+ False
3626
+ sage: EllipticCurve(j=1728).has_cm()
3627
+ True
3628
+ sage: EllipticCurve(j=8000).has_cm()
3629
+ True
3630
+ sage: K.<a> = QuadraticField(5)
3631
+ sage: EllipticCurve(j=282880*a + 632000).has_cm()
3632
+ True
3633
+ sage: x = polygen(ZZ, 'x')
3634
+ sage: K.<a> = NumberField(x^3 - 2)
3635
+ sage: EllipticCurve(j=31710790944000*a^2 + 39953093016000*a + 50337742902000).has_cm()
3636
+ True
3637
+ """
3638
+ return not self.cm_discriminant().is_zero()
3639
+
3640
+ @cached_method
3641
+ def has_rational_cm(self, field=None) -> bool:
3642
+ r"""
3643
+ Return whether or not this curve has CM defined over its
3644
+ base field or a given extension.
3645
+
3646
+ INPUT:
3647
+
3648
+ - ``field`` -- a field, which should be an extension of the
3649
+ base field of the curve. If ``field`` is ``None`` (the
3650
+ default), it is taken to be the base field of the curve.
3651
+
3652
+ OUTPUT:
3653
+
3654
+ ``True`` if the ring of endomorphisms of this curve over
3655
+ the given field is larger than `\ZZ`; otherwise ``False``.
3656
+ See also :meth:`cm_discriminant` and :meth:`has_cm`.
3657
+
3658
+ .. NOTE::
3659
+
3660
+ If `E` has CM but the discriminant `D` is not a square in
3661
+ the given field `K` then the extra endomorphisms will not
3662
+ be defined over `K`, and this function will return
3663
+ ``False``. See also :meth:`has_cm`. To obtain the CM
3664
+ discriminant, use :meth:`cm_discriminant`.
3665
+
3666
+ EXAMPLES::
3667
+
3668
+ sage: E = EllipticCurve(j=0)
3669
+ sage: E.has_cm()
3670
+ True
3671
+ sage: E.has_rational_cm()
3672
+ False
3673
+ sage: D = E.cm_discriminant(); D
3674
+ -3
3675
+ sage: E.has_rational_cm(QuadraticField(D))
3676
+ True
3677
+
3678
+ sage: E = EllipticCurve(j=1728)
3679
+ sage: E.has_cm()
3680
+ True
3681
+ sage: E.has_rational_cm()
3682
+ False
3683
+ sage: D = E.cm_discriminant(); D
3684
+ -4
3685
+ sage: E.has_rational_cm(QuadraticField(D))
3686
+ True
3687
+
3688
+ Higher degree examples::
3689
+
3690
+ sage: K.<a> = QuadraticField(5)
3691
+ sage: E = EllipticCurve(j=282880*a + 632000)
3692
+ sage: E.has_cm()
3693
+ True
3694
+ sage: E.has_rational_cm()
3695
+ False
3696
+ sage: E.cm_discriminant()
3697
+ -20
3698
+ sage: x = polygen(QQ)
3699
+ sage: E.has_rational_cm(K.extension(x^2 + 5, 'b'))
3700
+ True
3701
+
3702
+ An error is raised if a field is given which is not an extension of the base field::
3703
+
3704
+ sage: E.has_rational_cm(QuadraticField(-20))
3705
+ Traceback (most recent call last):
3706
+ ...
3707
+ ValueError: Error in has_rational_cm: Number Field in a
3708
+ with defining polynomial x^2 + 20 with a = 4.472135954999579?*I
3709
+ is not an extension field of Number Field in a
3710
+ with defining polynomial x^2 - 5 with a = 2.236067977499790?
3711
+
3712
+ sage: x = polygen(ZZ, 'x')
3713
+ sage: K.<a> = NumberField(x^3 - 2)
3714
+ sage: E = EllipticCurve(j=31710790944000*a^2 + 39953093016000*a + 50337742902000)
3715
+ sage: E.has_cm()
3716
+ True
3717
+ sage: E.has_rational_cm()
3718
+ False
3719
+ sage: D = E.cm_discriminant(); D
3720
+ -108
3721
+ sage: E.has_rational_cm(K.extension(x^2 + 108,'b'))
3722
+ True
3723
+ """
3724
+ D = self.cm_discriminant()
3725
+ if D.is_zero():
3726
+ return False
3727
+ if field is None:
3728
+ return self.base_field()(D).is_square()
3729
+ if self.base_field().embeddings(field):
3730
+ D = field(D)
3731
+ return D.is_square()
3732
+ raise ValueError("Error in has_rational_cm: %s is not an extension field of %s"
3733
+ % (field,self.base_field()))
3734
+
3735
+ @cached_method
3736
+ def is_Q_curve(self, maxp=100, certificate=False, verbose=False):
3737
+ r"""
3738
+ Return ``True`` if this is a `\QQ`-curve, with optional certificate.
3739
+
3740
+ INPUT:
3741
+
3742
+ - ``maxp`` -- integer (default: 100); bound on primes used for
3743
+ checking necessary local conditions. The result will not
3744
+ depend on this, but using a larger value may return
3745
+ ``False`` faster.
3746
+
3747
+ - ``certificate`` -- boolean (default: ``False``); if ``True`` then
3748
+ a second value is returned giving a certificate for the
3749
+ `\QQ`-curve property
3750
+
3751
+ OUTPUT:
3752
+
3753
+ If ``certificate`` is ``False``: either ``True`` (if `E` is a
3754
+ `\QQ`-curve), or ``False``.
3755
+
3756
+ If ``certificate`` is ``True``: a tuple consisting of a boolean
3757
+ flag as before and a certificate, defined as follows:
3758
+
3759
+ - when the flag is ``True``, so `E` is a `\QQ`-curve:
3760
+
3761
+ - either {'CM':`D`} where `D` is a negative discriminant, when
3762
+ `E` has potential CM with discriminant `D`;
3763
+
3764
+ - otherwise {'CM': `0`, 'core_poly': `f`, 'rho': `\rho`,
3765
+ 'r': `r`, 'N': `N`}, when `E` is a non-CM `\QQ`-curve,
3766
+ where the core polynomial `f` is an irreducible monic
3767
+ polynomial over `QQ` of degree `2^\rho`, all of whose
3768
+ roots are `j`-invariants of curves isogenous to `E`, the
3769
+ core level `N` is a square-free integer with `r` prime
3770
+ factors which is the LCM of the degrees of the isogenies
3771
+ between these conjugates. For example, if there exists
3772
+ a curve `E'` isogenous to `E` with `j(E')=j\in\QQ`, then
3773
+ the certificate is {'CM':0, 'r':0, 'rho':0, 'core_poly':
3774
+ x-j, 'N':1}.
3775
+
3776
+ - when the flag is ``False``, so `E` is not a `\QQ`-curve, the
3777
+ certificate is a prime `p` such that the reductions of `E`
3778
+ at the primes dividing `p` are inconsistent with the
3779
+ property of being a `\QQ`-curve. See the documentation for
3780
+ :meth:`sage.src.schemes.elliptic_curves.Qcurves.is_Q_curve`
3781
+ for details.
3782
+
3783
+ ALGORITHM:
3784
+
3785
+ See the documentation for
3786
+ :meth:`sage.src.schemes.elliptic_curves.Qcurves.is_Q_curve`, and
3787
+ [CrNa2020]_ for details.
3788
+
3789
+ EXAMPLES:
3790
+
3791
+ A non-CM curve over `\QQ` and a CM curve over `\QQ` are both
3792
+ trivially `\QQ`-curves::
3793
+
3794
+ sage: E = EllipticCurve([1,2,3,4,5])
3795
+ sage: flag, cert = E.is_Q_curve(certificate=True)
3796
+ sage: flag
3797
+ True
3798
+ sage: cert
3799
+ {'CM': 0, 'N': 1, 'core_poly': x, 'r': 0, 'rho': 0}
3800
+
3801
+ sage: E = EllipticCurve(j=8000)
3802
+ sage: flag, cert = E.is_Q_curve(certificate=True)
3803
+ sage: flag
3804
+ True
3805
+ sage: cert
3806
+ {'CM': -8}
3807
+
3808
+ A non-`\QQ`-curve over a quartic field. The local data at bad
3809
+ primes above `3` is inconsistent::
3810
+
3811
+ sage: R.<x> = PolynomialRing(QQ)
3812
+ sage: K.<a> = NumberField(R([3, 0, -5, 0, 1]))
3813
+ sage: E = EllipticCurve([K([-3,-4,1,1]), K([4,-1,-1,0]), K([-2,0,1,0]), K([-621,778,138,-178]), K([9509,2046,-24728,10380])])
3814
+ sage: E.is_Q_curve(certificate=True, verbose=True)
3815
+ Checking whether Elliptic Curve defined by y^2 + (a^3+a^2-4*a-3)*x*y + (a^2-2)*y = x^3 + (-a^2-a+4)*x^2 + (-178*a^3+138*a^2+778*a-621)*x + (10380*a^3-24728*a^2+2046*a+9509) over Number Field in a with defining polynomial x^4 - 5*x^2 + 3 is a Q-curve
3816
+ No: inconsistency at the 2 primes dividing 3
3817
+ - potentially multiplicative: [True, False]
3818
+ (False, 3)
3819
+
3820
+ A non-`\QQ`-curve over a quadratic field. The local data at bad
3821
+ primes is consistent, but the local test at good primes above `13`
3822
+ is not::
3823
+
3824
+ sage: K.<a> = NumberField(R([-10, 0, 1]))
3825
+ sage: E = EllipticCurve([K([0,1]), K([-1,-1]), K([0,0]), K([-236,40]), K([-1840,464])])
3826
+ sage: E.is_Q_curve(certificate=True, verbose=True)
3827
+ Checking whether Elliptic Curve defined by y^2 + a*x*y = x^3 + (-a-1)*x^2 + (40*a-236)*x + (464*a-1840) over Number Field in a with defining polynomial x^2 - 10 is a Q-curve
3828
+ Applying local tests at good primes above p<=100
3829
+ No: inconsistency at the 2 ordinary primes dividing 13
3830
+ - Frobenius discriminants mod squares: [-1, -3]
3831
+ No: local test at p=13 failed
3832
+ (False, 13)
3833
+
3834
+ A quadratic `\QQ`-curve with CM discriminant `-15`
3835
+ (so the `j`-invariant is not in `\QQ`)::
3836
+
3837
+ sage: R.<x> = PolynomialRing(QQ)
3838
+ sage: K.<a> = NumberField(R([-1, -1, 1]))
3839
+ sage: E = EllipticCurve([K([1,0]), K([-1,0]), K([0,1]), K([0,-2]), K([0,1])])
3840
+ sage: E.is_Q_curve(certificate=True, verbose=True)
3841
+ Checking whether Elliptic Curve defined by y^2 + x*y + a*y = x^3 + (-1)*x^2 + (-2*a)*x + a over Number Field in a with defining polynomial x^2 - x - 1 is a Q-curve
3842
+ Yes: E is CM (discriminant -15)
3843
+ (True, {'CM': -15})
3844
+
3845
+ An example over `\QQ(\sqrt{2},\sqrt{3})`. The `j`-invariant
3846
+ is in `\QQ(\sqrt{6})`, so computations will be done over that
3847
+ field, and in fact there is an isogenous curve with rational
3848
+ `j`, so we have a so-called rational `\QQ`-curve::
3849
+
3850
+ sage: K.<a> = NumberField(R([1, 0, -4, 0, 1]))
3851
+ sage: E = EllipticCurve([K([-2,-4,1,1]), K([0,1,0,0]), K([0,1,0,0]), K([-4780,9170,1265,-2463]), K([163923,-316598,-43876,84852])])
3852
+ sage: flag, cert = E.is_Q_curve(certificate=True) # long time
3853
+ sage: flag # long time
3854
+ True
3855
+ sage: cert # long time
3856
+ {'CM': 0, 'N': 1, 'core_degs': [1], 'core_poly': x - 85184/3, 'r': 0, 'rho': 0}
3857
+
3858
+ Over the same field, a so-called strict `\QQ`-curve which is
3859
+ not isogenous to one with rational `j`, but whose core field
3860
+ is quadratic. In fact the isogeny class over `K` consists of
3861
+ `6` curves, four with conjugate quartic `j`-invariants and `2`
3862
+ with quadratic conjugate `j`-invariants in `\QQ(\sqrt{3})`
3863
+ (but which are not base-changes from the quadratic subfield)::
3864
+
3865
+ sage: E = EllipticCurve([K([0,-3,0,1]), K([1,4,0,-1]), K([0,0,0,0]), K([-2,-16,0,4]), K([-19,-32,4,8])])
3866
+ sage: flag, cert = E.is_Q_curve(certificate=True) # long time
3867
+ sage: flag # long time
3868
+ True
3869
+ sage: cert # long time
3870
+ {'CM': 0,
3871
+ 'N': 2,
3872
+ 'core_degs': [1, 2],
3873
+ 'core_poly': x^2 - 840064*x + 1593413632,
3874
+ 'r': 1,
3875
+ 'rho': 1}
3876
+ """
3877
+ from sage.schemes.elliptic_curves.Qcurves import is_Q_curve as isQ
3878
+ return isQ(self, maxp, certificate, verbose)
3879
+
3880
+ def saturation(self, points, verbose=False,
3881
+ max_prime=0, one_prime=0, odd_primes_only=False,
3882
+ lower_ht_bound=None, reg=None, debug=False):
3883
+ r"""
3884
+ Given a list of rational points on `E` over `K`, compute the
3885
+ saturation in `E(K)` of the subgroup they generate.
3886
+
3887
+ INPUT:
3888
+
3889
+ - ``points (list)`` -- list of points on E. Points of finite
3890
+ order are ignored; the remaining points should be independent,
3891
+ or an error is raised.
3892
+
3893
+ - ``verbose`` -- boolean (default: ``False``); if ``True``, give
3894
+ verbose output
3895
+
3896
+ - ``max_prime`` -- integer (default: 0); saturation is performed
3897
+ for all primes up to ``max_prime``. If ``max_prime`` is 0,
3898
+ perform saturation at *all* primes, i.e., compute the true
3899
+ saturation.
3900
+
3901
+ - ``odd_primes_only`` -- boolean (default: ``False``); only do
3902
+ saturation at odd primes
3903
+
3904
+ - ``one_prime`` -- integer (default: 0); if nonzero, only do
3905
+ saturation at this prime
3906
+
3907
+ The following two inputs are optional, and may be provided to speed
3908
+ up the computation.
3909
+
3910
+ - ``lower_ht_bound`` -- real (default: ``None``); lower bound of
3911
+ the regulator `E(K)`, if known
3912
+
3913
+ - ``reg`` -- real (default: ``None``); regulator of the span of
3914
+ points, if known
3915
+
3916
+ - ``debug`` -- integer (default: 0); used for debugging and
3917
+ testing
3918
+
3919
+ OUTPUT:
3920
+
3921
+ - ``saturation`` -- list; points that form a basis for the
3922
+ saturation
3923
+
3924
+ - ``index`` -- integer; the index of the group generated by the
3925
+ input points in their saturation
3926
+
3927
+ - ``regulator`` -- real with default precision, or ``None``;
3928
+ regulator of saturated points
3929
+
3930
+ EXAMPLES::
3931
+
3932
+ sage: K.<i> = QuadraticField(-1)
3933
+ sage: E = EllipticCurve('389a1')
3934
+ sage: EK = E.change_ring(K)
3935
+ sage: P = EK(-1,1); Q = EK(0,-1)
3936
+
3937
+ sage: EK.saturation([2*P], max_prime=2)
3938
+ ([(-1 : 1 : 1)], 2, 0.686667083305587)
3939
+ sage: EK.saturation([12*P], max_prime=2)
3940
+ ([(26/361 : -5720/6859 : 1)], 4, 6.18000374975028)
3941
+ sage: EK.saturation([12*P], lower_ht_bound=0.1)
3942
+ ([(-1 : 1 : 1)], 12, 0.686667083305587)
3943
+ sage: EK.saturation([2*P, Q], max_prime=2)
3944
+ ([(-1 : 1 : 1), (0 : -1 : 1)], 2, 0.152460177943144)
3945
+ sage: EK.saturation([P + Q, P - Q], lower_ht_bound=.1, debug=2)
3946
+ ([(-1 : 1 : 1), (1 : 0 : 1)], 2, 0.152460177943144)
3947
+ sage: EK.saturation([P + Q, 17*Q], lower_ht_bound=0.1) # long time
3948
+ ([(4 : 8 : 1), (0 : -1 : 1)], 17, 0.152460177943143)
3949
+
3950
+ sage: R = EK(i-2,-i-3)
3951
+ sage: EK.saturation([P + R, P + Q, Q + R], lower_ht_bound=0.1)
3952
+ ([(841/1369*i - 171/1369 : 41334/50653*i - 74525/50653 : 1),
3953
+ (4 : 8 : 1),
3954
+ (-1/25*i + 18/25 : -69/125*i - 58/125 : 1)],
3955
+ 2,
3956
+ 0.103174443217351)
3957
+ sage: EK.saturation([26*Q], lower_ht_bound=0.1)
3958
+ ([(0 : -1 : 1)], 26, 0.327000773651605)
3959
+
3960
+ Another number field::
3961
+
3962
+ sage: E = EllipticCurve('389a1')
3963
+ sage: x = polygen(QQ)
3964
+ sage: K.<a> = NumberField(x^3 - x + 1)
3965
+ sage: EK = E.change_ring(K)
3966
+ sage: P = EK(-1,1); Q = EK(0,-1)
3967
+ sage: EK.saturation([P + Q, P - Q], lower_ht_bound=0.1)
3968
+ ([(-1 : 1 : 1), (1 : 0 : 1)], 2, 0.152460177943144)
3969
+ sage: EK.saturation([3*P, P + 5*Q], lower_ht_bound=0.1)
3970
+ ([(-185/2209 : -119510/103823 : 1), (80041/34225 : -26714961/6331625 : 1)],
3971
+ 15,
3972
+ 0.152460177943144)
3973
+
3974
+ A different curve::
3975
+
3976
+ sage: K.<a> = QuadraticField(3)
3977
+ sage: E = EllipticCurve('37a1')
3978
+ sage: EK = E.change_ring(K)
3979
+ sage: P = EK(0,0); Q = EK(2-a, 2*a-4)
3980
+ sage: EK.saturation([3*P - Q, 3*P + Q], lower_ht_bound=.01)
3981
+ ([(0 : 0 : 1), (1/2*a : -1/4*a - 1/4 : 1)], 6, 0.0317814530725985)
3982
+
3983
+ The points must be linearly independent::
3984
+
3985
+ sage: EK.saturation([2*P, 3*Q, P-Q])
3986
+ Traceback (most recent call last):
3987
+ ...
3988
+ ValueError: points not linearly independent in saturation()
3989
+
3990
+ Degenerate case::
3991
+
3992
+ sage: EK.saturation([])
3993
+ ([], 1, 1.00000000000000)
3994
+
3995
+ ALGORITHM:
3996
+
3997
+ For rank 1 subgroups, simply do trial division up to the maximal
3998
+ prime divisor. For higher rank subgroups, perform trial division
3999
+ on all linear combinations for small primes, and look for
4000
+ projections `E(K) \rightarrow \oplus E(k) \otimes \mathbf{F}_p` which
4001
+ are either full rank or provide `p`-divisible linear combinations,
4002
+ where the `k` here are residue fields of `K`.
4003
+
4004
+ TESTS::
4005
+
4006
+ sage: K.<i> = QuadraticField(-1)
4007
+ sage: E = EllipticCurve('389a1')
4008
+ sage: EK = E.change_ring(K)
4009
+ sage: P = EK(-1,1); Q = EK(0,-1)
4010
+
4011
+ sage: EK.saturation([P+Q, P-Q], lower_ht_bound=.1, debug=2)
4012
+ ([(-1 : 1 : 1), (1 : 0 : 1)], 2, 0.152460177943144)
4013
+ sage: EK.saturation([5*P + 6*Q, 5*P - 3*Q], lower_ht_bound=.1)
4014
+ ([(-3/4 : -15/8 : 1), (159965/16129 : -67536260/2048383 : 1)],
4015
+ 45,
4016
+ 0.152460177943144)
4017
+ sage: EK.saturation([5*P + 6*Q, 5*P - 3*Q], lower_ht_bound=.1, debug=2)
4018
+ ([(-3/4 : -15/8 : 1), (159965/16129 : -67536260/2048383 : 1)],
4019
+ 45,
4020
+ 0.152460177943144)
4021
+
4022
+ See :issue:`27387`::
4023
+
4024
+ sage: K.<a> = NumberField(x^2 - x - 26)
4025
+ sage: E = EllipticCurve([a, 1-a, 0, 93-16*a, 3150-560*a])
4026
+ sage: P = E([65-35*a/3, (959*a-5377)/9])
4027
+ sage: E.saturation([P], one_prime=2)
4028
+ ([(-1/4*a + 3/4 : 59/8*a - 317/8 : 1)], 2, 0.344624259712631)
4029
+ """
4030
+ full_saturation = (max_prime == 0) and (one_prime == 0)
4031
+ Plist = (self(P) for P in points)
4032
+ Plist = [P for P in Plist if P.has_infinite_order()]
4033
+ n = len(Plist)
4034
+ index = ZZ.one()
4035
+
4036
+ if n == 0:
4037
+ return Plist, index, RealField()(1)
4038
+
4039
+ # compute the list of primes p at which p-saturation is
4040
+ # required.
4041
+
4042
+ heights = [P.height() for P in Plist]
4043
+ if reg is None:
4044
+ reg = self.regulator_of_points(Plist)
4045
+ if reg / min(heights) < 1e-6:
4046
+ raise ValueError("points not linearly independent in saturation()")
4047
+ sat_reg = reg
4048
+
4049
+ from sage.rings.fast_arith import prime_range
4050
+ if full_saturation:
4051
+ if lower_ht_bound is None:
4052
+ # TODO (robertwb): verify this for rank > 1
4053
+ if verbose:
4054
+ print("Computing lower height bound..")
4055
+ lower_ht_bound = self.height_function().min(.1, 5) ** n
4056
+ if verbose:
4057
+ print("..done: %s" % lower_ht_bound)
4058
+ index_bound = (reg/lower_ht_bound).sqrt()
4059
+ if index_bound < 2:
4060
+ if verbose:
4061
+ print("Saturation index bound < 2, points are saturated already.")
4062
+ return Plist, index, RealField()(1)
4063
+ else:
4064
+ if verbose:
4065
+ print("p-saturating for primes p < {}".format(index_bound.ceil()))
4066
+ prime_list = prime_range(index_bound.ceil())
4067
+ else:
4068
+ if one_prime:
4069
+ prime_list = [one_prime]
4070
+ else:
4071
+ prime_list = prime_range(max_prime+1)
4072
+ if odd_primes_only and 2 in prime_list:
4073
+ prime_list.remove(2)
4074
+
4075
+ # Now saturate at each prime in prime_list. The dict
4076
+ # lin_combs keeps the values of linear combinations of the
4077
+ # points, indexed by coefficient tuples, for efficiency; it is
4078
+ # reset whenever the point list changes.
4079
+
4080
+ from sage.schemes.elliptic_curves.saturation import EllipticCurveSaturator
4081
+ saturator = EllipticCurveSaturator(self, verbose)
4082
+ for p in prime_list:
4083
+ if full_saturation and (p > index_bound):
4084
+ break
4085
+ if verbose:
4086
+ print("Saturating at p=%s" % p)
4087
+ newPlist, expo = saturator.full_p_saturation(Plist, p)
4088
+ if expo:
4089
+ if verbose:
4090
+ print(" --gaining index %s^%s" % (p, expo))
4091
+ pe = p**expo
4092
+ index *= pe
4093
+ if full_saturation:
4094
+ index_bound /= pe
4095
+ sat_reg /= pe**2
4096
+ Plist = newPlist
4097
+ else:
4098
+ if verbose:
4099
+ print(" --already %s-saturated" % p)
4100
+
4101
+ return Plist, index, sat_reg
4102
+
4103
+ def gens_quadratic(self, **kwds):
4104
+ r"""
4105
+ Return generators for the Mordell-Weil group modulo torsion, for a
4106
+ curve which is a base change from `\QQ` to a quadratic field.
4107
+
4108
+ EXAMPLES::
4109
+
4110
+ sage: E = EllipticCurve([1,2,3,40,50])
4111
+ sage: E.conductor()
4112
+ 2123582
4113
+ sage: E.gens() # needs eclib
4114
+ [(5 : 17 : 1)]
4115
+ sage: K.<i> = QuadraticField(-1)
4116
+ sage: EK = E.change_ring(K)
4117
+ sage: EK.gens_quadratic() # needs eclib
4118
+ [(5 : 17 : 1), (-13 : 48*i + 5 : 1)]
4119
+
4120
+ sage: E.change_ring(QuadraticField(3, 'a')).gens_quadratic() # needs eclib
4121
+ [(5 : 17 : 1), (-1 : 2*a - 1 : 1), (11/4 : 33/4*a - 23/8 : 1)]
4122
+
4123
+ sage: K.<a> = QuadraticField(-7)
4124
+ sage: E = EllipticCurve([0,0,0,197,0])
4125
+ sage: E.conductor()
4126
+ 2483776
4127
+ sage: E.gens() # needs eclib
4128
+ [(47995604297578081/7389879786648100 : -25038161802544048018837479/635266655830129794121000 : 1)]
4129
+ sage: K.<a> = QuadraticField(7)
4130
+ sage: E.change_ring(K).gens_quadratic() # needs eclib
4131
+ [(-1209642055/59583566*a + 1639995844/29791783 : -377240626321899/1720892553212*a + 138577803462855/245841793316 : 1),
4132
+ (1/28 : 393/392*a : 1),
4133
+ (-61*a + 162 : 1098*a - 2916 : 1)]
4134
+
4135
+ sage: E = EllipticCurve([1, a])
4136
+ sage: E.gens_quadratic() # needs eclib
4137
+ Traceback (most recent call last):
4138
+ ...
4139
+ ValueError: gens_quadratic() requires the elliptic curve to be a base change from Q
4140
+ """
4141
+ if not kwds:
4142
+ try:
4143
+ return list(self.__gens)
4144
+ except AttributeError:
4145
+ pass
4146
+
4147
+ K = self.base_ring()
4148
+ if K.absolute_degree() != 2:
4149
+ raise ValueError("gens_quadratic() requires the base field to be quadratic")
4150
+
4151
+ EE = self.descend_to(QQ)
4152
+ if not EE:
4153
+ raise ValueError("gens_quadratic() requires the elliptic curve to be a base change from Q")
4154
+
4155
+ # In all cases there are exactly two distinct curves /Q whose
4156
+ # base-change to K is the original. NB These need not be
4157
+ # quadratic twists of each other! For example, '32a1' and
4158
+ # '32a2' are not quadratic twists of each other (each is its
4159
+ # own twist by -1) but they become isomorphic over
4160
+ # Q(sqrt(-1)).
4161
+
4162
+ EQ1 = EE[0]
4163
+ EQ2 = EE[1]
4164
+ iso1 = EQ1.change_ring(K).isomorphism_to(self)
4165
+ iso2 = EQ2.change_ring(K).isomorphism_to(self)
4166
+ gens1 = [iso1(P) for P in EQ1.gens(**kwds)]
4167
+ gens2 = [iso2(P) for P in EQ2.gens(**kwds)]
4168
+ gens = self.saturation(gens1 + gens2, max_prime=2)[0]
4169
+ self.__gens = gens
4170
+ return gens
4171
+
4172
+ def rational_points(self, **kwds):
4173
+ r"""
4174
+ Find rational points on the elliptic curve, all arguments are passed
4175
+ on to :meth:`sage.schemes.generic.algebraic_scheme.rational_points`.
4176
+
4177
+ EXAMPLES::
4178
+
4179
+ sage: # needs database_cremona_mini_ellcurve
4180
+ sage: E = EllipticCurve('37a')
4181
+ sage: E.rational_points(bound=8) # long time
4182
+ [(-1 : -1 : 1),
4183
+ (-1 : 0 : 1),
4184
+ (0 : -1 : 1),
4185
+ (0 : 0 : 1),
4186
+ (0 : 1 : 0),
4187
+ (1/4 : -5/8 : 1),
4188
+ (1/4 : -3/8 : 1),
4189
+ (1 : -1 : 1),
4190
+ (1 : 0 : 1),
4191
+ (2 : -3 : 1),
4192
+ (2 : 2 : 1)]
4193
+
4194
+ Check that :issue:`26677` is fixed::
4195
+
4196
+ sage: # needs database_cremona_mini_ellcurve
4197
+ sage: E = EllipticCurve("11a1")
4198
+ sage: E.rational_points(bound=5) # needs sage.symbolic
4199
+ [(0 : 1 : 0), (5 : 5 : 1)]
4200
+ sage: E.rational_points(bound=6) # long time # needs sage.symbolic
4201
+ [(0 : 1 : 0), (5 : -6 : 1), (5 : 5 : 1)]
4202
+
4203
+ An example over a number field::
4204
+
4205
+ sage: E = EllipticCurve([1,0])
4206
+ sage: pts = E.rational_points(bound=2, F=QuadraticField(-1))
4207
+ sage: pts
4208
+ [(-a : 0 : 1), (0 : 0 : 1), (0 : 1 : 0), (a : 0 : 1)]
4209
+ sage: pts[0] + pts[1]
4210
+ (a : 0 : 1)
4211
+ """
4212
+ from sage.schemes.curves.constructor import Curve
4213
+ # we change E to be a plain curve to allow the generic rational
4214
+ # points code to reduce mod any prime, whereas an EllipticCurve
4215
+ # can only be base changed to good primes.
4216
+ E = self
4217
+ if 'F' in kwds:
4218
+ E = E.change_ring(kwds['F'])
4219
+
4220
+ return [E(pt) for pt in Curve(self).rational_points(**kwds)]