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,2576 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Wehler K3 Surfaces
4
+
5
+ AUTHORS:
6
+
7
+ - Ben Hutz (11-2012)
8
+ - Joao Alberto de Faria (10-2013)
9
+
10
+ .. TODO::
11
+
12
+ Hasse-Weil Zeta Function
13
+
14
+ Picard Number
15
+
16
+ Number Fields
17
+
18
+ REFERENCES: [FH2015]_, [CS1996]_, [Weh1998]_, [Hutz2007]
19
+ """
20
+ # ****************************************************************************
21
+ # This program is free software: you can redistribute it and/or modify
22
+ # it under the terms of the GNU General Public License as published by
23
+ # the Free Software Foundation, either version 2 of the License, or
24
+ # (at your option) any later version.
25
+ # https://www.gnu.org/licenses/
26
+ # ****************************************************************************
27
+
28
+ from copy import copy
29
+
30
+ import sage.rings.abc
31
+
32
+ from sage.categories.commutative_rings import CommutativeRings
33
+ from sage.categories.fields import Fields
34
+ from sage.categories.number_fields import NumberFields
35
+ from sage.misc.cachefunc import cached_method
36
+ from sage.misc.functional import sqrt
37
+ from sage.misc.lazy_import import lazy_import
38
+ from sage.misc.mrange import xmrange
39
+ from sage.rings.finite_rings.finite_field_constructor import GF
40
+ from sage.rings.fraction_field import FractionField
41
+ from sage.rings.integer_ring import ZZ
42
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
43
+ from sage.rings.rational_field import QQ
44
+ from sage.rings.real_mpfr import RealField
45
+ from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme
46
+ from sage.schemes.product_projective.space import ProductProjectiveSpaces
47
+ from sage.schemes.product_projective.subscheme import AlgebraicScheme_subscheme_product_projective
48
+
49
+ lazy_import("sage.calculus.functions", "jacobian")
50
+ lazy_import('sage.rings.padics.factory', 'Qp')
51
+
52
+
53
+ _NumberFields = NumberFields()
54
+ _Fields = Fields()
55
+ _CommutativeRings = CommutativeRings()
56
+
57
+
58
+ def WehlerK3Surface(polys):
59
+ r"""
60
+ Define a K3 Surface over `\mathbb{P}^2 \times \mathbb{P}^2` defined as
61
+ the intersection of a bilinear and biquadratic form. [Weh1998]_
62
+
63
+ INPUT:
64
+
65
+ - ``polys`` -- bilinear and biquadratic polynomials as a tuple or list
66
+
67
+ OUTPUT: :class:`WehlerK3Surface_ring`
68
+
69
+ EXAMPLES::
70
+
71
+ sage: PP.<x0,x1, x2, y0, y1, y2> = ProductProjectiveSpaces([2, 2], QQ)
72
+ sage: L = x0*y0 + x1*y1 - x2*y2
73
+ sage: Q = x0*x1*y1^2 + x2^2*y0*y2
74
+ sage: WehlerK3Surface([L, Q])
75
+ Closed subscheme of Product of projective spaces P^2 x P^2 over Rational
76
+ Field defined by:
77
+ x0*y0 + x1*y1 - x2*y2,
78
+ x0*x1*y1^2 + x2^2*y0*y2
79
+ """
80
+ if not isinstance(polys, (list, tuple)):
81
+ raise TypeError("polys must be a list or tuple of polynomials")
82
+
83
+ R = polys[0].parent().base_ring()
84
+ if R in _Fields:
85
+ if R in _Fields.Finite():
86
+ return WehlerK3Surface_finite_field(polys)
87
+ return WehlerK3Surface_field(polys)
88
+ if R in _CommutativeRings:
89
+ return WehlerK3Surface_ring(polys)
90
+ raise TypeError("R (= %s) must be a commutative ring" % R)
91
+
92
+
93
+ def random_WehlerK3Surface(PP):
94
+ r"""
95
+ Produces a random K3 surface in `\mathbb{P}^2 \times \mathbb{P}^2` defined as the
96
+ intersection of a bilinear and biquadratic form. [Weh1998]_
97
+
98
+ INPUT:
99
+
100
+ - ``PP`` -- projective space cartesian product
101
+
102
+ OUTPUT: :class:`WehlerK3Surface_ring`
103
+
104
+ EXAMPLES::
105
+
106
+ sage: PP.<x0, x1, x2, y0, y1, y2> = ProductProjectiveSpaces([2, 2], GF(3))
107
+ sage: w = random_WehlerK3Surface(PP)
108
+ sage: type(w)
109
+ <class 'sage.dynamics.arithmetic_dynamics.wehlerK3.WehlerK3Surface_finite_field_with_category'>
110
+ """
111
+
112
+ CR = PP.coordinate_ring()
113
+ BR = PP.base_ring()
114
+ Q = 0
115
+ for a in xmrange([3,3]):
116
+ for b in xmrange([3,3]):
117
+ Q += BR.random_element() * CR.gen(a[0]) * CR.gen(a[1]) * CR.gen(3+b[0]) * CR.gen(3+b[1])
118
+ #We can always change coordinates to make L diagonal
119
+ L = CR.gen(0) * CR.gen(3) + CR.gen(1) * CR.gen(4) + CR.gen(2) * CR.gen(5)
120
+ return WehlerK3Surface([L, Q])
121
+
122
+
123
+ class WehlerK3Surface_ring(AlgebraicScheme_subscheme_product_projective):
124
+ r"""
125
+ A K3 surface in `\mathbb{P}^2 \times \mathbb{P}^2` defined as the
126
+ intersection of a bilinear and biquadratic form. [Weh1998]_
127
+
128
+ EXAMPLES::
129
+
130
+ sage: R.<x,y,z,u,v,w> = PolynomialRing(QQ, 6)
131
+ sage: L = x*u - y*v
132
+ sage: Q = x*y*v^2 + z^2*u*w
133
+ sage: WehlerK3Surface([L, Q])
134
+ Closed subscheme of Product of projective spaces P^2 x P^2 over Rational
135
+ Field defined by:
136
+ x*u - y*v,
137
+ x*y*v^2 + z^2*u*w
138
+ """
139
+ def __init__(self, polys):
140
+ if not isinstance(polys, (list, tuple)):
141
+ raise TypeError("polys must be a list or tuple of polynomials")
142
+ R = polys[0].parent()
143
+ vars = R.variable_names()
144
+ A = ProductProjectiveSpaces([2, 2],R.base_ring(),vars)
145
+ CR = A.coordinate_ring()
146
+ #Check for following:
147
+ # Is the user calling in 2 polynomials from a list or tuple?
148
+ # Is there one biquadratic and one bilinear polynomial?
149
+ if len(polys) != 2:
150
+ raise AttributeError("there must be 2 polynomials")
151
+
152
+ if (all(((e[0] + e[1] + e[2]) == 1 and (e[3] + e[4] + e[5]) == 1) for e in polys[0].exponents())):
153
+ self.L = CR(polys[0])
154
+ elif (all(((e[0] + e[1] + e[2]) == 1 and (e[3] + e[4] + e[5]) == 1) for e in polys[1].exponents())):
155
+ self.L = CR(polys[1])
156
+ else:
157
+ raise AttributeError("there must be one bilinear polynomial")
158
+
159
+ if (all(((e[0] + e[1] + e[2]) == 2 and (e[3] + e[4] + e[5]) == 2) for e in polys[0].exponents())):
160
+ self.Q = CR(polys[0])
161
+ elif (all(((e[0] + e[1] + e[2]) == 2 and (e[3] + e[4] + e[5]) == 2) for e in polys[1].exponents())):
162
+ self.Q = CR(polys[1])
163
+ else:
164
+ raise AttributeError("there must be one biquadratic polynomial")
165
+ AlgebraicScheme_subscheme.__init__(self, A, polys)
166
+
167
+ def change_ring(self, R):
168
+ r"""
169
+ Changes the base ring on which the Wehler K3 Surface is defined.
170
+
171
+ INPUT:
172
+
173
+ - ``R`` -- ring
174
+
175
+ OUTPUT: K3 Surface defined over input ring
176
+
177
+ EXAMPLES::
178
+
179
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], GF(3))
180
+ sage: L = x0*y0 + x1*y1 - x2*y2
181
+ sage: Q = x0*x1*y1^2 + x2^2*y0*y2
182
+ sage: W = WehlerK3Surface([L, Q])
183
+ sage: W.base_ring()
184
+ Finite Field of size 3
185
+ sage: T = W.change_ring(GF(7))
186
+ sage: T.base_ring()
187
+ Finite Field of size 7
188
+ """
189
+
190
+ LR = self.L.change_ring(R)
191
+ LQ = self.Q.change_ring(R)
192
+ return (WehlerK3Surface( [LR,LQ]))
193
+
194
+ def _check_satisfies_equations(self, P):
195
+ r"""
196
+ Function checks to see if point ``P`` lies on the K3 Surface.
197
+
198
+ INPUT:
199
+
200
+ - ``P`` -- point in `\mathbb{P}^2 \times \mathbb{P}^2`
201
+
202
+ OUTPUT: ``True`` if the point is not on the surface; :exc:`AttributeError`
203
+ otherwise
204
+
205
+ EXAMPLES::
206
+
207
+ sage: P.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
208
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 \
209
+ ....: + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 - \
210
+ ....: 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
211
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - \
212
+ ....: 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
213
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
214
+ sage: Y = x0 * y0 + x1 * y1 + x2 * y2
215
+ sage: X = WehlerK3Surface([Z, Y])
216
+ sage: X._check_satisfies_equations([0, 0, 1, 1, 0, 0])
217
+ True
218
+
219
+ ::
220
+
221
+ sage: P.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
222
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 \
223
+ ....: + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 - \
224
+ ....: 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
225
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - \
226
+ ....: 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
227
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
228
+ sage: Y = x0*y0 + x1*y1 + x2*y2
229
+ sage: X = WehlerK3Surface([Z, Y])
230
+ sage: X._check_satisfies_equations([0, 1, 1, 1, 0, 0])
231
+ Traceback (most recent call last):
232
+ ...
233
+ AttributeError: point not on surface
234
+ """
235
+ Point = list(P)
236
+ if self.L(*Point) == 0 and self.Q(*Point) == 0:
237
+ return True
238
+ else:
239
+ raise AttributeError("point not on surface")
240
+
241
+ def _Lcoeff(self, component, i):
242
+ r"""
243
+ Return the polynomials `L^x_i` or `L^y_i`.
244
+
245
+ These polynomials are defined as:
246
+
247
+ `L^x_i` = the coefficients of `y_i` in `L(x, y)` (Component = 0)
248
+
249
+ `L^y_i` = the coefficients of `x_i` in `L(x, y)` (Component = 1)
250
+
251
+ Definition and Notation from: [CS1996]_
252
+
253
+ INPUT:
254
+
255
+ - ``component`` -- integer; 0 or 1
256
+
257
+ - ``i`` -- integer; 0, 1 or 2
258
+
259
+ OUTPUT: polynomial in terms of either y (Component = 0) or x (Component = 1)
260
+
261
+ EXAMPLES::
262
+
263
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
264
+ sage: Y = x0*y0 + x1*y1 - x2*y2
265
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 \
266
+ ....: + x2^2*y2^2 + x2^2*y1^2 + x1^2*y2^2
267
+ sage: X = WehlerK3Surface([Z, Y])
268
+ sage: X._Lcoeff(0, 0)
269
+ y0
270
+
271
+ ::
272
+
273
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
274
+ sage: Y = x0*y0 + x1*y1 - x2*y2
275
+ sage: Z =x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 \
276
+ ....: + x2^2*y2^2 + x2^2*y1^2 + x1^2*y2^2
277
+ sage: X = WehlerK3Surface([Z, Y])
278
+ sage: X._Lcoeff(1, 0)
279
+ x0
280
+ """
281
+ # Error Checks for Passed in Values
282
+ if component not in [0, 1]:
283
+ raise ValueError("component can only be 1 or 0")
284
+ if i not in [0, 1, 2]:
285
+ raise ValueError("index must be 0, 1, or 2")
286
+ R = self.ambient_space().coordinate_ring()
287
+ return self.L.coefficient(R.gen(component*3 + i))
288
+
289
+ def _Qcoeff(self, component, i, j):
290
+ r"""
291
+ Return the polynomials `Q^x_{ij}` or `Q^y_{ij}`.
292
+
293
+ These polynomials are defined as:
294
+
295
+ `Q^x_{ij}` = the coefficients of `y_{i}y_{j}` in `Q(x, y)` (Component = 0).
296
+
297
+ `Q^y_{ij}` = the coefficients of `x_{i}x_{j}` in `Q(x, y)` (Component = 1).
298
+
299
+ Definition and Notation from: [CS1996]_.
300
+
301
+ INPUT:
302
+
303
+ - ``component`` -- integer; 0 or 1
304
+
305
+ - ``i`` -- integer; 0, 1 or 2
306
+
307
+ - ``j`` -- integer; 0, 1 or 2
308
+
309
+ OUTPUT: polynomial in terms of either y (Component = 0) or x (Component = 1)
310
+
311
+ EXAMPLES::
312
+
313
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
314
+ sage: Y = x0*y0 + x1*y1 - x2*y2
315
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 \
316
+ ....: + x2^2*y2^2 + x2^2*y1^2 + x1^2*y2^2
317
+ sage: X = WehlerK3Surface([Z, Y])
318
+ sage: X._Qcoeff(0, 0, 0)
319
+ y0*y1 + y2^2
320
+
321
+ ::
322
+
323
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
324
+ sage: Y = x0*y0 + x1*y1 - x2*y2
325
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 \
326
+ ....: + x2^2*y2^2 + x2^2*y1^2 + x1^2*y2^2
327
+ sage: X = WehlerK3Surface([Z, Y])
328
+ sage: X._Qcoeff(1, 1, 0)
329
+ x0^2
330
+ """
331
+ # Check Errors in Passed in Values
332
+ if component not in [0, 1]:
333
+ raise ValueError("component can only be 1 or 0")
334
+
335
+ if i not in [0, 1, 2] or j not in [0, 1, 2]:
336
+ raise ValueError("the two indexes must be either 0, 1, or 2")
337
+
338
+ R = self.ambient_space().coordinate_ring()
339
+ return self.Q.coefficient(R.gen(component * 3 + i) * R.gen(component * 3 + j))
340
+
341
+ @cached_method
342
+ def Gpoly(self, component, k):
343
+ r"""
344
+ Return the G polynomials `G^*_k`.
345
+
346
+ They are defined as:
347
+ `G^*_k = \left(L^*_j\right)^2Q^*_{ii}-L^*_iL^*_jQ^*_{ij}+\left(L^*_i\right)^2Q^*_{jj}`
348
+ where `(i, j, k)` is some permutation of `(0, 1, 2)` and `*` is either
349
+ `x` (``component=1``) or `y` (``component=0``).
350
+
351
+ INPUT:
352
+
353
+ - ``component`` -- integer; 0 or 1
354
+
355
+ - ``k`` -- integer; 0, 1 or 2
356
+
357
+ OUTPUT: polynomial in terms of either `y` (``component=0``) or `x` (``component=1``)
358
+
359
+ EXAMPLES::
360
+
361
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
362
+ sage: Y = x0*y0 + x1*y1 - x2*y2
363
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 \
364
+ ....: + x2^2*y2^2 + x2^2*y1^2 + x1^2*y2^2
365
+ sage: X = WehlerK3Surface([Z, Y])
366
+ sage: X.Gpoly(1, 0)
367
+ x0^2*x1^2 + x1^4 - x0*x1^2*x2 + x1^3*x2 + x1^2*x2^2 + x2^4
368
+ """
369
+ # Check Errors in passed in values
370
+ if component not in [0, 1]:
371
+ raise ValueError("component can only be 1 or 0")
372
+
373
+ if k not in [0, 1, 2]:
374
+ raise ValueError("index must be either 0, 1, or 2")
375
+
376
+ Indices = [0, 1, 2]
377
+ Indices.remove( k)
378
+ i = Indices[0]
379
+ j = Indices[1]
380
+
381
+ return (self._Lcoeff(component, j)**2) * (self._Qcoeff(component, i, i)) - (self._Lcoeff(component, i)) * \
382
+ (self._Lcoeff(component, j)) * (self._Qcoeff(component, i, j)) + (self._Lcoeff( component, i)**2) * \
383
+ (self._Qcoeff( component, j, j))
384
+
385
+ @cached_method
386
+ def Hpoly(self, component, i, j):
387
+ r"""
388
+ Return the H polynomials defined as `H^*_{ij}`.
389
+
390
+ This polynomial is defined by:
391
+
392
+ `H^*_{ij} = 2L^*_iL^*_jQ^*_{kk}-L^*_iL^*_kQ^*_{jk} - L^*_jL^*_kQ^*_{ik}+\left(L^*_k\right)^2Q^*_{ij}`
393
+ where {i, j, k} is some permutation of (0, 1, 2) and * is either y (``component=0``) or x (``component=1``).
394
+
395
+ INPUT:
396
+
397
+ - ``component`` -- integer; 0 or 1
398
+
399
+ - ``i`` -- integer; 0, 1 or 2
400
+
401
+ - ``j`` -- integer; 0, 1 or 2
402
+
403
+ OUTPUT: polynomial in terms of either y (``component=0``) or x (``component=1``)
404
+
405
+ EXAMPLES::
406
+
407
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
408
+ sage: Y = x0*y0 + x1*y1 - x2*y2
409
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 \
410
+ ....: + x2^2*y2^2 + x2^2*y1^2 + x1^2*y2^2
411
+ sage: X = WehlerK3Surface([Z, Y])
412
+ sage: X.Hpoly(0, 1, 0)
413
+ 2*y0*y1^3 + 2*y0*y1*y2^2 - y1*y2^3
414
+ """
415
+ #Check Errors in Passed in Values
416
+ if component not in [0, 1]:
417
+ raise ValueError("component can only be 1 or 0")
418
+
419
+ if (i not in [0, 1, 2]) or (j not in [0, 1, 2]):
420
+ raise ValueError("the two indexes must be either 0, 1, or 2")
421
+
422
+ Indices = [0, 1, 2]
423
+ Indices.remove(i)
424
+ Indices.remove(j)
425
+
426
+ k = Indices[0]
427
+
428
+ return 2*(self._Lcoeff(component, i)) * (self._Lcoeff(component, j)) * (self._Qcoeff(component, k, k)) -\
429
+ (self._Lcoeff(component, i)) * (self._Lcoeff( component, k)) * (self._Qcoeff(component, j, k)) -\
430
+ (self._Lcoeff(component, j)) * (self._Lcoeff(component, k)) * (self._Qcoeff( component, i, k)) +\
431
+ (self._Lcoeff(component, k)**2) * (self._Qcoeff(component, i, j))
432
+
433
+ def Lxa(self, a):
434
+ r"""
435
+ Function will return the L polynomial defining the fiber, given by `L^{x}_{a}`.
436
+
437
+ This polynomial is defined as:
438
+
439
+ `L^{x}_{a} = \{(a, y) \in \mathbb{P}^{2} \times \mathbb{P}^{2} \colon L(a, y) = 0\}`.
440
+
441
+ Notation and definition from: [CS1996]_
442
+
443
+ INPUT:
444
+
445
+ - ``a`` -- point in `\mathbb{P}^2`
446
+
447
+ OUTPUT: a polynomial representing the fiber
448
+
449
+ EXAMPLES::
450
+
451
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
452
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 \
453
+ ....: + 3*x0*x1*y0*y1 - 2*x2^2*y0*y1 - \
454
+ ....: x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - 4*x1*x2*y1^2 \
455
+ ....: + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 \
456
+ ....: + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
457
+ sage: Y = x0*y0 + x1*y1 + x2*y2
458
+ sage: X = WehlerK3Surface([Z, Y])
459
+ sage: T = PP(1, 1, 0, 1, 0, 0)
460
+ sage: X.Lxa(T[0])
461
+ y0 + y1
462
+ """
463
+ if a not in self.ambient_space()[0]:
464
+ raise TypeError("point must be in projective space of dimension 2")
465
+ AS = self.ambient_space()
466
+ ASC = AS.coordinate_ring()
467
+ PSY = AS[1]
468
+ PSYC = PSY.coordinate_ring()
469
+ #Define projection homomorphism
470
+ p = ASC.hom([a[0],a[1],a[2]] + list(PSY.gens()), PSYC)
471
+ return p(self.L)
472
+
473
+ def Qxa(self, a):
474
+ r"""
475
+ Function will return the Q polynomial defining a fiber given by `Q^{x}_{a}`.
476
+
477
+ This polynomial is defined as:
478
+
479
+ `Q^{x}_{a} = \{(a,y) \in \mathbb{P}^{2} \times \mathbb{P}^{2} \colon Q(a,y) = 0\}`.
480
+
481
+ Notation and definition from: [CS1996]_
482
+
483
+ INPUT:
484
+
485
+ - ``a`` -- point in `\mathbb{P}^2`
486
+
487
+ OUTPUT: a polynomial representing the fiber
488
+
489
+ EXAMPLES::
490
+
491
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
492
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 \
493
+ ....: - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - 4*x1*x2*y1^2 \
494
+ ....: + 5*x0*x2*y0*y2 \
495
+ ....: - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
496
+ sage: Y = x0*y0 + x1*y1 + x2*y2
497
+ sage: X = WehlerK3Surface([Z, Y])
498
+ sage: T = PP(1, 1, 0, 1, 0, 0)
499
+ sage: X.Qxa(T[0])
500
+ 5*y0^2 + 7*y0*y1 + y1^2 + 11*y1*y2 + y2^2
501
+ """
502
+ if a not in self.ambient_space()[0]:
503
+ raise TypeError("point must be in Projective Space of dimension 2")
504
+ AS = self.ambient_space()
505
+ ASC = AS.coordinate_ring()
506
+ PSY = AS[1]
507
+ PSYC = PSY.coordinate_ring()
508
+ #Define projection homomorphism
509
+ p = ASC.hom([a[0], a[1], a[2]] + list(PSY.gens()), PSYC)
510
+ return p(self.Q)
511
+
512
+ def Sxa(self, a):
513
+ r"""
514
+ Function will return fiber by `S^{x}_{a}`.
515
+
516
+ This function is defined as:
517
+
518
+ `S^{x}_{a} = L^{x}_{a} \cap Q^{x}_{a}`.
519
+
520
+ Notation and definition from: [CS1996]_
521
+
522
+ INPUT:
523
+
524
+ - ``a`` -- point in `\mathbb{P}^2`
525
+
526
+ OUTPUT: a subscheme representing the fiber
527
+
528
+ EXAMPLES::
529
+
530
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
531
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 \
532
+ ....: + 3*x0*x1*y0*y1 \
533
+ ....: - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - 4*x1*x2*y1^2 \
534
+ ....: + 5*x0*x2*y0*y2 \
535
+ ....: - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
536
+ sage: Y = x0*y0 + x1*y1 + x2*y2
537
+ sage: Y = x0*y0 + x1*y1 + x2*y2
538
+ sage: X = WehlerK3Surface([Z, Y])
539
+ sage: T = PP(1, 1, 0, 1, 0, 0)
540
+ sage: X.Sxa(T[0])
541
+ Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
542
+ y0 + y1,
543
+ 5*y0^2 + 7*y0*y1 + y1^2 + 11*y1*y2 + y2^2
544
+ """
545
+ if a not in self.ambient_space()[0]:
546
+ raise TypeError("point must be in projective space of dimension 2")
547
+ PSY = self.ambient_space()[1]
548
+ return PSY.subscheme([self.Lxa(a),self.Qxa(a)])
549
+
550
+ def Lyb(self, b):
551
+ r"""
552
+ Function will return a fiber by `L^{y}_{b}`.
553
+
554
+ This polynomial is defined as:
555
+
556
+ `L^{y}_{b} = \{(x,b) \in \mathbb{P}^{2} \times \mathbb{P}^{2} \colon L(x,b) = 0\}`.
557
+
558
+ Notation and definition from: [CS1996]_
559
+
560
+ INPUT:
561
+
562
+ - ``b`` -- point in projective space
563
+
564
+ OUTPUT: a polynomial representing the fiber
565
+
566
+ EXAMPLES::
567
+
568
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
569
+ sage: Z =x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 \
570
+ ....: + 3*x0*x1*y0*y1 \
571
+ ....: - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - 4*x1*x2*y1^2 \
572
+ ....: + 5*x0*x2*y0*y2 \
573
+ ....: - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
574
+ sage: Y = x0*y0 + x1*y1 + x2*y2
575
+ sage: Y = x0*y0 + x1*y1 + x2*y2
576
+ sage: X = WehlerK3Surface([Z, Y])
577
+ sage: T = PP(1, 1, 0, 1, 0, 0)
578
+ sage: X.Lyb(T[1])
579
+ x0
580
+ """
581
+ if b not in self.ambient_space()[1]:
582
+ raise TypeError("point must be in projective space of dimension 2")
583
+ AS = self.ambient_space()
584
+ ASC = AS.coordinate_ring()
585
+ PSY = AS[0]
586
+ PSYC = PSY.coordinate_ring()
587
+ p = ASC.hom(list(PSY.gens()) + [b[0], b[1], b[2]], PSYC)
588
+ return (p(self.L))
589
+
590
+ def Qyb(self, b):
591
+ r"""
592
+
593
+ Function will return a fiber by `Q^{y}_{b}`.
594
+
595
+ This polynomial is defined as:
596
+
597
+ `Q^{y}_{b} = \{(x,b) \in \mathbb{P}^{2} \times \mathbb{P}^{2} \colon Q(x,b) = 0\}`.
598
+
599
+ Notation and definition from: [CS1996]_
600
+
601
+ INPUT:
602
+
603
+ - ``b`` -- point in projective space
604
+
605
+ OUTPUT: a polynomial representing the fiber
606
+
607
+ EXAMPLES::
608
+
609
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
610
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 \
611
+ ....: + 3*x0*x1*y0*y1 - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
612
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 \
613
+ ....: + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
614
+ sage: Y = x0*y0 + x1*y1 + x2*y2
615
+ sage: X = WehlerK3Surface([Z, Y])
616
+ sage: T = PP(1, 1, 0, 1, 0, 0)
617
+ sage: X.Qyb(T[1])
618
+ x0^2 + 3*x0*x1 + x1^2
619
+ """
620
+ if b not in self.ambient_space()[1]:
621
+ raise TypeError("point must be in projective space of dimension 2")
622
+ AS = self.ambient_space()
623
+ ASC = AS.coordinate_ring()
624
+ PSY = AS[0]
625
+ PSYC = PSY.coordinate_ring()
626
+ p = ASC.hom(list(PSY.gens()) + [b[0], b[1], b[2]], PSYC)
627
+ return (p(self.Q))
628
+
629
+ def Syb(self, b):
630
+ r"""
631
+ Function will return fiber by `S^{y}_{b}`.
632
+
633
+ This function is defined by:
634
+
635
+ `S^{y}_{b} = L^{y}_{b} \cap Q^{y}_{b}`.
636
+
637
+ Notation and definition from: [CS1996]_
638
+
639
+ INPUT:
640
+
641
+ - ``b`` -- point in `\mathbb{P}^2`
642
+
643
+ OUTPUT: a subscheme representing the fiber
644
+
645
+ EXAMPLES::
646
+
647
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
648
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
649
+ ....: 3*x0*x1*y0*y1 - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
650
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 \
651
+ ....: + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
652
+ sage: Y = x0 * y0 + x1 * y1 + x2 * y2
653
+ sage: X = WehlerK3Surface([Z, Y])
654
+ sage: T = PP(1, 1, 0, 1, 0, 0)
655
+ sage: X.Syb(T[1])
656
+ Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
657
+ x0,
658
+ x0^2 + 3*x0*x1 + x1^2
659
+ """
660
+ if b not in self.ambient_space()[1]:
661
+ raise TypeError("point must be in projective space of dimension 2")
662
+ AS = self.ambient_space()
663
+ PSY = AS[0]
664
+ return PSY.subscheme([self.Lyb(b), self.Qyb(b)])
665
+
666
+ def Ramification_poly(self, i):
667
+ r"""
668
+ Function will return the Ramification polynomial `g^*`.
669
+
670
+ This polynomial is defined by:
671
+
672
+ `g^* = \frac{\left(H^*_{ij}\right)^2 - 4G^*_iG^*_j}{\left(L^*_k\right)^2}`.
673
+
674
+ The roots of this polynomial will either be degenerate fibers or fixed points
675
+ of the involutions `\sigma_x` or `\sigma_y` for more information, see [CS1996]_.
676
+
677
+ INPUT:
678
+
679
+ - ``i`` -- integer; either 0 (polynomial in y) or 1 (polynomial in x)
680
+
681
+ OUTPUT: polynomial in the coordinate ring of the ambient space
682
+
683
+ EXAMPLES::
684
+
685
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
686
+ sage: Z = (x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1
687
+ ....: - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - 4*x1*x2*y1^2
688
+ ....: + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2
689
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2)
690
+ sage: Y = x0*y0 + x1*y1 + x2*y2
691
+ sage: X = WehlerK3Surface([Z, Y])
692
+ sage: X.Ramification_poly(0)
693
+ 8*y0^5*y1 - 24*y0^4*y1^2 + 48*y0^2*y1^4 - 16*y0*y1^5 + y1^6 + 84*y0^3*y1^2*y2
694
+ + 46*y0^2*y1^3*y2 - 20*y0*y1^4*y2 + 16*y1^5*y2 + 53*y0^4*y2^2 + 56*y0^3*y1*y2^2
695
+ - 32*y0^2*y1^2*y2^2 - 80*y0*y1^3*y2^2 - 92*y1^4*y2^2 - 12*y0^2*y1*y2^3
696
+ - 168*y0*y1^2*y2^3 - 122*y1^3*y2^3 + 14*y0^2*y2^4 + 8*y0*y1*y2^4 - 112*y1^2*y2^4
697
+ + y2^6
698
+ """
699
+ return ((self._Lcoeff(i, 0))**2)*(self._Qcoeff(i, 1, 2))**2 + \
700
+ ((self._Lcoeff(i, 1))**2)*(self._Qcoeff(i, 0, 2)**2) + \
701
+ ((self._Lcoeff(i, 2))**2)*(self._Qcoeff(i, 0, 1)**2) - \
702
+ 2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 1))*(self._Qcoeff(i, 0, 2))*(self._Qcoeff(i, 1, 2))\
703
+ - 2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 1, 2))\
704
+ - 2*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 0, 2)) + \
705
+ 4*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 1))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 2, 2)) + \
706
+ 4*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 2))*(self._Qcoeff(i, 1, 1)) + \
707
+ 4*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 1, 2))*(self._Qcoeff(i, 0, 0)) - \
708
+ 4*((self._Lcoeff(i, 0))**2)*(self._Qcoeff(i, 1, 1))*(self._Qcoeff(i, 2, 2)) - \
709
+ 4*((self._Lcoeff(i, 1))**2)*(self._Qcoeff(i, 0, 0))*(self._Qcoeff(i, 2, 2)) - \
710
+ 4*((self._Lcoeff(i, 2))**2)*(self._Qcoeff(i, 1, 1))*(self._Qcoeff(i, 0, 0))
711
+
712
+ @cached_method
713
+ def is_degenerate(self):
714
+ r"""
715
+ Function will return ``True`` if there is a fiber (over the algebraic closure of the
716
+ base ring) of dimension greater than 0 and ``False`` otherwise.
717
+
718
+ OUTPUT: boolean
719
+
720
+ EXAMPLES::
721
+
722
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
723
+ sage: Y = x0*y0 + x1*y1 - x2*y2
724
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 + x2^2*y2^2 + \
725
+ ....: x2^2*y1^2 + x1^2*y2^2
726
+ sage: X = WehlerK3Surface([Z, Y])
727
+ sage: X.is_degenerate()
728
+ True
729
+
730
+ ::
731
+
732
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
733
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 - \
734
+ ....: 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 -4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - \
735
+ ....: 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
736
+ sage: Y = x0*y0 + x1*y1 + x2*y2
737
+ sage: X = WehlerK3Surface([Z, Y])
738
+ sage: X.is_degenerate()
739
+ False
740
+
741
+ ::
742
+
743
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], GF(3))
744
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 - \
745
+ ....: 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 -4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - \
746
+ ....: 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
747
+ sage: Y = x0*y0 + x1*y1 + x2*y2
748
+ sage: X = WehlerK3Surface([Z, Y])
749
+ sage: X.is_degenerate()
750
+ True
751
+ """
752
+ PP = self.ambient_space()
753
+ K = FractionField(PP[0].base_ring())
754
+ R = PP.coordinate_ring()
755
+ PS = PP[0] #check for x fibers
756
+ vars = list(PS.gens())
757
+ R0 = PolynomialRing(K, 3, vars) #for dimension calculation to work,
758
+ #must be done with Polynomial ring over a field
759
+ #Degenerate is equivalent to a common zero, see Prop 1.4 in [CS1996]_
760
+ I = R.ideal(self.Gpoly(1, 0), self.Gpoly(1, 1), self.Gpoly(1, 2), self.Hpoly(1, 0, 1),
761
+ self.Hpoly(1, 0, 2), self.Hpoly(1, 1, 2))
762
+ phi = R.hom(vars + [0, 0, 0], R0)
763
+ I = phi(I)
764
+ if I.dimension() != 0:
765
+ return True
766
+
767
+ PS = PP[1] #check for y fibers
768
+ vars = list(PS.gens())
769
+ R0 = PolynomialRing(K,3,vars) #for dimension calculation to work,
770
+ #must be done with Polynomial ring over a field
771
+ #Degenerate is equivalent to a common zero, see Prop 1.4 in [CS1996]_
772
+ I = R.ideal(self.Gpoly(0, 0), self.Gpoly(0, 1), self.Gpoly(0, 2), self.Hpoly(0, 0, 1),
773
+ self.Hpoly(0, 0, 2), self.Hpoly(0, 1, 2))
774
+ phi = R.hom([0, 0, 0] + vars, R0)
775
+ I = phi(I)
776
+ return I.dimension() != 0
777
+
778
+ def degenerate_fibers(self):
779
+ r"""
780
+ Return the (rational) degenerate fibers of the surface defined over
781
+ the base ring, or the fraction field of the base ring if it is not a field.
782
+
783
+ ALGORITHM:
784
+
785
+ The criteria for degeneracy by the common vanishing of the polynomials
786
+ ``self.Gpoly(1, 0)``, ``self.Gpoly(1, 1)``, ``self.Gpoly(1, 2)``,
787
+ ``self.Hpoly(1, 0, 1)``, ``self.Hpoly(1, 0, 2)``,
788
+ ``self.Hpoly(1, 1, 2)`` (for the first component), is from Proposition 1.4
789
+ in the following article: [CS1996]_.
790
+
791
+ This function finds the common solution through elimination via Groebner bases
792
+ by using the .variety() function on the three affine charts in each component.
793
+
794
+ OUTPUT: the output is a list of lists where the elements of lists are
795
+ points in the appropriate projective space.
796
+ The first list is the points whose pullback by the projection to the
797
+ first component (projective space) is dimension greater than 0.
798
+ The second list is points in the second component
799
+
800
+ EXAMPLES::
801
+
802
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
803
+ sage: Y = x0*y0 + x1*y1 - x2*y2
804
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 + x2^2*y2^2\
805
+ ....: + x2^2*y1^2 + x1^2*y2^2
806
+ sage: X = WehlerK3Surface([Z, Y])
807
+ sage: X.degenerate_fibers()
808
+ [[], [(1 : 0 : 0)]]
809
+
810
+ ::
811
+
812
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
813
+ sage: Z = (x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1
814
+ ....: - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - 4*x1*x2*y1^2
815
+ ....: + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2
816
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2)
817
+ sage: Y = x0*y0 + x1*y1 + x2*y2
818
+ sage: X = WehlerK3Surface([Z, Y])
819
+ sage: X.degenerate_fibers()
820
+ [[], []]
821
+
822
+ ::
823
+
824
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
825
+ sage: R = PP.coordinate_ring()
826
+ sage: l = y0*x0 + y1*x1 + (y0 - y1)*x2
827
+ sage: q = (y1*y0 + y2^2)*x0^2 + ((y0^2 - y2*y1)*x1 + (y0^2 + (y1^2 - y2^2))*x2)*x0 \
828
+ ....: + (y2*y0 + y1^2)*x1^2 + (y0^2 + (-y1^2 + y2^2))*x2*x1
829
+ sage: X = WehlerK3Surface([l,q])
830
+ sage: X.degenerate_fibers()
831
+ [[(-1 : 1 : 1), (0 : 0 : 1)], [(-1 : -1 : 1), (0 : 0 : 1)]]
832
+ """
833
+ PP = self.ambient_space()
834
+ R = PP.coordinate_ring()
835
+ PSX = PP[0]
836
+ vars = list(PSX.gens())
837
+ K = FractionField(PSX.base_ring())
838
+ R0 = PolynomialRing(K, 3, vars)
839
+ I = R.ideal(self.Gpoly(1, 0), self.Gpoly(1, 1), self.Gpoly(1, 2), self.Hpoly(1, 0,1 ),
840
+ self.Hpoly(1, 0, 2), self.Hpoly(1, 1, 2))
841
+ phi = R.hom(vars + [0, 0, 0], R0)
842
+ I = phi(I)
843
+ xFibers = []
844
+ #check affine charts
845
+ for n in range(3):
846
+ affvars = list(R0.gens())
847
+ del affvars[n]
848
+ R1 = PolynomialRing(K, 2, affvars, order='lex')
849
+ mapvars = list(R1.gens())
850
+ mapvars.insert(n,1)
851
+ phi1 = R0.hom(mapvars, R1)
852
+ J = phi1(I)
853
+ if (J.dimension() == 0):
854
+ Var = J.variety()
855
+ if Var != [{}]:
856
+ for d in Var: #iterate through dictionaries
857
+ P = [] #new point
858
+ for z in mapvars: #assign coordinate values
859
+ if (z == 1):
860
+ P.append(1)
861
+ else:
862
+ P.append(d[z])
863
+ MP = PSX(P) #make projective point
864
+ if MP not in xFibers:
865
+ xFibers.append(MP)
866
+ PSY = PP[1]
867
+ vars = list(PSY.gens())
868
+ K = FractionField(PSY.base_ring())
869
+ R0 = PolynomialRing(K, 3, vars)
870
+ I = R.ideal(self.Gpoly(0, 0), self.Gpoly(0, 1), self.Gpoly(0, 2), self.Hpoly(0, 0, 1),
871
+ self.Hpoly(0, 0, 2), self.Hpoly(0, 1, 2))
872
+ phi = PP.coordinate_ring().hom([0, 0, 0] + vars, R0)
873
+ I = phi(I)
874
+ yFibers = []
875
+ #check affine charts
876
+ for n in range(3):
877
+ affvars = list(R0.gens())
878
+ del affvars[n]
879
+ R1 = PolynomialRing(K, 2, affvars, order='lex')
880
+ mapvars = list(R1.gens())
881
+ mapvars.insert(n, 1)
882
+ phi1 = R0.hom(mapvars,R1)
883
+ J = phi1(I)
884
+ if (J.dimension() == 0):
885
+ Var = J.variety()
886
+ if Var != [{}]:
887
+ for d in Var: #iterate through dictionaries
888
+ P = [] #new point
889
+ for z in mapvars: #assign coordinate values
890
+ if (z == 1):
891
+ P.append(1)
892
+ else:
893
+ P.append(d[z])
894
+ MP = PSY(P) #make projective point
895
+ if MP not in yFibers:
896
+ yFibers.append(MP)
897
+ return [xFibers,yFibers]
898
+
899
+ @cached_method
900
+ def degenerate_primes(self, check=True):
901
+ r"""
902
+ Determine which primes `p` ``self`` has degenerate fibers over `\GF{p}`.
903
+
904
+ If ``check`` is ``False``, then may return primes that do not have degenerate fibers.
905
+ Raises an error if the surface is degenerate.
906
+ Works only for ``ZZ`` or ``QQ``.
907
+
908
+ INPUT:
909
+
910
+ - ``check`` -- boolean (default: ``True``); whether the primes are verified
911
+
912
+ ALGORITHM:
913
+
914
+ `p` is a prime of bad reduction if and only if the defining
915
+ polynomials of ``self`` plus the G and H polynomials have a common
916
+ zero. Or stated another way, `p` is a prime of bad reduction if
917
+ and only if the radical of the ideal defined by the defining
918
+ polynomials of ``self`` plus the G and H polynomials is not
919
+ `(x_0,x_1,\ldots,x_N)`. This happens if and only if some
920
+ power of each `x_i` is not in the ideal defined by the
921
+ defining polynomials of ``self`` (with G and H). This last condition
922
+ is what is checked. The lcm of the coefficients of the monomials `x_i` in
923
+ a Groebner basis is computed. This may return extra primes.
924
+
925
+ OUTPUT: list of primes
926
+
927
+ EXAMPLES::
928
+
929
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(QQ, 6)
930
+ sage: L = y0*x0 + (y1*x1 + y2*x2)
931
+ sage: Q = (2*y0^2 + y2*y0 + (2*y1^2 + y2^2))*x0^2 + ((y0^2 + y1*y0 + \
932
+ ....: (y1^2 + 2*y2*y1 + y2^2))*x1 + (2*y1^2 + y2*y1 + y2^2)*x2)*x0 + ((2*y0^2\
933
+ ....: + (y1 + 2*y2)*y0 + (2*y1^2 + y2*y1))*x1^2 + ((2*y1 + 2*y2)*y0 + (y1^2 + \
934
+ ....: y2*y1 + 2*y2^2))*x2*x1 + (2*y0^2 + y1*y0 + (2*y1^2 + y2^2))*x2^2)
935
+ sage: X = WehlerK3Surface([L, Q])
936
+ sage: X.degenerate_primes()
937
+ [2, 3, 5, 11, 23, 47, 48747691, 111301831]
938
+ """
939
+ PP = self.ambient_space()
940
+ if PP.base_ring() != ZZ and PP.base_ring() != QQ:
941
+ if PP.base_ring() in _NumberFields or isinstance(PP.base_ring(), sage.rings.abc.Order):
942
+ raise NotImplementedError("only implemented for ZZ and QQ")
943
+ else:
944
+ raise TypeError("must be over a number field or number field order")
945
+ if self.is_degenerate():
946
+ raise TypeError("surface is degenerate at all primes")
947
+ RR = PP.coordinate_ring()
948
+
949
+ #x-fibers
950
+ PSX = PP[0]
951
+ vars = list(PSX.gens())
952
+ K = PSX.base_ring()
953
+ R = PolynomialRing(K, 3, vars)
954
+ I = RR.ideal(self.Gpoly(1, 0), self.Gpoly(1, 1), self.Gpoly(1, 2), self.Hpoly(1, 0, 1),
955
+ self.Hpoly(1, 0, 2), self.Hpoly(1, 1, 2))
956
+ phi = PP.coordinate_ring().hom(vars + [0, 0, 0], R)
957
+ I = phi(I)
958
+ bad_primes = []
959
+
960
+ #move the ideal to the ring of integers
961
+ if R.base_ring().is_field():
962
+ S = PolynomialRing(R.base_ring().ring_of_integers(),R.gens(),R.ngens())
963
+ I = S.ideal(I.gens())
964
+ GB = I.groebner_basis()
965
+ #get the primes dividing the coefficients of the monomials x_i^k_i
966
+ for i in range(len(GB)):
967
+ LT = GB[i].lt().degrees()
968
+ power = 0
969
+ for j in range(R.ngens()):
970
+ if LT[j] != 0:
971
+ power += 1
972
+ if power == 1:
973
+ bad_primes = bad_primes+GB[i].lt().coefficients()[0].support()
974
+
975
+ #y-fibers
976
+ PSY = PP[1]
977
+ vars = list(PSY.gens())
978
+ K = PSY.base_ring()
979
+ R = PolynomialRing(K, 3, vars)
980
+ I = RR.ideal(self.Gpoly(0, 0), self.Gpoly(0, 1), self.Gpoly(0, 2), self.Hpoly(0, 0, 1),
981
+ self.Hpoly(0, 0, 2), self.Hpoly(0, 1, 2))
982
+ phi = PP.coordinate_ring().hom([0, 0, 0] + vars, R)
983
+ I = phi(I)
984
+ #move the ideal to the ring of integers
985
+ if R.base_ring().is_field():
986
+ S = PolynomialRing(R.base_ring().ring_of_integers(),R.gens(),R.ngens())
987
+ I = S.ideal(I.gens())
988
+ GB = I.groebner_basis()
989
+ #get the primes dividing the coefficients of the monomials x_i^k_i
990
+ for i in range(len(GB)):
991
+ LT = GB[i].lt().degrees()
992
+ power = 0
993
+ for j in range(R.ngens()):
994
+ if LT[j] != 0:
995
+ power += 1
996
+ if power == 1:
997
+ bad_primes = bad_primes+GB[i].lt().coefficients()[0].support()
998
+ bad_primes = sorted(set(bad_primes))
999
+ #check to return only the truly bad primes
1000
+ if check:
1001
+ for p in bad_primes:
1002
+ X = self.change_ring(GF(p))
1003
+ if not X.is_degenerate():
1004
+ bad_primes.remove(p)
1005
+ return bad_primes
1006
+
1007
+ def is_smooth(self):
1008
+ r"""
1009
+ Function will return the status of the smoothness of the surface.
1010
+
1011
+ ALGORITHM:
1012
+
1013
+ Checks to confirm that all of the 2x2 minors of the Jacobian generated from
1014
+ the biquadratic and bilinear forms have no common vanishing points.
1015
+
1016
+ OUTPUT: boolean
1017
+
1018
+ EXAMPLES::
1019
+
1020
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
1021
+ sage: Y = x0*y0 + x1*y1 - x2*y2
1022
+ sage: Z = x0^2*y0*y1 + x0^2*y2^2 - x0*x1*y1*y2 + x1^2*y2*y1 +\
1023
+ ....: x2^2*y2^2 + x2^2*y1^2 + x1^2*y2^2
1024
+ sage: X = WehlerK3Surface([Z, Y])
1025
+ sage: X.is_smooth()
1026
+ False
1027
+
1028
+ ::
1029
+
1030
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1031
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
1032
+ ....: 3*x0*x1*y0*y1 - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
1033
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
1034
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
1035
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1036
+ sage: X = WehlerK3Surface([Z, Y])
1037
+ sage: X.is_smooth()
1038
+ True
1039
+ """
1040
+ vars = list(self.ambient_space().gens())
1041
+ M = jacobian([self.L, self.Q], vars)
1042
+ R = self.ambient_space().coordinate_ring()
1043
+ I = R.ideal(M.minors(2) + [self.L,self.Q])
1044
+ T = PolynomialRing(self.ambient_space().base_ring().fraction_field(), 4, 'h')
1045
+ #check the 9 affine charts for a singular point
1046
+ for l in xmrange([3, 3]):
1047
+ vars = list(T.gens())
1048
+ vars.insert(l[0], 1)
1049
+ vars.insert(3 + l[1], 1)
1050
+ phi = R.hom(vars, T)
1051
+ J = phi(I)
1052
+ if J.dimension() != -1:
1053
+ return False
1054
+ return True
1055
+
1056
+ def sigmaX(self, P, **kwds):
1057
+ r"""
1058
+ Function returns the involution on the Wehler K3 surface induced by the double covers.
1059
+
1060
+ In particular, it fixes the projection to the first coordinate and swaps the
1061
+ two points in the fiber, i.e. `(x, y) \to (x, y')`.
1062
+ Note that in the degenerate case, while we can split fiber into pairs of points,
1063
+ it is not always possibleto distinguish them, using this algorithm.
1064
+
1065
+ ALGORITHM:
1066
+
1067
+ Refer to Section 6: "An algorithm to compute `\sigma_x`, `\sigma_y`, `\phi`,
1068
+ and `\psi`" in [CS1996FH2015.
1069
+ For the degenerate case refer to [FH2015]_.
1070
+
1071
+ INPUT:
1072
+
1073
+ - ``P`` -- a point in `\mathbb{P}^2 \times \mathbb{P}^2`
1074
+
1075
+ kwds:
1076
+
1077
+ - ``check`` -- boolean (default: ``True``); checks to see if point is on the surface
1078
+
1079
+ - ``normalize`` -- boolean (default: ``True``); normalizes the point
1080
+
1081
+ OUTPUT: a point on the K3 surface
1082
+
1083
+ EXAMPLES::
1084
+
1085
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1086
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 +\
1087
+ ....: 3*x0*x1*y0*y1 -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 -\
1088
+ ....: 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 -4*x1*x2*y0*y2 + 7*x0^2*y1*y2 +\
1089
+ ....: 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
1090
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1091
+ sage: X = WehlerK3Surface([Z, Y])
1092
+ sage: T = PP(0, 0, 1, 1, 0, 0)
1093
+ sage: X.sigmaX(T)
1094
+ (0 : 0 : 1 , 0 : 1 : 0)
1095
+
1096
+ degenerate examples::
1097
+
1098
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1099
+ sage: l = y0*x0 + y1*x1 + (y0 - y1)*x2
1100
+ sage: q = (y1*y0)*x0^2 + ((y0^2)*x1 + (y0^2 + (y1^2 - y2^2))*x2)*x0\
1101
+ ....: + (y2*y0 + y1^2)*x1^2 + (y0^2 + (-y1^2 + y2^2))*x2*x1
1102
+ sage: X = WehlerK3Surface([l, q])
1103
+ sage: X.sigmaX(X([1, 0, 0, 0, 1, -2]))
1104
+ (1 : 0 : 0 , 0 : 1/2 : 1)
1105
+ sage: X.sigmaX(X([1, 0, 0, 0, 0, 1]))
1106
+ (1 : 0 : 0 , 0 : 0 : 1)
1107
+ sage: X.sigmaX(X([-1, 1, 1, -1, -1, 1]))
1108
+ (-1 : 1 : 1 , 2 : 2 : 1)
1109
+ sage: X.sigmaX(X([0, 0, 1, 1, 1, 0]))
1110
+ (0 : 0 : 1 , 1 : 1 : 0)
1111
+ sage: X.sigmaX(X([0, 0, 1, 1, 1, 1]))
1112
+ (0 : 0 : 1 , -1 : -1 : 1)
1113
+
1114
+ Case where we cannot distinguish the two points::
1115
+
1116
+ sage: PP.<y0,y1,y2,x0,x1,x2>=ProductProjectiveSpaces([2, 2], GF(3))
1117
+ sage: l = x0*y0 + x1*y1 + x2*y2
1118
+ sage: q = (-3*x0^2*y0^2 + 4*x0*x1*y0^2 - 3*x0*x2*y0^2 - 5*x0^2*y0*y1
1119
+ ....: - 190*x0*x1*y0*y1 - 5*x1^2*y0*y1 + 5*x0*x2*y0*y1 + 14*x1*x2*y0*y1
1120
+ ....: + 5*x2^2*y0*y1 - x0^2*y1^2 - 6*x0*x1*y1^2 - 2*x1^2*y1^2
1121
+ ....: + 2*x0*x2*y1^2 - 4*x2^2*y1^2 + 4*x0^2*y0*y2 - x1^2*y0*y2
1122
+ ....: + 3*x0*x2*y0*y2 + 6*x1*x2*y0*y2 - 6*x0^2*y1*y2 - 4*x0*x1*y1*y2
1123
+ ....: - x1^2*y1*y2 + 51*x0*x2*y1*y2 - 7*x1*x2*y1*y2 - 9*x2^2*y1*y2
1124
+ ....: - x0^2*y2^2 - 4*x0*x1*y2^2 + 4*x1^2*y2^2 - x0*x2*y2^2
1125
+ ....: + 13*x1*x2*y2^2 - x2^2*y2^2)
1126
+ sage: X = WehlerK3Surface([l, q])
1127
+ sage: P = X([1, 0, 0, 0, 1, 1])
1128
+ sage: X.sigmaX(X.sigmaX(P))
1129
+ Traceback (most recent call last):
1130
+ ...
1131
+ ValueError: cannot distinguish points in the degenerate fiber
1132
+ """
1133
+ check = kwds.get("check", True)
1134
+ normalize = kwds.get("normalize", True)
1135
+
1136
+ if check:
1137
+ if self != P.codomain():
1138
+ try:
1139
+ P = self(list(P))
1140
+ except (TypeError, NotImplementedError, AttributeError):
1141
+ raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self))
1142
+ pt = list(P[0]) + [0, 0, 0]
1143
+ if P[1][0] != 0:
1144
+ a, b, c = [P[1][0]*self.Gpoly(1, 0)(*pt),
1145
+ -1*P[1][0]*self.Hpoly(1, 0, 1)(*pt) - P[1][1]*self.Gpoly(1, 0)(*pt),
1146
+ -P[1][0]*self.Hpoly(1, 0, 2)(*pt) - P[1][2]*self.Gpoly(1, 0)(*pt)]
1147
+ elif P[1][1] != 0:
1148
+ a, b, c = [-1*P[1][1]*self.Hpoly(1, 0, 1)(*pt)-P[1][0]*self.Gpoly(1, 1)(*pt),
1149
+ P[1][1]*self.Gpoly(1, 1)(*pt),
1150
+ -P[1][1]*self.Hpoly(1, 1, 2)(*pt)-P[1][2]*self.Gpoly(1, 1)(*pt)]
1151
+ else:
1152
+ a, b, c = [-1*P[1][2]*self.Hpoly(1, 0, 2)(*pt) - P[1][0]*self.Gpoly(1, 2)(*pt),
1153
+ -P[1][2]*self.Hpoly(1, 1, 2)(*pt) - P[1][1]*self.Gpoly(1, 2)(*pt),
1154
+ P[1][2]*self.Gpoly(1, 2)(*pt)]
1155
+ Point = [P[0][0], P[0][1], P[0][2], a, b, c]
1156
+
1157
+ if any([a, b, c]):
1158
+ if normalize:
1159
+ Point = self.point(Point,False)
1160
+ Point.normalize_coordinates()
1161
+ return Point
1162
+ return self.point(Point,False)
1163
+ #Start of the degenerate case
1164
+ R = self.ambient_space().coordinate_ring()
1165
+ BR = self.ambient_space().base_ring()
1166
+ S = PolynomialRing(BR, 6, 's0, s1, w1, z0, z1, z2')
1167
+ s0,s1,w1,z0,z1,z2 = S.gens()
1168
+ #Define the blow-up map with (s0,s1) the new `\mathbb{P}^1` coordinates
1169
+ #so that the points on the fiber come in pairs on the lines defined by `(s0,s1)`
1170
+ #this allows us to extend the involution to degenerate fibers
1171
+ if P[0][0] != 0:
1172
+ t1 = BR(P[0][1]/P[0][0])
1173
+ t = w1 - t1
1174
+ phi = R.hom([s0, s0*w1, s1*t + s0*P[0][2]/P[0][0], z0, z1, z2], S)
1175
+ elif P[0][1] != 0:
1176
+ t1 = BR(P[0][0]/P[0][1])
1177
+ t = w1 - t1
1178
+ phi = R.hom([s0*w1, s0, s1*t + s0*P[0][2]/P[0][1], z0, z1, z2], S)
1179
+ else:
1180
+ t1 = BR(P[0][1]/P[0][2])
1181
+ t = w1 - t1
1182
+ phi = R.hom([s1*(t) + s0*P[0][0]/P[0][2], s0*w1, s0, z0, z1, z2], S)
1183
+
1184
+ # Blow-up the fiber
1185
+ T = [phi(self.L),phi(self.Q),
1186
+ phi(self.Gpoly(1, 0)),
1187
+ phi(self.Gpoly(1, 1)),
1188
+ phi(self.Gpoly(1, 2)),
1189
+ -phi(self.Hpoly(1, 0, 1)),
1190
+ -phi(self.Hpoly(1, 0, 2)),
1191
+ -phi(self.Hpoly(1, 1, 2))]
1192
+ maxexp = []
1193
+
1194
+ #Find highest exponent that we can divide out by to get a nonzero answer
1195
+ for i in range(2,len(T)):
1196
+ e = 0
1197
+ while (T[i]/t**e).subs({w1:t1}) == 0:
1198
+ e += 1
1199
+ maxexp.append(e)
1200
+
1201
+ e = min(maxexp)
1202
+
1203
+ #Fix L and Q
1204
+ for i in range(2):
1205
+ while T[i].subs({w1:t1}) == 0:
1206
+ T[i] = T[i]/t
1207
+ T[i] = T[i].subs({w1:t1})
1208
+
1209
+ #Fix G and H polys
1210
+ for i in range(2,len(T)):
1211
+ T[i] = T[i]/t**e
1212
+ T[i] = T[i].subs({w1:t1})
1213
+
1214
+ #Defines the ideal whose solution gives `(s0, s1)` and the two points
1215
+ #on the fiber
1216
+ RR = PolynomialRing(BR, 5,'s0, s1, z0, z1, z2',order='lex')
1217
+ s0, s1, z0, z1, z2 = RR.gens()
1218
+ I = RR.ideal([RR(T[0]),
1219
+ RR(T[1]),
1220
+ RR(T[2]) - P[1][0]*z0, RR(T[3]) - P[1][1]*z1, RR(T[4])-P[1][2]*z2,
1221
+ RR(T[5]) - (P[1][0]*z1 + P[1][1]*z0),
1222
+ RR(T[6]) - (P[1][0]*z2 + P[1][2]*z0),
1223
+ RR(T[7]) - (P[1][1]*z2 + P[1][2]*z1)])
1224
+
1225
+ #Find the points
1226
+ SS = PolynomialRing(BR, 4,'s, z0, z1, z2', order='lex')
1227
+ s, z0, z1, z2 = SS.gens()
1228
+ phi = RR.hom([s, 1, z0, z1, z2], SS)
1229
+ J = phi(I)
1230
+ if J.dimension() > 0:
1231
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1232
+ V = J.variety()
1233
+ #Our blow-up point has more than one line passing through it, thus we cannot find
1234
+ #the corresponding point on the surface
1235
+ if len(V) > 2:
1236
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1237
+ #We always expect to have the trivial solution (0, 0, 0)
1238
+ if len(V) == 2:
1239
+ for D in V:
1240
+ if D[s] != 0:
1241
+ a, b, c = [D[z0], D[z1], D[z2]]
1242
+ else:
1243
+ newT = [phi(tee) for tee in T]
1244
+ for i in range(2):
1245
+ while newT[i] != 0 and s.divides(newT[i]):
1246
+ newT[i] = SS(newT[i]/s)
1247
+ maxexp = []
1248
+
1249
+ for i in range(2, len(T)):
1250
+ e = 0
1251
+ if newT[i] != 0:
1252
+ while (newT[i]/s**e).subs({s:0}) == 0:
1253
+ e += 1
1254
+ maxexp.append(e)
1255
+ e = min(maxexp)
1256
+
1257
+ #Cancel the powers of s
1258
+ for i in range(2,len(T)):
1259
+ newT[i] = newT[i]/s**e
1260
+ #Create the new ideal
1261
+ II = SS.ideal([SS(newT[0]),
1262
+ SS(newT[1]),
1263
+ SS(newT[2]) - P[1][0]*z0,
1264
+ SS(newT[3]) - P[1][1]*z1,
1265
+ SS(newT[4]) - P[1][2]*z2,
1266
+ SS(newT[5]) - (P[1][0]*z1 + P[1][1]*z0),
1267
+ SS(newT[6]) - (P[1][0]*z2 + P[1][2]*z0),
1268
+ SS(newT[7]) - (P[1][1]*z2 + P[1][2]*z1)])
1269
+
1270
+ #Find the points
1271
+ SSS = PolynomialRing(BR, 3, 'z0, z1, z2', order='lex')
1272
+ z0,z1,z2 = SSS.gens()
1273
+ phi = SS.hom([0, z0, z1, z2], SSS)
1274
+ J2 = phi(II)
1275
+ if J2.dimension() > 0:
1276
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1277
+ V = J2.variety()
1278
+ if len(V) > 1:
1279
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1280
+
1281
+ if len(V) == 1:
1282
+ a, b, c = [V[0][z0], V[0][z1], V[0][z2]]
1283
+
1284
+ if len(V) == 0 or not any([a, b, c]):
1285
+ SS = PolynomialRing(BR, 3, 'z0, z1, z2', order='lex')
1286
+ z0,z1,z2 = SS.gens()
1287
+ phi = RR.hom([1, 0, z0, z1, z2], SS)
1288
+ J = phi(I)
1289
+ if J.dimension() > 0:
1290
+ raise ValueError( "cannot distinguish points in the degenerate fiber")
1291
+ V = phi(I).variety()
1292
+ if len(V) > 1:
1293
+ raise ValueError( "cannot distinguish points in the degenerate fiber")
1294
+ a, b, c = [V[0][z0], V[0][z1], V[0][z2]]
1295
+
1296
+ Point = [P[0][0], P[0][1], P[0][2], a, b, c]
1297
+ if normalize:
1298
+ Point = self.point(Point, False)
1299
+ Point.normalize_coordinates()
1300
+ return Point
1301
+ return self.point(Point, False)
1302
+
1303
+ def sigmaY(self, P, **kwds):
1304
+ r"""
1305
+ Return the involution on the Wehler K3 surfaces induced by the double covers.
1306
+
1307
+ In particular, it fixes the projection to the second coordinate and swaps
1308
+ the two points in the fiber, i.e. `(x,y) \to (x',y)`.
1309
+ Note that in the degenerate case, while we can split the fiber into two points,
1310
+ it is not always possible to distinguish them, using this algorithm.
1311
+
1312
+ ALGORITHM:
1313
+
1314
+ Refer to Section 6: "An algorithm to compute `\sigma_x`, `\sigma_y`, `\phi`,
1315
+ and `\psi`" in [CS1996]_.
1316
+ For the degenerate case refer to [FH2015]_.
1317
+
1318
+ INPUT:
1319
+
1320
+ - ``P`` -- a point in `\mathbb{P}^2 \times \mathbb{P}^2`
1321
+
1322
+ kwds:
1323
+
1324
+ - ``check`` -- boolean (default: ``True``); checks to see if point is on the surface
1325
+
1326
+ - ``normalize`` -- boolean (default: ``True``); normalizes the point
1327
+
1328
+ OUTPUT: a point on the K3 surface
1329
+
1330
+ EXAMPLES::
1331
+
1332
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1333
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
1334
+ ....: 3*x0*x1*y0*y1 -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
1335
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
1336
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
1337
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1338
+ sage: X = WehlerK3Surface([Z, Y])
1339
+ sage: T = PP(0, 0, 1, 1, 0, 0)
1340
+ sage: X.sigmaY(T)
1341
+ (0 : 0 : 1 , 1 : 0 : 0)
1342
+
1343
+ degenerate examples::
1344
+
1345
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1346
+ sage: l = y0*x0 + y1*x1 + (y0 - y1)*x2
1347
+ sage: q = (y1*y0)*x0^2 + ((y0^2)*x1 + (y0^2 + (y1^2 - y2^2))*x2)*x0 +\
1348
+ ....: (y2*y0 + y1^2)*x1^2 + (y0^2 + (-y1^2 + y2^2))*x2*x1
1349
+ sage: X = WehlerK3Surface([l, q])
1350
+ sage: X.sigmaY(X([1, -1, 0 ,-1, -1, 1]))
1351
+ (1/10 : -1/10 : 1 , -1 : -1 : 1)
1352
+ sage: X.sigmaY(X([0, 0, 1, -1, -1, 1]))
1353
+ (-4 : 4 : 1 , -1 : -1 : 1)
1354
+ sage: X.sigmaY(X([1, 2, 0, 0, 0, 1]))
1355
+ (-3 : -3 : 1 , 0 : 0 : 1)
1356
+ sage: X.sigmaY(X([1, 1, 1, 0, 0, 1]))
1357
+ (1 : 0 : 0 , 0 : 0 : 1)
1358
+
1359
+ Case where we cannot distinguish the two points::
1360
+
1361
+ sage: PP.<x0,x1,x2,y0,y1,y2>=ProductProjectiveSpaces([2, 2], GF(3))
1362
+ sage: l = x0*y0 + x1*y1 + x2*y2
1363
+ sage: q = (-3*x0^2*y0^2 + 4*x0*x1*y0^2 - 3*x0*x2*y0^2 - 5*x0^2*y0*y1
1364
+ ....: - 190*x0*x1*y0*y1 - 5*x1^2*y0*y1 + 5*x0*x2*y0*y1 + 14*x1*x2*y0*y1
1365
+ ....: + 5*x2^2*y0*y1 - x0^2*y1^2 - 6*x0*x1*y1^2 - 2*x1^2*y1^2 + 2*x0*x2*y1^2
1366
+ ....: - 4*x2^2*y1^2 + 4*x0^2*y0*y2 - x1^2*y0*y2 + 3*x0*x2*y0*y2
1367
+ ....: + 6*x1*x2*y0*y2 - 6*x0^2*y1*y2 - 4*x0*x1*y1*y2 - x1^2*y1*y2
1368
+ ....: + 51*x0*x2*y1*y2 - 7*x1*x2*y1*y2 - 9*x2^2*y1*y2 - x0^2*y2^2
1369
+ ....: - 4*x0*x1*y2^2 + 4*x1^2*y2^2 - x0*x2*y2^2 + 13*x1*x2*y2^2 - x2^2*y2^2)
1370
+ sage: X = WehlerK3Surface([l ,q])
1371
+ sage: P = X([0, 1, 1, 1, 0, 0])
1372
+ sage: X.sigmaY(X.sigmaY(P))
1373
+ Traceback (most recent call last):
1374
+ ...
1375
+ ValueError: cannot distinguish points in the degenerate fiber
1376
+ """
1377
+ check = kwds.get("check", True)
1378
+ normalize = kwds.get("normalize", True)
1379
+
1380
+ if check:
1381
+ if self != P.codomain():
1382
+ try:
1383
+ P = self(list(P))
1384
+ except (TypeError, NotImplementedError, AttributeError):
1385
+ raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self))
1386
+ pt = [0, 0, 0] + list(P[1])
1387
+ if P[0][0] != 0:
1388
+ a, b, c = [P[0][0]*self.Gpoly(0, 0)(*pt),
1389
+ -1*P[0][0]*self.Hpoly(0, 0, 1)(*pt) - P[0][1]*self.Gpoly(0, 0)(*pt),
1390
+ -P[0][0]*self.Hpoly(0, 0, 2)(*pt) - P[0][2]*self.Gpoly(0, 0)(*pt)]
1391
+ elif P[0][1] != 0:
1392
+ a, b, c = [-1*P[0][1]*self.Hpoly(0, 0, 1)(*pt) - P[0][0]*self.Gpoly(0, 1)(*pt),
1393
+ P[0][1]*self.Gpoly(0, 1)(*pt),
1394
+ -P[0][1]*self.Hpoly(0, 1, 2)(*pt) - P[0][2]*self.Gpoly(0, 1)(*pt)]
1395
+ else:
1396
+ a, b, c = [-1*P[0][2]*self.Hpoly(0, 0, 2)(*pt) - P[0][0]*self.Gpoly(0, 2)(*pt),
1397
+ - P[0][2]*self.Hpoly(0, 1, 2)(*pt) - P[0][1]*self.Gpoly(0, 2)(*pt),
1398
+ P[0][2]*self.Gpoly(0, 2)(*pt)]
1399
+ Point = [a, b, c, P[1][0], P[1][1], P[1][2]]
1400
+ if any([a, b, c]):
1401
+ if normalize:
1402
+ Point = self.point(Point, False)
1403
+ Point.normalize_coordinates()
1404
+ return Point
1405
+ return self.point(Point, False)
1406
+
1407
+ #Start of the degenerate case
1408
+ R = self.ambient_space().coordinate_ring()
1409
+ BR = self.ambient_space().base_ring()
1410
+ S = PolynomialRing(BR, 6, 'z0, z1, z2, s0, s1, w1')
1411
+ z0, z1, z2, s0, s1, w1 = S.gens()
1412
+ #Define the blow-up map with (s0,s1) the new `\mathbb{P}^1` coordinates
1413
+ #so that the points on the fiber come in pairs on the lines defined by `(s0,s1)`
1414
+ #this allows us to extend the involution to degenerate fibers
1415
+ if P[1][0] != 0:
1416
+ t1 = BR(P[1][1]/P[1][0])
1417
+ t = w1 - t1
1418
+ phi = R.hom([z0, z1, z2, s0, s0*w1, s1*t + s0*P[1][2]/P[1][0]], S)
1419
+ elif P[1][1] != 0:
1420
+ t1 = BR(P[1][0]/P[1][1])
1421
+ t = w1 - t1
1422
+ phi = R.hom([z0, z1, z2, s0*w1, s0, s1*t + s0*P[1][2]/P[1][1]], S)
1423
+ else:
1424
+ t1 = BR(P[1][1]/P[1][2])
1425
+ t = w1 - t1
1426
+ phi = R.hom([z0, z1, z2, s1*(t) + s0*P[1][0]/P[1][2], s0*w1, s0], S)
1427
+
1428
+ #Blow-up the fiber
1429
+ T = [phi(self.L),
1430
+ phi(self.Q),
1431
+ phi(self.Gpoly(0, 0)),
1432
+ phi(self.Gpoly(0, 1)),
1433
+ phi(self.Gpoly(0, 2)),
1434
+ -phi(self.Hpoly(0, 0, 1)),
1435
+ -phi(self.Hpoly(0, 0, 2)),
1436
+ -phi(self.Hpoly(0, 1, 2))]
1437
+ maxexp = []
1438
+
1439
+ # Find highest exponent that we can divide out by to get a
1440
+ # nonzero answer
1441
+ for i in range(2, len(T)):
1442
+ e = 0
1443
+ while (T[i]/t**e).subs({w1:t1}) == 0:
1444
+ e += 1
1445
+ maxexp.append(e)
1446
+
1447
+ e = min(maxexp)
1448
+
1449
+ for i in range(2):
1450
+ while T[i].subs({w1:t1}) == 0:
1451
+ T[i] = T[i]/t
1452
+ T[i] = T[i].subs({w1:t1})
1453
+ for i in range(2, len(T)):
1454
+ T[i] = T[i]/t**e
1455
+ T[i] = T[i].subs({w1:t1})
1456
+
1457
+ # Defines the ideal whose solution gives `(s0,s1)` and the two points
1458
+ # on the fiber
1459
+ RR = PolynomialRing(BR, 5, 's0, s1, z0, z1, z2', order='lex')
1460
+ s0, s1, z0, z1, z2 = RR.gens()
1461
+ I = RR.ideal([RR(T[0]),
1462
+ RR(T[1]),
1463
+ RR(T[2]) - P[0][0]*z0,
1464
+ RR(T[3]) - P[0][1]*z1,
1465
+ RR(T[4]) - P[0][2]*z2,
1466
+ RR(T[5]) - (P[0][0]*z1 + P[0][1]*z0),
1467
+ RR(T[6]) - (P[0][0]*z2 + P[0][2]*z0),
1468
+ RR(T[7]) - (P[0][1]*z2 + P[0][2]*z1)])
1469
+ #Find the points
1470
+ SS = PolynomialRing(BR, 4, 's, z0, z1, z2', order='lex')
1471
+ s, z0, z1, z2 = SS.gens()
1472
+ phi = RR.hom([s, 1, z0, z1, z2], SS)
1473
+ J = phi(I)
1474
+ if J.dimension() > 0:
1475
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1476
+ V = J.variety()
1477
+
1478
+ #Our blow-up point has more than one line passing through it, thus we cannot find
1479
+ #the corresponding point on the surface
1480
+ if len(V) > 2:
1481
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1482
+ # We always expect to have the trivial solution (0, 0, 0)
1483
+ if len(V) == 2:
1484
+ for D in V:
1485
+ if D[s] != 0:
1486
+ a, b, c = [D[z0], D[z1], D[z2]]
1487
+ else:
1488
+ newT = [phi(tee) for tee in T]
1489
+ for i in range(2):
1490
+ while newT[i] != 0 and s.divides(newT[i]):
1491
+ newT[i] = SS(newT[i]/s)
1492
+ maxexp = []
1493
+ for i in range(2, len(T)):
1494
+ e = 0
1495
+ if newT[i] != 0:
1496
+ while (newT[i]/s**e).subs({s:0}) == 0:
1497
+ e += 1
1498
+ maxexp.append(e)
1499
+ e = min(maxexp)
1500
+ #Cancel out the powers of s
1501
+ for i in range(2,len(T)):
1502
+ newT[i] = newT[i]/s**e
1503
+ #Create the new ideal
1504
+ II = SS.ideal([SS(newT[0]),
1505
+ SS(newT[1]),
1506
+ SS(newT[2]) - P[0][0]*z0,
1507
+ SS(newT[3]) - P[0][1]*z1,
1508
+ SS(newT[4]) - P[0][2]*z2,
1509
+ SS(newT[5]) - (P[0][0]*z1 + P[0][1]*z0),
1510
+ SS(newT[6]) - (P[0][0]*z2 + P[0][2]*z0),
1511
+ SS(newT[7]) - (P[0][1]*z2 + P[0][2]*z1)])
1512
+ # Find the points
1513
+ SSS = PolynomialRing(BR, 3, 'z0, z1, z2', order='lex')
1514
+ z0, z1, z2 = SSS.gens()
1515
+ phi = SS.hom([0, z0, z1, z2], SSS)
1516
+ J2 = phi(II)
1517
+ if J2.dimension() > 0:
1518
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1519
+ V = J2.variety()
1520
+
1521
+ if len(V) > 1:
1522
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1523
+ if len(V) == 1:
1524
+ a, b, c = [V[0][z0], V[0][z1], V[0][z2]]
1525
+ if len(V) == 0 or not any([a, b, c]):
1526
+ SS = PolynomialRing(BR, 3, 'z0, z1, z2', order='lex')
1527
+ z0, z1, z2 = SS.gens()
1528
+ phi = RR.hom([1, 0, z0, z1, z2], SS)
1529
+ J = phi(I)
1530
+ if J.dimension() > 0:
1531
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1532
+ V = phi(I).variety()
1533
+ if len(V) > 1:
1534
+ raise ValueError("cannot distinguish points in the degenerate fiber")
1535
+ a, b, c = [V[0][z0], V[0][z1], V[0][z2]]
1536
+
1537
+ Point = [a, b, c, P[1][0], P[1][1], P[1][2]]
1538
+ if normalize:
1539
+ Point = self.point(Point, False)
1540
+ Point.normalize_coordinates()
1541
+ return Point
1542
+ return self.point(Point, False)
1543
+
1544
+ def phi(self, a, **kwds):
1545
+ r"""
1546
+ Evaluates the function `\phi = \sigma_y \circ \sigma_x`.
1547
+
1548
+ ALGORITHM:
1549
+
1550
+ Refer to Section 6: "An algorithm to compute `\sigma_x`, `\sigma_y`,
1551
+ `\phi`, and `\psi`" in [CS1996]_.
1552
+
1553
+ For the degenerate case refer to [FH2015]_.
1554
+
1555
+ INPUT:
1556
+
1557
+ - ``a`` -- point in `\mathbb{P}^2 \times \mathbb{P}^2`
1558
+
1559
+ kwds:
1560
+
1561
+ - ``check`` -- boolean (default: ``True``); checks to see if point is on the surface
1562
+
1563
+ - ``normalize`` -- boolean (default: ``True``); normalizes the point
1564
+
1565
+ OUTPUT: a point on this surface
1566
+
1567
+ EXAMPLES::
1568
+
1569
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1570
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
1571
+ ....: 3*x0*x1*y0*y1 -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
1572
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 -4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
1573
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
1574
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1575
+ sage: X = WehlerK3Surface([Z, Y])
1576
+ sage: T = PP([0, 0, 1, 1 ,0, 0])
1577
+ sage: X.phi(T)
1578
+ (-1 : 0 : 1 , 0 : 1 : 0)
1579
+ """
1580
+ A = self.sigmaX(a, **kwds)
1581
+ kwds.update({"check":False})
1582
+ return self.sigmaY(A, **kwds)
1583
+
1584
+ def psi(self, a, **kwds):
1585
+ r"""
1586
+ Evaluates the function `\psi = \sigma_x \circ \sigma_y`.
1587
+
1588
+ ALGORITHM:
1589
+
1590
+ Refer to Section 6: "An algorithm to compute `\sigma_x`, `\sigma_y`,
1591
+ `\phi`, and `\psi`" in [CS1996]_.
1592
+
1593
+ For the degenerate case refer to [FH2015]_.
1594
+
1595
+ INPUT:
1596
+
1597
+ - ``a`` -- point in `\mathbb{P}^2 \times \mathbb{P}^2`
1598
+
1599
+ kwds:
1600
+
1601
+ - ``check`` -- boolean (default: ``True``); checks to see if point is on the surface
1602
+
1603
+ - ``normalize`` -- boolean (default: ``True``); normalizes the point
1604
+
1605
+ OUTPUT: a point on this surface
1606
+
1607
+ EXAMPLES::
1608
+
1609
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1610
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
1611
+ ....: 3*x0*x1*y0*y1 -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
1612
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
1613
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
1614
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1615
+ sage: X = WehlerK3Surface([Z, Y])
1616
+ sage: T = PP([0, 0, 1, 1, 0, 0])
1617
+ sage: X.psi(T)
1618
+ (0 : 0 : 1 , 0 : 1 : 0)
1619
+ """
1620
+ A = self.sigmaY(a, **kwds)
1621
+ kwds.update({"check":False})
1622
+ return self.sigmaX(A, **kwds)
1623
+
1624
+ def lambda_plus(self, P, v, N, m, n, prec=100):
1625
+ r"""
1626
+ Evaluates the local canonical height plus function of Call-Silverman at
1627
+ the place ``v`` for ``P`` with ``N`` terms of the series.
1628
+
1629
+ Use ``v = 0`` for the archimedean place. Must be over `\ZZ` or `\QQ`.
1630
+
1631
+ ALGORITHM:
1632
+
1633
+ Sum over local heights using convergent series, for more details,
1634
+ see section 4 of [CS1996]_.
1635
+
1636
+ INPUT:
1637
+
1638
+ - ``P`` -- a surface point
1639
+
1640
+ - ``N`` -- positive integer; number of terms of the series to use
1641
+
1642
+ - ``v`` -- nonnegative integer; a place, use v = 0 for the Archimedean place
1643
+
1644
+ - ``m``, ``n`` -- positive integers; we compute the local height for
1645
+ the divisor `E_{mn}^{+}`. These must be indices of nonzero
1646
+ coordinates of the point ``P``
1647
+
1648
+ - ``prec`` -- (default: 100) float point or `p`-adic precision
1649
+
1650
+ OUTPUT: a real number
1651
+
1652
+ EXAMPLES::
1653
+
1654
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1655
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1\
1656
+ ....: - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 -4*x1*x2*y1^2 + 5*x0*x2*y0*y2\
1657
+ ....: - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
1658
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1659
+ sage: X = WehlerK3Surface([Z, Y])
1660
+ sage: P = X([0, 0, 1, 1, 0, 0])
1661
+ sage: X.lambda_plus(P, 0, 10, 2, 0) # needs sage.symbolic
1662
+ 0.89230705169161608922595928129
1663
+ """
1664
+ if not (v == 0 or v.is_prime()):
1665
+ raise ValueError("invalid valuation (= %s) entered" % v)
1666
+ R = RealField(prec)
1667
+ if v == 0:
1668
+ K = R
1669
+ else:
1670
+ K = Qp(v, prec)
1671
+ PK = P.change_ring(K)
1672
+ W = self.change_ring(K)
1673
+ Rx = W.ambient_space().coordinate_ring().hom(
1674
+ list(W.ambient_space()[0].coordinate_ring().gens()) + [0, 0, 0],
1675
+ W.ambient_space()[0].coordinate_ring())
1676
+ Ry = W.ambient_space().coordinate_ring().hom(
1677
+ [0, 0, 0] + list(W.ambient_space()[1].coordinate_ring().gens()),
1678
+ W.ambient_space()[1].coordinate_ring())
1679
+ beta = R(2 + sqrt(3))
1680
+ L = [x.abs() for x in list(PK[0])]
1681
+ i = L.index(max(L))
1682
+ L = [y.abs() for y in list(PK[1])]
1683
+ j = L.index(max(L))
1684
+
1685
+ #Compute the local height wrt the divisor E_{mn}^{+}
1686
+ local_height = beta*R((PK[0][i]/PK[0][m]).abs()).log() - R((PK[1][j]/PK[1][n]).abs()).log()
1687
+
1688
+ for e in range(N):
1689
+ #Take next iterate
1690
+ Q = W.phi(PK, check=False)
1691
+ L = [x.abs() for x in list(Q[0])]
1692
+ k = L.index(max(L))
1693
+ L = [y.abs() for y in list(Q[1])]
1694
+ l = L.index(max(L))
1695
+ newP = copy(PK)
1696
+ #normalize PK
1697
+ newP.scale_by([~PK[0][i], ZZ.one()])
1698
+
1699
+ #Find B and A, helper values for the local height
1700
+ if PK[1][j].abs() <= PK[1][l].abs():
1701
+ B = Rx(W.Gpoly(1, l))(tuple(newP[0]))*PK[1][j]/PK[1][l]
1702
+ else:
1703
+ B = -Rx(W.Gpoly(1, j))(tuple(newP[0]))*PK[1][l]/PK[1][j]
1704
+ B = B - Rx(W.Hpoly(1, j, l))(tuple(newP[0]))
1705
+
1706
+ #Normalize Q
1707
+ newQ = copy(Q)
1708
+ newQ.scale_by([ZZ.one(), ~Q[1][l]])
1709
+
1710
+ if PK[0][i].abs() <= PK[0][k].abs():
1711
+ A = Ry(W.Gpoly(0, k))(tuple(newQ[1]))*PK[0][i]/PK[0][k]
1712
+ else:
1713
+ A = -Ry(W.Gpoly(0, i))(tuple(newQ[1]))*PK[0][k]/PK[0][i]
1714
+ A = A - Ry(W.Hpoly(0, i, k))(tuple(newQ[1]))
1715
+ #Compute the new local height
1716
+ local_height += beta**(-2*R(e)-1)*R(A.abs()).log() + beta**(-2*R(e))*R(B.abs()).log()
1717
+
1718
+ i = k
1719
+ j = l
1720
+ newQ.scale_by([~Q[0][k], ZZ.one()])
1721
+ PK = newQ
1722
+ return local_height
1723
+
1724
+ def lambda_minus(self, P, v, N, m, n, prec=100):
1725
+ r"""
1726
+ Evaluates the local canonical height minus function of Call-Silverman
1727
+ at the place ``v`` for ``P`` with ``N`` terms of the series.
1728
+
1729
+ Use ``v = 0`` for the Archimedean place. Must be over `\ZZ` or `\QQ`.
1730
+
1731
+ ALGORITHM:
1732
+
1733
+ Sum over local heights using convergent series, for more details,
1734
+ see section 4 of [CS1996]_.
1735
+
1736
+ INPUT:
1737
+
1738
+ - ``P`` -- a projective point
1739
+
1740
+ - ``N`` -- positive integer. number of terms of the series to use
1741
+
1742
+ - ``v`` -- nonnegative integer. a place, use v = 0 for the Archimedean place
1743
+
1744
+ - ``m``, ``n`` -- positive integers; we compute the local height for
1745
+ the divisor `E_{mn}^{+}`. These must be indices of nonzero
1746
+ coordinates of the point ``P``.
1747
+
1748
+ - ``prec`` -- (default: 100) float point or `p`-adic precision
1749
+
1750
+ OUTPUT: a real number
1751
+
1752
+ EXAMPLES::
1753
+
1754
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1755
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 \
1756
+ ....: - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 -4*x1*x2*y1^2 + 5*x0*x2*y0*y2\
1757
+ ....: - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
1758
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1759
+ sage: X = WehlerK3Surface([Z, Y])
1760
+ sage: P = X([0, 0, 1, 1, 0, 0])
1761
+ sage: X.lambda_minus(P, 2, 20, 2, 0, 200) # needs sage.symbolic
1762
+ -0.18573351672047135037172805779671791488351056677474271893705
1763
+ """
1764
+ R = RealField(prec)
1765
+ if v == 0:
1766
+ K = R
1767
+ else:
1768
+ K = Qp(v, prec)
1769
+ PK = P.change_ring(K)
1770
+ W = self.change_ring(K)
1771
+ Rx = W.ambient_space().coordinate_ring().hom(list(W.ambient_space()[0].coordinate_ring().gens())
1772
+ + [0, 0, 0], W.ambient_space()[0].coordinate_ring())
1773
+ Ry = W.ambient_space().coordinate_ring().hom([0, 0, 0] +
1774
+ list(W.ambient_space()[1].coordinate_ring().gens()),
1775
+ W.ambient_space()[1].coordinate_ring())
1776
+ beta = R(2 + sqrt(3))
1777
+ L = [x.abs() for x in list(PK[0])]
1778
+ j = L.index(max(L))
1779
+ L = [y.abs() for y in list(PK[1])]
1780
+ i = L.index(max(L))
1781
+
1782
+ ##Compute the local height wrt the divisor E_{mn}^{-}
1783
+ local_height = beta*R((PK[1][i]/PK[1][n]).abs()).log() - R((PK[0][j]/PK[0][m]).abs()).log()
1784
+ for e in range(N):
1785
+ #Take the next iterate
1786
+ Q = W.psi(PK, check=False)
1787
+ L = [x.abs() for x in list(Q[0])]
1788
+ l = L.index(max(L))
1789
+ L = [y.abs() for y in list(Q[1])]
1790
+ k = L.index(max(L))
1791
+ #Normalize the point
1792
+ newP = copy(PK)
1793
+ newP.scale_by([ZZ.one(), ~PK[1][i]])
1794
+ #Find A and B, helper functions for computing local height
1795
+ if PK[0][j].abs() <= PK[0][l].abs():
1796
+ B = Ry(W.Gpoly(0, l))(tuple(newP[1]))*PK[0][j]/PK[0][l]
1797
+ else:
1798
+ B = -Ry(W.Gpoly(0, j))(tuple(newP[1]))*PK[0][l]/PK[0][j]
1799
+ B = B - Ry(W.Hpoly(0, j, l))(tuple(newP[1]))
1800
+
1801
+ #Normalize Q
1802
+ newQ = copy(Q)
1803
+ newQ.scale_by([~Q[0][l], ZZ.one()])
1804
+
1805
+ if PK[1][i].abs() <= PK[1][k].abs():
1806
+ A = Rx(W.Gpoly(1, k))(tuple(newQ[0]))*PK[1][i]/PK[1][k]
1807
+ else:
1808
+ A = -Rx(W.Gpoly(1, i))(tuple(newQ[0]))*PK[1][k]/PK[1][i]
1809
+ A = A-Rx(W.Hpoly(1, i, k))(tuple(newQ[0]))
1810
+
1811
+ #Compute the local height
1812
+ local_height += beta**(-2*R(e)-1)*R(A.abs()).log() + beta**(-2*R(e))*R(B.abs()).log()
1813
+ i = k
1814
+ j = l
1815
+ newQ.scale_by([ZZ.one(), ~Q[1][k]])
1816
+ PK = newQ
1817
+ return local_height
1818
+
1819
+ def canonical_height_plus(self, P, N, badprimes=None, prec=100):
1820
+ r"""
1821
+ Evaluates the canonical height plus function of Call-Silverman
1822
+ for ``P`` with ``N`` terms of the series of the local heights.
1823
+
1824
+ Must be over `\ZZ` or `\QQ`.
1825
+
1826
+ ALGORITHM:
1827
+
1828
+ Sum over the lambda plus heights (local heights) in a convergent series,
1829
+ for more detail see section 7 of [CS1996]_.
1830
+
1831
+ INPUT:
1832
+
1833
+ - ``P`` -- a surface point
1834
+
1835
+ - ``N`` -- positive integer. Number of terms of the series to use
1836
+
1837
+ - ``badprimes`` -- (optional) list of integer primes (where the surface is degenerate)
1838
+
1839
+ - ``prec`` -- (default: 100) float point or `p`-adic precision
1840
+
1841
+ OUTPUT: a real number
1842
+
1843
+ EXAMPLES::
1844
+
1845
+ sage: set_verbose(None)
1846
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(QQ, 6)
1847
+ sage: L = (-y0 - y1)*x0 + (-y0*x1 - y2*x2)
1848
+ sage: Q = (-y2*y0 - y1^2)*x0^2 + ((-y0^2 - y2*y0 + (-y2*y1 - y2^2))*x1 + \
1849
+ ....: (-y0^2 - y2*y1)*x2)*x0 + ((-y0^2 - y2*y0 - y2^2)*x1^2 + (-y2*y0 - y1^2)*x2*x1 \
1850
+ ....: + (-y0^2 + (-y1 - y2)*y0)*x2^2)
1851
+ sage: X = WehlerK3Surface([L, Q])
1852
+ sage: P = X([1, 0, -1, 1, -1, 0]) #order 16
1853
+ sage: X.canonical_height_plus(P, 5) # long time
1854
+ 0.00000000000000000000000000000
1855
+
1856
+ Call-Silverman Example::
1857
+
1858
+ sage: set_verbose(None)
1859
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1860
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
1861
+ ....: 3*x0*x1*y0*y1 - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
1862
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 -4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
1863
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
1864
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1865
+ sage: X = WehlerK3Surface([Z, Y])
1866
+ sage: P = X([0, 1, 0, 0, 0, 1])
1867
+ sage: X.canonical_height_plus(P, 4) # long time
1868
+ 0.14752753298983071394400412161
1869
+ """
1870
+ if badprimes is None:
1871
+ badprimes = self.degenerate_primes()
1872
+ m = 2
1873
+ while P[0][m] == 0:
1874
+ m = m - 1
1875
+ n = 2
1876
+ while P[1][n] == 0:
1877
+ n = n-1
1878
+ h = self.lambda_plus(P, 0, N, m, n, prec)
1879
+ for p in badprimes:
1880
+ h += self.lambda_plus(P, p, N, m, n, prec)
1881
+ return h
1882
+
1883
+ def canonical_height_minus(self, P, N, badprimes=None, prec=100):
1884
+ r"""
1885
+ Evaluates the canonical height minus function of Call-Silverman
1886
+ for ``P`` with ``N`` terms of the series of the local heights.
1887
+
1888
+ Must be over `\ZZ` or `\QQ`.
1889
+
1890
+ ALGORITHM:
1891
+
1892
+ Sum over the lambda minus heights (local heights) in a convergent series,
1893
+ for more detail see section 7 of [CS1996]_.
1894
+
1895
+ INPUT:
1896
+
1897
+ - ``P`` -- a surface point
1898
+
1899
+ - ``N`` -- positive integer (number of terms of the series to use)
1900
+
1901
+ - ``badprimes`` -- (optional) list of integer primes (where the surface is degenerate)
1902
+
1903
+ - ``prec`` -- (default: 100) float point or `p`-adic precision
1904
+
1905
+ OUTPUT: a real number
1906
+
1907
+ EXAMPLES::
1908
+
1909
+ sage: set_verbose(None)
1910
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(QQ, 6)
1911
+ sage: L = (-y0 - y1)*x0 + (-y0*x1 - y2*x2)
1912
+ sage: Q = (-y2*y0 - y1^2)*x0^2 + ((-y0^2 - y2*y0 + (-y2*y1 - y2^2))*x1\
1913
+ ....: + (-y0^2 - y2*y1)*x2)*x0 + ((-y0^2 - y2*y0 - y2^2)*x1^2 + (-y2*y0 - y1^2)*x2*x1\
1914
+ ....: + (-y0^2 + (-y1 - y2)*y0)*x2^2)
1915
+ sage: X = WehlerK3Surface([L, Q])
1916
+ sage: P = X([1, 0, -1, 1, -1, 0]) #order 16
1917
+ sage: X.canonical_height_minus(P, 5) # long time
1918
+ 0.00000000000000000000000000000
1919
+
1920
+ Call-Silverman example::
1921
+
1922
+ sage: set_verbose(None)
1923
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1924
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 +\
1925
+ ....: 3*x0*x1*y0*y1 - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - \
1926
+ ....: 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + \
1927
+ ....: x0*x1*y2^2 + 3*x2^2*y2^2
1928
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1929
+ sage: X = WehlerK3Surface([Z, Y])
1930
+ sage: P = X([0, 1, 0, 0, 0, 1])
1931
+ sage: X.canonical_height_minus(P, 4) # long time
1932
+ 0.55073705369676788175590206734
1933
+ """
1934
+ if badprimes is None:
1935
+ badprimes = self.degenerate_primes()
1936
+ m = 2
1937
+ while P[0][m] == 0:
1938
+ m = m - 1
1939
+ n = 2
1940
+ while P[1][n] == 0:
1941
+ n = n-1
1942
+ h = self.lambda_minus(P, 0, N, m, n, prec)
1943
+ for p in badprimes:
1944
+ h += self.lambda_minus(P, p, N, m, n, prec)
1945
+ return h
1946
+
1947
+ def canonical_height(self, P, N, badprimes=None, prec=100):
1948
+ r"""
1949
+ Evaluates the canonical height for ``P`` with ``N`` terms of the series of the local
1950
+ heights.
1951
+
1952
+ ALGORITHM:
1953
+
1954
+ The sum of the canonical height minus and canonical height plus,
1955
+ for more info see section 4 of [CS1996]_.
1956
+
1957
+ INPUT:
1958
+
1959
+ - ``P`` -- a surface point
1960
+
1961
+ - ``N`` -- positive integer (number of terms of the series to use)
1962
+
1963
+ - ``badprimes`` -- (optional) list of integer primes (where the surface is degenerate)
1964
+
1965
+ - ``prec`` -- (default: 100) float point or `p`-adic precision
1966
+
1967
+ OUTPUT: a real number
1968
+
1969
+ EXAMPLES::
1970
+
1971
+ sage: set_verbose(None)
1972
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(QQ, 6)
1973
+ sage: L = (-y0 - y1)*x0 + (-y0*x1 - y2*x2)
1974
+ sage: Q = (-y2*y0 - y1^2)*x0^2 + ((-y0^2 - y2*y0 + (-y2*y1 - y2^2))*x1 + \
1975
+ ....: (-y0^2 - y2*y1)*x2)*x0 + ((-y0^2 - y2*y0 - y2^2)*x1^2 + (-y2*y0 - y1^2)*x2*x1 \
1976
+ ....: + (-y0^2 + (-y1 - y2)*y0)*x2^2)
1977
+ sage: X = WehlerK3Surface([L, Q])
1978
+ sage: P = X([1, 0, -1, 1,- 1, 0]) #order 16
1979
+ sage: X.canonical_height(P, 5) # long time
1980
+ 0.00000000000000000000000000000
1981
+
1982
+ Call-Silverman example::
1983
+
1984
+ sage: set_verbose(None)
1985
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
1986
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 - \
1987
+ ....: 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 \
1988
+ ....: -4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
1989
+ sage: Y = x0*y0 + x1*y1 + x2*y2
1990
+ sage: X = WehlerK3Surface([Z, Y])
1991
+ sage: P = X(0, 1, 0, 0, 0, 1)
1992
+ sage: X.canonical_height(P, 4) # needs sage.symbolic
1993
+ 0.69826458668659859569990618895
1994
+ """
1995
+ if badprimes is None:
1996
+ badprimes = self.degenerate_primes()
1997
+ return (self.canonical_height_plus(P, N, badprimes, prec) +
1998
+ self.canonical_height_minus(P, N, badprimes, prec))
1999
+
2000
+ def fiber(self, p, component):
2001
+ r"""
2002
+ Return the fibers [y (component = 1) or x (Component = 0)] of
2003
+ a point on a K3 Surface.
2004
+
2005
+ This will work for nondegenerate fibers only.
2006
+
2007
+ For algorithm, see [Hutz2007]_.
2008
+
2009
+ INPUT:
2010
+
2011
+ - ``p`` -- a point in `\mathbb{P}^2`
2012
+
2013
+ OUTPUT: the corresponding fiber (as a list)
2014
+
2015
+ EXAMPLES::
2016
+
2017
+ sage: R.<x0,x1,x2,y0,y1,y2> = PolynomialRing(ZZ, 6)
2018
+ sage: Y = x0*y0 + x1*y1 - x2*y2
2019
+ sage: Z = y0^2*x0*x1 + y0^2*x2^2 - y0*y1*x1*x2 + y1^2*x2*x1 + y2^2*x2^2 +\
2020
+ ....: y2^2*x1^2 + y1^2*x2^2
2021
+ sage: X = WehlerK3Surface([Z, Y])
2022
+ sage: Proj = ProjectiveSpace(QQ, 2)
2023
+ sage: P = Proj([1, 0, 0])
2024
+ sage: X.fiber(P, 1)
2025
+ Traceback (most recent call last):
2026
+ ...
2027
+ TypeError: fiber is degenerate
2028
+
2029
+ ::
2030
+
2031
+ sage: P.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2032
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 - \
2033
+ ....: 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 -4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - \
2034
+ ....: 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
2035
+ sage: Y = x0*y0 + x1*y1 + x2*y2
2036
+ sage: X = WehlerK3Surface([Z, Y])
2037
+ sage: Proj = P[0]
2038
+ sage: T = Proj([0, 0, 1])
2039
+ sage: X.fiber(T, 1)
2040
+ [(0 : 0 : 1 , 0 : 1 : 0), (0 : 0 : 1 , 2 : 0 : 0)]
2041
+
2042
+ ::
2043
+
2044
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], GF(7))
2045
+ sage: L = x0*y0 + x1*y1 - 1*x2*y2
2046
+ sage: Q = ((2*x0^2 + x2*x0 + (2*x1^2 + x2^2))*y0^2
2047
+ ....: + ((x0^2 + x1*x0 +(x1^2 + 2*x2*x1 + x2^2))*y1
2048
+ ....: + (2*x1^2 + x2*x1 + x2^2)*y2)*y0
2049
+ ....: + ((2*x0^2 + (x1 + 2*x2)*x0 + (2*x1^2 + x2*x1))*y1^2
2050
+ ....: + ((2*x1 + 2*x2)*x0 + (x1^2 + x2*x1 + 2*x2^2))*y2*y1
2051
+ ....: + (2*x0^2 + x1*x0 + (2*x1^2 + x2^2))*y2^2))
2052
+ sage: W = WehlerK3Surface([L, Q])
2053
+ sage: W.fiber([4, 0, 1], 0)
2054
+ [(0 : 1 : 0 , 4 : 0 : 1), (4 : 0 : 2 , 4 : 0 : 1)]
2055
+ """
2056
+ R = self.base_ring()
2057
+ Zero = R(0)
2058
+ One = R(1)
2059
+ P = []
2060
+ for i in list(p):
2061
+ j = R(i)
2062
+ P.append(j)
2063
+ if component == 1:
2064
+ P0 = P + [Zero, Zero, Zero]
2065
+ else:
2066
+ P0 = [Zero, Zero, Zero] + P
2067
+ Points = []
2068
+
2069
+ if (self.Gpoly(component,0)(P0) != 0):
2070
+ # We are using the quadratic formula, we need this check
2071
+ # to ensure that the points will be rational
2072
+ T0 = (self.Hpoly(component, 0, 1)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 1)(P0))
2073
+ T1 = (self.Hpoly(component, 0, 2)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 2)(P0))
2074
+ if (T0.is_square() and T1.is_square()):
2075
+ T0 = T0.sqrt()
2076
+ T1 = T1.sqrt()
2077
+ B1 = (-self.Hpoly(component, 0, 1)(P0)+T0)/(2*self.Gpoly(component, 0)(P0))
2078
+ B2 = (-self.Hpoly(component, 0, 1)(P0)-T0)/(2*self.Gpoly(component, 0)(P0))
2079
+ C1 = (-self.Hpoly(component, 0, 2)(P0)+T1)/(2*self.Gpoly(component, 0)(P0))
2080
+ C2 = (-self.Hpoly(component, 0, 2)(P0)-T1)/(2*self.Gpoly(component, 0)(P0))
2081
+ if component == 1:
2082
+ Points.append(P+[One, B1, C1])
2083
+ Points.append(P+[One, B2, C1])
2084
+ Points.append(P+[One, B1, C2])
2085
+ Points.append(P+[One, B2, C2])
2086
+ else:
2087
+ Points.append([One, B1, C1]+P)
2088
+ Points.append([One, B2, C1]+P)
2089
+ Points.append([One, B1, C2]+P)
2090
+ Points.append([One, B2, C2]+P)
2091
+ else:
2092
+ return []
2093
+ elif (self.Gpoly(component, 1)(P0) != 0):
2094
+ T0 = (self.Hpoly(component, 0, 1)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 1)(P0))
2095
+ T1 = (self.Hpoly(component, 1, 2)(P0)**2 - 4*self.Gpoly(component, 1)(P0)*self.Gpoly(component, 2)(P0))
2096
+ if (T0.is_square() and T1.is_square()):
2097
+ T0 = T0.sqrt()
2098
+ T1 = T1.sqrt()
2099
+ A1 = (-self.Hpoly(component, 0, 1)(P0)+T0)/(2*self.Gpoly(component, 1)(P0))
2100
+ A2 = (-self.Hpoly(component, 0, 1)(P0)-T0)/(2*self.Gpoly(component, 1)(P0))
2101
+ C1 = (-self.Hpoly(component, 1, 2)(P0)+T1)/(2*self.Gpoly(component, 1)(P0))
2102
+ C2 = (-self.Hpoly(component, 1, 2)(P0)-T1)/(2*self.Gpoly(component, 1)(P0))
2103
+ if component == 1:
2104
+ Points.append(P + [A1, One, C1])
2105
+ Points.append(P + [A1, One, C2])
2106
+ Points.append(P + [A2, One, C1])
2107
+ Points.append(P + [A2, One, C2])
2108
+ else:
2109
+ Points.append([A1, One, C1] + P)
2110
+ Points.append([A1, One, C2] + P)
2111
+ Points.append([A2, One, C1] + P)
2112
+ Points.append([A2, One, C2] + P)
2113
+ else:
2114
+ return []
2115
+ elif self.Gpoly(component, 2)(P0) != 0:
2116
+ T0 = (self.Hpoly(component, 0, 2)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 2)(P0))
2117
+ T1 = (self.Hpoly(component, 1, 2)(P0)**2 - 4*self.Gpoly(component, 1)(P0)*self.Gpoly(component, 2)(P0))
2118
+ if (T0.is_square() and T1.is_square()):
2119
+ T0 = T0.sqrt()
2120
+ T1 = T1.sqrt()
2121
+ A1 = (-self.Hpoly(component, 0, 2)(P0)+T0)/(2*self.Gpoly(component, 2)(P0))
2122
+ A2 = (-self.Hpoly(component, 0, 2)(P0)-T0)/(2*self.Gpoly(component, 2)(P0))
2123
+ B1 = (-self.Hpoly(component, 1, 2)(P0)+T1)/(2*self.Gpoly(component, 2)(P0))
2124
+ B2 = (-self.Hpoly(component, 1, 2)(P0)-T1)/(2*self.Gpoly(component, 2)(P0))
2125
+ if component == 1:
2126
+ Points.append(P + [A1, B1, One])
2127
+ Points.append(P + [A1, B2, One])
2128
+ Points.append(P + [A2, B1, One])
2129
+ Points.append(P + [A2, B2, One])
2130
+ else:
2131
+ Points.append([A1, B1, One] + P)
2132
+ Points.append([A1, B2, One] + P)
2133
+ Points.append([A2, B1, One] + P)
2134
+ Points.append([A2, B2, One] + P)
2135
+ else:
2136
+ return []
2137
+ elif self.Hpoly(component, 0, 1)(P0) != 0:
2138
+ if component == 1:
2139
+ Points.append(P+[Zero, One, Zero])
2140
+ Points.append(P+[-self.Hpoly(component, 0, 1)(P0),Zero,
2141
+ -self.Hpoly(component, 1, 2)(P0)])
2142
+ Points.append(P+[One,Zero,Zero])
2143
+ Points.append(P+[Zero,-self.Hpoly(component, 0, 1)(P0),
2144
+ -self.Hpoly(component, 0, 2)(P0)])
2145
+ else:
2146
+ Points.append([Zero,One,Zero]+P)
2147
+ Points.append([-self.Hpoly(component, 0, 1)(P0),Zero,
2148
+ -self.Hpoly(component, 1, 2)(P0)] + P)
2149
+ Points.append([One,Zero,Zero]+P)
2150
+ Points.append([Zero,-self.Hpoly(component, 0, 1)(P0),
2151
+ -self.Hpoly(component, 0, 2)(P0)] + P)
2152
+ elif self.Hpoly(component, 0, 2)(P0) != 0:
2153
+ if component == 1:
2154
+ Points.append(P+[Zero, Zero, One])
2155
+ Points.append(P+[-self.Hpoly(component, 0, 2)(P0),
2156
+ -self.Hpoly(component, 1, 2)(P0), Zero])
2157
+ else:
2158
+ Points.append([Zero, Zero, One]+P)
2159
+ Points.append([-self.Hpoly(component, 0, 2)(P0),
2160
+ -self.Hpoly(component, 1, 2)(P0), Zero] + P)
2161
+ elif self.Hpoly(component, 1, 2)(P0) != 0:
2162
+ if component == 1:
2163
+ Points.append(P + [Zero, Zero, One])
2164
+ Points.append(P + [Zero, One, Zero])
2165
+ else:
2166
+ Points.append([Zero, Zero, One] + P)
2167
+ Points.append([Zero, One, Zero] + P)
2168
+ else:
2169
+ raise TypeError("fiber is degenerate")
2170
+
2171
+ fiber = []
2172
+ for x in Points:
2173
+ if (self.L(x) == 0) and (self.Q(x) == 0):
2174
+ Y = self.point(x, False)
2175
+ if Y not in fiber:
2176
+ fiber.append(Y)
2177
+ return fiber
2178
+
2179
+ def nth_iterate_phi(self, P, n, **kwds):
2180
+ r"""
2181
+ Compute the `n`-th iterate for the phi function.
2182
+
2183
+ INPUT:
2184
+
2185
+ - ``P`` -- a point in `\mathbb{P}^2 \times \mathbb{P}^2`
2186
+
2187
+ - ``n`` -- integer
2188
+
2189
+ kwds:
2190
+
2191
+ - ``check`` -- boolean (default: ``True``); checks to see if point is
2192
+ on the surface
2193
+
2194
+ - ``normalize`` -- boolean (default: ``False``); normalizes the point
2195
+
2196
+ OUTPUT: the `n`-th iterate of the point given the phi function (if `n`
2197
+ is positive), or the psi function (if `n` is negative)
2198
+
2199
+ EXAMPLES::
2200
+
2201
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2202
+ sage: L = x0*y0 + x1*y1 + x2*y2
2203
+ sage: Q = x1^2*y0^2 + 2*x2^2*y0*y1 + x0^2*y1^2 - x0*x1*y2^2
2204
+ sage: W = WehlerK3Surface([L, Q])
2205
+ sage: T = W([-1, -1, 1, 1, 0, 1])
2206
+ sage: W.nth_iterate_phi(T, 7)
2207
+ (-1 : 0 : 1 , 1 : -2 : 1)
2208
+
2209
+ ::
2210
+
2211
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2212
+ sage: L = x0*y0 + x1*y1 + x2*y2
2213
+ sage: Q = x1^2*y0^2 + 2*x2^2*y0*y1 + x0^2*y1^2 - x0*x1*y2^2
2214
+ sage: W = WehlerK3Surface([L, Q])
2215
+ sage: T = W([-1, -1, 1, 1, 0, 1])
2216
+ sage: W.nth_iterate_phi(T, -7)
2217
+ (1 : 0 : 1 , -1 : 2 : 1)
2218
+
2219
+ ::
2220
+
2221
+ sage: R.<x0,x1,x2,y0,y1,y2>=PolynomialRing(QQ, 6)
2222
+ sage: L = (-y0 - y1)*x0 + (-y0*x1 - y2*x2)
2223
+ sage: Q = (-y2*y0 - y1^2)*x0^2 + ((-y0^2 - y2*y0 + (-y2*y1 - y2^2))*x1 + (-y0^2 - y2*y1)*x2)*x0 \
2224
+ ....: + ((-y0^2 - y2*y0 - y2^2)*x1^2 + (-y2*y0 - y1^2)*x2*x1 + (-y0^2 + (-y1 - y2)*y0)*x2^2)
2225
+ sage: X = WehlerK3Surface([L, Q])
2226
+ sage: P = X([1, 0, -1, 1, -1, 0])
2227
+ sage: X.nth_iterate_phi(P, 8) == X.nth_iterate_psi(P, 8)
2228
+ True
2229
+ """
2230
+ try:
2231
+ n = ZZ(n)
2232
+ except TypeError:
2233
+ raise TypeError("iterate number must be an integer")
2234
+ #Since phi and psi are inverses and automorphisms
2235
+ if n < 0:
2236
+ return self.nth_iterate_psi(P, abs(n), **kwds)
2237
+ if n == 0:
2238
+ return self
2239
+ else:
2240
+ Q = self.phi(P, **kwds)
2241
+ for i in range(2, n+1):
2242
+ Q = self.phi(Q, **kwds)
2243
+ return Q
2244
+
2245
+ def nth_iterate_psi(self, P, n, **kwds):
2246
+ r"""
2247
+ Compute the `n`-th iterate for the psi function.
2248
+
2249
+ INPUT:
2250
+
2251
+ - ``P`` -- a point in `\mathbb{P}^2 \times \mathbb{P}^2`
2252
+
2253
+ - ``n`` -- integer
2254
+
2255
+ kwds:
2256
+
2257
+ - ``check`` -- boolean (default: ``True``); checks to see if point is on the surface
2258
+
2259
+ - ``normalize`` -- boolean (default: ``False``); normalizes the point
2260
+
2261
+ OUTPUT: the `n`-th iterate of the point given the psi function (if `n` is positive),
2262
+ or the phi function (if `n` is negative)
2263
+
2264
+ EXAMPLES::
2265
+
2266
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2267
+ sage: L = x0*y0 + x1*y1 + x2*y2
2268
+ sage: Q = x1^2*y0^2 + 2*x2^2*y0*y1 + x0^2*y1^2 - x0*x1*y2^2
2269
+ sage: W = WehlerK3Surface([L, Q])
2270
+ sage: T = W([-1, -1, 1, 1, 0, 1])
2271
+ sage: W.nth_iterate_psi(T, -7)
2272
+ (-1 : 0 : 1 , 1 : -2 : 1)
2273
+
2274
+ ::
2275
+
2276
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2277
+ sage: L = x0*y0 + x1*y1 + x2*y2
2278
+ sage: Q = x1^2*y0^2 + 2*x2^2*y0*y1 + x0^2*y1^2 - x0*x1*y2^2
2279
+ sage: W = WehlerK3Surface([L, Q])
2280
+ sage: T = W([-1, -1, 1, 1, 0, 1])
2281
+ sage: W.nth_iterate_psi(T, 7)
2282
+ (1 : 0 : 1 , -1 : 2 : 1)
2283
+ """
2284
+ try:
2285
+ n = ZZ(n)
2286
+ except TypeError:
2287
+ raise TypeError("iterate number must be an integer")
2288
+ #Since phi and psi and inverses
2289
+ if n < 0:
2290
+ return self.nth_iterate_phi(P, abs(n), **kwds)
2291
+ if n == 0:
2292
+ return self
2293
+ else:
2294
+ Q = self.psi(P, **kwds)
2295
+ for i in range(2, n+1):
2296
+ Q = self.psi(Q, **kwds)
2297
+ return Q
2298
+
2299
+ def orbit_phi(self, P, N, **kwds):
2300
+ r"""
2301
+ Return the orbit of the `\phi` function defined by
2302
+ `\phi = \sigma_y \circ \sigma_x`.
2303
+
2304
+ This function is defined in [CS1996]_.
2305
+
2306
+ INPUT:
2307
+
2308
+ - ``P`` -- point on the K3 surface
2309
+
2310
+ - ``N`` -- nonnegative integer or list or tuple of two nonnegative integers
2311
+
2312
+ kwds:
2313
+
2314
+ - ``check`` -- boolean (default: ``True``); checks to see if point is on the surface
2315
+
2316
+ - ``normalize`` -- boolean (default: ``False``); normalizes the point
2317
+
2318
+ OUTPUT: list of points in the orbit
2319
+
2320
+ EXAMPLES::
2321
+
2322
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2323
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
2324
+ ....: 3*x0*x1*y0*y1 -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - \
2325
+ ....: 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + \
2326
+ ....: x0*x1*y2^2 + 3*x2^2*y2^2
2327
+ sage: Y = x0*y0 + x1*y1 + x2*y2
2328
+ sage: X = WehlerK3Surface([Z, Y])
2329
+ sage: T = PP(0, 0, 1, 1, 0, 0)
2330
+ sage: X.orbit_phi(T,2, normalize = True)
2331
+ [(0 : 0 : 1 , 1 : 0 : 0), (-1 : 0 : 1 , 0 : 1 : 0), (-12816/6659 : 55413/6659 : 1 , 1 : 1/9 : 1)]
2332
+ sage: X.orbit_phi(T,[2,3], normalize = True)
2333
+ [(-12816/6659 : 55413/6659 : 1 , 1 : 1/9 : 1),
2334
+ (7481279673854775690938629732119966552954626693713001783595660989241/18550615454277582153932951051931712107449915856862264913424670784695
2335
+ : 3992260691327218828582255586014718568398539828275296031491644987908/18550615454277582153932951051931712107449915856862264913424670784695 :
2336
+ 1 , -117756062505511/54767410965117 : -23134047983794359/37466994368025041 : 1)]
2337
+ """
2338
+ if not isinstance(N, (list, tuple)):
2339
+ N = [0, N]
2340
+ try:
2341
+ N[0] = ZZ(N[0])
2342
+ N[1] = ZZ(N[1])
2343
+ except TypeError:
2344
+ raise TypeError("orbit bounds must be integers")
2345
+ if N[0] < 0 or N[1] < 0:
2346
+ raise TypeError("orbit bounds must be nonnegative")
2347
+ if N[0] > N[1]:
2348
+ return []
2349
+ Q = self(copy(P))
2350
+ for i in range(1, N[0] + 1):
2351
+ Q = self.phi(Q, **kwds)
2352
+ Orb = [Q]
2353
+ for i in range(N[0] + 1, N[1] + 1):
2354
+ Q = self.phi(Q, **kwds)
2355
+ Orb.append(Q)
2356
+ return Orb
2357
+
2358
+ def orbit_psi(self, P, N, **kwds):
2359
+ r"""
2360
+ Return the orbit of the `\psi` function defined by
2361
+ `\psi = \sigma_x \circ \sigma_y`.
2362
+
2363
+ This function is defined in [CS1996]_.
2364
+
2365
+ INPUT:
2366
+
2367
+ - ``P`` -- a point on the K3 surface
2368
+
2369
+ - ``N`` -- nonnegative integer or list or tuple of two nonnegative integers
2370
+
2371
+ kwds:
2372
+
2373
+ - ``check`` -- boolean (default: ``True``); checks to see if point is on the surface
2374
+
2375
+ - ``normalize`` -- boolean (default: ``False``); normalizes the point
2376
+
2377
+ OUTPUT: list of points in the orbit
2378
+
2379
+ EXAMPLES::
2380
+
2381
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2382
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
2383
+ ....: 3*x0*x1*y0*y1 -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 - \
2384
+ ....: 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 -4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + \
2385
+ ....: x0*x1*y2^2 + 3*x2^2*y2^2
2386
+ sage: Y = x0*y0 + x1*y1 + x2*y2
2387
+ sage: X = WehlerK3Surface([Z, Y])
2388
+ sage: T = X(0, 0, 1, 1, 0, 0)
2389
+ sage: X.orbit_psi(T, 2, normalize=True)
2390
+ [(0 : 0 : 1 , 1 : 0 : 0), (0 : 0 : 1 , 0 : 1 : 0), (-1 : 0 : 1 , 1 : 1/9 : 1)]
2391
+ sage: X.orbit_psi(T,[2,3], normalize=True)
2392
+ [(-1 : 0 : 1 , 1 : 1/9 : 1),
2393
+ (-12816/6659 : 55413/6659 : 1 , -117756062505511/54767410965117 : -23134047983794359/37466994368025041 : 1)]
2394
+ """
2395
+ if not isinstance(N, (list, tuple)):
2396
+ N = [0, N]
2397
+ try:
2398
+ N[0] = ZZ(N[0])
2399
+ N[1] = ZZ(N[1])
2400
+ except TypeError:
2401
+ raise TypeError("orbit bounds must be integers")
2402
+ if N[0] < 0 or N[1] < 0:
2403
+ raise TypeError("orbit bounds must be nonnegative")
2404
+ if N[0] > N[1]:
2405
+ return []
2406
+ Q = self(copy(P))
2407
+ for i in range(1, N[0] + 1):
2408
+ Q = self.psi(Q, **kwds)
2409
+ Orb = [Q]
2410
+ for i in range(N[0] + 1, N[1] + 1):
2411
+ Q = self.psi(Q, **kwds)
2412
+ Orb.append(Q)
2413
+ return Orb
2414
+
2415
+ def is_isomorphic(self, right):
2416
+ r"""
2417
+ Check to see if two K3 surfaces have the same defining ideal.
2418
+
2419
+ INPUT:
2420
+
2421
+ - ``right`` -- the K3 surface to compare to the original
2422
+
2423
+ OUTPUT: boolean
2424
+
2425
+ EXAMPLES::
2426
+
2427
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2428
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
2429
+ ....: 3*x0*x1*y0*y1 -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
2430
+ ....: -4*x1*x2*y1^2 + 5*x0*x2*y0*y2 - 4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
2431
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
2432
+ sage: Y = x0*y0 + x1*y1 + x2*y2
2433
+ sage: X = WehlerK3Surface([Z, Y])
2434
+ sage: W = WehlerK3Surface([Z + Y^2, Y])
2435
+ sage: X.is_isomorphic(W)
2436
+ True
2437
+
2438
+ ::
2439
+
2440
+ sage: R.<x,y,z,u,v,w> = PolynomialRing(QQ, 6)
2441
+ sage: L = x*u - y*v
2442
+ sage: Q = x*y*v^2 + z^2*u*w
2443
+ sage: W1 = WehlerK3Surface([L, Q])
2444
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2445
+ sage: L = x0*y0 + x1*y1 + x2*y2
2446
+ sage: Q = x1^2*y0^2 + 2*x2^2*y0*y1 + x0^2*y1^2 - x0*x1*y2^2
2447
+ sage: W2 = WehlerK3Surface([L, Q])
2448
+ sage: W1.is_isomorphic(W2)
2449
+ False
2450
+ """
2451
+ return self.defining_ideal() == right.defining_ideal()
2452
+
2453
+ def is_symmetric_orbit(self, orbit):
2454
+ r"""
2455
+ Check to see if the orbit is symmetric (i.e. if one of the points on the
2456
+ orbit is fixed by '\sigma_x' or '\sigma_y').
2457
+
2458
+ INPUT:
2459
+
2460
+ - ``orbit`` -- a periodic cycle of either psi or phi
2461
+
2462
+ OUTPUT: boolean
2463
+
2464
+ EXAMPLES::
2465
+
2466
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], GF(7))
2467
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + 3*x0*x1*y0*y1 \
2468
+ ....: -2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 -4*x1*x2*y1^2 + 5*x0*x2*y0*y2 \
2469
+ ....: -4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 + x0*x1*y2^2 + 3*x2^2*y2^2
2470
+ sage: Y = x0*y0 + x1*y1 + x2*y2
2471
+ sage: X = WehlerK3Surface([Z, Y])
2472
+ sage: T = PP([0, 0, 1, 1, 0, 0])
2473
+ sage: orbit = X.orbit_psi(T, 4)
2474
+ sage: X.is_symmetric_orbit(orbit)
2475
+ True
2476
+
2477
+ ::
2478
+
2479
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], QQ)
2480
+ sage: L = x0*y0 + x1*y1 + x2*y2
2481
+ sage: Q = x1^2*y0^2 + 2*x2^2*y0*y1 + x0^2*y1^2 - x0*x1*y2^2
2482
+ sage: W = WehlerK3Surface([L, Q])
2483
+ sage: T = W([-1, -1, 1, 1, 0, 1])
2484
+ sage: Orb = W.orbit_phi(T, 7)
2485
+ sage: W.is_symmetric_orbit(Orb)
2486
+ False
2487
+ """
2488
+ N = len(orbit)
2489
+ if self.nth_iterate_phi(orbit[0], N) != orbit[0] and self.nth_iterate_psi(orbit[0], N) != orbit[0]:
2490
+ raise ValueError("must be an orbit of phi or psi functions")
2491
+ sym = False
2492
+ i = 0
2493
+ while i < len(orbit) - 1 and not sym:
2494
+ P = orbit[i]
2495
+ Q = orbit[i + 1]
2496
+ if P[0] == Q[0] or P[1] == Q[1]:
2497
+ sym = True
2498
+ i += 1
2499
+ return sym
2500
+
2501
+
2502
+ class WehlerK3Surface_field( WehlerK3Surface_ring):
2503
+ pass
2504
+
2505
+
2506
+ class WehlerK3Surface_finite_field( WehlerK3Surface_field):
2507
+ def cardinality( self):
2508
+ r"""
2509
+ Count the total number of points on the K3 surface.
2510
+
2511
+ ALGORITHM:
2512
+
2513
+ Enumerate points over `\mathbb{P}^2`, and then count the points on the fiber of
2514
+ each of those points.
2515
+
2516
+ OUTPUT: integer; total number of points on the surface
2517
+
2518
+ EXAMPLES::
2519
+
2520
+ sage: PP.<x0,x1,x2,y0,y1,y2> = ProductProjectiveSpaces([2, 2], GF(7))
2521
+ sage: Z = x0^2*y0^2 + 3*x0*x1*y0^2 + x1^2*y0^2 + 4*x0^2*y0*y1 + \
2522
+ ....: 3*x0*x1*y0*y1 - 2*x2^2*y0*y1 - x0^2*y1^2 + 2*x1^2*y1^2 - x0*x2*y1^2 \
2523
+ ....: - 4*x1*x2*y1^2 + 5*x0*x2*y0*y2 -4*x1*x2*y0*y2 + 7*x0^2*y1*y2 + 4*x1^2*y1*y2 \
2524
+ ....: + x0*x1*y2^2 + 3*x2^2*y2^2
2525
+ sage: Y = x0*y0 + x1*y1 + x2*y2
2526
+ sage: X = WehlerK3Surface([Z, Y])
2527
+ sage: X.cardinality()
2528
+ 55
2529
+ """
2530
+ def getPx1():
2531
+ return ([x, y, 1] for x in self.base_ring() for y in self.base_ring())
2532
+
2533
+ def getPx2():
2534
+ return ([x, 1, 0] for x in self.base_ring())
2535
+ Count = 0
2536
+ Xpoint = [1, 0, 0]
2537
+ Ypoint = [1, 0, 0]
2538
+ # Create all possible Px1 Values
2539
+ for i in getPx1():
2540
+ for j in getPx1():
2541
+ A = i + j
2542
+ if self.L(A) == 0 and self.Q(A) == 0:
2543
+ Count += 1
2544
+ for k in getPx2():
2545
+ A = i + k
2546
+ if self.L(A) == 0 and self.Q(A) == 0:
2547
+ Count += 1
2548
+ B = i + Ypoint
2549
+ if self.L(B) == 0 and self.Q(B) == 0:
2550
+ Count += 1
2551
+ #Create all possible Px2 Values
2552
+ for i in getPx2():
2553
+ for j in getPx1():
2554
+ A = i + j
2555
+ if self.L(A) == 0 and self.Q(A) == 0:
2556
+ Count += 1
2557
+ for k in getPx2():
2558
+ A = i + k
2559
+ if (self.L(A) == 0 and self.Q(A) == 0):
2560
+ Count += 1
2561
+ B = i + Ypoint
2562
+ if (self.L(B) == 0 and self.Q(B) == 0):
2563
+ Count += 1
2564
+ #Create all Xpoint values
2565
+ for j in getPx1():
2566
+ A = Xpoint+j
2567
+ if (self.L(A) == 0 and self.Q(A) == 0):
2568
+ Count += 1
2569
+ for k in getPx2():
2570
+ B = Xpoint + k
2571
+ if (self.L(B) == 0 and self.Q(B) == 0):
2572
+ Count += 1
2573
+ C = Xpoint + Ypoint
2574
+ if (self.L(C) == 0 and self.Q(C) == 0):
2575
+ Count += 1
2576
+ return Count