passagemath-schemes 10.6.47__cp312-cp312-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) 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.47.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
  9. passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.47.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-312-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-312-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-312-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-312-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-312-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-312-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-312-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-312-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_nf.py +1241 -0
  154. sage/modular/modsym/relation_matrix.py +591 -0
  155. sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
  156. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  157. sage/modular/modsym/space.py +2468 -0
  158. sage/modular/modsym/subspace.py +455 -0
  159. sage/modular/modsym/tests.py +375 -0
  160. sage/modular/multiple_zeta.py +2632 -0
  161. sage/modular/multiple_zeta_F_algebra.py +786 -0
  162. sage/modular/overconvergent/all.py +6 -0
  163. sage/modular/overconvergent/genus0.py +1878 -0
  164. sage/modular/overconvergent/hecke_series.py +1187 -0
  165. sage/modular/overconvergent/weightspace.py +778 -0
  166. sage/modular/pollack_stevens/all.py +4 -0
  167. sage/modular/pollack_stevens/distributions.py +874 -0
  168. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  169. sage/modular/pollack_stevens/manin_map.py +859 -0
  170. sage/modular/pollack_stevens/modsym.py +1593 -0
  171. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  172. sage/modular/pollack_stevens/sigma0.py +534 -0
  173. sage/modular/pollack_stevens/space.py +1076 -0
  174. sage/modular/quasimodform/all.py +3 -0
  175. sage/modular/quasimodform/element.py +845 -0
  176. sage/modular/quasimodform/ring.py +828 -0
  177. sage/modular/quatalg/all.py +3 -0
  178. sage/modular/quatalg/brandt.py +1642 -0
  179. sage/modular/ssmod/all.py +8 -0
  180. sage/modular/ssmod/ssmod.py +827 -0
  181. sage/rings/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  183. sage/rings/polynomial/binary_form_reduce.py +585 -0
  184. sage/schemes/all.py +41 -0
  185. sage/schemes/berkovich/all.py +6 -0
  186. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  187. sage/schemes/berkovich/berkovich_space.py +748 -0
  188. sage/schemes/curves/affine_curve.py +2928 -0
  189. sage/schemes/curves/all.py +33 -0
  190. sage/schemes/curves/closed_point.py +434 -0
  191. sage/schemes/curves/constructor.py +381 -0
  192. sage/schemes/curves/curve.py +542 -0
  193. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  194. sage/schemes/curves/point.py +463 -0
  195. sage/schemes/curves/projective_curve.py +3026 -0
  196. sage/schemes/curves/zariski_vankampen.py +1932 -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 +1036 -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 +1102 -0
  208. sage/schemes/elliptic_curves/constructor.py +1552 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -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 +4787 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -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 +1669 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7335 -0
  229. sage/schemes/elliptic_curves/height.py +2109 -0
  230. sage/schemes/elliptic_curves/hom.py +1406 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  232. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  233. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  234. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  235. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  236. sage/schemes/elliptic_curves/homset.py +271 -0
  237. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  238. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  239. sage/schemes/elliptic_curves/jacobian.py +237 -0
  240. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  241. sage/schemes/elliptic_curves/kraus.py +1014 -0
  242. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  243. sage/schemes/elliptic_curves/mod5family.py +105 -0
  244. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  245. sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  247. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  248. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  249. sage/schemes/elliptic_curves/padics.py +1816 -0
  250. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  251. sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  253. sage/schemes/elliptic_curves/saturation.py +715 -0
  254. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  255. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  256. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  257. sage/schemes/hyperelliptic_curves/all.py +6 -0
  258. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  259. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  264. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  265. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  270. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  271. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  272. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  273. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  274. sage/schemes/jacobians/all.py +2 -0
  275. sage/schemes/overview.py +161 -0
  276. sage/schemes/plane_conics/all.py +22 -0
  277. sage/schemes/plane_conics/con_field.py +1296 -0
  278. sage/schemes/plane_conics/con_finite_field.py +158 -0
  279. sage/schemes/plane_conics/con_number_field.py +456 -0
  280. sage/schemes/plane_conics/con_rational_field.py +406 -0
  281. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  282. sage/schemes/plane_conics/constructor.py +249 -0
  283. sage/schemes/plane_quartics/all.py +2 -0
  284. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  285. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  286. sage/schemes/riemann_surfaces/all.py +1 -0
  287. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  288. sage_wheels/share/cremona/cremona_mini.db +0 -0
  289. sage_wheels/share/ellcurves/rank0 +30427 -0
  290. sage_wheels/share/ellcurves/rank1 +31871 -0
  291. sage_wheels/share/ellcurves/rank10 +6 -0
  292. sage_wheels/share/ellcurves/rank11 +6 -0
  293. sage_wheels/share/ellcurves/rank12 +1 -0
  294. sage_wheels/share/ellcurves/rank14 +1 -0
  295. sage_wheels/share/ellcurves/rank15 +1 -0
  296. sage_wheels/share/ellcurves/rank17 +1 -0
  297. sage_wheels/share/ellcurves/rank19 +1 -0
  298. sage_wheels/share/ellcurves/rank2 +2388 -0
  299. sage_wheels/share/ellcurves/rank20 +1 -0
  300. sage_wheels/share/ellcurves/rank21 +1 -0
  301. sage_wheels/share/ellcurves/rank22 +1 -0
  302. sage_wheels/share/ellcurves/rank23 +1 -0
  303. sage_wheels/share/ellcurves/rank24 +1 -0
  304. sage_wheels/share/ellcurves/rank28 +1 -0
  305. sage_wheels/share/ellcurves/rank3 +836 -0
  306. sage_wheels/share/ellcurves/rank4 +10 -0
  307. sage_wheels/share/ellcurves/rank5 +5 -0
  308. sage_wheels/share/ellcurves/rank6 +5 -0
  309. sage_wheels/share/ellcurves/rank7 +5 -0
  310. sage_wheels/share/ellcurves/rank8 +6 -0
  311. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,2109 @@
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):
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):
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):
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):
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: # we may beat the record, cannot yet tell: insert this region
638
+ # into the list at the appropriate place to maintain sorting
639
+ bisect.insort(L, (-fs.lower(), fs.relative_diameter(), s, s_in_disk))
640
+
641
+ # If we get here, then even after max_iter iterations the tolerance has not been reached.
642
+ raise ValueError("too many iterations")
643
+
644
+
645
+ two_pi_i_CDF = CDF(0, 2 * RDF.pi())
646
+ two_pi_i_CIF = CIF(0, 2 * RIF.pi())
647
+
648
+ # Ideas: We know tau, so we know the direction of the diagonal.
649
+ # We can solve for x in p1, will this allow us to find the maxima exactly?
650
+
651
+
652
+ def rat_term_CIF(z, try_strict=True):
653
+ r"""
654
+ Compute the value of `u/(1-u)^2` in ``CIF``, where `u=\exp(2\pi i z)`.
655
+
656
+ INPUT:
657
+
658
+ - ``z`` -- complex; a CIF element
659
+
660
+ - ``try_strict`` -- boolean; flag
661
+
662
+ EXAMPLES::
663
+
664
+ sage: from sage.schemes.elliptic_curves.height import rat_term_CIF
665
+ sage: z = CIF(0.5,0.2)
666
+ sage: rat_term_CIF(z)
667
+ -0.172467461182437? + 0.?e-16*I
668
+ sage: rat_term_CIF(z, False)
669
+ -0.172467461182437? + 0.?e-16*I
670
+ """
671
+ two_pi_i_z = two_pi_i_CIF * z
672
+ r = (two_pi_i_z.real()).exp() # = |u|
673
+ x, y = two_pi_i_z.imag().cos(), two_pi_i_z.imag().sin()
674
+
675
+ real_part = imag_part = None
676
+
677
+ # If there are no local minima the intervals are strictly
678
+ # determined by their values at the endpoints.
679
+
680
+ if try_strict:
681
+
682
+ # evaluate the function at the four corners:
683
+
684
+ corner_reals = []
685
+ corner_imags = []
686
+ for a, b in product(z.real().endpoints(), z.imag().endpoints()):
687
+ zz = CDF(a,b)
688
+ u = (two_pi_i_CDF*zz).exp()
689
+ f = u/(1-u)**2
690
+ corner_reals.append(f.real())
691
+ corner_imags.append(f.imag())
692
+
693
+ p1 = (((((r+2*x)*r - 6)*r + 2*x) * r) + 1)
694
+ # = r^4 + 2*r^3*x - 6*r^2 + 2*r*x + 1
695
+ p2 = (r*(x*(r+2*x)-4)+x)
696
+ # = r^2*x + 2*r*x^2 - 4*r + x
697
+
698
+ df_dr = (r**2-1) * p2
699
+ dg_dr = p1 * y
700
+ dg_dx = r * df_dr / y
701
+
702
+ if not dg_dr.contains_zero() or not dg_dx.contains_zero():
703
+ real_part = RIF(min(corner_reals), max(corner_reals))
704
+
705
+ if not dg_dr.contains_zero() or not dg_dx.contains_zero():
706
+ imag_part = RIF(min(corner_imags), max(corner_imags))
707
+
708
+ if real_part is None or imag_part is None:
709
+ denom = (1-r*(2*x-r))**2
710
+ if real_part is None:
711
+ real_part = r*(x*(1+r**2)-2*r)/denom
712
+ if imag_part is None:
713
+ imag_part = -(r**2-1)*y*r/denom
714
+
715
+ return CIF(real_part, imag_part)
716
+
717
+
718
+ def eps(err, is_real):
719
+ r"""
720
+ Return a Real or Complex interval centered on 0 with radius err.
721
+
722
+ INPUT:
723
+
724
+ - ``err`` -- a positive real number; the radius of the interval
725
+
726
+ - ``is_real`` -- boolean; if ``True``, returns a real interval in
727
+ RIF, else a complex interval in CIF
728
+
729
+ OUTPUT:
730
+
731
+ An element of RIF or CIF (as specified), centered on 0, with given radius.
732
+
733
+ EXAMPLES::
734
+
735
+ sage: from sage.schemes.elliptic_curves.height import eps
736
+ sage: eps(0.01, True)
737
+ 0.0?
738
+ sage: eps(0.01, False)
739
+ 0.0? + 0.0?*I
740
+ """
741
+ e = RIF(-err, err)
742
+ if is_real:
743
+ return e
744
+ else:
745
+ return CIF(e, e)
746
+
747
+
748
+ class EllipticCurveCanonicalHeight:
749
+ r"""
750
+ Class for computing canonical heights of points on elliptic curves
751
+ defined over number fields, including rigorous lower bounds for
752
+ the canonical height of non-torsion points.
753
+
754
+ EXAMPLES::
755
+
756
+ sage: from sage.schemes.elliptic_curves.height import EllipticCurveCanonicalHeight
757
+ sage: E = EllipticCurve([0,0,0,0,1])
758
+ sage: EllipticCurveCanonicalHeight(E)
759
+ EllipticCurveCanonicalHeight object associated to
760
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
761
+
762
+ Normally this object would be created like this::
763
+
764
+ sage: E.height_function()
765
+ EllipticCurveCanonicalHeight object associated to
766
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
767
+ """
768
+
769
+ def __init__(self, E):
770
+ r"""
771
+ Initialize the class with an elliptic curve.
772
+
773
+ INPUT:
774
+
775
+ - ``E`` -- an elliptic curve defined over a number field
776
+
777
+ EXAMPLES::
778
+
779
+ sage: from sage.schemes.elliptic_curves.height import EllipticCurveCanonicalHeight
780
+ sage: E = EllipticCurve([0,0,0,0,1])
781
+ sage: EllipticCurveCanonicalHeight(E)
782
+ EllipticCurveCanonicalHeight object associated to
783
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
784
+
785
+ An example over a number field::
786
+
787
+ sage: K.<i> = QuadraticField(-1) # needs sage.rings.number_field
788
+ sage: E = EllipticCurve([0,i,0,i,i]) # needs sage.rings.number_field
789
+ sage: EllipticCurveCanonicalHeight(E) # needs sage.rings.number_field
790
+ EllipticCurveCanonicalHeight object associated to
791
+ Elliptic Curve defined by y^2 = x^3 + i*x^2 + i*x + i
792
+ over Number Field in i with defining polynomial x^2 + 1 with i = 1*I
793
+
794
+ TESTS:
795
+
796
+ The base field must be a number field (or `\QQ`)::
797
+
798
+ sage: from sage.schemes.elliptic_curves.height import EllipticCurveCanonicalHeight
799
+ sage: E = EllipticCurve(GF(7), [0,0,0,0,1])
800
+ sage: EllipticCurveCanonicalHeight(E)
801
+ Traceback (most recent call last):
802
+ ...
803
+ ValueError: EllipticCurveCanonicalHeight class can only be created
804
+ from an elliptic curve defined over a number field
805
+ """
806
+ from sage.schemes.elliptic_curves.ell_generic import EllipticCurve_generic
807
+ if isinstance(E, EllipticCurve_generic):
808
+ self.E = E
809
+ from sage.rings.number_field.number_field_base import NumberField
810
+ K = E.base_ring()
811
+ if isinstance(K, NumberField):
812
+ self.K = K
813
+ else:
814
+ raise ValueError("EllipticCurveCanonicalHeight class can only be created from an elliptic curve defined over a number field")
815
+ else:
816
+ raise ValueError("EllipticCurveCanonicalHeight class can only be created from an elliptic curve")
817
+
818
+ def __repr__(self):
819
+ r"""
820
+ Return the string representation.
821
+
822
+ EXAMPLES::
823
+
824
+ sage: E = EllipticCurve([0,0,0,0,1])
825
+ sage: E.height_function()
826
+ EllipticCurveCanonicalHeight object associated to
827
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
828
+ """
829
+ return "EllipticCurveCanonicalHeight object associated to %s" % self.E
830
+
831
+ def curve(self):
832
+ r"""
833
+ Return the elliptic curve.
834
+
835
+ EXAMPLES::
836
+
837
+ sage: E = EllipticCurve([0,0,0,0,1])
838
+ sage: H = E.height_function()
839
+ sage: H.curve()
840
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
841
+ """
842
+ return self.E
843
+
844
+ def base_field(self):
845
+ r"""
846
+ Return the base field.
847
+
848
+ EXAMPLES::
849
+
850
+ sage: E = EllipticCurve([0,0,0,0,1])
851
+ sage: H = E.height_function()
852
+ sage: H.base_field()
853
+ Rational Field
854
+ """
855
+ return self.K
856
+
857
+ def __call__(self, P):
858
+ r"""
859
+ Return the canonical height of the point ``P``.
860
+
861
+ INPUT:
862
+
863
+ - ``P`` -- a point on the elliptic curve
864
+
865
+ OUTPUT: the canonical height of ``P``
866
+
867
+ EXAMPLES::
868
+
869
+ sage: E = EllipticCurve([0,0,1,-1,0])
870
+ sage: P = E(0,0)
871
+ sage: P.height()
872
+ 0.0511114082399688
873
+ sage: H = E.height_function()
874
+ sage: H(P)
875
+ 0.0511114082399688
876
+ sage: H([0,0])
877
+ 0.0511114082399688
878
+ sage: H((0,0))
879
+ 0.0511114082399688
880
+
881
+ Over a number field other than `\QQ`::
882
+
883
+ sage: # needs sage.rings.number_field
884
+ sage: K.<i> = QuadraticField(-1)
885
+ sage: E = EllipticCurve(K, [0,0,0,1,-27])
886
+ sage: H = E.height_function()
887
+ sage: H.base_field()
888
+ Number Field in i with defining polynomial x^2 + 1 with i = 1*I
889
+ sage: H((1, 5*i))
890
+ 1.22257115164148
891
+ """
892
+ return self.E(P).height()
893
+
894
+ @cached_method
895
+ def alpha(self, v, tol=0.01):
896
+ r"""
897
+ Return the constant `\alpha_v` associated to the embedding ``v``.
898
+
899
+ INPUT:
900
+
901
+ - ``v`` -- an embedding of the base field into `\RR` or `\CC`
902
+
903
+ OUTPUT:
904
+
905
+ The constant `\alpha_v`. In the notation of [CPS2006]_ and
906
+ [Tho2010]_ (section 3.2), `\alpha_v^3=\epsilon_v`. The result is
907
+ cached since it only depends on the curve.
908
+
909
+ EXAMPLES:
910
+
911
+ Example 1 from [CPS2006]_::
912
+
913
+ sage: # needs sage.rings.number_field
914
+ sage: K.<i> = QuadraticField(-1)
915
+ sage: E = EllipticCurve([0, 0, 0, 1 + 5*i, 3 + i])
916
+ sage: H = E.height_function()
917
+ sage: alpha = H.alpha(K.places()[0])
918
+ sage: alpha
919
+ 1.12272013439355
920
+
921
+ Compare with `\log(\epsilon_v)=0.344562...` in [CPS2006]_::
922
+
923
+ sage: 3*alpha.log() # needs sage.rings.number_field
924
+ 0.347263296676126
925
+ """
926
+ from sage.rings.polynomial.polynomial_ring import polygen
927
+ b2, b4, b6, b8 = (v(b) for b in self.E.b_invariants())
928
+ x = polygen(v.codomain())
929
+ f = 4*x**3 + b2*x**2 + 2*b4*x + b6
930
+ g = x**4 - b4*x**2 - 2*b6*x - b8
931
+ F = f.reverse() << (4-f.degree())
932
+ G = g.reverse() << (4-g.degree())
933
+
934
+ if v(self.K.gen()) in RR:
935
+ I = UnionOfIntervals([-1,1])
936
+ min_fg = inf_max_abs(f, g, nonneg_region(f) & I)
937
+ min_FG = inf_max_abs(F, G, nonneg_region(F) & I)
938
+ return min(min_fg, min_FG) ** (-1/QQ(3))
939
+
940
+ else:
941
+ # def pair_max(f, g):
942
+ # f = f.change_ring(CIF)
943
+ # g = g.change_ring(CIF)
944
+ # max = type(RIF(0)).max
945
+ # def max_f_g(z):
946
+ # return max(abs(f(z)), abs(g(z)))
947
+ # return max_f_g
948
+ def pair_max(f, g):
949
+ f = f.change_ring(CDF)
950
+ g = g.change_ring(CDF)
951
+ dfn = [fast_callable(f.derivative(n)/factorial(n), CDF) for n in range(f.degree()+1)]
952
+ dgn = [fast_callable(g.derivative(n)/factorial(n), CDF) for n in range(g.degree()+1)]
953
+
954
+ def max_f_g(s):
955
+ (a,b), (c,d) = s.real().endpoints(), s.imag().endpoints()
956
+ dx = a - b
957
+ dy = c - d
958
+ eta = RDF(dx*dx + dy*dy).sqrt()
959
+ z = CDF(s.center())
960
+ err_f = sum(eta ** n * abs(df(z)) for n, df in enumerate(dfn) if n)
961
+ err_g = sum(eta ** n * abs(dg(z)) for n, dg in enumerate(dgn) if n)
962
+ return RIF(max(abs(f(z)), abs(g(z)))) + eps(max(err_f, err_g), True)
963
+ return max_f_g
964
+ _, min_fg = min_on_disk(pair_max(f, g), tol)
965
+ _, min_FG = min_on_disk(pair_max(F, G), tol)
966
+ return min(min_fg, min_FG) ** QQ((-1, 3))
967
+
968
+ @cached_method
969
+ def e_p(self, p):
970
+ r"""
971
+ Return the exponent of the group over the residue field at ``p``.
972
+
973
+ INPUT:
974
+
975
+ - ``p`` -- a prime ideal of `K` (or a prime number if `K=\QQ`)
976
+
977
+ OUTPUT:
978
+
979
+ A positive integer `e_p`, the exponent of the group of
980
+ nonsingular points on the reduction of the elliptic curve
981
+ modulo `p`. The result is cached.
982
+
983
+ EXAMPLES::
984
+
985
+ sage: # needs sage.rings.number_field
986
+ sage: K.<i> = QuadraticField(-1)
987
+ sage: E = EllipticCurve([0, 0, 0, 1 + 5*i, 3 + i])
988
+ sage: H = E.height_function()
989
+ sage: H.e_p(K.prime_above(2))
990
+ 2
991
+ sage: H.e_p(K.prime_above(3))
992
+ 10
993
+ sage: H.e_p(K.prime_above(5))
994
+ 9
995
+ sage: E.conductor().norm().factor()
996
+ 2^10 * 20921
997
+ sage: p1, p2 = K.primes_above(20921)
998
+ sage: E.local_data(p1)
999
+ Local data at Fractional ideal (-40*i + 139):
1000
+ Reduction type: bad split multiplicative
1001
+ ...
1002
+ sage: H.e_p(p1)
1003
+ 20920
1004
+ sage: E.local_data(p2)
1005
+ Local data at Fractional ideal (40*i + 139):
1006
+ Reduction type: good
1007
+ ...
1008
+ sage: H.e_p(p2)
1009
+ 20815
1010
+ """
1011
+ kp = self.K.residue_field(p)
1012
+ if self.E.has_bad_reduction(p):
1013
+ if self.E.has_additive_reduction(p):
1014
+ ep = kp.characteristic()
1015
+ elif self.E.has_split_multiplicative_reduction(p):
1016
+ ep = len(kp) - 1
1017
+ else:
1018
+ ep = len(kp) + 1
1019
+ else:
1020
+ ep = self.E.reduction(p).abelian_group().exponent()
1021
+ return ZZ(ep)
1022
+
1023
+ @cached_method
1024
+ def DE(self, n):
1025
+ r"""
1026
+ Return the value `D_E(n)`.
1027
+
1028
+ INPUT:
1029
+
1030
+ - ``n`` -- positive integer
1031
+
1032
+ OUTPUT:
1033
+
1034
+ The value `D_E(n)` as defined in [Tho2010]_, section 4.
1035
+
1036
+ EXAMPLES::
1037
+
1038
+ sage: # needs sage.rings.number_field sage.symbolic
1039
+ sage: K.<i> = QuadraticField(-1)
1040
+ sage: E = EllipticCurve([0, 0, 0, 1+5*i, 3+i])
1041
+ sage: H = E.height_function()
1042
+ sage: [H.DE(n) for n in srange(1,6)]
1043
+ [0, 2*log(5) + 2*log(2), 0, 2*log(13) + 2*log(5) + 4*log(2), 0]
1044
+ """
1045
+ s = 0
1046
+ B = (n+1) ** max(2, self.K.degree())
1047
+ for p in self.K.primes_of_bounded_norm_iter(B):
1048
+ ep = self.e_p(p)
1049
+ if ep.divides(n):
1050
+ kp = self.K.residue_field(p)
1051
+ s += 2*(1+(n/ep).valuation(kp.characteristic())) * log(len(kp))
1052
+ return s
1053
+
1054
+ @cached_method
1055
+ def ME(self):
1056
+ r"""
1057
+ Return the norm of the ideal `M_E`.
1058
+
1059
+ OUTPUT:
1060
+
1061
+ The norm of the ideal `M_E` as defined in [Tho2010]_, section 3.1.
1062
+ This is `1` if `E` is a global minimal model, and in general
1063
+ measures the non-minimality of `E`.
1064
+
1065
+ EXAMPLES::
1066
+
1067
+ sage: K.<i> = QuadraticField(-1) # needs sage.rings.number_field
1068
+ sage: E = EllipticCurve([0, 0, 0, 1+5*i, 3+i]) # needs sage.rings.number_field
1069
+ sage: H = E.height_function() # needs sage.rings.number_field
1070
+ sage: H.ME() # needs sage.rings.number_field
1071
+ 1
1072
+ sage: E = EllipticCurve([0,0,0,0,1])
1073
+ sage: E.height_function().ME()
1074
+ 1
1075
+ sage: E = EllipticCurve([0,0,0,0,64])
1076
+ sage: E.height_function().ME()
1077
+ 4096
1078
+ sage: E.discriminant()/E.minimal_model().discriminant()
1079
+ 4096
1080
+ """
1081
+ from sage.misc.misc_c import prod
1082
+ if self.K is QQ:
1083
+ return prod([p ** (e - self.E.local_data(p).discriminant_valuation()) for p, e in self.E.discriminant().factor()], QQ.one())
1084
+
1085
+ 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())
1086
+ return ME.norm()
1087
+
1088
+ def B(self, n, mu):
1089
+ r"""
1090
+ Return the value `B_n(\mu)`.
1091
+
1092
+ INPUT:
1093
+
1094
+ - ``n`` -- positive integer
1095
+
1096
+ - ``mu`` -- positive real number
1097
+
1098
+ OUTPUT:
1099
+
1100
+ The real value `B_n(\mu)` as defined in [Tho2010]_, section 5.
1101
+
1102
+ EXAMPLES:
1103
+
1104
+ Example 10.2 from [Tho2010]_::
1105
+
1106
+ sage: K.<i> = QuadraticField(-1) # needs sage.rings.number_field
1107
+ sage: E = EllipticCurve([0, 1-i, i, -i, 0]) # needs sage.rings.number_field
1108
+ sage: H = E.height_function() # needs sage.rings.number_field
1109
+
1110
+ In [Tho2010]_ the value is given as 0.772::
1111
+
1112
+ sage: RealField(12)( H.B(5, 0.01) ) # needs sage.rings.number_field sage.symbolic
1113
+ 0.777
1114
+ """
1115
+ K = self.K
1116
+ B = exp(K.degree() * n**2 * mu - RDF(self.DE(n))) / self.ME() ** 6
1117
+ for v in K.places():
1118
+ if v(K.gen()) in RR:
1119
+ B *= self.alpha(v)
1120
+ else:
1121
+ B *= self.alpha(v) ** 2
1122
+ return B
1123
+
1124
+ ######################################
1125
+ # Empty real intersection detection. #
1126
+ ######################################
1127
+
1128
+ def psi(self, xi, v):
1129
+ r"""
1130
+ Return the normalised elliptic log of a point with this x-coordinate.
1131
+
1132
+ INPUT:
1133
+
1134
+ - ``xi`` -- real; the real x-coordinate of a point on the
1135
+ curve in the connected component with respect to a real
1136
+ embedding
1137
+
1138
+ - ``v`` -- a real embedding of the number field
1139
+
1140
+ OUTPUT:
1141
+
1142
+ A real number in the interval [0.5,1] giving the elliptic
1143
+ logarithm of a point on `E` with `x`-coordinate ``xi``, on the
1144
+ connected component with respect to the embedding `v`, scaled
1145
+ by the real period.
1146
+
1147
+ EXAMPLES:
1148
+
1149
+ An example over `\QQ`::
1150
+
1151
+ sage: E = EllipticCurve('389a')
1152
+ sage: v = QQ.places()[0]
1153
+ sage: L = E.period_lattice(v)
1154
+ sage: P = E.lift_x(10/9)
1155
+ sage: L(P)
1156
+ 0.958696500380439
1157
+ sage: L(P) / L.real_period()
1158
+ 0.384985810227885
1159
+ sage: H = E.height_function()
1160
+ sage: H.psi(10/9, v)
1161
+ 0.615014189772115
1162
+
1163
+ An example over a number field::
1164
+
1165
+ sage: # needs sage.rings.number_field
1166
+ sage: x = polygen(ZZ, 'x')
1167
+ sage: K.<a> = NumberField(x^3 - 2)
1168
+ sage: E = EllipticCurve([0,0,0,0,a])
1169
+ sage: P = E.lift_x(1/3*a^2 + a + 5/3)
1170
+ sage: v = K.real_places()[0]
1171
+ sage: L = E.period_lattice(v)
1172
+ sage: L(P)
1173
+ 3.51086196882538
1174
+ sage: L(P) / L.real_period()
1175
+ 0.867385122699931
1176
+ sage: xP = v(P.x())
1177
+ sage: H = E.height_function()
1178
+ sage: H.psi(xP, v)
1179
+ 0.867385122699931
1180
+ sage: H.psi(1.23, v)
1181
+ 0.785854718241495
1182
+ """
1183
+ if xi > 1e9:
1184
+ return 1
1185
+ L = self.E.period_lattice(v)
1186
+ w1, w2 = L.basis()
1187
+ from sage.schemes.elliptic_curves.constructor import EllipticCurve
1188
+ ER = EllipticCurve([v(ai) for ai in self.E.a_invariants()])
1189
+ xP, yP = ER.lift_x(xi).xy()
1190
+ t = L.e_log_RC(xP,yP) / w1
1191
+ if t < 0.5:
1192
+ t = 1 - t
1193
+ return t
1194
+
1195
+ def S(self, xi1, xi2, v):
1196
+ r"""
1197
+ Return the union of intervals `S^{(v)}(\xi_1,\xi_2)`.
1198
+
1199
+ INPUT:
1200
+
1201
+ - ``xi1``, ``xi2`` -- real numbers with `\xi_1\le\xi_2`
1202
+
1203
+ - ``v`` -- a real embedding of the field
1204
+
1205
+ OUTPUT:
1206
+
1207
+ The union of intervals `S^{(v)}(\xi_1,\xi_2)` defined in [Tho2010]_
1208
+ section 6.1.
1209
+
1210
+ EXAMPLES:
1211
+
1212
+ An example over `\QQ`::
1213
+
1214
+ sage: E = EllipticCurve('389a')
1215
+ sage: v = QQ.places()[0]
1216
+ sage: H = E.height_function()
1217
+ sage: H.S(2, 3, v)
1218
+ ([0.224512677391895, 0.274544821597130] U [0.725455178402870, 0.775487322608105])
1219
+
1220
+ An example over a number field::
1221
+
1222
+ sage: # needs sage.rings.number_field
1223
+ sage: x = polygen(ZZ, 'x')
1224
+ sage: K.<a> = NumberField(x^3 - 2)
1225
+ sage: E = EllipticCurve([0,0,0,0,a])
1226
+ sage: v = K.real_places()[0]
1227
+ sage: H = E.height_function()
1228
+ sage: H.S(9, 10, v)
1229
+ ([0.078119444725347..., 0.082342373201640...] U [0.91765762679836..., 0.92188055527465...])
1230
+ """
1231
+ L = self.E.period_lattice(v)
1232
+ w1, w2 = L.basis(prec=v.codomain().prec())
1233
+ beta = L.elliptic_exponential(w1/2)[0]
1234
+ if xi2 < beta:
1235
+ return UnionOfIntervals([])
1236
+ elif xi1 < beta <= xi2:
1237
+ a = self.psi(xi2, v)
1238
+ return UnionOfIntervals([1-a, a])
1239
+ else:
1240
+ a, b = self.psi(xi1, v), self.psi(xi2, v)
1241
+ return UnionOfIntervals([1-b, 1-a, a, b])
1242
+
1243
+ def Sn(self, xi1, xi2, n, v):
1244
+ r"""
1245
+ Return the union of intervals `S_n^{(v)}(\xi_1,\xi_2)`.
1246
+
1247
+ INPUT:
1248
+
1249
+ - ``xi1``, ``xi2`` -- real numbers with `\xi_1\le\xi_2`
1250
+
1251
+ - ``n`` -- positive integer
1252
+
1253
+ - ``v`` -- a real embedding of the field
1254
+
1255
+ OUTPUT:
1256
+
1257
+ The union of intervals `S_n^{(v)}(\xi_1,\xi_2)` defined in [Tho2010]_
1258
+ (Lemma 6.1).
1259
+
1260
+ EXAMPLES:
1261
+
1262
+ An example over `\QQ`::
1263
+
1264
+ sage: E = EllipticCurve('389a')
1265
+ sage: v = QQ.places()[0]
1266
+ sage: H = E.height_function()
1267
+ sage: H.S(2, 3, v), H.Sn(2, 3, 1, v)
1268
+ (([0.224512677391895, 0.274544821597130] U [0.725455178402870, 0.775487322608105]),
1269
+ ([0.224512677391895, 0.274544821597130] U [0.725455178402870, 0.775487322608105]))
1270
+ sage: H.Sn(2, 3, 6, v)
1271
+ ([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])
1272
+
1273
+ An example over a number field::
1274
+
1275
+ sage: # needs sage.rings.number_field
1276
+ sage: x = polygen(ZZ, 'x')
1277
+ sage: K.<a> = NumberField(x^3 - 2)
1278
+ sage: E = EllipticCurve([0,0,0,0,a])
1279
+ sage: v = K.real_places()[0]
1280
+ sage: H = E.height_function()
1281
+ sage: H.S(2, 3, v), H.Sn(2, 3, 1, v)
1282
+ (([0.142172065860075, 0.172845716928584] U [0.827154283071416, 0.857827934139925]),
1283
+ ([0.142172065860075, 0.172845716928584] U [0.827154283071416, 0.857827934139925]))
1284
+ sage: H.Sn(2, 3, 6, v)
1285
+ ([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])
1286
+ """
1287
+ SS = 1/ZZ(n) * self.S(xi1, xi2, v)
1288
+ return UnionOfIntervals.union([t/ZZ(n) + SS for t in range(n)])
1289
+
1290
+ def real_intersection_is_empty(self, Bk, v):
1291
+ r"""
1292
+ Return ``True`` iff an intersection of `S_n^{(v)}` sets is empty.
1293
+
1294
+ INPUT:
1295
+
1296
+ - ``Bk`` -- list of reals
1297
+
1298
+ - ``v`` -- a real embedding of the number field
1299
+
1300
+ OUTPUT:
1301
+
1302
+ ``True`` or ``False``, according as the intersection of the unions of
1303
+ intervals `S_n^{(v)}(-b,b)` for `b` in the list ``Bk`` is
1304
+ empty or not. When ``Bk`` is the list of `b=B_n(\mu)` for
1305
+ `n=1,2,3,\dots` for some `\mu>0` this means that all
1306
+ non-torsion points on `E` with everywhere good reduction have
1307
+ canonical height strictly greater than `\mu`, by [Tho2010]_,
1308
+ Proposition 6.2.
1309
+
1310
+ EXAMPLES:
1311
+
1312
+ An example over `\QQ`::
1313
+
1314
+ sage: E = EllipticCurve('389a')
1315
+ sage: v = QQ.places()[0]
1316
+ sage: H = E.height_function()
1317
+
1318
+ The following two lines prove that the heights of non-torsion
1319
+ points on `E` with everywhere good reduction have canonical
1320
+ height strictly greater than 0.2, but fail to prove the same
1321
+ for 0.3::
1322
+
1323
+ sage: H.real_intersection_is_empty([H.B(n,0.2) for n in srange(1,10)], v) # needs sage.symbolic
1324
+ True
1325
+ sage: H.real_intersection_is_empty([H.B(n,0.3) for n in srange(1,10)], v) # needs sage.symbolic
1326
+ False
1327
+
1328
+ An example over a number field::
1329
+
1330
+ sage: # needs sage.rings.number_field
1331
+ sage: x = polygen(ZZ, 'x')
1332
+ sage: K.<a> = NumberField(x^3 - 2)
1333
+ sage: E = EllipticCurve([0,0,0,0,a])
1334
+ sage: v = K.real_places()[0]
1335
+ sage: H = E.height_function()
1336
+
1337
+ The following two lines prove that the heights of non-torsion
1338
+ points on `E` with everywhere good reduction have canonical
1339
+ height strictly greater than 0.07, but fail to prove the same
1340
+ for 0.08::
1341
+
1342
+ 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
1343
+ True
1344
+ 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
1345
+ False
1346
+ """
1347
+ return UnionOfIntervals.intersection([self.Sn(-B, B, k+1, v) for k,B in enumerate(Bk)]).is_empty()
1348
+
1349
+ ########################################
1350
+ # Empty complex intersection detection.#
1351
+ ########################################
1352
+
1353
+ def tau(self, v):
1354
+ r"""
1355
+ Return the normalised upper half-plane parameter `\tau` for
1356
+ the period lattice with respect to the embedding `v`.
1357
+
1358
+ INPUT:
1359
+
1360
+ - ``v`` -- a real or complex embedding of the number field
1361
+
1362
+ OUTPUT:
1363
+
1364
+ (Complex) `\tau = \omega_1/\omega_2` in the fundamental region
1365
+ of the upper half-plane.
1366
+
1367
+ EXAMPLES::
1368
+
1369
+ sage: E = EllipticCurve('37a')
1370
+ sage: H = E.height_function()
1371
+ sage: H.tau(QQ.places()[0])
1372
+ 1.22112736076463*I
1373
+ """
1374
+ return self.E.period_lattice(v).tau()
1375
+
1376
+ def wp_c(self, v):
1377
+ r"""
1378
+ Return a bound for the Weierstrass `\wp`-function.
1379
+
1380
+ INPUT:
1381
+
1382
+ - ``v`` -- a real or complex embedding of the number field
1383
+
1384
+ OUTPUT:
1385
+
1386
+ (Real) `c>0` such that
1387
+
1388
+ .. MATH::
1389
+
1390
+ |\wp(z) - z^-2| \le \frac{c^2|z|^2}{1-c|z|^2}
1391
+
1392
+ whenever `c|z|^2<1`. Given the recurrence relations for the
1393
+ Laurent series expansion of `\wp`, it is easy to see that
1394
+ there is such a constant `c`. [Reference?]
1395
+
1396
+ EXAMPLES::
1397
+
1398
+ sage: E = EllipticCurve('37a')
1399
+ sage: H = E.height_function()
1400
+ sage: H.wp_c(QQ.places()[0])
1401
+ 2.68744508779950
1402
+
1403
+ sage: # needs sage.rings.number_field
1404
+ sage: K.<i> = QuadraticField(-1)
1405
+ sage: E = EllipticCurve([0, 0, 0, 1 + 5*i, 3 + i])
1406
+ sage: H = E.height_function()
1407
+ sage: H.wp_c(K.places()[0])
1408
+ 2.66213425640096
1409
+ """
1410
+ # Note that we normalise w1, w2 differently from [Tho2010]_!
1411
+ w2, w1 = self.E.period_lattice(v).normalised_basis()
1412
+ return max(abs(v(self.E.c4()/240)) ** 0.5,
1413
+ abs(v(self.E.c6()/6048)) ** (1.0/3)) * abs(w1)**2
1414
+
1415
+ def fk_intervals(self, v=None, N=20, domain=CIF):
1416
+ r"""
1417
+ Return a function approximating the Weierstrass function, with error.
1418
+
1419
+ INPUT:
1420
+
1421
+ - ``v`` -- an embedding of the number field. If
1422
+ ``None`` (default) use the real embedding if the field is `\QQ`
1423
+ and raise an error for other fields.
1424
+
1425
+ - ``N`` -- integer; the number of terms to use in the
1426
+ `q`-expansion of `\wp`
1427
+
1428
+ - ``domain`` -- (complex field) the model of `\CC` to use, for
1429
+ example ``CDF`` of ``CIF`` (default)
1430
+
1431
+ OUTPUT:
1432
+
1433
+ A pair of functions fk, err which can be evaluated at complex
1434
+ numbers `z` (in the correct ``domain``) to give an
1435
+ approximation to `\wp(z)` and an upper bound on the error,
1436
+ respectively. The Weierstrass function returned is with
1437
+ respect to the normalised lattice `[1,\tau]` associated to the
1438
+ given embedding.
1439
+
1440
+ EXAMPLES::
1441
+
1442
+ sage: E = EllipticCurve('37a')
1443
+ sage: L = E.period_lattice()
1444
+ sage: w1, w2 = L.normalised_basis()
1445
+ sage: z = CDF(0.3, 0.4)
1446
+
1447
+ Compare the value give by the standard elliptic exponential
1448
+ (scaled since ``fk`` is with respect to the normalised
1449
+ lattice)::
1450
+
1451
+ sage: L.elliptic_exponential(z*w2, to_curve=False)[0] * w2 ** 2
1452
+ -1.82543539306049 - 2.49336319992847*I
1453
+
1454
+ to the value given by this function, and see the error::
1455
+
1456
+ sage: fk, err = E.height_function().fk_intervals(N=10)
1457
+ sage: fk(CIF(z))
1458
+ -1.82543539306049? - 2.49336319992847?*I
1459
+ sage: err(CIF(z))
1460
+ 2.71750621458744e-31
1461
+
1462
+ The same, but in the domain ``CDF`` instead of ``CIF``::
1463
+
1464
+ sage: fk, err = E.height_function().fk_intervals(N=10, domain=CDF)
1465
+ sage: fk(z)
1466
+ -1.8254353930604... - 2.493363199928...*I
1467
+ """
1468
+ if v is None:
1469
+ if self.K is QQ:
1470
+ v = QQ.hom(RR)
1471
+ else:
1472
+ raise ValueError("must specify embedding")
1473
+ # pre-compute some constants
1474
+ tau = self.tau(v)
1475
+ const_term = 1/CC(12)
1476
+ qn = q = (2 * CC.gen() * CC.pi() * tau).exp()
1477
+ for n in range(1, N):
1478
+ const_term -= 2 * qn/(1-qn) ** 2
1479
+ qn *= q
1480
+
1481
+ two_pi_i = 2 * domain.gen() * domain.pi()
1482
+ neg_four_pi2 = -4 * domain.pi() ** 2
1483
+ const_term = domain(const_term)
1484
+ tau = domain(tau)
1485
+
1486
+ abs_q = abs(domain(q))
1487
+ abs_qN = abs(domain(qn))
1488
+ err_factor = abs(neg_four_pi2) / (1-abs_q)
1489
+ err_term = 2*abs_qN/(1-abs_qN) ** 2
1490
+
1491
+ # choose u/(1-u)^2 evaluation method
1492
+ if domain is CIF:
1493
+ rat_term = rat_term_CIF
1494
+ else:
1495
+ def rat_term(z):
1496
+ u = (two_pi_i*z).exp()
1497
+ return u/(1-u)**2
1498
+
1499
+ # the actual series
1500
+ def fk(z):
1501
+ return (const_term +
1502
+ sum([rat_term(z+n*tau) for n in range(1-N,N)])
1503
+ ) * neg_four_pi2
1504
+
1505
+ # the error function
1506
+ def err(z):
1507
+ alpha = z.imag() / tau.imag()
1508
+ qNa = abs_q**(N+alpha)
1509
+ qNai = abs_q**(N-alpha)
1510
+ return (err_factor * (qNa/(1-qNa) ** 2 + qNai/(1-qNai) ** 2 + err_term)).upper()
1511
+
1512
+ return fk, err
1513
+
1514
+ @cached_method
1515
+ def wp_intervals(self, v=None, N=20, abs_only=False):
1516
+ r"""
1517
+ Return a function approximating the Weierstrass function.
1518
+
1519
+ INPUT:
1520
+
1521
+ - ``v`` -- an embedding of the number field; if
1522
+ ``None`` (default) use the real embedding if the field is `\QQ`
1523
+ and raise an error for other fields
1524
+
1525
+ - ``N`` -- integer (default: 20); The number of terms to use in the
1526
+ `q`-expansion of `\wp`
1527
+
1528
+ - ``abs_only``-- boolean (default: ``False``); flag to determine
1529
+ whether (if ``True``) the error adjustment should use the
1530
+ absolute value or (if ``False``) the real and imaginary parts
1531
+
1532
+ OUTPUT:
1533
+
1534
+ A function wp which can be evaluated at complex numbers `z` to
1535
+ give an approximation to `\wp(z)`. The Weierstrass function
1536
+ returned is with respect to the normalised lattice `[1,\tau]`
1537
+ associated to the given embedding. For `z` which are not near
1538
+ a lattice point the function ``fk`` is used, otherwise a
1539
+ better approximation is used.
1540
+
1541
+ EXAMPLES::
1542
+
1543
+ sage: E = EllipticCurve('37a')
1544
+ sage: wp = E.height_function().wp_intervals()
1545
+ sage: z = CDF(0.3, 0.4)
1546
+ sage: wp(CIF(z))
1547
+ -1.82543539306049? - 2.4933631999285?*I
1548
+
1549
+ sage: L = E.period_lattice()
1550
+ sage: w1, w2 = L.normalised_basis()
1551
+ sage: L.elliptic_exponential(z*w2, to_curve=False)[0] * w2^2
1552
+ -1.82543539306049 - 2.49336319992847*I
1553
+
1554
+ sage: z = CDF(0.3, 0.1)
1555
+ sage: wp(CIF(z))
1556
+ 8.5918243572165? - 5.4751982004351?*I
1557
+ sage: L.elliptic_exponential(z*w2, to_curve=False)[0] * w2^2
1558
+ 8.59182435721650 - 5.47519820043503*I
1559
+ """
1560
+ if v is None:
1561
+ if self.K is QQ:
1562
+ v = QQ.hom(RR)
1563
+ else:
1564
+ raise ValueError("must specify embedding")
1565
+
1566
+ tau = self.tau(v)
1567
+ fk, fk_err = self.fk_intervals(v, N)
1568
+ c = self.wp_c(v)
1569
+
1570
+ def wp(z):
1571
+
1572
+ # center around origin
1573
+ offset = (z.imag().lower() / tau.imag()).round()
1574
+ if offset:
1575
+ z -= CIF(offset * tau)
1576
+ offset = z.real().lower().round()
1577
+ if offset:
1578
+ z -= offset
1579
+
1580
+ # estimate using the series
1581
+ approx = fk(z)
1582
+ err = fk_err(z)
1583
+ if abs_only:
1584
+ approx = abs(approx)
1585
+ approx += eps(err, abs_only)
1586
+
1587
+ # refine using an estimate that's better near the pole
1588
+ z_bound = abs(z).upper()
1589
+ cz2 = c * z_bound ** 2
1590
+ if cz2 < 1:
1591
+ err = (c * cz2) / (1 - cz2)
1592
+ if abs_only:
1593
+ pole_approx = abs(z) ** -2
1594
+ else:
1595
+ pole_approx = z ** -2
1596
+ approx = approx.intersection(pole_approx + eps(err, abs_only))
1597
+ return approx
1598
+ return wp
1599
+
1600
+ @cached_method
1601
+ def wp_on_grid(self, v, N, half=False):
1602
+ r"""
1603
+ Return an array of the values of `\wp` on an `N\times N` grid.
1604
+
1605
+ INPUT:
1606
+
1607
+ - ``v`` -- an embedding of the number field
1608
+
1609
+ - ``N`` -- integer; the number of terms to use in the
1610
+ `q`-expansion of `\wp`
1611
+
1612
+ - ``half``-- boolean (default: ``False``); if ``True``, use an array of
1613
+ size `N\times N/2` instead of `N\times N`
1614
+
1615
+ OUTPUT:
1616
+
1617
+ An array of size either `N\times N/2` or `N\times N` whose
1618
+ `(i,j)` entry is the value of the Weierstrass `\wp`-function
1619
+ at `(i+.5)/N + (j+.5)*\tau/N`, a grid of points in the
1620
+ fundamental region for the lattice `[1,\tau]`.
1621
+
1622
+ EXAMPLES::
1623
+
1624
+ sage: E = EllipticCurve('37a')
1625
+ sage: H = E.height_function()
1626
+ sage: v = QQ.places()[0]
1627
+
1628
+ The array of values on the grid shows symmetry, since `\wp` is
1629
+ even::
1630
+
1631
+ sage: H.wp_on_grid(v, 4) # needs sage.symbolic
1632
+ array([[25.43920182, 5.28760943, 5.28760943, 25.43920182],
1633
+ [ 6.05099485, 1.83757786, 1.83757786, 6.05099485],
1634
+ [ 6.05099485, 1.83757786, 1.83757786, 6.05099485],
1635
+ [25.43920182, 5.28760943, 5.28760943, 25.43920182]])
1636
+
1637
+ The array of values on the half-grid::
1638
+
1639
+ sage: H.wp_on_grid(v, 4, True) # needs sage.symbolic
1640
+ array([[25.43920182, 5.28760943],
1641
+ [ 6.05099485, 1.83757786],
1642
+ [ 6.05099485, 1.83757786],
1643
+ [25.43920182, 5.28760943]])
1644
+ """
1645
+ tau = self.tau(v)
1646
+ fk, err = self.fk_intervals(v, 15, CDF)
1647
+ var_z = SR.var('z')
1648
+ ff = fast_callable(fk(var_z), CDF, [var_z])
1649
+ N_or_half = N // (1+half) # array is NxN or Nx(N/2)
1650
+ vals = numpy.empty((N,N_or_half)) # empty array tp hold values
1651
+ for i in range(N):
1652
+ for j in range(N_or_half):
1653
+ vals[i,j] = abs(ff((i+.5)/N + (j+.5)*tau/N))
1654
+ return vals
1655
+
1656
+ def complex_intersection_is_empty(self, Bk, v, verbose=False, use_half=True):
1657
+ r"""
1658
+ Return ``True`` iff an intersection of `T_n^{(v)}` sets is empty.
1659
+
1660
+ INPUT:
1661
+
1662
+ - ``Bk`` -- list of reals
1663
+
1664
+ - ``v`` -- a complex embedding of the number field
1665
+
1666
+ - ``verbose``-- boolean (default: ``False``); verbosity flag
1667
+
1668
+ - ``use_half``-- boolean (default: ``False``); if ``True``, use only half
1669
+ the fundamental region
1670
+
1671
+ OUTPUT:
1672
+
1673
+ ``True`` or ``False``, according as the intersection of the unions of
1674
+ intervals `T_n^{(v)}(-b,b)` for `b` in the list ``Bk`` (see
1675
+ [Tho2010]_, section 7) is empty or not. When ``Bk`` is the list of
1676
+ `b=\sqrt{B_n(\mu)}` for `n=1,2,3,\dots` for some `\mu>0` this
1677
+ means that all non-torsion points on `E` with everywhere good
1678
+ reduction have canonical height strictly greater than `\mu`,
1679
+ by [Tho2010]_, Proposition 7.8.
1680
+
1681
+ EXAMPLES::
1682
+
1683
+ sage: # needs sage.rings.number_field
1684
+ sage: x = polygen(ZZ, 'x')
1685
+ sage: K.<a> = NumberField(x^3 - 2)
1686
+ sage: E = EllipticCurve([0,0,0,0,a])
1687
+ sage: v = K.complex_embeddings()[0]
1688
+ sage: H = E.height_function()
1689
+
1690
+ The following two lines prove that the heights of non-torsion
1691
+ points on `E` with everywhere good reduction have canonical
1692
+ height strictly greater than 0.02, but fail to prove the same
1693
+ for 0.03. For the first proof, using only `n=1,2,3` is not
1694
+ sufficient::
1695
+
1696
+ 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
1697
+ False
1698
+ 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
1699
+ True
1700
+ 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
1701
+ False
1702
+
1703
+ Using `n\le6` enables us to prove the lower bound 0.03. Note
1704
+ that it takes longer when the result is ``False`` than when it
1705
+ is ``True``::
1706
+
1707
+ sage: H.complex_intersection_is_empty([H.B(n, 0.03) for n in [1..6]], v) # needs sage.rings.number_field sage.symbolic
1708
+ True
1709
+ """
1710
+ from sage.schemes.elliptic_curves.period_lattice_region import PeriodicRegion
1711
+
1712
+ b2 = v(self.E.b2())
1713
+ # Note that we normalise w1, w2 differently from [Tho2010]_!
1714
+ w2, w1 = self.E.period_lattice(v).normalised_basis()
1715
+ tau = w2/w1
1716
+ bounds = [RDF((B.sqrt() + abs(b2)/12) * abs(w1) ** 2) for B in Bk]
1717
+ vals = self.wp_on_grid(v, 30, half=use_half)
1718
+ wp = self.wp_intervals(v, abs_only=True)
1719
+
1720
+ k = len(bounds)
1721
+
1722
+ # First try and prove a negative result (cheap).
1723
+ if verbose:
1724
+ print("trying to prove negative result...")
1725
+ intersection = None
1726
+ for B, n in sorted(zip(bounds, ZZ.range(1, k+1))):
1727
+ T = PeriodicRegion(CDF(1), CDF(tau), vals < B, full=not use_half)
1728
+ if intersection is None:
1729
+ intersection = PeriodicRegion(CDF(1), CDF(tau), vals < B, full=not use_half)
1730
+ else:
1731
+ intersection &= T/n
1732
+ if intersection.is_empty():
1733
+ break
1734
+ else:
1735
+ z = CIF(intersection.innermost_point())
1736
+ if all(wp((k+1)*z).upper() < B for k, B in enumerate(bounds)):
1737
+ return False
1738
+
1739
+ # Now try to prove a positive result.
1740
+ if verbose:
1741
+ print("trying to prove positive result...")
1742
+ intersection = None
1743
+ for B, n in sorted(zip(bounds, ZZ.range(1, k+1))):
1744
+
1745
+ T = PeriodicRegion(CDF(1), CDF(tau), vals < B, full=not use_half).expand().refine()
1746
+ B = RIF(B)
1747
+ leaning_right = tau.real() / tau.imag() >= 0
1748
+
1749
+ def check_line(z):
1750
+ wpz = wp(z)
1751
+ if wpz > B:
1752
+ return True
1753
+ # Try refining once before we declare failure.
1754
+ z00, z01, z10, z11 = z.bisection()
1755
+ if leaning_right:
1756
+ start, end = z00, z11
1757
+ else:
1758
+ start, end = z01, z10
1759
+ if wp(start) > B and wp(end) > B:
1760
+ return True
1761
+ return False
1762
+
1763
+ # This step here is the bottleneck.
1764
+ while not T.verify(check_line):
1765
+ if verbose:
1766
+ print("bad")
1767
+ T = T.expand()
1768
+ if intersection is None:
1769
+ intersection = T
1770
+ else:
1771
+ intersection &= T/n
1772
+ if intersection.is_empty():
1773
+ return True
1774
+
1775
+ return False
1776
+
1777
+ def test_mu(self, mu, N, verbose=True):
1778
+ r"""
1779
+ Return ``True`` if we can prove that `\mu` is a lower bound.
1780
+
1781
+ INPUT:
1782
+
1783
+ - ``mu`` -- positive real number
1784
+
1785
+ - ``N`` -- integer; upper bound on the multiples to be used
1786
+
1787
+ - ``verbose``-- boolean (default: ``True``); verbosity flag
1788
+
1789
+ OUTPUT:
1790
+
1791
+ ``True`` or ``False``, according to whether we succeed in
1792
+ proving that `\mu` is a lower bound for the canonical heights
1793
+ of points of infinite order with everywhere good reduction.
1794
+
1795
+ .. NOTE::
1796
+
1797
+ A ``True`` result is rigorous; ``False`` only means that
1798
+ the attempt failed: trying again with larger `N` may yield
1799
+ ``True``.
1800
+
1801
+ EXAMPLES::
1802
+
1803
+ sage: x = polygen(ZZ, 'x')
1804
+ sage: K.<a> = NumberField(x^3 - 2) # needs sage.rings.number_field
1805
+ sage: E = EllipticCurve([0,0,0,0,a]) # needs sage.rings.number_field
1806
+ sage: H = E.height_function() # needs sage.rings.number_field
1807
+
1808
+ This curve does have a point of good reduction whose canonical
1809
+ point is approximately 1.68::
1810
+
1811
+ sage: P = E.gens(lim3=5)[0]; P # needs sage.rings.number_field
1812
+ (1/3*a^2 + a + 5/3 : -2*a^2 - 4/3*a - 5/3 : 1)
1813
+ sage: P.height() # needs sage.rings.number_field
1814
+ 1.68038085233673
1815
+ sage: P.has_good_reduction() # needs sage.rings.number_field
1816
+ True
1817
+
1818
+ Using `N=5` we can prove that 0.1 is a lower bound (in fact we
1819
+ only need `N=2`), but not that 0.2 is::
1820
+
1821
+ sage: H.test_mu(0.1, 5) # needs sage.rings.number_field sage.symbolic
1822
+ B_1(0.100000000000000) = 1.51580969677387
1823
+ B_2(0.100000000000000) = 0.932072561526720
1824
+ True
1825
+ sage: H.test_mu(0.2, 5) # needs sage.rings.number_field sage.symbolic
1826
+ B_1(0.200000000000000) = 2.04612906979932
1827
+ B_2(0.200000000000000) = 3.09458988474327
1828
+ B_3(0.200000000000000) = 27.6251108409484
1829
+ B_4(0.200000000000000) = 1036.24722370223
1830
+ B_5(0.200000000000000) = 3.67090854562318e6
1831
+ False
1832
+
1833
+ Since 0.1 is a lower bound we can deduce that the point `P` is
1834
+ either primitive or divisible by either 2 or 3. In fact it is
1835
+ primitive::
1836
+
1837
+ sage: (P.height()/0.1).sqrt() # needs sage.rings.number_field
1838
+ 4.09924487233530
1839
+ sage: P.division_points(2) # needs sage.rings.number_field
1840
+ []
1841
+ sage: P.division_points(3) # needs sage.rings.number_field
1842
+ []
1843
+ """
1844
+ # Compute the list of values `B_n(\mu)` for n in 1..N. If any
1845
+ # of these is 1 we can return True right away (see [Tho2010]_,
1846
+ # Proposition 5.1).
1847
+ Bk = []
1848
+ for n in ZZ.range(1, N + 1):
1849
+ b = self.B(n, mu)
1850
+ if verbose:
1851
+ print("B_%s(%s) = %s" % (n, mu, b))
1852
+ if b < 1:
1853
+ return True
1854
+ Bk.append(b)
1855
+
1856
+ # Each real or complex embedding of the number field gives us
1857
+ # a chance to prove the lower bound. We try each in turn,
1858
+ # stopping if one gives a True result.
1859
+
1860
+ from sage.rings.number_field.number_field import refine_embedding
1861
+ for v in self.K.places():
1862
+ ok = False
1863
+ while not ok:
1864
+ try:
1865
+ if v(self.K.gen()) in RR:
1866
+ if self.real_intersection_is_empty(Bk, v):
1867
+ return True
1868
+ else:
1869
+ if self.complex_intersection_is_empty(Bk, v):
1870
+ return True
1871
+ ok = True
1872
+ except ArithmeticError:
1873
+ v = refine_embedding(v)
1874
+ if verbose:
1875
+ print("Refining embedding, codomain now {}".format(v.codomain()))
1876
+ return False # Couldn't prove it...
1877
+
1878
+ def min_gr(self, tol, n_max, verbose=False):
1879
+ r"""
1880
+ Return a lower bound for points of infinite order with good reduction.
1881
+
1882
+ INPUT:
1883
+
1884
+ - ``tol`` -- tolerance in output (see below)
1885
+
1886
+ - ``n_max`` -- how many multiples to use in iteration
1887
+
1888
+ - ``verbose``-- boolean (default: ``False``); verbosity flag
1889
+
1890
+ OUTPUT:
1891
+
1892
+ A positive real `\mu` for which it has been established
1893
+ rigorously that every point of infinite order on the elliptic
1894
+ curve (defined over its ground field), which has good
1895
+ reduction at all primes, has canonical height greater than
1896
+ `\mu`, and such that it is not possible (at least without
1897
+ increasing ``n_max``) to prove the same for
1898
+ `\mu\cdot\text{tol}`.
1899
+
1900
+ EXAMPLES:
1901
+
1902
+ Example 1 from [CS2006]_ (where a lower bound of 1.9865 was
1903
+ given)::
1904
+
1905
+ sage: E = EllipticCurve([1, 0, 1, 421152067, 105484554028056]) # 60490d1
1906
+ sage: E.height_function().min_gr(.0001, 5) # needs sage.symbolic
1907
+ 1.98684388146518
1908
+
1909
+ Example 10.1 from [Tho2010]_ (where a lower bound of 0.18 was
1910
+ given)::
1911
+
1912
+ sage: # needs sage.rings.number_field
1913
+ sage: K.<i> = QuadraticField(-1)
1914
+ sage: E = EllipticCurve([0, 0, 0, 91 - 26*i, -144 - 323*i])
1915
+ sage: H = E.height_function()
1916
+ sage: H.min_gr(0.1, 4) # long time, needs sage.symbolic
1917
+ 0.1621049443313762
1918
+
1919
+ Example 10.2 from [Tho2010]_::
1920
+
1921
+ sage: # needs sage.rings.number_field
1922
+ sage: K.<i> = QuadraticField(-1)
1923
+ sage: E = EllipticCurve([0, 1 - i, i, -i, 0])
1924
+ sage: H = E.height_function()
1925
+ sage: H.min_gr(0.01, 5) # long time, needs sage.symbolic
1926
+ 0.020153685521979152
1927
+
1928
+ In this example the point `P=(0,0)` has height 0.023 so our
1929
+ lower bound is quite good::
1930
+
1931
+ sage: P = E((0,0)) # needs sage.rings.number_field
1932
+ sage: P.has_good_reduction() # needs sage.rings.number_field
1933
+ True
1934
+ sage: P.height() # needs sage.rings.number_field
1935
+ 0.0230242154471211
1936
+
1937
+ Example 10.3 from [Tho2010]_ (where the same bound of 0.25 is
1938
+ given)::
1939
+
1940
+ sage: # needs sage.rings.number_field
1941
+ sage: x = polygen(ZZ, 'x')
1942
+ sage: K.<a> = NumberField(x^3 - 2)
1943
+ sage: E = EllipticCurve([0, 0, 0, -3*a - a^2, a^2])
1944
+ sage: H = E.height_function()
1945
+ sage: H.min_gr(0.1, 5) # long time, needs sage.symbolic
1946
+ 0.25
1947
+
1948
+ TESTS:
1949
+
1950
+ This example from the LMFDB gave problems before the fix in :issue:`8829`::
1951
+
1952
+ sage: # needs sage.rings.number_field
1953
+ sage: x = polygen(ZZ, 'x')
1954
+ sage: K.<phi> = NumberField(x^2 - x - 1)
1955
+ sage: E = EllipticCurve([phi + 1, -phi + 1, 1, 20*phi - 39, 196*phi + 237])
1956
+ sage: H = E.height_function()
1957
+ sage: H.min_gr(.1, 5, verbose=True) # long time, needs sage.symbolic
1958
+ B_1(1) = 1540.199246369678
1959
+ ...
1960
+ halving mu to 0.25 and increasing n_max to 6
1961
+ ...
1962
+ halving mu to 0.001953125 and increasing n_max to 13
1963
+ doubling mu to 0.0078125
1964
+ doubling mu to 0.015625
1965
+ height bound in [0.0078125, 0.015625] using n_max = 13
1966
+ ...
1967
+ height bound in [0.012048522073499539, 0.01313900648833929] using n_max = 13
1968
+ 0.012048522073499539
1969
+ """
1970
+ test = self.test_mu
1971
+ if test(1, n_max, verbose):
1972
+ mu = 2.0
1973
+ while test(mu, n_max, False):
1974
+ mu *= 2
1975
+ mu *= 0.5
1976
+ else:
1977
+ mu = 0.5
1978
+ while not test(mu, n_max, False):
1979
+ mu *= 0.5
1980
+ n_max += 1
1981
+ if verbose:
1982
+ print("halving mu to %r and increasing n_max to %r" % (mu, n_max))
1983
+ # now we have (mu,n_max) which work we can try to increase
1984
+ # mu again using this larger n_max:
1985
+ mu *= 2
1986
+ while test(mu, n_max, False):
1987
+ mu *= 2
1988
+ if verbose:
1989
+ print("doubling mu to %r" % mu)
1990
+ mu *= 0.5
1991
+
1992
+ # The true value lies between mu and eps * mu.
1993
+ eps = 2.0
1994
+ while eps > tol + 1:
1995
+ if verbose:
1996
+ print("height bound in [%r, %r] using n_max = %r"
1997
+ % (mu, mu * eps, n_max))
1998
+ eps = math.sqrt(eps)
1999
+ if test(mu * eps, n_max, False):
2000
+ mu = mu * eps
2001
+ if verbose:
2002
+ print("height bound in [%r, %r] using n_max = %r"
2003
+ % (mu, mu * eps, n_max))
2004
+ return RDF(mu)
2005
+
2006
+ def min(self, tol, n_max, verbose=False):
2007
+ r"""
2008
+ Return a lower bound for all points of infinite order.
2009
+
2010
+ INPUT:
2011
+
2012
+ - ``tol`` -- tolerance in output (see below)
2013
+
2014
+ - ``n_max`` -- how many multiples to use in iteration
2015
+
2016
+ - ``verbose``-- boolean (default: ``False``); verbosity flag
2017
+
2018
+ OUTPUT:
2019
+
2020
+ A positive real `\mu` for which it has been established
2021
+ rigorously that every point of infinite order on the elliptic
2022
+ curve (defined over its ground field) has canonical height
2023
+ greater than `\mu`, and such that it is not possible (at least
2024
+ without increasing ``n_max``) to prove the same for
2025
+ `\mu\cdot\text{tol}`.
2026
+
2027
+ EXAMPLES:
2028
+
2029
+ Example 1 from [CS2006]_ (where the same lower bound of 0.1126 was
2030
+ given)::
2031
+
2032
+ sage: E = EllipticCurve([1, 0, 1, 421152067, 105484554028056]) # 60490d1
2033
+ sage: E.height_function().min(.0001, 5) # needs sage.symbolic
2034
+ 0.0011263287309893311
2035
+
2036
+ Example 10.1 from [Tho2010]_ (where a lower bound of 0.18 was
2037
+ given)::
2038
+
2039
+ sage: # needs sage.rings.number_field
2040
+ sage: K.<i> = QuadraticField(-1)
2041
+ sage: E = EllipticCurve([0, 0, 0, 91 - 26*i, -144 - 323*i])
2042
+ sage: H = E.height_function()
2043
+ sage: H.min(0.1, 4) # long time
2044
+ 0.1621049443313762
2045
+
2046
+ Example 10.2 from [Tho2010]_::
2047
+
2048
+ sage: # needs sage.rings.number_field
2049
+ sage: K.<i> = QuadraticField(-1)
2050
+ sage: E = EllipticCurve([0, 1 - i, i, -i, 0])
2051
+ sage: H = E.height_function()
2052
+ sage: H.min(0.01, 5) # long time
2053
+ 0.020153685521979152
2054
+
2055
+ In this example the point `P=(0,0)` has height 0.023 so our
2056
+ lower bound is quite good::
2057
+
2058
+ sage: P = E((0,0)) # needs sage.rings.number_field
2059
+ sage: P.height() # needs sage.rings.number_field
2060
+ 0.0230242154471211
2061
+
2062
+ Example 10.3 from [Tho2010]_ (where the same bound of 0.0625 is
2063
+ given)::
2064
+
2065
+ sage: # needs sage.rings.number_field
2066
+ sage: x = polygen(ZZ, 'x')
2067
+ sage: K.<a> = NumberField(x^3 - 2)
2068
+ sage: E = EllipticCurve([0, 0, 0, -3*a - a^2, a^2])
2069
+ sage: H = E.height_function()
2070
+ sage: H.min(0.1, 5) # long time
2071
+ 0.0625
2072
+
2073
+ More examples over `\QQ`::
2074
+
2075
+ sage: E = EllipticCurve('37a')
2076
+ sage: h = E.height_function()
2077
+ sage: h.min(.01, 5) # needs sage.symbolic
2078
+ 0.03987318057488725
2079
+ sage: E.gen(0).height()
2080
+ 0.0511114082399688
2081
+
2082
+ After base change the lower bound can decrease::
2083
+
2084
+ sage: K.<a> = QuadraticField(-5) # needs sage.rings.number_field
2085
+ sage: E.change_ring(K).height_function().min(0.5, 10) # long time, needs sage.rings.number_field sage.symbolic
2086
+ 0.04419417382415922
2087
+
2088
+ sage: E = EllipticCurve('389a')
2089
+ sage: h = E.height_function()
2090
+ sage: h.min(0.1, 5) # needs sage.symbolic
2091
+ 0.05731275270029196
2092
+ sage: [P.height() for P in E.gens()]
2093
+ [0.686667083305587, 0.327000773651605]
2094
+ """
2095
+ # The lcm of the exponents of all the component groups at
2096
+ # finite places (allowing for everywhere good reduction!)
2097
+ tp = lcm([L.tamagawa_exponent() for L in self.E.local_data()] + [ZZ(1)])
2098
+
2099
+ # Include infinite places:
2100
+ if tp % 2 == 1:
2101
+ if self.K == QQ:
2102
+ if self.E.real_components() == 2:
2103
+ tp *= 2
2104
+ elif any(v(self.E.discriminant()) > 0
2105
+ for v in self.K.real_places()):
2106
+ tp *= 2
2107
+ # Now tp is such that tp*P has good reduction at all places
2108
+ # for all points P:
2109
+ return self.min_gr(tol, n_max, verbose) / tp ** 2