passagemath-schemes 10.8.1a4__cp314-cp314t-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.
Files changed (312) 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.8.1a4.dist-info/METADATA +203 -0
  7. passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
  8. passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
  9. passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.8.1a4.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 +9556 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +727 -0
  29. sage/lfunctions/pari.py +971 -0
  30. sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5132 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
  34. sage/modular/abvar/abvar_newform.py +246 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +187 -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 +721 -0
  40. sage/modular/abvar/homspace.py +989 -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 +741 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1406 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +361 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +659 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1491 -0
  57. sage/modular/arithgroup/congroup_generic.py +630 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +266 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1067 -0
  61. sage/modular/arithgroup/tests.py +425 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3736 -0
  64. sage/modular/btquotients/pautomorphicform.py +2564 -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 +1107 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +571 -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 +1076 -0
  77. sage/modular/hecke/algebra.py +725 -0
  78. sage/modular/hecke/all.py +19 -0
  79. sage/modular/hecke/ambient_module.py +994 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +302 -0
  82. sage/modular/hecke/hecke_operator.py +736 -0
  83. sage/modular/hecke/homspace.py +185 -0
  84. sage/modular/hecke/module.py +1744 -0
  85. sage/modular/hecke/morphism.py +139 -0
  86. sage/modular/hecke/submodule.py +970 -0
  87. sage/modular/hypergeometric_misc.cpython-314t-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 +2020 -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 +1070 -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 +817 -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 +120 -0
  101. sage/modular/modform/ambient_g1.py +199 -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 +487 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4105 -0
  108. sage/modular/modform/half_integral.py +154 -0
  109. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  110. sage/modular/modform/j_invariant.py +47 -0
  111. sage/modular/modform/l_series_gross_zagier.py +127 -0
  112. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  114. sage/modular/modform/notes.py +45 -0
  115. sage/modular/modform/numerical.py +514 -0
  116. sage/modular/modform/periods.py +14 -0
  117. sage/modular/modform/ring.py +1257 -0
  118. sage/modular/modform/space.py +1859 -0
  119. sage/modular/modform/submodule.py +118 -0
  120. sage/modular/modform/tests.py +64 -0
  121. sage/modular/modform/theta.py +110 -0
  122. sage/modular/modform/vm_basis.py +380 -0
  123. sage/modular/modform/weight1.py +221 -0
  124. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  125. sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
  126. sage/modular/modform_hecketriangle/all.py +30 -0
  127. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  128. sage/modular/modform_hecketriangle/constructor.py +416 -0
  129. sage/modular/modform_hecketriangle/element.py +351 -0
  130. sage/modular/modform_hecketriangle/functors.py +752 -0
  131. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  132. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  133. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
  135. sage/modular/modform_hecketriangle/readme.py +1214 -0
  136. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  137. sage/modular/modform_hecketriangle/space.py +1037 -0
  138. sage/modular/modform_hecketriangle/subspace.py +423 -0
  139. sage/modular/modsym/all.py +17 -0
  140. sage/modular/modsym/ambient.py +3844 -0
  141. sage/modular/modsym/boundary.py +1420 -0
  142. sage/modular/modsym/element.py +336 -0
  143. sage/modular/modsym/g1list.py +178 -0
  144. sage/modular/modsym/ghlist.py +182 -0
  145. sage/modular/modsym/hecke_operator.py +73 -0
  146. sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
  147. sage/modular/modsym/manin_symbol.pxd +5 -0
  148. sage/modular/modsym/manin_symbol.pyx +497 -0
  149. sage/modular/modsym/manin_symbol_list.py +1291 -0
  150. sage/modular/modsym/modsym.py +400 -0
  151. sage/modular/modsym/modular_symbols.py +384 -0
  152. sage/modular/modsym/p1list_nf.py +1241 -0
  153. sage/modular/modsym/relation_matrix.py +591 -0
  154. sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
  155. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  156. sage/modular/modsym/space.py +2468 -0
  157. sage/modular/modsym/subspace.py +455 -0
  158. sage/modular/modsym/tests.py +376 -0
  159. sage/modular/multiple_zeta.py +2635 -0
  160. sage/modular/multiple_zeta_F_algebra.py +789 -0
  161. sage/modular/overconvergent/all.py +6 -0
  162. sage/modular/overconvergent/genus0.py +1879 -0
  163. sage/modular/overconvergent/hecke_series.py +1187 -0
  164. sage/modular/overconvergent/weightspace.py +776 -0
  165. sage/modular/pollack_stevens/all.py +4 -0
  166. sage/modular/pollack_stevens/distributions.py +874 -0
  167. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  168. sage/modular/pollack_stevens/manin_map.py +856 -0
  169. sage/modular/pollack_stevens/modsym.py +1590 -0
  170. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  171. sage/modular/pollack_stevens/sigma0.py +534 -0
  172. sage/modular/pollack_stevens/space.py +1078 -0
  173. sage/modular/quasimodform/all.py +3 -0
  174. sage/modular/quasimodform/element.py +846 -0
  175. sage/modular/quasimodform/ring.py +826 -0
  176. sage/modular/quatalg/all.py +3 -0
  177. sage/modular/quatalg/brandt.py +1642 -0
  178. sage/modular/ssmod/all.py +8 -0
  179. sage/modular/ssmod/ssmod.py +827 -0
  180. sage/rings/all__sagemath_schemes.py +1 -0
  181. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/binary_form_reduce.py +585 -0
  183. sage/schemes/all.py +41 -0
  184. sage/schemes/berkovich/all.py +6 -0
  185. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  186. sage/schemes/berkovich/berkovich_space.py +700 -0
  187. sage/schemes/curves/affine_curve.py +2924 -0
  188. sage/schemes/curves/all.py +33 -0
  189. sage/schemes/curves/closed_point.py +434 -0
  190. sage/schemes/curves/constructor.py +397 -0
  191. sage/schemes/curves/curve.py +542 -0
  192. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  193. sage/schemes/curves/point.py +463 -0
  194. sage/schemes/curves/projective_curve.py +3203 -0
  195. sage/schemes/curves/weighted_projective_curve.py +106 -0
  196. sage/schemes/curves/zariski_vankampen.py +1931 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +991 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1103 -0
  208. sage/schemes/elliptic_curves/constructor.py +1530 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +457 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2837 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4944 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7328 -0
  229. sage/schemes/elliptic_curves/height.py +2108 -0
  230. sage/schemes/elliptic_curves/hom.py +1788 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +1084 -0
  232. sage/schemes/elliptic_curves/hom_fractional.py +544 -0
  233. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  234. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  235. sage/schemes/elliptic_curves/hom_sum.py +681 -0
  236. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  237. sage/schemes/elliptic_curves/homset.py +271 -0
  238. sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
  239. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  240. sage/schemes/elliptic_curves/jacobian.py +247 -0
  241. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  242. sage/schemes/elliptic_curves/kraus.py +1014 -0
  243. sage/schemes/elliptic_curves/lseries_ell.py +915 -0
  244. sage/schemes/elliptic_curves/mod5family.py +105 -0
  245. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
  247. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  248. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  249. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  250. sage/schemes/elliptic_curves/padics.py +1816 -0
  251. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
  253. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  254. sage/schemes/elliptic_curves/saturation.py +716 -0
  255. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  256. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  257. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  258. sage/schemes/hyperelliptic_curves/all.py +6 -0
  259. sage/schemes/hyperelliptic_curves/constructor.py +369 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  265. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
  271. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  272. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  273. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
  274. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  275. sage/schemes/jacobians/all.py +2 -0
  276. sage/schemes/overview.py +161 -0
  277. sage/schemes/plane_conics/all.py +22 -0
  278. sage/schemes/plane_conics/con_field.py +1296 -0
  279. sage/schemes/plane_conics/con_finite_field.py +158 -0
  280. sage/schemes/plane_conics/con_number_field.py +456 -0
  281. sage/schemes/plane_conics/con_rational_field.py +406 -0
  282. sage/schemes/plane_conics/con_rational_function_field.py +581 -0
  283. sage/schemes/plane_conics/constructor.py +249 -0
  284. sage/schemes/plane_quartics/all.py +2 -0
  285. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  286. sage/schemes/plane_quartics/quartic_generic.py +53 -0
  287. sage/schemes/riemann_surfaces/all.py +1 -0
  288. sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
  289. sage_wheels/share/cremona/cremona_mini.db +0 -0
  290. sage_wheels/share/ellcurves/rank0 +30427 -0
  291. sage_wheels/share/ellcurves/rank1 +31871 -0
  292. sage_wheels/share/ellcurves/rank10 +6 -0
  293. sage_wheels/share/ellcurves/rank11 +6 -0
  294. sage_wheels/share/ellcurves/rank12 +1 -0
  295. sage_wheels/share/ellcurves/rank14 +1 -0
  296. sage_wheels/share/ellcurves/rank15 +1 -0
  297. sage_wheels/share/ellcurves/rank17 +1 -0
  298. sage_wheels/share/ellcurves/rank19 +1 -0
  299. sage_wheels/share/ellcurves/rank2 +2388 -0
  300. sage_wheels/share/ellcurves/rank20 +1 -0
  301. sage_wheels/share/ellcurves/rank21 +1 -0
  302. sage_wheels/share/ellcurves/rank22 +1 -0
  303. sage_wheels/share/ellcurves/rank23 +1 -0
  304. sage_wheels/share/ellcurves/rank24 +1 -0
  305. sage_wheels/share/ellcurves/rank28 +1 -0
  306. sage_wheels/share/ellcurves/rank3 +836 -0
  307. sage_wheels/share/ellcurves/rank4 +10 -0
  308. sage_wheels/share/ellcurves/rank5 +5 -0
  309. sage_wheels/share/ellcurves/rank6 +5 -0
  310. sage_wheels/share/ellcurves/rank7 +5 -0
  311. sage_wheels/share/ellcurves/rank8 +6 -0
  312. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,2108 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Canonical heights for elliptic curves over number fields
4
+
5
+ Also, rigorous lower bounds for the canonical height of non-torsion
6
+ points, implementing the algorithms in [CS2006]_ (over `\QQ`) and [Tho2010]_,
7
+ which also refer to [CPS2006]_.
8
+
9
+ AUTHORS:
10
+
11
+ - Robert Bradshaw (2010): initial version
12
+
13
+ - John Cremona (2014): added many docstrings and doctests
14
+ """
15
+ ##############################################################################
16
+ # Copyright (C) 2010 Robert Bradshaw <robertwb@math.washington.edu>
17
+ # 2014 John Cremona <john.cremona@gmail.com>
18
+ #
19
+ # Distributed under the terms of the GNU General Public License (GPL)
20
+ #
21
+ # This code is distributed in the hope that it will be useful,
22
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24
+ # General Public License for more details.
25
+ #
26
+ # The full text of the GPL is available at:
27
+ #
28
+ # https://www.gnu.org/licenses/
29
+ ##############################################################################
30
+ import numpy
31
+ import math
32
+ import bisect
33
+
34
+ from itertools import product
35
+
36
+ from sage.arith.functions import lcm
37
+ from sage.arith.misc import factorial
38
+ from sage.ext.fast_callable import fast_callable
39
+ from sage.misc.cachefunc import cached_method
40
+ from sage.misc.lazy_import import lazy_import
41
+ from sage.rings.cc import CC
42
+ from sage.rings.complex_double import CDF
43
+ from sage.rings.infinity import infinity
44
+ from sage.rings.integer_ring import ZZ
45
+ from sage.rings.rational_field import QQ
46
+ from sage.rings.real_double import RDF
47
+ from sage.rings.real_mpfr import RR
48
+
49
+ lazy_import("sage.functions.log", ["log", "exp"])
50
+ lazy_import("sage.rings.cif", "CIF")
51
+ lazy_import("sage.rings.real_mpfi", "RIF")
52
+ lazy_import("sage.symbolic.ring", "SR")
53
+
54
+
55
+ class UnionOfIntervals:
56
+ r"""
57
+ A class representing a finite union of closed intervals in
58
+ `\RR` which can be scaled, shifted, intersected, etc.
59
+
60
+ The intervals are represented as an ordered list of their
61
+ endpoints, which may include `-\infty` and `+\infty`.
62
+
63
+ EXAMPLES::
64
+
65
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
66
+ sage: R = UnionOfIntervals([1, 2, 3, infinity]); R
67
+ ([1, 2] U [3, +Infinity])
68
+ sage: R + 5
69
+ ([6, 7] U [8, +Infinity])
70
+ sage: ~R
71
+ ([-Infinity, 1] U [2, 3])
72
+ sage: ~R | (10*R + 100)
73
+ ([-Infinity, 1] U [2, 3] U [110, 120] U [130, +Infinity])
74
+
75
+ .. TODO::
76
+
77
+ Unify :class:`UnionOfIntervals` with the class ``RealSet``
78
+ introduced by :issue:`13125`; see :issue:`16063`.
79
+ """
80
+ def __init__(self, endpoints) -> None:
81
+ r"""
82
+ An union of intervals is initialized by giving an increasing list
83
+ of endpoints, the first of which may be `-\infty` and the last of
84
+ which may be `+\infty`.
85
+
86
+ EXAMPLES::
87
+
88
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
89
+ sage: UnionOfIntervals([0, 1])
90
+ ([0, 1])
91
+ sage: UnionOfIntervals([-infinity, pi, 17, infinity]) # needs sage.symbolic
92
+ ([-Infinity, pi] U [17, +Infinity])
93
+ sage: UnionOfIntervals([])
94
+ ()
95
+
96
+ sage: UnionOfIntervals([1])
97
+ Traceback (most recent call last):
98
+ ...
99
+ ValueError: an even number of endpoints must be given (got 1)
100
+ sage: UnionOfIntervals([3, 2, 1, 0])
101
+ Traceback (most recent call last):
102
+ ...
103
+ ValueError: endpoints must be given in order
104
+ """
105
+ if len(endpoints) % 2:
106
+ raise ValueError("an even number of endpoints must be given (got %s)" % len(endpoints))
107
+ if endpoints != sorted(endpoints):
108
+ raise ValueError("endpoints must be given in order")
109
+ self._endpoints = endpoints
110
+
111
+ def finite_endpoints(self):
112
+ r"""
113
+ Return the finite endpoints of this union of intervals.
114
+
115
+ EXAMPLES::
116
+
117
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
118
+ sage: UnionOfIntervals([0, 1]).finite_endpoints()
119
+ [0, 1]
120
+ sage: UnionOfIntervals([-infinity, 0, 1, infinity]).finite_endpoints()
121
+ [0, 1]
122
+ """
123
+ return [e for e in self._endpoints if -infinity < e < infinity]
124
+
125
+ def intervals(self):
126
+ r"""
127
+ Return the intervals in self, as a list of 2-tuples.
128
+
129
+ EXAMPLES::
130
+
131
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
132
+ sage: UnionOfIntervals(list(range(10))).intervals()
133
+ [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
134
+ sage: UnionOfIntervals([-infinity, pi, 17, infinity]).intervals() # needs sage.symbolic
135
+ [(-Infinity, pi), (17, +Infinity)]
136
+ """
137
+ return list(zip(self._endpoints[::2], self._endpoints[1::2]))
138
+
139
+ def is_empty(self):
140
+ r"""
141
+ Return whether ``self`` is empty.
142
+
143
+ EXAMPLES::
144
+
145
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
146
+ sage: UnionOfIntervals([3, 4]).is_empty()
147
+ False
148
+ sage: all = UnionOfIntervals([-infinity, infinity])
149
+ sage: all.is_empty()
150
+ False
151
+ sage: (~all).is_empty()
152
+ True
153
+ sage: A = UnionOfIntervals([0, 1]) & UnionOfIntervals([2, 3])
154
+ sage: A.is_empty()
155
+ True
156
+ """
157
+ return not self._endpoints
158
+
159
+ def __add__(left, right):
160
+ r"""
161
+ If both left and right are unions of intervals, take their union,
162
+ otherwise treat the non-union of intervals as a scalar and shift.
163
+
164
+ EXAMPLES::
165
+
166
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
167
+ sage: A = UnionOfIntervals([0, 1/2, 2, infinity]); A
168
+ ([0, 1/2] U [2, +Infinity])
169
+ sage: A + 1
170
+ ([1, 3/2] U [3, +Infinity])
171
+ sage: pi + A # needs sage.symbolic
172
+ ([pi, pi + 1/2] U [pi + 2, +Infinity])
173
+ sage: A + UnionOfIntervals([-infinity, -1])
174
+ ([-Infinity, -1] U [0, 1/2] U [2, +Infinity])
175
+ """
176
+ if not isinstance(left, UnionOfIntervals):
177
+ left, right = right, left
178
+ elif not isinstance(right, UnionOfIntervals):
179
+ return UnionOfIntervals([right + e for e in left._endpoints])
180
+ else:
181
+ return left.union([left, right])
182
+
183
+ def __mul__(left, right):
184
+ r"""
185
+ Scale a union of intervals on the left or right.
186
+
187
+ EXAMPLES::
188
+
189
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
190
+ sage: A = UnionOfIntervals([0, 1/2, 2, infinity]); A
191
+ ([0, 1/2] U [2, +Infinity])
192
+ sage: 2 * A
193
+ ([0, 1] U [4, +Infinity])
194
+ sage: A * 100
195
+ ([0, 50] U [200, +Infinity])
196
+ sage: 1.5 * A
197
+ ([0.000000000000000, 0.750000000000000] U [3.00000000000000, +Infinity])
198
+ """
199
+ if not isinstance(right, UnionOfIntervals):
200
+ return UnionOfIntervals([e*right for e in left._endpoints])
201
+ elif not isinstance(left, UnionOfIntervals):
202
+ return UnionOfIntervals([left*e for e in right._endpoints])
203
+ else:
204
+ return NotImplemented
205
+
206
+ def __rmul__(self, other):
207
+ r"""
208
+ Scale by an operand on the left.
209
+
210
+ TESTS::
211
+
212
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
213
+ sage: A = UnionOfIntervals([0, 1/2, 2, infinity]); A
214
+ ([0, 1/2] U [2, +Infinity])
215
+ sage: pi * A # needs sage.symbolic
216
+ ([0, 1/2*pi] U [2*pi, +Infinity])
217
+ """
218
+ return self * other
219
+
220
+ def __radd__(self, other):
221
+ r"""
222
+ Add a scalar operand on the left.
223
+
224
+ TESTS::
225
+
226
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
227
+ sage: A = UnionOfIntervals([0, 1/2, 2, infinity]); A
228
+ ([0, 1/2] U [2, +Infinity])
229
+ sage: 100 + A
230
+ ([100, 201/2] U [102, +Infinity])
231
+ """
232
+ return self + other
233
+
234
+ def __invert__(self):
235
+ r"""
236
+ Return the closure of the complement of ``self``.
237
+
238
+ .. NOTE::
239
+
240
+ We take the closure because open intervals are not supported.
241
+
242
+ EXAMPLES::
243
+
244
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
245
+ sage: A = UnionOfIntervals([0, 1/2, 2, infinity]); A
246
+ ([0, 1/2] U [2, +Infinity])
247
+ sage: ~A
248
+ ([-Infinity, 0] U [1/2, 2])
249
+ sage: A | ~A
250
+ ([-Infinity, +Infinity])
251
+ sage: A & ~A
252
+ ([0, 0] U [1/2, 1/2] U [2, 2])
253
+ """
254
+ endpoints = list(self._endpoints)
255
+ if endpoints[0] == -infinity:
256
+ del endpoints[0]
257
+ else:
258
+ endpoints.insert(0, -infinity)
259
+ if endpoints[-1] == infinity:
260
+ endpoints.pop()
261
+ else:
262
+ endpoints.append(infinity)
263
+ return UnionOfIntervals(endpoints)
264
+
265
+ @staticmethod
266
+ def join(L, condition):
267
+ r"""
268
+ Utility function to form the union or intersection of a list of UnionOfIntervals.
269
+
270
+ INPUT:
271
+
272
+ - ``L`` -- list of UnionOfIntervals instances
273
+
274
+ - ``condition`` -- function; either ``any`` or ``all``, or
275
+ some other boolean function of a list of boolean values
276
+
277
+ OUTPUT:
278
+
279
+ A new UnionOfIntervals instance representing the subset of
280
+ '\RR' equal to those reals in any/all/condition of the
281
+ UnionOfIntervals in the list.
282
+
283
+ .. NOTE::
284
+
285
+ This is a static method for the class.
286
+
287
+ EXAMPLES::
288
+
289
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
290
+ sage: A = UnionOfIntervals([1,3,5,7]); A
291
+ ([1, 3] U [5, 7])
292
+ sage: B = A + 1; B
293
+ ([2, 4] U [6, 8])
294
+ sage: A.join([A,B], any) # union
295
+ ([1, 4] U [5, 8])
296
+ sage: A.join([A,B], all) # intersection
297
+ ([2, 3] U [6, 7])
298
+ sage: A.join([A,B], sum) # symmetric difference
299
+ ([1, 2] U [3, 4] U [5, 6] U [7, 8])
300
+ """
301
+ all = []
302
+ for ix, region in enumerate(L):
303
+ for i, e in enumerate(region._endpoints):
304
+ all.append((e, -(not (i % 2)), ix))
305
+ all.sort()
306
+ join = []
307
+ in_join = False
308
+ in_L = [False] * len(L)
309
+ for e, start, ix in all:
310
+ in_L[ix] = start
311
+ if condition(in_L) != in_join:
312
+ join.append(e)
313
+ in_join = not in_join
314
+ return UnionOfIntervals(join)
315
+
316
+ @classmethod
317
+ def union(cls, L):
318
+ r"""
319
+ Return the union of a list of UnionOfIntervals.
320
+
321
+ INPUT:
322
+
323
+ - ``L`` -- list of UnionOfIntervals instances
324
+
325
+ OUTPUT:
326
+
327
+ A new UnionOfIntervals instance representing the union of the
328
+ UnionOfIntervals in the list.
329
+
330
+ .. NOTE::
331
+
332
+ This is a class method.
333
+
334
+ EXAMPLES::
335
+
336
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
337
+ sage: A = UnionOfIntervals([1,3,5,7]); A
338
+ ([1, 3] U [5, 7])
339
+ sage: B = A + 1; B
340
+ ([2, 4] U [6, 8])
341
+ sage: A.union([A,B])
342
+ ([1, 4] U [5, 8])
343
+ """
344
+ return cls.join(L, any)
345
+
346
+ @classmethod
347
+ def intersection(cls, L):
348
+ r"""
349
+ Return the intersection of a list of UnionOfIntervals.
350
+
351
+ INPUT:
352
+
353
+ - ``L`` -- list of UnionOfIntervals instances
354
+
355
+ OUTPUT:
356
+
357
+ A new UnionOfIntervals instance representing the intersection
358
+ of the UnionOfIntervals in the list.
359
+
360
+ .. NOTE::
361
+
362
+ This is a class method.
363
+
364
+ EXAMPLES::
365
+
366
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
367
+ sage: A = UnionOfIntervals([1,3,5,7]); A
368
+ ([1, 3] U [5, 7])
369
+ sage: B = A + 1; B
370
+ ([2, 4] U [6, 8])
371
+ sage: A.intersection([A,B])
372
+ ([2, 3] U [6, 7])
373
+ """
374
+ for R in L:
375
+ if R.is_empty():
376
+ return R
377
+ return cls.join(L, all)
378
+
379
+ def __or__(left, right):
380
+ r"""
381
+ Return the union of a two UnionOfIntervals instances.
382
+
383
+ INPUT:
384
+
385
+ - ``left``, ``right`` -- two UnionOfIntervals instances
386
+
387
+ OUTPUT: a new UnionOfIntervals instance representing the union of ``left`` and ``right``
388
+
389
+ EXAMPLES::
390
+
391
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
392
+ sage: A = UnionOfIntervals([1,3,5,7]); A
393
+ ([1, 3] U [5, 7])
394
+ sage: B = A + 1; B
395
+ ([2, 4] U [6, 8])
396
+ sage: A | B
397
+ ([1, 4] U [5, 8])
398
+ """
399
+ return left.union([left, right])
400
+
401
+ def __and__(left, right):
402
+ r"""
403
+ Return the intersection of a two UnionOfIntervals instances.
404
+
405
+ INPUT:
406
+
407
+ - ``left``, ``right`` -- two UnionOfIntervals instances
408
+
409
+ OUTPUT: a new UnionOfIntervals instance representing the intersection of ``left`` and ``right``
410
+
411
+ EXAMPLES::
412
+
413
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
414
+ sage: A = UnionOfIntervals([1,3,5,7]); A
415
+ ([1, 3] U [5, 7])
416
+ sage: B = A + 1; B
417
+ ([2, 4] U [6, 8])
418
+ sage: A & B
419
+ ([2, 3] U [6, 7])
420
+ """
421
+ return left.intersection([left, right])
422
+
423
+ def __contains__(self, x) -> bool:
424
+ r"""
425
+ Return ``True`` if ``x`` is in the UnionOfIntervals.
426
+
427
+ INPUT:
428
+
429
+ - ``x`` -- real number
430
+
431
+ OUTPUT: boolean; ``True`` if and only if `x` is in the union of intervals
432
+
433
+ EXAMPLES::
434
+
435
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
436
+ sage: A = UnionOfIntervals([1,3,5,7]); A
437
+ ([1, 3] U [5, 7])
438
+ sage: 1 in A
439
+ True
440
+ sage: 4 in A
441
+ False
442
+ sage: -infinity in A
443
+ False
444
+ """
445
+ return x in self._endpoints or bisect.bisect_left(self._endpoints, x) % 2 == 1
446
+
447
+ def __str__(self) -> str:
448
+ r"""
449
+ Return the string representation of this UnionOfIntervals.
450
+
451
+ EXAMPLES::
452
+
453
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
454
+ sage: A = UnionOfIntervals([1,3,5,7])
455
+ sage: str(A)
456
+ '([1, 3] U [5, 7])'
457
+ """
458
+ return repr(self)
459
+
460
+ def __repr__(self) -> str:
461
+ r"""
462
+ Return the string representation of this UnionOfIntervals.
463
+
464
+ EXAMPLES::
465
+
466
+ sage: from sage.schemes.elliptic_curves.height import UnionOfIntervals
467
+ sage: A = UnionOfIntervals([1,3,5,7]); A
468
+ ([1, 3] U [5, 7])
469
+ """
470
+ return "(%s)" % " U ".join(str(list(I)) for I in self.intervals())
471
+
472
+
473
+ def nonneg_region(f):
474
+ r"""
475
+ Return the UnionOfIntervals representing the region where ``f`` is nonnegative.
476
+
477
+ INPUT:
478
+
479
+ - ``f`` -- a univariate polynomial over `\RR`
480
+
481
+ OUTPUT:
482
+
483
+ A UnionOfIntervals representing the set `\{x \in\RR mid f(x) \ge 0\}`.
484
+
485
+ EXAMPLES::
486
+
487
+ sage: from sage.schemes.elliptic_curves.height import nonneg_region
488
+ sage: x = polygen(RR)
489
+ sage: nonneg_region(x^2 - 1)
490
+ ([-Infinity, -1.00000000000000] U [1.00000000000000, +Infinity])
491
+ sage: nonneg_region(1 - x^2)
492
+ ([-1.00000000000000, 1.00000000000000])
493
+ sage: nonneg_region(1 - x^3)
494
+ ([-Infinity, 1.00000000000000])
495
+ sage: nonneg_region(x^3 - 1)
496
+ ([1.00000000000000, +Infinity])
497
+ sage: nonneg_region((x-1)*(x-2))
498
+ ([-Infinity, 1.00000000000000] U [2.00000000000000, +Infinity])
499
+ sage: nonneg_region(-(x-1)*(x-2))
500
+ ([1.00000000000000, 2.00000000000000])
501
+ sage: nonneg_region((x-1)*(x-2)*(x-3))
502
+ ([1.00000000000000, 2.00000000000000] U [3.00000000000000, +Infinity])
503
+ sage: nonneg_region(-(x-1)*(x-2)*(x-3))
504
+ ([-Infinity, 1.00000000000000] U [2.00000000000000, 3.00000000000000])
505
+ sage: nonneg_region(x^4 + 1)
506
+ ([-Infinity, +Infinity])
507
+ sage: nonneg_region(-x^4 - 1)
508
+ ()
509
+ """
510
+ roots = sorted(f.roots())
511
+ sign_changes = [r for r,e in roots if e % 2 == 1]
512
+ if (f.leading_coefficient() * (-1)**f.degree()) > 0:
513
+ sign_changes = [-infinity] + sign_changes
514
+ if f.leading_coefficient() > 0:
515
+ sign_changes += [infinity]
516
+ return UnionOfIntervals(sign_changes)
517
+
518
+
519
+ def inf_max_abs(f, g, D):
520
+ r"""
521
+ Return `\inf_D(\max(|f|, |g|))`.
522
+
523
+ INPUT:
524
+
525
+ - ``f``, ``g`` -- real univariate polynomials
526
+
527
+ - ``D`` -- :class:`UnionOfIntervals`; a subset of `\RR`
528
+
529
+ OUTPUT:
530
+
531
+ A real number approximating the value of `\inf_D(\max(|f|, |g|))`.
532
+
533
+ ALGORITHM:
534
+
535
+ The extreme values must occur at an endpoint of a subinterval of
536
+ `D` or at a point where one of `f`, `f'`, `g`, `g'`, `f\pm g` is
537
+ zero.
538
+
539
+ EXAMPLES::
540
+
541
+ sage: from sage.schemes.elliptic_curves.height import inf_max_abs, UnionOfIntervals
542
+ sage: x = polygen(RR)
543
+ sage: f = (x-10)^4 + 1
544
+ sage: g = 2*x^3 + 100
545
+ sage: inf_max_abs(f, g, UnionOfIntervals([1,2,3,4,5,6]))
546
+ 425.638201706391
547
+ sage: r0 = (f - g).roots()[0][0]
548
+ sage: r0
549
+ 5.46053402234697
550
+ sage: max(abs(f(r0)), abs(g(r0)))
551
+ 425.638201706391
552
+ """
553
+ xs = f.roots() + f.derivative().roots()
554
+ xs += g.roots() + g.derivative().roots()
555
+ xs += (f - g).roots() + (f + g).roots()
556
+ xs = [r for r, _ in xs if r in D] # ignore multiplicities and points outside D
557
+ xs += D.finite_endpoints() # include endpoints of intervals
558
+ if xs:
559
+ return min(max(abs(f(r)), abs(g(r))) for r in xs)
560
+ return infinity
561
+
562
+
563
+ def min_on_disk(f, tol, max_iter=10000):
564
+ r"""
565
+ Return the minimum of a real-valued complex function on a square.
566
+
567
+ INPUT:
568
+
569
+ - ``f`` -- a function from CIF to RIF
570
+
571
+ - ``tol`` -- a positive real number
572
+
573
+ - ``max_iter`` -- integer (default: 10000); a positive integer
574
+ bounding the number of iterations to be used
575
+
576
+ OUTPUT:
577
+
578
+ A 2-tuple `(s,t)`, where `t=f(s)` and `s` is a CIF element
579
+ contained in the disk `|z|\le1`, at which `f` takes its minimum
580
+ value.
581
+
582
+ EXAMPLES::
583
+
584
+ sage: from sage.schemes.elliptic_curves.height import min_on_disk
585
+ sage: f = lambda x: (x^2 + 100).abs()
586
+ sage: s, t = min_on_disk(f, 0.0001)
587
+ sage: s, f(s), t
588
+ (0.01? + 1.00?*I, 99.01?, 99.0000000000000)
589
+ """
590
+ # L holds a list of 4-tuples (mfs, ds, s, in_disk) where s is a
591
+ # subregion of the initial square, ds its relative diameter,
592
+ # mfs=-f(s) (actually minus the lower bound on f(s)) and in_disk
593
+ # is a flag indicating whether or not s is a subset of the unit
594
+ # disk.
595
+
596
+ # We store the negative of the lower bound on f(s) so that we can
597
+ # use the bisect module to sort these 4-tuples.
598
+
599
+ # Initially L contains one element, the whole unit box, which is
600
+ # not contained in the unit square.
601
+
602
+ s = CIF(RIF(-1,1), RIF(-1,1))
603
+ fs = f(s)
604
+ L = [(-fs.lower(), fs.relative_diameter(), s, False)]
605
+
606
+ # min_max holds the minimum over L of fs.upper().
607
+
608
+ min_max = fs.upper()
609
+
610
+ # We iterate at most max_iter times. At each step we look at the
611
+ # best so far and return it if is good enough, meaning that its
612
+ # relative diameter is less than the given tolerance; otherwise we
613
+ # bisect this best region (into 4 pieces) and replace the entry in
614
+ # L with at most 4 smaller entries.
615
+
616
+ for k in range(max_iter):
617
+ value, err, region, in_disk = L.pop()
618
+ if err < tol: # reached desired tolerance, so return
619
+ return region, -value
620
+ for s in region.bisection(): # 4 sub-regions
621
+ if in_disk:
622
+ s_in_disk = True # if the original region si in the disk so are all its children
623
+ else:
624
+ r = abs(s) # otherwise we test each one
625
+ if r > 1:
626
+ continue # skip this subregion if it is entirely outside the disk
627
+ s_in_disk = r < 1 # meaning it is entirely inside the disk
628
+
629
+ fs = f(s)
630
+
631
+ if fs.upper() < min_max: # we definitely beat the record
632
+ min_max = fs.upper()
633
+ unneeded = bisect.bisect(L, (-min_max,))
634
+ if unneeded > 100: # discard the worse entries (if there are many)
635
+ L = L[unneeded:]
636
+
637
+ if fs.lower() < min_max:
638
+ # we may beat the record, cannot yet tell: insert this region
639
+ # into the list at the appropriate place to maintain sorting
640
+ bisect.insort(L, (-fs.lower(), fs.relative_diameter(), s, s_in_disk))
641
+
642
+ # If we get here, then even after max_iter iterations the tolerance has not been reached.
643
+ raise ValueError("too many iterations")
644
+
645
+
646
+ two_pi_i_CDF = CDF(0, 2 * RDF.pi())
647
+ two_pi_i_CIF = CIF(0, 2 * RIF.pi())
648
+
649
+ # Ideas: We know tau, so we know the direction of the diagonal.
650
+ # We can solve for x in p1, will this allow us to find the maxima exactly?
651
+
652
+
653
+ def rat_term_CIF(z, try_strict=True):
654
+ r"""
655
+ Compute the value of `u/(1-u)^2` in ``CIF``, where `u=\exp(2\pi i z)`.
656
+
657
+ INPUT:
658
+
659
+ - ``z`` -- complex; a CIF element
660
+
661
+ - ``try_strict`` -- boolean; flag
662
+
663
+ EXAMPLES::
664
+
665
+ sage: from sage.schemes.elliptic_curves.height import rat_term_CIF
666
+ sage: z = CIF(0.5,0.2)
667
+ sage: rat_term_CIF(z)
668
+ -0.172467461182437? + 0.?e-16*I
669
+ sage: rat_term_CIF(z, False)
670
+ -0.172467461182437? + 0.?e-16*I
671
+ """
672
+ two_pi_i_z = two_pi_i_CIF * z
673
+ r = (two_pi_i_z.real()).exp() # = |u|
674
+ x, y = two_pi_i_z.imag().cos(), two_pi_i_z.imag().sin()
675
+
676
+ real_part = imag_part = None
677
+
678
+ # If there are no local minima the intervals are strictly
679
+ # determined by their values at the endpoints.
680
+
681
+ if try_strict:
682
+
683
+ # evaluate the function at the four corners:
684
+
685
+ corner_reals = []
686
+ corner_imags = []
687
+ for a, b in product(z.real().endpoints(), z.imag().endpoints()):
688
+ zz = CDF(a,b)
689
+ u = (two_pi_i_CDF*zz).exp()
690
+ f = u/(1-u)**2
691
+ corner_reals.append(f.real())
692
+ corner_imags.append(f.imag())
693
+
694
+ p1 = (((((r+2*x)*r - 6)*r + 2*x) * r) + 1)
695
+ # = r^4 + 2*r^3*x - 6*r^2 + 2*r*x + 1
696
+ p2 = (r*(x*(r+2*x)-4)+x)
697
+ # = r^2*x + 2*r*x^2 - 4*r + x
698
+
699
+ df_dr = (r**2-1) * p2
700
+ dg_dr = p1 * y
701
+ dg_dx = r * df_dr / y
702
+
703
+ if not dg_dr.contains_zero() or not dg_dx.contains_zero():
704
+ real_part = RIF(min(corner_reals), max(corner_reals))
705
+
706
+ if not dg_dr.contains_zero() or not dg_dx.contains_zero():
707
+ imag_part = RIF(min(corner_imags), max(corner_imags))
708
+
709
+ if real_part is None or imag_part is None:
710
+ denom = (1-r*(2*x-r))**2
711
+ if real_part is None:
712
+ real_part = r*(x*(1+r**2)-2*r)/denom
713
+ if imag_part is None:
714
+ imag_part = -(r**2-1)*y*r/denom
715
+
716
+ return CIF(real_part, imag_part)
717
+
718
+
719
+ def eps(err, is_real):
720
+ r"""
721
+ Return a Real or Complex interval centered on 0 with radius err.
722
+
723
+ INPUT:
724
+
725
+ - ``err`` -- a positive real number; the radius of the interval
726
+
727
+ - ``is_real`` -- boolean; if ``True``, returns a real interval in
728
+ RIF, else a complex interval in CIF
729
+
730
+ OUTPUT:
731
+
732
+ An element of RIF or CIF (as specified), centered on 0, with given radius.
733
+
734
+ EXAMPLES::
735
+
736
+ sage: from sage.schemes.elliptic_curves.height import eps
737
+ sage: eps(0.01, True)
738
+ 0.0?
739
+ sage: eps(0.01, False)
740
+ 0.0? + 0.0?*I
741
+ """
742
+ e = RIF(-err, err)
743
+ if is_real:
744
+ return e
745
+ else:
746
+ return CIF(e, e)
747
+
748
+
749
+ class EllipticCurveCanonicalHeight:
750
+ r"""
751
+ Class for computing canonical heights of points on elliptic curves
752
+ defined over number fields, including rigorous lower bounds for
753
+ the canonical height of non-torsion points.
754
+
755
+ EXAMPLES::
756
+
757
+ sage: from sage.schemes.elliptic_curves.height import EllipticCurveCanonicalHeight
758
+ sage: E = EllipticCurve([0,0,0,0,1])
759
+ sage: EllipticCurveCanonicalHeight(E)
760
+ EllipticCurveCanonicalHeight object associated to
761
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
762
+
763
+ Normally this object would be created like this::
764
+
765
+ sage: E.height_function()
766
+ EllipticCurveCanonicalHeight object associated to
767
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
768
+ """
769
+
770
+ def __init__(self, E) -> None:
771
+ r"""
772
+ Initialize the class with an elliptic curve.
773
+
774
+ INPUT:
775
+
776
+ - ``E`` -- an elliptic curve defined over a number field
777
+
778
+ EXAMPLES::
779
+
780
+ sage: from sage.schemes.elliptic_curves.height import EllipticCurveCanonicalHeight
781
+ sage: E = EllipticCurve([0,0,0,0,1])
782
+ sage: EllipticCurveCanonicalHeight(E)
783
+ EllipticCurveCanonicalHeight object associated to
784
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
785
+
786
+ An example over a number field::
787
+
788
+ sage: K.<i> = QuadraticField(-1) # needs sage.rings.number_field
789
+ sage: E = EllipticCurve([0,i,0,i,i]) # needs sage.rings.number_field
790
+ sage: EllipticCurveCanonicalHeight(E) # needs sage.rings.number_field
791
+ EllipticCurveCanonicalHeight object associated to
792
+ Elliptic Curve defined by y^2 = x^3 + i*x^2 + i*x + i
793
+ over Number Field in i with defining polynomial x^2 + 1 with i = 1*I
794
+
795
+ TESTS:
796
+
797
+ The base field must be a number field (or `\QQ`)::
798
+
799
+ sage: from sage.schemes.elliptic_curves.height import EllipticCurveCanonicalHeight
800
+ sage: E = EllipticCurve(GF(7), [0,0,0,0,1])
801
+ sage: EllipticCurveCanonicalHeight(E)
802
+ Traceback (most recent call last):
803
+ ...
804
+ ValueError: EllipticCurveCanonicalHeight class can only be created
805
+ from an elliptic curve defined over a number field
806
+ """
807
+ from sage.schemes.elliptic_curves.ell_generic import EllipticCurve_generic
808
+ if isinstance(E, EllipticCurve_generic):
809
+ self.E = E
810
+ from sage.rings.number_field.number_field_base import NumberField
811
+ K = E.base_ring()
812
+ if isinstance(K, NumberField):
813
+ self.K = K
814
+ else:
815
+ raise ValueError("EllipticCurveCanonicalHeight class can only be created from an elliptic curve defined over a number field")
816
+ else:
817
+ raise ValueError("EllipticCurveCanonicalHeight class can only be created from an elliptic curve")
818
+
819
+ def __repr__(self) -> str:
820
+ r"""
821
+ Return the string representation.
822
+
823
+ EXAMPLES::
824
+
825
+ sage: E = EllipticCurve([0,0,0,0,1])
826
+ sage: E.height_function()
827
+ EllipticCurveCanonicalHeight object associated to
828
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
829
+ """
830
+ return "EllipticCurveCanonicalHeight object associated to %s" % self.E
831
+
832
+ def curve(self):
833
+ r"""
834
+ Return the elliptic curve.
835
+
836
+ EXAMPLES::
837
+
838
+ sage: E = EllipticCurve([0,0,0,0,1])
839
+ sage: H = E.height_function()
840
+ sage: H.curve()
841
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
842
+ """
843
+ return self.E
844
+
845
+ def base_field(self):
846
+ r"""
847
+ Return the base field.
848
+
849
+ EXAMPLES::
850
+
851
+ sage: E = EllipticCurve([0,0,0,0,1])
852
+ sage: H = E.height_function()
853
+ sage: H.base_field()
854
+ Rational Field
855
+ """
856
+ return self.K
857
+
858
+ def __call__(self, P):
859
+ r"""
860
+ Return the canonical height of the point ``P``.
861
+
862
+ INPUT:
863
+
864
+ - ``P`` -- a point on the elliptic curve
865
+
866
+ OUTPUT: the canonical height of ``P``
867
+
868
+ EXAMPLES::
869
+
870
+ sage: E = EllipticCurve([0,0,1,-1,0])
871
+ sage: P = E(0,0)
872
+ sage: P.height()
873
+ 0.0511114082399688
874
+ sage: H = E.height_function()
875
+ sage: H(P)
876
+ 0.0511114082399688
877
+ sage: H([0,0])
878
+ 0.0511114082399688
879
+ sage: H((0,0))
880
+ 0.0511114082399688
881
+
882
+ Over a number field other than `\QQ`::
883
+
884
+ sage: # needs sage.rings.number_field
885
+ sage: K.<i> = QuadraticField(-1)
886
+ sage: E = EllipticCurve(K, [0,0,0,1,-27])
887
+ sage: H = E.height_function()
888
+ sage: H.base_field()
889
+ Number Field in i with defining polynomial x^2 + 1 with i = 1*I
890
+ sage: H((1, 5*i))
891
+ 1.22257115164148
892
+ """
893
+ return self.E(P).height()
894
+
895
+ @cached_method
896
+ def alpha(self, v, tol=0.01):
897
+ r"""
898
+ Return the constant `\alpha_v` associated to the embedding ``v``.
899
+
900
+ INPUT:
901
+
902
+ - ``v`` -- an embedding of the base field into `\RR` or `\CC`
903
+
904
+ OUTPUT:
905
+
906
+ The constant `\alpha_v`. In the notation of [CPS2006]_ and
907
+ [Tho2010]_ (section 3.2), `\alpha_v^3=\epsilon_v`. The result is
908
+ cached since it only depends on the curve.
909
+
910
+ EXAMPLES:
911
+
912
+ Example 1 from [CPS2006]_::
913
+
914
+ sage: # needs sage.rings.number_field
915
+ sage: K.<i> = QuadraticField(-1)
916
+ sage: E = EllipticCurve([0, 0, 0, 1 + 5*i, 3 + i])
917
+ sage: H = E.height_function()
918
+ sage: alpha = H.alpha(K.places()[0])
919
+ sage: alpha
920
+ 1.12272013439355
921
+
922
+ Compare with `\log(\epsilon_v)=0.344562...` in [CPS2006]_::
923
+
924
+ sage: 3*alpha.log() # needs sage.rings.number_field
925
+ 0.347263296676126
926
+ """
927
+ from sage.rings.polynomial.polynomial_ring import polygen
928
+ b2, b4, b6, b8 = (v(b) for b in self.E.b_invariants())
929
+ x = polygen(v.codomain())
930
+ f = 4*x**3 + b2*x**2 + 2*b4*x + b6
931
+ g = x**4 - b4*x**2 - 2*b6*x - b8
932
+ F = f.reverse() << (4-f.degree())
933
+ G = g.reverse() << (4-g.degree())
934
+
935
+ if v(self.K.gen()) in RR:
936
+ I = UnionOfIntervals([-1,1])
937
+ min_fg = inf_max_abs(f, g, nonneg_region(f) & I)
938
+ min_FG = inf_max_abs(F, G, nonneg_region(F) & I)
939
+ return min(min_fg, min_FG) ** (-1/QQ(3))
940
+
941
+ else:
942
+ # def pair_max(f, g):
943
+ # f = f.change_ring(CIF)
944
+ # g = g.change_ring(CIF)
945
+ # max = type(RIF(0)).max
946
+ # def max_f_g(z):
947
+ # return max(abs(f(z)), abs(g(z)))
948
+ # return max_f_g
949
+ def pair_max(f, g):
950
+ f = f.change_ring(CDF)
951
+ g = g.change_ring(CDF)
952
+ dfn = [fast_callable(f.derivative(n)/factorial(n), CDF) for n in range(f.degree()+1)]
953
+ dgn = [fast_callable(g.derivative(n)/factorial(n), CDF) for n in range(g.degree()+1)]
954
+
955
+ def max_f_g(s):
956
+ (a,b), (c,d) = s.real().endpoints(), s.imag().endpoints()
957
+ dx = a - b
958
+ dy = c - d
959
+ eta = RDF(dx*dx + dy*dy).sqrt()
960
+ z = CDF(s.center())
961
+ err_f = sum(eta ** n * abs(df(z)) for n, df in enumerate(dfn) if n)
962
+ err_g = sum(eta ** n * abs(dg(z)) for n, dg in enumerate(dgn) if n)
963
+ return RIF(max(abs(f(z)), abs(g(z)))) + eps(max(err_f, err_g), True)
964
+ return max_f_g
965
+ _, min_fg = min_on_disk(pair_max(f, g), tol)
966
+ _, min_FG = min_on_disk(pair_max(F, G), tol)
967
+ return min(min_fg, min_FG) ** QQ((-1, 3))
968
+
969
+ @cached_method
970
+ def e_p(self, p):
971
+ r"""
972
+ Return the exponent of the group over the residue field at ``p``.
973
+
974
+ INPUT:
975
+
976
+ - ``p`` -- a prime ideal of `K` (or a prime number if `K=\QQ`)
977
+
978
+ OUTPUT:
979
+
980
+ A positive integer `e_p`, the exponent of the group of
981
+ nonsingular points on the reduction of the elliptic curve
982
+ modulo `p`. The result is cached.
983
+
984
+ EXAMPLES::
985
+
986
+ sage: # needs sage.rings.number_field
987
+ sage: K.<i> = QuadraticField(-1)
988
+ sage: E = EllipticCurve([0, 0, 0, 1 + 5*i, 3 + i])
989
+ sage: H = E.height_function()
990
+ sage: H.e_p(K.prime_above(2))
991
+ 2
992
+ sage: H.e_p(K.prime_above(3))
993
+ 10
994
+ sage: H.e_p(K.prime_above(5))
995
+ 9
996
+ sage: E.conductor().norm().factor()
997
+ 2^10 * 20921
998
+ sage: p1, p2 = K.primes_above(20921)
999
+ sage: E.local_data(p1)
1000
+ Local data at Fractional ideal (-40*i + 139):
1001
+ Reduction type: bad split multiplicative
1002
+ ...
1003
+ sage: H.e_p(p1)
1004
+ 20920
1005
+ sage: E.local_data(p2)
1006
+ Local data at Fractional ideal (40*i + 139):
1007
+ Reduction type: good
1008
+ ...
1009
+ sage: H.e_p(p2)
1010
+ 20815
1011
+ """
1012
+ kp = self.K.residue_field(p)
1013
+ if self.E.has_bad_reduction(p):
1014
+ if self.E.has_additive_reduction(p):
1015
+ ep = kp.characteristic()
1016
+ elif self.E.has_split_multiplicative_reduction(p):
1017
+ ep = len(kp) - 1
1018
+ else:
1019
+ ep = len(kp) + 1
1020
+ else:
1021
+ ep = self.E.reduction(p).abelian_group().exponent()
1022
+ return ZZ(ep)
1023
+
1024
+ @cached_method
1025
+ def DE(self, n):
1026
+ r"""
1027
+ Return the value `D_E(n)`.
1028
+
1029
+ INPUT:
1030
+
1031
+ - ``n`` -- positive integer
1032
+
1033
+ OUTPUT:
1034
+
1035
+ The value `D_E(n)` as defined in [Tho2010]_, section 4.
1036
+
1037
+ EXAMPLES::
1038
+
1039
+ sage: # needs sage.rings.number_field sage.symbolic
1040
+ sage: K.<i> = QuadraticField(-1)
1041
+ sage: E = EllipticCurve([0, 0, 0, 1+5*i, 3+i])
1042
+ sage: H = E.height_function()
1043
+ sage: [H.DE(n) for n in srange(1,6)]
1044
+ [0, 2*log(5) + 2*log(2), 0, 2*log(13) + 2*log(5) + 4*log(2), 0]
1045
+ """
1046
+ s = 0
1047
+ B = (n+1) ** max(2, self.K.degree())
1048
+ for p in self.K.primes_of_bounded_norm_iter(B):
1049
+ ep = self.e_p(p)
1050
+ if ep.divides(n):
1051
+ kp = self.K.residue_field(p)
1052
+ s += 2*(1+(n/ep).valuation(kp.characteristic())) * log(len(kp))
1053
+ return s
1054
+
1055
+ @cached_method
1056
+ def ME(self):
1057
+ r"""
1058
+ Return the norm of the ideal `M_E`.
1059
+
1060
+ OUTPUT:
1061
+
1062
+ The norm of the ideal `M_E` as defined in [Tho2010]_, section 3.1.
1063
+ This is `1` if `E` is a global minimal model, and in general
1064
+ measures the non-minimality of `E`.
1065
+
1066
+ EXAMPLES::
1067
+
1068
+ sage: K.<i> = QuadraticField(-1) # needs sage.rings.number_field
1069
+ sage: E = EllipticCurve([0, 0, 0, 1+5*i, 3+i]) # needs sage.rings.number_field
1070
+ sage: H = E.height_function() # needs sage.rings.number_field
1071
+ sage: H.ME() # needs sage.rings.number_field
1072
+ 1
1073
+ sage: E = EllipticCurve([0,0,0,0,1])
1074
+ sage: E.height_function().ME()
1075
+ 1
1076
+ sage: E = EllipticCurve([0,0,0,0,64])
1077
+ sage: E.height_function().ME()
1078
+ 4096
1079
+ sage: E.discriminant()/E.minimal_model().discriminant()
1080
+ 4096
1081
+ """
1082
+ from sage.misc.misc_c import prod
1083
+ if self.K is QQ:
1084
+ return prod([p ** (e - self.E.local_data(p).discriminant_valuation()) for p, e in self.E.discriminant().factor()], QQ.one())
1085
+
1086
+ ME = prod([p.norm() ** (e - self.E.local_data(p).discriminant_valuation()) for p, e in self.K.ideal(self.E.discriminant()).factor()], QQ.one())
1087
+ return ME.norm()
1088
+
1089
+ def B(self, n, mu):
1090
+ r"""
1091
+ Return the value `B_n(\mu)`.
1092
+
1093
+ INPUT:
1094
+
1095
+ - ``n`` -- positive integer
1096
+
1097
+ - ``mu`` -- positive real number
1098
+
1099
+ OUTPUT:
1100
+
1101
+ The real value `B_n(\mu)` as defined in [Tho2010]_, section 5.
1102
+
1103
+ EXAMPLES:
1104
+
1105
+ Example 10.2 from [Tho2010]_::
1106
+
1107
+ sage: K.<i> = QuadraticField(-1) # needs sage.rings.number_field
1108
+ sage: E = EllipticCurve([0, 1-i, i, -i, 0]) # needs sage.rings.number_field
1109
+ sage: H = E.height_function() # needs sage.rings.number_field
1110
+
1111
+ In [Tho2010]_ the value is given as 0.772::
1112
+
1113
+ sage: RealField(12)( H.B(5, 0.01) ) # needs sage.rings.number_field sage.symbolic
1114
+ 0.777
1115
+ """
1116
+ K = self.K
1117
+ B = exp(K.degree() * n**2 * mu - RDF(self.DE(n))) / self.ME() ** 6
1118
+ for v in K.places():
1119
+ if v(K.gen()) in RR:
1120
+ B *= self.alpha(v)
1121
+ else:
1122
+ B *= self.alpha(v) ** 2
1123
+ return B
1124
+
1125
+ ######################################
1126
+ # Empty real intersection detection. #
1127
+ ######################################
1128
+
1129
+ def psi(self, xi, v):
1130
+ r"""
1131
+ Return the normalised elliptic log of a point with this x-coordinate.
1132
+
1133
+ INPUT:
1134
+
1135
+ - ``xi`` -- real; the real x-coordinate of a point on the
1136
+ curve in the connected component with respect to a real
1137
+ embedding
1138
+
1139
+ - ``v`` -- a real embedding of the number field
1140
+
1141
+ OUTPUT:
1142
+
1143
+ A real number in the interval [0.5,1] giving the elliptic
1144
+ logarithm of a point on `E` with `x`-coordinate ``xi``, on the
1145
+ connected component with respect to the embedding `v`, scaled
1146
+ by the real period.
1147
+
1148
+ EXAMPLES:
1149
+
1150
+ An example over `\QQ`::
1151
+
1152
+ sage: E = EllipticCurve('389a')
1153
+ sage: v = QQ.places()[0]
1154
+ sage: L = E.period_lattice(v)
1155
+ sage: P = E.lift_x(10/9)
1156
+ sage: L(P)
1157
+ 0.958696500380439
1158
+ sage: L(P) / L.real_period()
1159
+ 0.384985810227885
1160
+ sage: H = E.height_function()
1161
+ sage: H.psi(10/9, v)
1162
+ 0.615014189772115
1163
+
1164
+ An example over a number field::
1165
+
1166
+ sage: # needs sage.rings.number_field
1167
+ sage: x = polygen(ZZ, 'x')
1168
+ sage: K.<a> = NumberField(x^3 - 2)
1169
+ sage: E = EllipticCurve([0,0,0,0,a])
1170
+ sage: P = E.lift_x(1/3*a^2 + a + 5/3)
1171
+ sage: v = K.real_places()[0]
1172
+ sage: L = E.period_lattice(v)
1173
+ sage: L(P)
1174
+ 3.51086196882538
1175
+ sage: L(P) / L.real_period()
1176
+ 0.867385122699931
1177
+ sage: xP = v(P.x())
1178
+ sage: H = E.height_function()
1179
+ sage: H.psi(xP, v)
1180
+ 0.867385122699931
1181
+ sage: H.psi(1.23, v)
1182
+ 0.785854718241495
1183
+ """
1184
+ if xi > 1e9:
1185
+ return 1
1186
+ L = self.E.period_lattice(v)
1187
+ w1, w2 = L.basis()
1188
+ from sage.schemes.elliptic_curves.constructor import EllipticCurve
1189
+ ER = EllipticCurve([v(ai) for ai in self.E.a_invariants()])
1190
+ xP, yP = ER.lift_x(xi).xy()
1191
+ t = L.e_log_RC(xP,yP) / w1
1192
+ if t < 0.5:
1193
+ t = 1 - t
1194
+ return t
1195
+
1196
+ def S(self, xi1, xi2, v):
1197
+ r"""
1198
+ Return the union of intervals `S^{(v)}(\xi_1,\xi_2)`.
1199
+
1200
+ INPUT:
1201
+
1202
+ - ``xi1``, ``xi2`` -- real numbers with `\xi_1\le\xi_2`
1203
+
1204
+ - ``v`` -- a real embedding of the field
1205
+
1206
+ OUTPUT:
1207
+
1208
+ The union of intervals `S^{(v)}(\xi_1,\xi_2)` defined in [Tho2010]_
1209
+ section 6.1.
1210
+
1211
+ EXAMPLES:
1212
+
1213
+ An example over `\QQ`::
1214
+
1215
+ sage: E = EllipticCurve('389a')
1216
+ sage: v = QQ.places()[0]
1217
+ sage: H = E.height_function()
1218
+ sage: H.S(2, 3, v)
1219
+ ([0.224512677391895, 0.274544821597130] U [0.725455178402870, 0.775487322608105])
1220
+
1221
+ An example over a number field::
1222
+
1223
+ sage: # needs sage.rings.number_field
1224
+ sage: x = polygen(ZZ, 'x')
1225
+ sage: K.<a> = NumberField(x^3 - 2)
1226
+ sage: E = EllipticCurve([0,0,0,0,a])
1227
+ sage: v = K.real_places()[0]
1228
+ sage: H = E.height_function()
1229
+ sage: H.S(9, 10, v)
1230
+ ([0.078119444725347..., 0.082342373201640...] U [0.91765762679836..., 0.92188055527465...])
1231
+ """
1232
+ L = self.E.period_lattice(v)
1233
+ w1, w2 = L.basis(prec=v.codomain().prec())
1234
+ beta = L.elliptic_exponential(w1/2)[0]
1235
+ if xi2 < beta:
1236
+ return UnionOfIntervals([])
1237
+ elif xi1 < beta <= xi2:
1238
+ a = self.psi(xi2, v)
1239
+ return UnionOfIntervals([1-a, a])
1240
+ else:
1241
+ a, b = self.psi(xi1, v), self.psi(xi2, v)
1242
+ return UnionOfIntervals([1-b, 1-a, a, b])
1243
+
1244
+ def Sn(self, xi1, xi2, n, v):
1245
+ r"""
1246
+ Return the union of intervals `S_n^{(v)}(\xi_1,\xi_2)`.
1247
+
1248
+ INPUT:
1249
+
1250
+ - ``xi1``, ``xi2`` -- real numbers with `\xi_1\le\xi_2`
1251
+
1252
+ - ``n`` -- positive integer
1253
+
1254
+ - ``v`` -- a real embedding of the field
1255
+
1256
+ OUTPUT:
1257
+
1258
+ The union of intervals `S_n^{(v)}(\xi_1,\xi_2)` defined in [Tho2010]_
1259
+ (Lemma 6.1).
1260
+
1261
+ EXAMPLES:
1262
+
1263
+ An example over `\QQ`::
1264
+
1265
+ sage: E = EllipticCurve('389a')
1266
+ sage: v = QQ.places()[0]
1267
+ sage: H = E.height_function()
1268
+ sage: H.S(2, 3, v), H.Sn(2, 3, 1, v)
1269
+ (([0.224512677391895, 0.274544821597130] U [0.725455178402870, 0.775487322608105]),
1270
+ ([0.224512677391895, 0.274544821597130] U [0.725455178402870, 0.775487322608105]))
1271
+ sage: H.Sn(2, 3, 6, v)
1272
+ ([0.0374187795653158, 0.0457574702661884] U [0.120909196400478, 0.129247887101351] U [0.204085446231982, 0.212424136932855] U [0.287575863067145, 0.295914553768017] U [0.370752112898649, 0.379090803599522] U [0.454242529733812, 0.462581220434684] U [0.537418779565316, 0.545757470266188] U [0.620909196400478, 0.629247887101351] U [0.704085446231982, 0.712424136932855] U [0.787575863067145, 0.795914553768017] U [0.870752112898649, 0.879090803599522] U [0.954242529733812, 0.962581220434684])
1273
+
1274
+ An example over a number field::
1275
+
1276
+ sage: # needs sage.rings.number_field
1277
+ sage: x = polygen(ZZ, 'x')
1278
+ sage: K.<a> = NumberField(x^3 - 2)
1279
+ sage: E = EllipticCurve([0,0,0,0,a])
1280
+ sage: v = K.real_places()[0]
1281
+ sage: H = E.height_function()
1282
+ sage: H.S(2, 3, v), H.Sn(2, 3, 1, v)
1283
+ (([0.142172065860075, 0.172845716928584] U [0.827154283071416, 0.857827934139925]),
1284
+ ([0.142172065860075, 0.172845716928584] U [0.827154283071416, 0.857827934139925]))
1285
+ sage: H.Sn(2, 3, 6, v)
1286
+ ([0.0236953443100124, 0.0288076194880974] U [0.137859047178569, 0.142971322356654] U [0.190362010976679, 0.195474286154764] U [0.304525713845236, 0.309637989023321] U [0.357028677643346, 0.362140952821431] U [0.471192380511903, 0.476304655689988] U [0.523695344310012, 0.528807619488097] U [0.637859047178569, 0.642971322356654] U [0.690362010976679, 0.695474286154764] U [0.804525713845236, 0.809637989023321] U [0.857028677643346, 0.862140952821431] U [0.971192380511903, 0.976304655689988])
1287
+ """
1288
+ SS = 1/ZZ(n) * self.S(xi1, xi2, v)
1289
+ return UnionOfIntervals.union([t/ZZ(n) + SS for t in range(n)])
1290
+
1291
+ def real_intersection_is_empty(self, Bk, v):
1292
+ r"""
1293
+ Return ``True`` iff an intersection of `S_n^{(v)}` sets is empty.
1294
+
1295
+ INPUT:
1296
+
1297
+ - ``Bk`` -- list of reals
1298
+
1299
+ - ``v`` -- a real embedding of the number field
1300
+
1301
+ OUTPUT:
1302
+
1303
+ ``True`` or ``False``, according as the intersection of the unions of
1304
+ intervals `S_n^{(v)}(-b,b)` for `b` in the list ``Bk`` is
1305
+ empty or not. When ``Bk`` is the list of `b=B_n(\mu)` for
1306
+ `n=1,2,3,\dots` for some `\mu>0` this means that all
1307
+ non-torsion points on `E` with everywhere good reduction have
1308
+ canonical height strictly greater than `\mu`, by [Tho2010]_,
1309
+ Proposition 6.2.
1310
+
1311
+ EXAMPLES:
1312
+
1313
+ An example over `\QQ`::
1314
+
1315
+ sage: E = EllipticCurve('389a')
1316
+ sage: v = QQ.places()[0]
1317
+ sage: H = E.height_function()
1318
+
1319
+ The following two lines prove that the heights of non-torsion
1320
+ points on `E` with everywhere good reduction have canonical
1321
+ height strictly greater than 0.2, but fail to prove the same
1322
+ for 0.3::
1323
+
1324
+ sage: H.real_intersection_is_empty([H.B(n,0.2) for n in srange(1,10)], v) # needs sage.symbolic
1325
+ True
1326
+ sage: H.real_intersection_is_empty([H.B(n,0.3) for n in srange(1,10)], v) # needs sage.symbolic
1327
+ False
1328
+
1329
+ An example over a number field::
1330
+
1331
+ sage: # needs sage.rings.number_field
1332
+ sage: x = polygen(ZZ, 'x')
1333
+ sage: K.<a> = NumberField(x^3 - 2)
1334
+ sage: E = EllipticCurve([0,0,0,0,a])
1335
+ sage: v = K.real_places()[0]
1336
+ sage: H = E.height_function()
1337
+
1338
+ The following two lines prove that the heights of non-torsion
1339
+ points on `E` with everywhere good reduction have canonical
1340
+ height strictly greater than 0.07, but fail to prove the same
1341
+ for 0.08::
1342
+
1343
+ sage: H.real_intersection_is_empty([H.B(n,0.07) for n in srange(1,5)], v) # long time, needs sage.rings.number_field sage.symbolic
1344
+ True
1345
+ sage: H.real_intersection_is_empty([H.B(n,0.08) for n in srange(1,5)], v) # needs sage.rings.number_field sage.symbolic
1346
+ False
1347
+ """
1348
+ return UnionOfIntervals.intersection([self.Sn(-B, B, k+1, v) for k,B in enumerate(Bk)]).is_empty()
1349
+
1350
+ ########################################
1351
+ # Empty complex intersection detection.#
1352
+ ########################################
1353
+
1354
+ def tau(self, v):
1355
+ r"""
1356
+ Return the normalised upper half-plane parameter `\tau` for
1357
+ the period lattice with respect to the embedding `v`.
1358
+
1359
+ INPUT:
1360
+
1361
+ - ``v`` -- a real or complex embedding of the number field
1362
+
1363
+ OUTPUT:
1364
+
1365
+ (Complex) `\tau = \omega_1/\omega_2` in the fundamental region
1366
+ of the upper half-plane.
1367
+
1368
+ EXAMPLES::
1369
+
1370
+ sage: E = EllipticCurve('37a')
1371
+ sage: H = E.height_function()
1372
+ sage: H.tau(QQ.places()[0])
1373
+ 1.22112736076463*I
1374
+ """
1375
+ return self.E.period_lattice(v).tau()
1376
+
1377
+ def wp_c(self, v):
1378
+ r"""
1379
+ Return a bound for the Weierstrass `\wp`-function.
1380
+
1381
+ INPUT:
1382
+
1383
+ - ``v`` -- a real or complex embedding of the number field
1384
+
1385
+ OUTPUT:
1386
+
1387
+ (Real) `c>0` such that
1388
+
1389
+ .. MATH::
1390
+
1391
+ |\wp(z) - z^-2| \le \frac{c^2|z|^2}{1-c|z|^2}
1392
+
1393
+ whenever `c|z|^2<1`. Given the recurrence relations for the
1394
+ Laurent series expansion of `\wp`, it is easy to see that
1395
+ there is such a constant `c`. [Reference?]
1396
+
1397
+ EXAMPLES::
1398
+
1399
+ sage: E = EllipticCurve('37a')
1400
+ sage: H = E.height_function()
1401
+ sage: H.wp_c(QQ.places()[0])
1402
+ 2.68744508779950
1403
+
1404
+ sage: # needs sage.rings.number_field
1405
+ sage: K.<i> = QuadraticField(-1)
1406
+ sage: E = EllipticCurve([0, 0, 0, 1 + 5*i, 3 + i])
1407
+ sage: H = E.height_function()
1408
+ sage: H.wp_c(K.places()[0])
1409
+ 2.66213425640096
1410
+ """
1411
+ # Note that we normalise w1, w2 differently from [Tho2010]_!
1412
+ w2, w1 = self.E.period_lattice(v).normalised_basis()
1413
+ return max(abs(v(self.E.c4()/240)) ** 0.5,
1414
+ abs(v(self.E.c6()/6048)) ** (1.0/3)) * abs(w1)**2
1415
+
1416
+ def fk_intervals(self, v=None, N=20, domain=CIF):
1417
+ r"""
1418
+ Return a function approximating the Weierstrass function, with error.
1419
+
1420
+ INPUT:
1421
+
1422
+ - ``v`` -- an embedding of the number field. If
1423
+ ``None`` (default) use the real embedding if the field is `\QQ`
1424
+ and raise an error for other fields.
1425
+
1426
+ - ``N`` -- integer; the number of terms to use in the
1427
+ `q`-expansion of `\wp`
1428
+
1429
+ - ``domain`` -- (complex field) the model of `\CC` to use, for
1430
+ example ``CDF`` of ``CIF`` (default)
1431
+
1432
+ OUTPUT:
1433
+
1434
+ A pair of functions fk, err which can be evaluated at complex
1435
+ numbers `z` (in the correct ``domain``) to give an
1436
+ approximation to `\wp(z)` and an upper bound on the error,
1437
+ respectively. The Weierstrass function returned is with
1438
+ respect to the normalised lattice `[1,\tau]` associated to the
1439
+ given embedding.
1440
+
1441
+ EXAMPLES::
1442
+
1443
+ sage: E = EllipticCurve('37a')
1444
+ sage: L = E.period_lattice()
1445
+ sage: w1, w2 = L.normalised_basis()
1446
+ sage: z = CDF(0.3, 0.4)
1447
+
1448
+ Compare the value give by the standard elliptic exponential
1449
+ (scaled since ``fk`` is with respect to the normalised
1450
+ lattice)::
1451
+
1452
+ sage: L.elliptic_exponential(z*w2, to_curve=False)[0] * w2 ** 2
1453
+ -1.82543539306049 - 2.49336319992847*I
1454
+
1455
+ to the value given by this function, and see the error::
1456
+
1457
+ sage: fk, err = E.height_function().fk_intervals(N=10)
1458
+ sage: fk(CIF(z))
1459
+ -1.82543539306049? - 2.49336319992847?*I
1460
+ sage: err(CIF(z))
1461
+ 2.71750621458744e-31
1462
+
1463
+ The same, but in the domain ``CDF`` instead of ``CIF``::
1464
+
1465
+ sage: fk, err = E.height_function().fk_intervals(N=10, domain=CDF)
1466
+ sage: fk(z)
1467
+ -1.8254353930604... - 2.493363199928...*I
1468
+ """
1469
+ if v is None:
1470
+ if self.K is QQ:
1471
+ v = QQ.hom(RR)
1472
+ else:
1473
+ raise ValueError("must specify embedding")
1474
+ # pre-compute some constants
1475
+ tau = self.tau(v)
1476
+ const_term = 1/CC(12)
1477
+ qn = q = (2 * CC.gen() * CC.pi() * tau).exp()
1478
+ for n in range(1, N):
1479
+ const_term -= 2 * qn/(1-qn) ** 2
1480
+ qn *= q
1481
+
1482
+ two_pi_i = 2 * domain.gen() * domain.pi()
1483
+ neg_four_pi2 = -4 * domain.pi() ** 2
1484
+ const_term = domain(const_term)
1485
+ tau = domain(tau)
1486
+
1487
+ abs_q = abs(domain(q))
1488
+ abs_qN = abs(domain(qn))
1489
+ err_factor = abs(neg_four_pi2) / (1-abs_q)
1490
+ err_term = 2*abs_qN/(1-abs_qN) ** 2
1491
+
1492
+ # choose u/(1-u)^2 evaluation method
1493
+ if domain is CIF:
1494
+ rat_term = rat_term_CIF
1495
+ else:
1496
+ def rat_term(z):
1497
+ u = (two_pi_i*z).exp()
1498
+ return u/(1-u)**2
1499
+
1500
+ # the actual series
1501
+ def fk(z):
1502
+ return (const_term +
1503
+ sum([rat_term(z+n*tau) for n in range(1-N,N)])
1504
+ ) * neg_four_pi2
1505
+
1506
+ # the error function
1507
+ def err(z):
1508
+ alpha = z.imag() / tau.imag()
1509
+ qNa = abs_q**(N+alpha)
1510
+ qNai = abs_q**(N-alpha)
1511
+ return (err_factor * (qNa/(1-qNa) ** 2 + qNai/(1-qNai) ** 2 + err_term)).upper()
1512
+
1513
+ return fk, err
1514
+
1515
+ @cached_method
1516
+ def wp_intervals(self, v=None, N=20, abs_only=False):
1517
+ r"""
1518
+ Return a function approximating the Weierstrass function.
1519
+
1520
+ INPUT:
1521
+
1522
+ - ``v`` -- an embedding of the number field; if
1523
+ ``None`` (default) use the real embedding if the field is `\QQ`
1524
+ and raise an error for other fields
1525
+
1526
+ - ``N`` -- integer (default: 20); The number of terms to use in the
1527
+ `q`-expansion of `\wp`
1528
+
1529
+ - ``abs_only``-- boolean (default: ``False``); flag to determine
1530
+ whether (if ``True``) the error adjustment should use the
1531
+ absolute value or (if ``False``) the real and imaginary parts
1532
+
1533
+ OUTPUT:
1534
+
1535
+ A function wp which can be evaluated at complex numbers `z` to
1536
+ give an approximation to `\wp(z)`. The Weierstrass function
1537
+ returned is with respect to the normalised lattice `[1,\tau]`
1538
+ associated to the given embedding. For `z` which are not near
1539
+ a lattice point the function ``fk`` is used, otherwise a
1540
+ better approximation is used.
1541
+
1542
+ EXAMPLES::
1543
+
1544
+ sage: E = EllipticCurve('37a')
1545
+ sage: wp = E.height_function().wp_intervals()
1546
+ sage: z = CDF(0.3, 0.4)
1547
+ sage: wp(CIF(z))
1548
+ -1.82543539306049? - 2.4933631999285?*I
1549
+
1550
+ sage: L = E.period_lattice()
1551
+ sage: w1, w2 = L.normalised_basis()
1552
+ sage: L.elliptic_exponential(z*w2, to_curve=False)[0] * w2^2
1553
+ -1.82543539306049 - 2.49336319992847*I
1554
+
1555
+ sage: z = CDF(0.3, 0.1)
1556
+ sage: wp(CIF(z))
1557
+ 8.5918243572165? - 5.4751982004351?*I
1558
+ sage: L.elliptic_exponential(z*w2, to_curve=False)[0] * w2^2
1559
+ 8.59182435721650 - 5.47519820043503*I
1560
+ """
1561
+ if v is None:
1562
+ if self.K is QQ:
1563
+ v = QQ.hom(RR)
1564
+ else:
1565
+ raise ValueError("must specify embedding")
1566
+
1567
+ tau = self.tau(v)
1568
+ fk, fk_err = self.fk_intervals(v, N)
1569
+ c = self.wp_c(v)
1570
+
1571
+ def wp(z):
1572
+
1573
+ # center around origin
1574
+ offset = (z.imag().lower() / tau.imag()).round()
1575
+ if offset:
1576
+ z -= CIF(offset * tau)
1577
+ offset = z.real().lower().round()
1578
+ if offset:
1579
+ z -= offset
1580
+
1581
+ # estimate using the series
1582
+ approx = fk(z)
1583
+ err = fk_err(z)
1584
+ if abs_only:
1585
+ approx = abs(approx)
1586
+ approx += eps(err, abs_only)
1587
+
1588
+ # refine using an estimate that's better near the pole
1589
+ z_bound = abs(z).upper()
1590
+ cz2 = c * z_bound ** 2
1591
+ if cz2 < 1:
1592
+ err = (c * cz2) / (1 - cz2)
1593
+ if abs_only:
1594
+ pole_approx = abs(z) ** -2
1595
+ else:
1596
+ pole_approx = z ** -2
1597
+ approx = approx.intersection(pole_approx + eps(err, abs_only))
1598
+ return approx
1599
+ return wp
1600
+
1601
+ @cached_method
1602
+ def wp_on_grid(self, v, N, half=False):
1603
+ r"""
1604
+ Return an array of the values of `\wp` on an `N\times N` grid.
1605
+
1606
+ INPUT:
1607
+
1608
+ - ``v`` -- an embedding of the number field
1609
+
1610
+ - ``N`` -- integer; the number of terms to use in the
1611
+ `q`-expansion of `\wp`
1612
+
1613
+ - ``half``-- boolean (default: ``False``); if ``True``, use an array of
1614
+ size `N\times N/2` instead of `N\times N`
1615
+
1616
+ OUTPUT:
1617
+
1618
+ An array of size either `N\times N/2` or `N\times N` whose
1619
+ `(i,j)` entry is the value of the Weierstrass `\wp`-function
1620
+ at `(i+.5)/N + (j+.5)*\tau/N`, a grid of points in the
1621
+ fundamental region for the lattice `[1,\tau]`.
1622
+
1623
+ EXAMPLES::
1624
+
1625
+ sage: E = EllipticCurve('37a')
1626
+ sage: H = E.height_function()
1627
+ sage: v = QQ.places()[0]
1628
+
1629
+ The array of values on the grid shows symmetry, since `\wp` is
1630
+ even::
1631
+
1632
+ sage: H.wp_on_grid(v, 4) # needs sage.symbolic
1633
+ array([[25.43920182, 5.28760943, 5.28760943, 25.43920182],
1634
+ [ 6.05099485, 1.83757786, 1.83757786, 6.05099485],
1635
+ [ 6.05099485, 1.83757786, 1.83757786, 6.05099485],
1636
+ [25.43920182, 5.28760943, 5.28760943, 25.43920182]])
1637
+
1638
+ The array of values on the half-grid::
1639
+
1640
+ sage: H.wp_on_grid(v, 4, True) # needs sage.symbolic
1641
+ array([[25.43920182, 5.28760943],
1642
+ [ 6.05099485, 1.83757786],
1643
+ [ 6.05099485, 1.83757786],
1644
+ [25.43920182, 5.28760943]])
1645
+ """
1646
+ tau = self.tau(v)
1647
+ fk, err = self.fk_intervals(v, 15, CDF)
1648
+ var_z = SR.var('z')
1649
+ ff = fast_callable(fk(var_z), CDF, [var_z])
1650
+ N_or_half = N // (1+half) # array is NxN or Nx(N/2)
1651
+ vals = numpy.empty((N,N_or_half)) # empty array tp hold values
1652
+ for i in range(N):
1653
+ for j in range(N_or_half):
1654
+ vals[i,j] = abs(ff((i+.5)/N + (j+.5)*tau/N))
1655
+ return vals
1656
+
1657
+ def complex_intersection_is_empty(self, Bk, v, verbose=False, use_half=True):
1658
+ r"""
1659
+ Return ``True`` iff an intersection of `T_n^{(v)}` sets is empty.
1660
+
1661
+ INPUT:
1662
+
1663
+ - ``Bk`` -- list of reals
1664
+
1665
+ - ``v`` -- a complex embedding of the number field
1666
+
1667
+ - ``verbose``-- boolean (default: ``False``); verbosity flag
1668
+
1669
+ - ``use_half``-- boolean (default: ``False``); if ``True``, use only half
1670
+ the fundamental region
1671
+
1672
+ OUTPUT:
1673
+
1674
+ ``True`` or ``False``, according as the intersection of the unions of
1675
+ intervals `T_n^{(v)}(-b,b)` for `b` in the list ``Bk`` (see
1676
+ [Tho2010]_, section 7) is empty or not. When ``Bk`` is the list of
1677
+ `b=\sqrt{B_n(\mu)}` for `n=1,2,3,\dots` for some `\mu>0` this
1678
+ means that all non-torsion points on `E` with everywhere good
1679
+ reduction have canonical height strictly greater than `\mu`,
1680
+ by [Tho2010]_, Proposition 7.8.
1681
+
1682
+ EXAMPLES::
1683
+
1684
+ sage: # needs sage.rings.number_field
1685
+ sage: x = polygen(ZZ, 'x')
1686
+ sage: K.<a> = NumberField(x^3 - 2)
1687
+ sage: E = EllipticCurve([0,0,0,0,a])
1688
+ sage: v = K.complex_embeddings()[0]
1689
+ sage: H = E.height_function()
1690
+
1691
+ The following two lines prove that the heights of non-torsion
1692
+ points on `E` with everywhere good reduction have canonical
1693
+ height strictly greater than 0.02, but fail to prove the same
1694
+ for 0.03. For the first proof, using only `n=1,2,3` is not
1695
+ sufficient::
1696
+
1697
+ sage: H.complex_intersection_is_empty([H.B(n, 0.02) for n in [1,2,3]], v) # long time, needs sage.rings.number_field sage.symbolic
1698
+ False
1699
+ sage: H.complex_intersection_is_empty([H.B(n, 0.02) for n in [1,2,3,4]], v) # needs sage.rings.number_field sage.symbolic
1700
+ True
1701
+ sage: H.complex_intersection_is_empty([H.B(n, 0.03) for n in [1,2,3,4]], v) # long time, needs sage.rings.number_field sage.symbolic
1702
+ False
1703
+
1704
+ Using `n\le6` enables us to prove the lower bound 0.03. Note
1705
+ that it takes longer when the result is ``False`` than when it
1706
+ is ``True``::
1707
+
1708
+ sage: H.complex_intersection_is_empty([H.B(n, 0.03) for n in [1..6]], v) # needs sage.rings.number_field sage.symbolic
1709
+ True
1710
+ """
1711
+ from sage.schemes.elliptic_curves.period_lattice_region import PeriodicRegion
1712
+
1713
+ b2 = v(self.E.b2())
1714
+ # Note that we normalise w1, w2 differently from [Tho2010]_!
1715
+ w2, w1 = self.E.period_lattice(v).normalised_basis()
1716
+ tau = w2/w1
1717
+ bounds = [RDF((B.sqrt() + abs(b2)/12) * abs(w1) ** 2) for B in Bk]
1718
+ vals = self.wp_on_grid(v, 30, half=use_half)
1719
+ wp = self.wp_intervals(v, abs_only=True)
1720
+
1721
+ k = len(bounds)
1722
+
1723
+ # First try and prove a negative result (cheap).
1724
+ if verbose:
1725
+ print("trying to prove negative result...")
1726
+ intersection = None
1727
+ for B, n in sorted(zip(bounds, ZZ.range(1, k+1))):
1728
+ T = PeriodicRegion(CDF(1), CDF(tau), vals < B, full=not use_half)
1729
+ if intersection is None:
1730
+ intersection = PeriodicRegion(CDF(1), CDF(tau), vals < B, full=not use_half)
1731
+ else:
1732
+ intersection &= T/n
1733
+ if intersection.is_empty():
1734
+ break
1735
+ else:
1736
+ z = CIF(intersection.innermost_point())
1737
+ if all(wp((k+1)*z).upper() < B for k, B in enumerate(bounds)):
1738
+ return False
1739
+
1740
+ # Now try to prove a positive result.
1741
+ if verbose:
1742
+ print("trying to prove positive result...")
1743
+ intersection = None
1744
+ for B, n in sorted(zip(bounds, ZZ.range(1, k+1))):
1745
+
1746
+ T = PeriodicRegion(CDF(1), CDF(tau), vals < B, full=not use_half).expand().refine()
1747
+ B = RIF(B)
1748
+ leaning_right = tau.real() / tau.imag() >= 0
1749
+
1750
+ def check_line(z):
1751
+ wpz = wp(z)
1752
+ if wpz > B:
1753
+ return True
1754
+ # Try refining once before we declare failure.
1755
+ z00, z01, z10, z11 = z.bisection()
1756
+ if leaning_right:
1757
+ start, end = z00, z11
1758
+ else:
1759
+ start, end = z01, z10
1760
+ return wp(start) > B and wp(end) > B
1761
+
1762
+ # This step here is the bottleneck.
1763
+ while not T.verify(check_line):
1764
+ if verbose:
1765
+ print("bad")
1766
+ T = T.expand()
1767
+ if intersection is None:
1768
+ intersection = T
1769
+ else:
1770
+ intersection &= T/n
1771
+ if intersection.is_empty():
1772
+ return True
1773
+
1774
+ return False
1775
+
1776
+ def test_mu(self, mu, N, verbose=True):
1777
+ r"""
1778
+ Return ``True`` if we can prove that `\mu` is a lower bound.
1779
+
1780
+ INPUT:
1781
+
1782
+ - ``mu`` -- positive real number
1783
+
1784
+ - ``N`` -- integer; upper bound on the multiples to be used
1785
+
1786
+ - ``verbose``-- boolean (default: ``True``); verbosity flag
1787
+
1788
+ OUTPUT:
1789
+
1790
+ ``True`` or ``False``, according to whether we succeed in
1791
+ proving that `\mu` is a lower bound for the canonical heights
1792
+ of points of infinite order with everywhere good reduction.
1793
+
1794
+ .. NOTE::
1795
+
1796
+ A ``True`` result is rigorous; ``False`` only means that
1797
+ the attempt failed: trying again with larger `N` may yield
1798
+ ``True``.
1799
+
1800
+ EXAMPLES::
1801
+
1802
+ sage: x = polygen(ZZ, 'x')
1803
+ sage: K.<a> = NumberField(x^3 - 2) # needs sage.rings.number_field
1804
+ sage: E = EllipticCurve([0,0,0,0,a]) # needs sage.rings.number_field
1805
+ sage: H = E.height_function() # needs sage.rings.number_field
1806
+
1807
+ This curve does have a point of good reduction whose canonical
1808
+ point is approximately 1.68::
1809
+
1810
+ sage: P = E.gens(lim3=5)[0]; P # needs sage.rings.number_field
1811
+ (1/3*a^2 + a + 5/3 : -2*a^2 - 4/3*a - 5/3 : 1)
1812
+ sage: P.height() # needs sage.rings.number_field
1813
+ 1.68038085233673
1814
+ sage: P.has_good_reduction() # needs sage.rings.number_field
1815
+ True
1816
+
1817
+ Using `N=5` we can prove that 0.1 is a lower bound (in fact we
1818
+ only need `N=2`), but not that 0.2 is::
1819
+
1820
+ sage: H.test_mu(0.1, 5) # needs sage.rings.number_field sage.symbolic
1821
+ B_1(0.100000000000000) = 1.51580969677387
1822
+ B_2(0.100000000000000) = 0.932072561526720
1823
+ True
1824
+ sage: H.test_mu(0.2, 5) # needs sage.rings.number_field sage.symbolic
1825
+ B_1(0.200000000000000) = 2.04612906979932
1826
+ B_2(0.200000000000000) = 3.09458988474327
1827
+ B_3(0.200000000000000) = 27.6251108409484
1828
+ B_4(0.200000000000000) = 1036.24722370223
1829
+ B_5(0.200000000000000) = 3.67090854562318e6
1830
+ False
1831
+
1832
+ Since 0.1 is a lower bound we can deduce that the point `P` is
1833
+ either primitive or divisible by either 2 or 3. In fact it is
1834
+ primitive::
1835
+
1836
+ sage: (P.height()/0.1).sqrt() # needs sage.rings.number_field
1837
+ 4.09924487233530
1838
+ sage: P.division_points(2) # needs sage.rings.number_field
1839
+ []
1840
+ sage: P.division_points(3) # needs sage.rings.number_field
1841
+ []
1842
+ """
1843
+ # Compute the list of values `B_n(\mu)` for n in 1..N. If any
1844
+ # of these is 1 we can return True right away (see [Tho2010]_,
1845
+ # Proposition 5.1).
1846
+ Bk = []
1847
+ for n in ZZ.range(1, N + 1):
1848
+ b = self.B(n, mu)
1849
+ if verbose:
1850
+ print("B_%s(%s) = %s" % (n, mu, b))
1851
+ if b < 1:
1852
+ return True
1853
+ Bk.append(b)
1854
+
1855
+ # Each real or complex embedding of the number field gives us
1856
+ # a chance to prove the lower bound. We try each in turn,
1857
+ # stopping if one gives a True result.
1858
+
1859
+ from sage.rings.number_field.number_field import refine_embedding
1860
+ for v in self.K.places():
1861
+ ok = False
1862
+ while not ok:
1863
+ try:
1864
+ if v(self.K.gen()) in RR:
1865
+ if self.real_intersection_is_empty(Bk, v):
1866
+ return True
1867
+ else:
1868
+ if self.complex_intersection_is_empty(Bk, v):
1869
+ return True
1870
+ ok = True
1871
+ except ArithmeticError:
1872
+ v = refine_embedding(v)
1873
+ if verbose:
1874
+ print("Refining embedding, codomain now {}".format(v.codomain()))
1875
+ return False # Couldn't prove it...
1876
+
1877
+ def min_gr(self, tol, n_max, verbose=False):
1878
+ r"""
1879
+ Return a lower bound for points of infinite order with good reduction.
1880
+
1881
+ INPUT:
1882
+
1883
+ - ``tol`` -- tolerance in output (see below)
1884
+
1885
+ - ``n_max`` -- how many multiples to use in iteration
1886
+
1887
+ - ``verbose``-- boolean (default: ``False``); verbosity flag
1888
+
1889
+ OUTPUT:
1890
+
1891
+ A positive real `\mu` for which it has been established
1892
+ rigorously that every point of infinite order on the elliptic
1893
+ curve (defined over its ground field), which has good
1894
+ reduction at all primes, has canonical height greater than
1895
+ `\mu`, and such that it is not possible (at least without
1896
+ increasing ``n_max``) to prove the same for
1897
+ `\mu\cdot\text{tol}`.
1898
+
1899
+ EXAMPLES:
1900
+
1901
+ Example 1 from [CS2006]_ (where a lower bound of 1.9865 was
1902
+ given)::
1903
+
1904
+ sage: E = EllipticCurve([1, 0, 1, 421152067, 105484554028056]) # 60490d1
1905
+ sage: E.height_function().min_gr(.0001, 5) # needs sage.symbolic
1906
+ 1.98684388146518
1907
+
1908
+ Example 10.1 from [Tho2010]_ (where a lower bound of 0.18 was
1909
+ given)::
1910
+
1911
+ sage: # needs sage.rings.number_field
1912
+ sage: K.<i> = QuadraticField(-1)
1913
+ sage: E = EllipticCurve([0, 0, 0, 91 - 26*i, -144 - 323*i])
1914
+ sage: H = E.height_function()
1915
+ sage: H.min_gr(0.1, 4) # long time, needs sage.symbolic
1916
+ 0.1621049443313762
1917
+
1918
+ Example 10.2 from [Tho2010]_::
1919
+
1920
+ sage: # needs sage.rings.number_field
1921
+ sage: K.<i> = QuadraticField(-1)
1922
+ sage: E = EllipticCurve([0, 1 - i, i, -i, 0])
1923
+ sage: H = E.height_function()
1924
+ sage: H.min_gr(0.01, 5) # long time, needs sage.symbolic
1925
+ 0.020153685521979152
1926
+
1927
+ In this example the point `P=(0,0)` has height 0.023 so our
1928
+ lower bound is quite good::
1929
+
1930
+ sage: P = E((0,0)) # needs sage.rings.number_field
1931
+ sage: P.has_good_reduction() # needs sage.rings.number_field
1932
+ True
1933
+ sage: P.height() # needs sage.rings.number_field
1934
+ 0.0230242154471211
1935
+
1936
+ Example 10.3 from [Tho2010]_ (where the same bound of 0.25 is
1937
+ given)::
1938
+
1939
+ sage: # needs sage.rings.number_field
1940
+ sage: x = polygen(ZZ, 'x')
1941
+ sage: K.<a> = NumberField(x^3 - 2)
1942
+ sage: E = EllipticCurve([0, 0, 0, -3*a - a^2, a^2])
1943
+ sage: H = E.height_function()
1944
+ sage: H.min_gr(0.1, 5) # long time, needs sage.symbolic
1945
+ 0.25
1946
+
1947
+ TESTS:
1948
+
1949
+ This example from the LMFDB gave problems before the fix in :issue:`8829`::
1950
+
1951
+ sage: # needs sage.rings.number_field
1952
+ sage: x = polygen(ZZ, 'x')
1953
+ sage: K.<phi> = NumberField(x^2 - x - 1)
1954
+ sage: E = EllipticCurve([phi + 1, -phi + 1, 1, 20*phi - 39, 196*phi + 237])
1955
+ sage: H = E.height_function()
1956
+ sage: H.min_gr(.1, 5, verbose=True) # long time, needs sage.symbolic
1957
+ B_1(1) = 1540.199246369678
1958
+ ...
1959
+ halving mu to 0.25 and increasing n_max to 6
1960
+ ...
1961
+ halving mu to 0.001953125 and increasing n_max to 13
1962
+ doubling mu to 0.0078125
1963
+ doubling mu to 0.015625
1964
+ height bound in [0.0078125, 0.015625] using n_max = 13
1965
+ ...
1966
+ height bound in [0.012048522073499539, 0.01313900648833929] using n_max = 13
1967
+ 0.012048522073499539
1968
+ """
1969
+ test = self.test_mu
1970
+ if test(1, n_max, verbose):
1971
+ mu = 2.0
1972
+ while test(mu, n_max, False):
1973
+ mu *= 2
1974
+ mu *= 0.5
1975
+ else:
1976
+ mu = 0.5
1977
+ while not test(mu, n_max, False):
1978
+ mu *= 0.5
1979
+ n_max += 1
1980
+ if verbose:
1981
+ print("halving mu to %r and increasing n_max to %r" % (mu, n_max))
1982
+ # now we have (mu,n_max) which work we can try to increase
1983
+ # mu again using this larger n_max:
1984
+ mu *= 2
1985
+ while test(mu, n_max, False):
1986
+ mu *= 2
1987
+ if verbose:
1988
+ print("doubling mu to %r" % mu)
1989
+ mu *= 0.5
1990
+
1991
+ # The true value lies between mu and eps * mu.
1992
+ eps = 2.0
1993
+ while eps > tol + 1:
1994
+ if verbose:
1995
+ print("height bound in [%r, %r] using n_max = %r"
1996
+ % (mu, mu * eps, n_max))
1997
+ eps = math.sqrt(eps)
1998
+ if test(mu * eps, n_max, False):
1999
+ mu = mu * eps
2000
+ if verbose:
2001
+ print("height bound in [%r, %r] using n_max = %r"
2002
+ % (mu, mu * eps, n_max))
2003
+ return RDF(mu)
2004
+
2005
+ def min(self, tol, n_max, verbose=False):
2006
+ r"""
2007
+ Return a lower bound for all points of infinite order.
2008
+
2009
+ INPUT:
2010
+
2011
+ - ``tol`` -- tolerance in output (see below)
2012
+
2013
+ - ``n_max`` -- how many multiples to use in iteration
2014
+
2015
+ - ``verbose``-- boolean (default: ``False``); verbosity flag
2016
+
2017
+ OUTPUT:
2018
+
2019
+ A positive real `\mu` for which it has been established
2020
+ rigorously that every point of infinite order on the elliptic
2021
+ curve (defined over its ground field) has canonical height
2022
+ greater than `\mu`, and such that it is not possible (at least
2023
+ without increasing ``n_max``) to prove the same for
2024
+ `\mu\cdot\text{tol}`.
2025
+
2026
+ EXAMPLES:
2027
+
2028
+ Example 1 from [CS2006]_ (where the same lower bound of 0.1126 was
2029
+ given)::
2030
+
2031
+ sage: E = EllipticCurve([1, 0, 1, 421152067, 105484554028056]) # 60490d1
2032
+ sage: E.height_function().min(.0001, 5) # needs sage.symbolic
2033
+ 0.0011263287309893311
2034
+
2035
+ Example 10.1 from [Tho2010]_ (where a lower bound of 0.18 was
2036
+ given)::
2037
+
2038
+ sage: # needs sage.rings.number_field
2039
+ sage: K.<i> = QuadraticField(-1)
2040
+ sage: E = EllipticCurve([0, 0, 0, 91 - 26*i, -144 - 323*i])
2041
+ sage: H = E.height_function()
2042
+ sage: H.min(0.1, 4) # long time
2043
+ 0.1621049443313762
2044
+
2045
+ Example 10.2 from [Tho2010]_::
2046
+
2047
+ sage: # needs sage.rings.number_field
2048
+ sage: K.<i> = QuadraticField(-1)
2049
+ sage: E = EllipticCurve([0, 1 - i, i, -i, 0])
2050
+ sage: H = E.height_function()
2051
+ sage: H.min(0.01, 5) # long time
2052
+ 0.020153685521979152
2053
+
2054
+ In this example the point `P=(0,0)` has height 0.023 so our
2055
+ lower bound is quite good::
2056
+
2057
+ sage: P = E((0,0)) # needs sage.rings.number_field
2058
+ sage: P.height() # needs sage.rings.number_field
2059
+ 0.0230242154471211
2060
+
2061
+ Example 10.3 from [Tho2010]_ (where the same bound of 0.0625 is
2062
+ given)::
2063
+
2064
+ sage: # needs sage.rings.number_field
2065
+ sage: x = polygen(ZZ, 'x')
2066
+ sage: K.<a> = NumberField(x^3 - 2)
2067
+ sage: E = EllipticCurve([0, 0, 0, -3*a - a^2, a^2])
2068
+ sage: H = E.height_function()
2069
+ sage: H.min(0.1, 5) # long time
2070
+ 0.0625
2071
+
2072
+ More examples over `\QQ`::
2073
+
2074
+ sage: E = EllipticCurve('37a')
2075
+ sage: h = E.height_function()
2076
+ sage: h.min(.01, 5) # needs sage.symbolic
2077
+ 0.03987318057488725
2078
+ sage: E.gen(0).height()
2079
+ 0.0511114082399688
2080
+
2081
+ After base change the lower bound can decrease::
2082
+
2083
+ sage: K.<a> = QuadraticField(-5) # needs sage.rings.number_field
2084
+ sage: E.change_ring(K).height_function().min(0.5, 10) # long time, needs sage.rings.number_field sage.symbolic
2085
+ 0.04419417382415922
2086
+
2087
+ sage: E = EllipticCurve('389a')
2088
+ sage: h = E.height_function()
2089
+ sage: h.min(0.1, 5) # needs sage.symbolic
2090
+ 0.05731275270029196
2091
+ sage: [P.height() for P in E.gens()]
2092
+ [0.686667083305587, 0.327000773651605]
2093
+ """
2094
+ # The lcm of the exponents of all the component groups at
2095
+ # finite places (allowing for everywhere good reduction!)
2096
+ tp = lcm([L.tamagawa_exponent() for L in self.E.local_data()] + [ZZ(1)])
2097
+
2098
+ # Include infinite places:
2099
+ if tp % 2 == 1:
2100
+ if self.K == QQ:
2101
+ if self.E.real_components() == 2:
2102
+ tp *= 2
2103
+ elif any(v(self.E.discriminant()) > 0
2104
+ for v in self.K.real_places()):
2105
+ tp *= 2
2106
+ # Now tp is such that tp*P has good reduction at all places
2107
+ # for all points P:
2108
+ return self.min_gr(tol, n_max, verbose) / tp ** 2