passagemath-polyhedra 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (205) hide show
  1. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +368 -0
  2. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +371 -0
  3. passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +205 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.dylibs/libgmp.10.dylib +0 -0
  7. sage/all__sagemath_polyhedra.py +50 -0
  8. sage/game_theory/all.py +8 -0
  9. sage/game_theory/catalog.py +6 -0
  10. sage/game_theory/catalog_normal_form_games.py +923 -0
  11. sage/game_theory/cooperative_game.py +844 -0
  12. sage/game_theory/matching_game.py +1181 -0
  13. sage/game_theory/normal_form_game.py +2697 -0
  14. sage/game_theory/parser.py +275 -0
  15. sage/geometry/all__sagemath_polyhedra.py +22 -0
  16. sage/geometry/cone.py +6940 -0
  17. sage/geometry/cone_catalog.py +847 -0
  18. sage/geometry/cone_critical_angles.py +1027 -0
  19. sage/geometry/convex_set.py +1119 -0
  20. sage/geometry/fan.py +3743 -0
  21. sage/geometry/fan_isomorphism.py +389 -0
  22. sage/geometry/fan_morphism.py +1884 -0
  23. sage/geometry/hasse_diagram.py +202 -0
  24. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  25. sage/geometry/hyperplane_arrangement/all.py +1 -0
  26. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  27. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  28. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  29. sage/geometry/hyperplane_arrangement/library.py +825 -0
  30. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  31. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  32. sage/geometry/integral_points.py +35 -0
  33. sage/geometry/integral_points_generic_dense.cpython-314-darwin.so +0 -0
  34. sage/geometry/integral_points_generic_dense.pyx +7 -0
  35. sage/geometry/lattice_polytope.py +5894 -0
  36. sage/geometry/linear_expression.py +773 -0
  37. sage/geometry/newton_polygon.py +767 -0
  38. sage/geometry/point_collection.cpython-314-darwin.so +0 -0
  39. sage/geometry/point_collection.pyx +1008 -0
  40. sage/geometry/polyhedral_complex.py +2616 -0
  41. sage/geometry/polyhedron/all.py +8 -0
  42. sage/geometry/polyhedron/backend_cdd.py +460 -0
  43. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  44. sage/geometry/polyhedron/backend_field.py +347 -0
  45. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  46. sage/geometry/polyhedron/backend_number_field.py +168 -0
  47. sage/geometry/polyhedron/backend_polymake.py +765 -0
  48. sage/geometry/polyhedron/backend_ppl.py +582 -0
  49. sage/geometry/polyhedron/base.py +1206 -0
  50. sage/geometry/polyhedron/base0.py +1444 -0
  51. sage/geometry/polyhedron/base1.py +886 -0
  52. sage/geometry/polyhedron/base2.py +812 -0
  53. sage/geometry/polyhedron/base3.py +1845 -0
  54. sage/geometry/polyhedron/base4.py +1262 -0
  55. sage/geometry/polyhedron/base5.py +2700 -0
  56. sage/geometry/polyhedron/base6.py +1741 -0
  57. sage/geometry/polyhedron/base7.py +997 -0
  58. sage/geometry/polyhedron/base_QQ.py +1258 -0
  59. sage/geometry/polyhedron/base_RDF.py +98 -0
  60. sage/geometry/polyhedron/base_ZZ.py +934 -0
  61. sage/geometry/polyhedron/base_mutable.py +215 -0
  62. sage/geometry/polyhedron/base_number_field.py +122 -0
  63. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  64. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  65. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-darwin.so +0 -0
  66. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-darwin.so +0 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-darwin.so +0 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-darwin.so +0 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-darwin.so +0 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-darwin.so +0 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-darwin.so +0 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  87. sage/geometry/polyhedron/constructor.py +773 -0
  88. sage/geometry/polyhedron/double_description.py +753 -0
  89. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  90. sage/geometry/polyhedron/face.py +1060 -0
  91. sage/geometry/polyhedron/generating_function.py +1810 -0
  92. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  93. sage/geometry/polyhedron/library.py +3502 -0
  94. sage/geometry/polyhedron/misc.py +121 -0
  95. sage/geometry/polyhedron/modules/all.py +1 -0
  96. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  97. sage/geometry/polyhedron/palp_database.py +447 -0
  98. sage/geometry/polyhedron/parent.py +1279 -0
  99. sage/geometry/polyhedron/plot.py +1986 -0
  100. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  101. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  102. sage/geometry/polyhedron/representation.py +1723 -0
  103. sage/geometry/pseudolines.py +515 -0
  104. sage/geometry/relative_interior.py +445 -0
  105. sage/geometry/toric_plotter.py +1103 -0
  106. sage/geometry/triangulation/all.py +2 -0
  107. sage/geometry/triangulation/base.cpython-314-darwin.so +0 -0
  108. sage/geometry/triangulation/base.pyx +963 -0
  109. sage/geometry/triangulation/data.h +147 -0
  110. sage/geometry/triangulation/data.pxd +4 -0
  111. sage/geometry/triangulation/element.py +914 -0
  112. sage/geometry/triangulation/functions.h +10 -0
  113. sage/geometry/triangulation/functions.pxd +4 -0
  114. sage/geometry/triangulation/point_configuration.py +2256 -0
  115. sage/geometry/triangulation/triangulations.h +49 -0
  116. sage/geometry/triangulation/triangulations.pxd +7 -0
  117. sage/geometry/voronoi_diagram.py +319 -0
  118. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  119. sage/interfaces/polymake.py +2028 -0
  120. sage/numerical/all.py +13 -0
  121. sage/numerical/all__sagemath_polyhedra.py +11 -0
  122. sage/numerical/backends/all.py +1 -0
  123. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  124. sage/numerical/backends/cvxopt_backend.cpython-314-darwin.so +0 -0
  125. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  126. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  127. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-darwin.so +0 -0
  128. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  129. sage/numerical/backends/cvxpy_backend.cpython-314-darwin.so +0 -0
  130. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  131. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  132. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  133. sage/numerical/backends/generic_backend_test.py +24 -0
  134. sage/numerical/backends/interactivelp_backend.cpython-314-darwin.so +0 -0
  135. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  136. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  137. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  138. sage/numerical/backends/logging_backend.py +391 -0
  139. sage/numerical/backends/matrix_sdp_backend.cpython-314-darwin.so +0 -0
  140. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  141. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  142. sage/numerical/backends/ppl_backend.cpython-314-darwin.so +0 -0
  143. sage/numerical/backends/ppl_backend.pyx +1126 -0
  144. sage/numerical/backends/ppl_backend_test.py +13 -0
  145. sage/numerical/backends/scip_backend.cpython-314-darwin.so +0 -0
  146. sage/numerical/backends/scip_backend.pxd +22 -0
  147. sage/numerical/backends/scip_backend.pyx +1289 -0
  148. sage/numerical/backends/scip_backend_test.py +13 -0
  149. sage/numerical/interactive_simplex_method.py +5338 -0
  150. sage/numerical/knapsack.py +665 -0
  151. sage/numerical/linear_functions.cpython-314-darwin.so +0 -0
  152. sage/numerical/linear_functions.pxd +31 -0
  153. sage/numerical/linear_functions.pyx +1648 -0
  154. sage/numerical/linear_tensor.py +470 -0
  155. sage/numerical/linear_tensor_constraints.py +448 -0
  156. sage/numerical/linear_tensor_element.cpython-314-darwin.so +0 -0
  157. sage/numerical/linear_tensor_element.pxd +6 -0
  158. sage/numerical/linear_tensor_element.pyx +459 -0
  159. sage/numerical/mip.cpython-314-darwin.so +0 -0
  160. sage/numerical/mip.pxd +40 -0
  161. sage/numerical/mip.pyx +3667 -0
  162. sage/numerical/sdp.cpython-314-darwin.so +0 -0
  163. sage/numerical/sdp.pxd +39 -0
  164. sage/numerical/sdp.pyx +1433 -0
  165. sage/rings/all__sagemath_polyhedra.py +3 -0
  166. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  167. sage/rings/polynomial/omega.py +982 -0
  168. sage/schemes/all__sagemath_polyhedra.py +2 -0
  169. sage/schemes/toric/all.py +10 -0
  170. sage/schemes/toric/chow_group.py +1248 -0
  171. sage/schemes/toric/divisor.py +2082 -0
  172. sage/schemes/toric/divisor_class.cpython-314-darwin.so +0 -0
  173. sage/schemes/toric/divisor_class.pyx +322 -0
  174. sage/schemes/toric/fano_variety.py +1606 -0
  175. sage/schemes/toric/homset.py +650 -0
  176. sage/schemes/toric/ideal.py +451 -0
  177. sage/schemes/toric/library.py +1322 -0
  178. sage/schemes/toric/morphism.py +1958 -0
  179. sage/schemes/toric/points.py +1032 -0
  180. sage/schemes/toric/sheaf/all.py +1 -0
  181. sage/schemes/toric/sheaf/constructor.py +302 -0
  182. sage/schemes/toric/sheaf/klyachko.py +921 -0
  183. sage/schemes/toric/toric_subscheme.py +905 -0
  184. sage/schemes/toric/variety.py +3460 -0
  185. sage/schemes/toric/weierstrass.py +1078 -0
  186. sage/schemes/toric/weierstrass_covering.py +457 -0
  187. sage/schemes/toric/weierstrass_higher.py +288 -0
  188. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  189. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  190. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  193. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  194. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  195. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  204. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  205. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
@@ -0,0 +1,1078 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ # sage.doctest: needs sage.geometry.polyhedron sage.graphs
3
+ r"""
4
+ Weierstrass form of a toric elliptic curve
5
+
6
+ There are 16 reflexive polygons in the plane, see
7
+ :func:`~sage.geometry.lattice_polytope.ReflexivePolytopes`. Each of
8
+ them defines a toric Fano variety. And each of them has a unique
9
+ crepant resolution to a smooth toric surface (Section 10.4 in [CLS2011]_) by
10
+ subdividing the face fan. An anticanonical hypersurface defines an
11
+ elliptic curve in this ambient space, which we call a toric elliptic
12
+ curve. The purpose of this module is to write an anticanonical
13
+ hypersurface equation in the short Weierstrass form `y^2 = x^3 + f x +
14
+ g`. This works over any base ring as long as its characteristic `\not=
15
+ 2,3`.
16
+
17
+ For an analogous treatment of elliptic curves defined as complete
18
+ intersection in higher dimensional toric varieties, see
19
+ the module :mod:`~sage.schemes.toric.weierstrass_higher`.
20
+
21
+ Technically, this module computes the Weierstrass form of the Jacobian
22
+ of the elliptic curve. This is why you will never have to specify the
23
+ origin (or zero section) in the following.
24
+
25
+ It turns out [Bra2011]_ that the anticanonical hypersurface
26
+ equation of any one of the above 16 toric surfaces is a specialization
27
+ (that is, set one or more of the coefficients to zero) of the
28
+ following three cases. In inhomogeneous coordinates, they are
29
+
30
+ * Cubic in `\mathbb{P}^2`:
31
+
32
+ .. MATH::
33
+
34
+ \begin{split}
35
+ p(x,y) =&\;
36
+ a_{30} x^{3} + a_{21} x^{2} y + a_{12} x y^{2} +
37
+ a_{03} y^{3} + a_{20} x^{2} +
38
+ \\ &\;
39
+ a_{11} x y +
40
+ a_{02} y^{2} + a_{10} x + a_{01} y + a_{00}
41
+ \end{split}
42
+
43
+ * Biquadric in `\mathbb{P}^1\times \mathbb{P}^1`:
44
+
45
+ .. MATH::
46
+
47
+ \begin{split}
48
+ p(x,y) =&\;
49
+ a_{22} x^2 y^2 + a_{21} x^2 y + a_{20} x^2 +
50
+ a_{12} x y^2 +
51
+ \\ &\;
52
+ a_{11} x y + x a_{10} +
53
+ y^2 a_{02} + y a_{01} + a_{00}
54
+ \end{split}
55
+
56
+ * Anticanonical hypersurface in weighted projective space `\mathbb{P}^2[1,1,2]`:
57
+
58
+ .. MATH::
59
+
60
+ \begin{split}
61
+ p(x,y) =&\;
62
+ a_{40} x^4 +
63
+ a_{30} x^3 +
64
+ a_{21} x^2 y +
65
+ a_{20} x^2 +
66
+ \\ &\;
67
+ a_{11} x y +
68
+ a_{02} y^2 +
69
+ a_{10} x +
70
+ a_{01} y +
71
+ a_{00}
72
+ \end{split}
73
+
74
+ EXAMPLES:
75
+
76
+ The main functionality is provided by :func:`WeierstrassForm`, which
77
+ brings each of the above hypersurface equations into Weierstrass
78
+ form::
79
+
80
+ sage: R.<x,y> = QQ[]
81
+ sage: cubic = x^3 + y^3 + 1
82
+ sage: WeierstrassForm(cubic)
83
+ (0, -27/4)
84
+ sage: WeierstrassForm(x^4 + y^2 + 1)
85
+ (-4, 0)
86
+ sage: WeierstrassForm(x^2*y^2 + x^2 + y^2 + 1)
87
+ (-16/3, 128/27)
88
+
89
+ Only the affine span of the Newton polytope of the polynomial
90
+ matters. For example::
91
+
92
+ sage: R.<x,y,z> = QQ[]
93
+ sage: WeierstrassForm(x^3 + y^3 + z^3)
94
+ (0, -27/4)
95
+ sage: WeierstrassForm(x * cubic)
96
+ (0, -27/4)
97
+
98
+ This allows you to work with either homogeneous or inhomogeneous
99
+ variables. For example, here is the del Pezzo surface of degree 8::
100
+
101
+ sage: dP8 = toric_varieties.dP8()
102
+ sage: dP8.inject_variables()
103
+ Defining t, x, y, z
104
+ sage: WeierstrassForm(x*y^2 + y^2*z + t^2*x^3 + t^2*z^3)
105
+ (-3, -2)
106
+ sage: WeierstrassForm(x*y^2 + y^2 + x^3 + 1)
107
+ (-3, -2)
108
+
109
+ By specifying only certain variables we can compute the Weierstrass
110
+ form over the polynomial ring generated by the remaining
111
+ variables. For example, here is a cubic over `\QQ[a]` ::
112
+
113
+ sage: R.<a, x, y, z> = QQ[]
114
+ sage: cubic = x^3 + a*y^3 + a^2*z^3
115
+ sage: WeierstrassForm(cubic, variables=[x,y,z])
116
+ (0, -27/4*a^6)
117
+
118
+ TESTS::
119
+
120
+ sage: R.<f, g, x, y> = QQ[]
121
+ sage: cubic = -y^2 + x^3 + f*x + g
122
+ sage: WeierstrassForm(cubic, variables=[x,y])
123
+ (f, g)
124
+
125
+ REFERENCES:
126
+
127
+ - [Bra2011]_
128
+ - [Du2010]_
129
+ - [ARVT2005]_
130
+ - [CLS2011]_
131
+ """
132
+
133
+ ########################################################################
134
+ # Copyright (C) 2012 Volker Braun <vbraun.name@gmail.com>
135
+ #
136
+ # Distributed under the terms of the GNU General Public License (GPL)
137
+ #
138
+ # https://www.gnu.org/licenses/
139
+ ########################################################################
140
+
141
+ from sage.misc.misc_c import prod
142
+ from sage.rings.infinity import Infinity
143
+ from sage.modules.free_module_element import vector
144
+ from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
145
+ from sage.rings.invariants.invariant_theory import invariant_theory
146
+
147
+
148
+ ######################################################################
149
+ #
150
+ # Discriminant and j-invariant
151
+ #
152
+ ######################################################################
153
+
154
+
155
+ def Discriminant(polynomial, variables=None):
156
+ r"""
157
+ The discriminant of the elliptic curve.
158
+
159
+ INPUT:
160
+
161
+ See :func:`WeierstrassForm` for how to specify the input
162
+ polynomial(s) and variables.
163
+
164
+ OUTPUT: the discriminant of the elliptic curve
165
+
166
+ EXAMPLES::
167
+
168
+ sage: from sage.schemes.toric.weierstrass import Discriminant
169
+ sage: R.<x, y, z> = QQ[]
170
+ sage: Discriminant(x^3 + y^3 + z^3)
171
+ 19683/16
172
+ sage: Discriminant(x*y*z)
173
+ 0
174
+ sage: R.<w,x,y,z> = QQ[]
175
+ sage: quadratic1 = w^2 + x^2 + y^2
176
+ sage: quadratic2 = z^2 + w*x
177
+ sage: Discriminant([quadratic1, quadratic2])
178
+ -1/16
179
+ """
180
+ f, g = WeierstrassForm(polynomial, variables)
181
+ return 4*f**3 + 27*g**2
182
+
183
+
184
+ ######################################################################
185
+ def j_invariant(polynomial, variables=None):
186
+ r"""
187
+ Return the `j`-invariant of the elliptic curve.
188
+
189
+ INPUT:
190
+
191
+ See :func:`WeierstrassForm` for how to specify the input
192
+ polynomial(s) and variables.
193
+
194
+ OUTPUT:
195
+
196
+ The j-invariant of the (irreducible) cubic. Notable special values:
197
+
198
+ * The Fermat cubic: `j(x^3+y^3+z^3) = 0`
199
+
200
+ * A nodal cubic: `j(-y^2 + x^2 + x^3) = \infty`
201
+
202
+ * A cuspidal cubic `y^2=x^3` has undefined `j`-invariant. In this
203
+ case, a :exc:`ValueError` is raised.
204
+
205
+ EXAMPLES::
206
+
207
+ sage: from sage.schemes.toric.weierstrass import j_invariant
208
+ sage: R.<x,y,z> = QQ[]
209
+ sage: j_invariant(x^3 + y^3 + z^3)
210
+ 0
211
+ sage: j_invariant(-y^2 + x^2 + x^3)
212
+ +Infinity
213
+ sage: R.<x,y,z, a,b> = QQ[]
214
+ sage: j_invariant( -y^2*z + x^3 + a*x*z^2, [x,y,z])
215
+ 1728
216
+
217
+ TESTS::
218
+
219
+ sage: j_invariant(x*y*z)
220
+ Traceback (most recent call last):
221
+ ...
222
+ ValueError: curve is singular and has no well-defined j-invariant
223
+ """
224
+ f, g = WeierstrassForm(polynomial, variables)
225
+ disc = 4*f**3 + 27*g**2
226
+ if disc != 0:
227
+ return 1728 * 4 * f**3 / disc
228
+ if f != 0:
229
+ return Infinity
230
+ raise ValueError('curve is singular and has no well-defined j-invariant')
231
+
232
+
233
+ ######################################################################
234
+ #
235
+ # Weierstrass form of any elliptic curve
236
+ #
237
+ ######################################################################
238
+ def Newton_polytope_vars_coeffs(polynomial, variables):
239
+ """
240
+ Return the Newton polytope in the given variables.
241
+
242
+ INPUT:
243
+
244
+ See :func:`WeierstrassForm` for how to specify the input
245
+ polynomial and variables.
246
+
247
+ OUTPUT:
248
+
249
+ A dictionary with keys the integral values of the Newton polytope
250
+ and values the corresponding coefficient of ``polynomial``.
251
+
252
+ EXAMPLES::
253
+
254
+ sage: from sage.schemes.toric.weierstrass import Newton_polytope_vars_coeffs
255
+ sage: R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[]
256
+ sage: p = (a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z +
257
+ ....: a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3)
258
+ sage: p_data = Newton_polytope_vars_coeffs(p, [x,y,z]); p_data
259
+ {(0, 0, 3): a00,
260
+ (0, 1, 2): a01,
261
+ (0, 2, 1): a02,
262
+ (0, 3, 0): a03,
263
+ (1, 0, 2): a10,
264
+ (1, 1, 1): a11,
265
+ (1, 2, 0): a12,
266
+ (2, 0, 1): a20,
267
+ (2, 1, 0): a21,
268
+ (3, 0, 0): a30}
269
+
270
+ sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
271
+ sage: polytope = LatticePolytope_PPL(list(p_data)); polytope
272
+ A 2-dimensional lattice polytope in ZZ^3 with 3 vertices
273
+ sage: polytope.vertices()
274
+ ((0, 0, 3), (3, 0, 0), (0, 3, 0))
275
+ sage: polytope.embed_in_reflexive_polytope()
276
+ The map A*x+b with A=
277
+ [-1 -1]
278
+ [ 0 1]
279
+ [ 1 0]
280
+ b =
281
+ (3, 0, 0)
282
+ """
283
+ R = polynomial.parent()
284
+ var_indices = [R.gens().index(x) for x in variables]
285
+ result = {}
286
+ for c, m in polynomial:
287
+ e = m.exponents()[0]
288
+ v = tuple([e[i] for i in var_indices])
289
+ m_red = m // prod(x**i for x, i in zip(variables, v))
290
+ result[v] = result.get(v, R.zero()) + c*m_red
291
+ return result
292
+
293
+
294
+ ######################################################################
295
+ def Newton_polygon_embedded(polynomial, variables):
296
+ r"""
297
+ Embed the Newton polytope of the polynomial in one of the three
298
+ maximal reflexive polygons.
299
+
300
+ This function is a helper for :func:`WeierstrassForm`
301
+
302
+ INPUT:
303
+
304
+ Same as :func:`WeierstrassForm` with only a single polynomial passed.
305
+
306
+ OUTPUT:
307
+
308
+ A tuple `(\Delta, P, (x,y))` where
309
+
310
+ * `\Delta` is the Newton polytope of ``polynomial``.
311
+
312
+ * `P(x,y)` equals the input ``polynomial`` but with redefined variables
313
+ such that its Newton polytope is `\Delta`.
314
+
315
+ EXAMPLES::
316
+
317
+ sage: from sage.schemes.toric.weierstrass import Newton_polygon_embedded
318
+ sage: R.<x,y,z> = QQ[]
319
+ sage: cubic = x^3 + y^3 + z^3
320
+ sage: Newton_polygon_embedded(cubic, [x,y,z])
321
+ (A 2-dimensional lattice polytope in ZZ^3 with 3 vertices,
322
+ x^3 + y^3 + 1,
323
+ (x, y))
324
+
325
+ sage: R.<a, x,y,z> = QQ[]
326
+ sage: cubic = x^3 + a*y^3 + a^2*z^3
327
+ sage: Newton_polygon_embedded(cubic, variables=[x,y,z])
328
+ (A 2-dimensional lattice polytope in ZZ^3 with 3 vertices,
329
+ a^2*x^3 + y^3 + a,
330
+ (x, y))
331
+
332
+ sage: R.<s,t,x,y> = QQ[]
333
+ sage: biquadric = (s+t)^2 * (x+y)^2
334
+ sage: Newton_polygon_embedded(biquadric, [s,t,x,y])
335
+ (A 2-dimensional lattice polytope in ZZ^4 with 4 vertices,
336
+ s^2*t^2 + 2*s^2*t + 2*s*t^2 + s^2 + 4*s*t + t^2 + 2*s + 2*t + 1,
337
+ (s, t))
338
+ """
339
+ p_dict = Newton_polytope_vars_coeffs(polynomial, variables)
340
+ newton_polytope = LatticePolytope_PPL(list(p_dict))
341
+ assert newton_polytope.affine_dimension() <= 2
342
+ embedding = newton_polytope.embed_in_reflexive_polytope('points')
343
+ x, y = variables[0:2]
344
+ embedded_polynomial = polynomial.parent().zero()
345
+ for e, c in p_dict.items():
346
+ e_embed = embedding[e]
347
+ embedded_polynomial += c * x**(e_embed[0]) * y**(e_embed[1])
348
+ return newton_polytope, embedded_polynomial, (x, y)
349
+
350
+
351
+ ######################################################################
352
+ def WeierstrassForm(polynomial, variables=None, transformation=False):
353
+ r"""
354
+ Return the Weierstrass form of an elliptic curve inside either
355
+ inside a toric surface or `\mathbb{P}^3`.
356
+
357
+ INPUT:
358
+
359
+ - ``polynomial`` -- either a polynomial or a list of polynomials
360
+ defining the elliptic curve.
361
+ A single polynomial can be either a cubic, a biquadric, or the
362
+ hypersurface in `\mathbb{P}^2[1,1,2]`. In this case the
363
+ equation need not be in any standard form, only its Newton
364
+ polyhedron is used.
365
+ If two polynomials are passed, they must both be quadratics in
366
+ `\mathbb{P}^3`.
367
+
368
+ - ``variables`` -- list of variables of the parent polynomial
369
+ ring or ``None`` (default). In the latter case, all variables
370
+ are taken to be polynomial ring variables. If a subset of
371
+ polynomial ring variables are given, the Weierstrass form is
372
+ determined over the function field generated by the remaining
373
+ variables.
374
+
375
+ - ``transformation`` -- boolean (default: ``False``); whether to
376
+ return the new variables that bring ``polynomial`` into
377
+ Weierstrass form
378
+
379
+ OUTPUT:
380
+
381
+ The pair of coefficients `(f,g)` of the Weierstrass form `y^2 =
382
+ x^3 + f x + g` of the hypersurface equation.
383
+
384
+ If ``transformation=True``, a triple `(X,Y,Z)` of polynomials
385
+ defining a rational map of the toric hypersurface or complete
386
+ intersection in `\mathbb{P}^3` to its Weierstrass form in
387
+ `\mathbb{P}^2[2,3,1]` is returned.
388
+ That is, the triple satisfies
389
+
390
+ .. MATH::
391
+
392
+ Y^2 = X^3 + f X Z^4 + g Z^6
393
+
394
+ when restricted to the toric hypersurface or complete intersection.
395
+
396
+ EXAMPLES::
397
+
398
+ sage: R.<x,y,z> = QQ[]
399
+ sage: cubic = x^3 + y^3 + z^3
400
+ sage: f, g = WeierstrassForm(cubic); (f, g)
401
+ (0, -27/4)
402
+
403
+ Same in inhomogeneous coordinates::
404
+
405
+ sage: R.<x,y> = QQ[]
406
+ sage: cubic = x^3 + y^3 + 1
407
+ sage: f, g = WeierstrassForm(cubic); (f, g)
408
+ (0, -27/4)
409
+
410
+ sage: X,Y,Z = WeierstrassForm(cubic, transformation=True); (X,Y,Z)
411
+ (-x^3*y^3 - x^3 - y^3,
412
+ 1/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6 + 1/2*y^6 + 1/2*x^3 - 1/2*y^3,
413
+ x*y)
414
+
415
+ Note that plugging in `[X:Y:Z]` to the Weierstrass equation is a
416
+ complicated polynomial, but contains the hypersurface equation as
417
+ a factor::
418
+
419
+ sage: -Y^2 + X^3 + f*X*Z^4 + g*Z^6
420
+ -1/4*x^12*y^6 - 1/2*x^9*y^9 - 1/4*x^6*y^12 + 1/2*x^12*y^3
421
+ - 7/2*x^9*y^6 - 7/2*x^6*y^9 + 1/2*x^3*y^12 - 1/4*x^12 - 7/2*x^9*y^3
422
+ - 45/4*x^6*y^6 - 7/2*x^3*y^9 - 1/4*y^12 - 1/2*x^9 - 7/2*x^6*y^3
423
+ - 7/2*x^3*y^6 - 1/2*y^9 - 1/4*x^6 + 1/2*x^3*y^3 - 1/4*y^6
424
+ sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)
425
+ True
426
+
427
+ Only the affine span of the Newton polytope of the polynomial
428
+ matters. For example::
429
+
430
+ sage: R.<x,y,z> = QQ[]
431
+ sage: cubic = x^3 + y^3 + z^3
432
+ sage: WeierstrassForm(cubic.subs(z=1))
433
+ (0, -27/4)
434
+ sage: WeierstrassForm(x * cubic)
435
+ (0, -27/4)
436
+
437
+ This allows you to work with either homogeneous or inhomogeneous
438
+ variables. For example, here is the del Pezzo surface of degree 8::
439
+
440
+ sage: dP8 = toric_varieties.dP8()
441
+ sage: dP8.inject_variables()
442
+ Defining t, x, y, z
443
+ sage: WeierstrassForm(x*y^2 + y^2*z + t^2*x^3 + t^2*z^3)
444
+ (-3, -2)
445
+ sage: WeierstrassForm(x*y^2 + y^2 + x^3 + 1)
446
+ (-3, -2)
447
+
448
+ By specifying only certain variables we can compute the
449
+ Weierstrass form over the function field generated by the
450
+ remaining variables. For example, here is a cubic over `\QQ[a]` ::
451
+
452
+ sage: R.<a, x,y,z> = QQ[]
453
+ sage: cubic = x^3 + a*y^3 + a^2*z^3
454
+ sage: WeierstrassForm(cubic, variables=[x,y,z])
455
+ (0, -27/4*a^6)
456
+
457
+ TESTS::
458
+
459
+ sage: for P in ReflexivePolytopes(2): # needs polytopes_db
460
+ ....: S = ToricVariety(FaceFan(P))
461
+ ....: p = sum((-S.K()).sections_monomials())
462
+ ....: print(WeierstrassForm(p))
463
+ (-25/48, -1475/864)
464
+ (-97/48, 17/864)
465
+ (-25/48, -611/864)
466
+ (-27/16, 27/32)
467
+ (47/48, -199/864)
468
+ (47/48, -71/864)
469
+ (5/16, -21/32)
470
+ (23/48, -235/864)
471
+ (-1/48, 161/864)
472
+ (-25/48, 253/864)
473
+ (5/16, 11/32)
474
+ (-25/48, 125/864)
475
+ (-67/16, 63/32)
476
+ (-11/16, 3/32)
477
+ (-241/48, 3689/864)
478
+ (215/48, -5291/864)
479
+ """
480
+ if isinstance(polynomial, (list, tuple)):
481
+ from sage.schemes.toric.weierstrass_higher import WeierstrassForm2
482
+ return WeierstrassForm2(polynomial, variables=variables, transformation=transformation)
483
+ if transformation:
484
+ from sage.schemes.toric.weierstrass_covering import WeierstrassMap
485
+ return WeierstrassMap(polynomial, variables=variables)
486
+ if variables is None:
487
+ variables = polynomial.variables()
488
+ from sage.geometry.polyhedron.ppl_lattice_polygon import (
489
+ polar_P2_polytope, polar_P1xP1_polytope, polar_P2_112_polytope)
490
+ newton_polytope, polynomial, variables = \
491
+ Newton_polygon_embedded(polynomial, variables)
492
+ polygon = newton_polytope.embed_in_reflexive_polytope('polytope')
493
+ if polygon is polar_P2_polytope():
494
+ return WeierstrassForm_P2(polynomial, variables)
495
+ if polygon is polar_P1xP1_polytope():
496
+ return WeierstrassForm_P1xP1(polynomial, variables)
497
+ if polygon is polar_P2_112_polytope():
498
+ return WeierstrassForm_P2_112(polynomial, variables)
499
+ raise ValueError('Newton polytope is not contained in a reflexive polygon')
500
+
501
+
502
+ ######################################################################
503
+ #
504
+ # Weierstrass form of cubic in P^2
505
+ #
506
+ ######################################################################
507
+ def _check_homogeneity(polynomial, variables, weights, total_weight=None):
508
+ """
509
+ Raise :exc:`ValueError` if the polynomial is not weighted
510
+ homogeneous.
511
+
512
+ INPUT:
513
+
514
+ - ``polynomial`` -- the input polynomial; see
515
+ :func:`WeierstrassForm` for details
516
+
517
+ - ``variables`` -- the variables; see :func:`WeierstrassForm` for
518
+ details
519
+
520
+ - ``weights`` -- list of integers, one per variable; the weights
521
+ of the variables
522
+
523
+ - ``total_weight`` -- integer or ``None`` (default); if an
524
+ integer is passed, it is also checked that the weighted total
525
+ degree of polynomial is this value
526
+
527
+ OUTPUT:
528
+
529
+ This function returns nothing. If the polynomial is not weighted
530
+ homogeneous, a :exc:`ValueError` is raised.
531
+
532
+ EXAMPLES::
533
+
534
+ sage: from sage.schemes.toric.weierstrass import _check_homogeneity
535
+ sage: R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[]
536
+ sage: p = (a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z +
537
+ ....: a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3)
538
+ sage: _check_homogeneity(p, [x,y,z], (1,1,1), 3)
539
+
540
+ sage: _check_homogeneity(p + x^4, [x,y,z], (1,1,1), 3)
541
+ Traceback (most recent call last):
542
+ ...
543
+ ValueError: the polynomial is not homogeneous with weights (1, 1, 1)
544
+ """
545
+ w = vector(weights)
546
+ n = w.degree()
547
+ all_variables = polynomial.parent().gens()
548
+ variable_indices = [all_variables.index(x) for x in variables]
549
+ total_weight = None
550
+ for e in polynomial.exponents():
551
+ weight_e = sum(e[variable_indices[i]] * weights[i] for i in range(n))
552
+ if total_weight is None:
553
+ total_weight = weight_e
554
+ else:
555
+ if weight_e != total_weight:
556
+ msg = f'the polynomial is not homogeneous with weights {weights}'
557
+ raise ValueError(msg)
558
+
559
+
560
+ ######################################################################
561
+ def _extract_coefficients(polynomial, monomials, variables):
562
+ """
563
+ Return the coefficients of ``monomials``.
564
+
565
+ INPUT:
566
+
567
+ - ``polynomial`` -- the input polynomial
568
+
569
+ - ``monomials`` -- list of monomials in the polynomial ring
570
+
571
+ - ``variables`` -- list of variables in the polynomial ring
572
+
573
+ OUTPUT:
574
+
575
+ A tuple containing the coefficients of the monomials in the given
576
+ polynomial.
577
+
578
+ EXAMPLES::
579
+
580
+ sage: from sage.schemes.toric.weierstrass import _extract_coefficients
581
+ sage: R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[]
582
+ sage: p = (a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z +
583
+ ....: a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3)
584
+ sage: m = [x^3, y^3, z^3, x^2*y, x^2*z, x*y^2, y^2*z, x*z^2, y*z^2, x*y*z]
585
+ sage: _extract_coefficients(p, m, [x,y,z])
586
+ (a30, a03, a00, a21, a20, a12, a02, a10, a01, a11)
587
+
588
+ sage: m = [x^3, y^3, 1, x^2*y, x^2, x*y^2, y^2, x, y, x*y]
589
+ sage: _extract_coefficients(p.subs(z=1), m, [x,y])
590
+ (a30, a03, a00, a21, a20, a12, a02, a10, a01, a11)
591
+ """
592
+ R = polynomial.parent()
593
+ indices = [R.gens().index(x) for x in variables]
594
+
595
+ def index(monomial):
596
+ if monomial in R.base_ring():
597
+ return tuple(0 for i in indices)
598
+ e = monomial.exponents()[0]
599
+ return tuple(e[i] for i in indices)
600
+ coeffs = {}
601
+ for c, m in polynomial:
602
+ i = index(m)
603
+ coeffs[i] = c*m + coeffs.pop(i, R.zero())
604
+ result = tuple(coeffs.pop(index(m), R.zero()) // m for m in monomials)
605
+ if coeffs:
606
+ msg = f'the polynomial contains more monomials than given: {coeffs}'
607
+ raise ValueError(msg)
608
+ return result
609
+
610
+
611
+ ######################################################################
612
+ def _check_polynomial_P2(cubic, variables):
613
+ """
614
+ Check the polynomial is weighted homogeneous in standard variables.
615
+
616
+ INPUT:
617
+
618
+ - ``cubic`` -- the input polynomial; see
619
+ :func:`WeierstrassForm` for details
620
+
621
+ - ``variables`` -- the variables or ``None``; see
622
+ :func:`WeierstrassForm` for details
623
+
624
+ OUTPUT:
625
+
626
+ This functions returns ``variables``, potentially guessed from the
627
+ polynomial ring. A :exc:`ValueError` is raised if the polynomial is
628
+ not homogeneous.
629
+
630
+ EXAMPLES::
631
+
632
+ sage: from sage.schemes.toric.weierstrass import _check_polynomial_P2
633
+ sage: R.<x,y,z> = QQ[]
634
+ sage: cubic = x^3 + y^3 + z^3
635
+ sage: _check_polynomial_P2(cubic, [x,y,z])
636
+ (x, y, z)
637
+ sage: _check_polynomial_P2(cubic, None)
638
+ (x, y, z)
639
+ sage: _check_polynomial_P2(cubic.subs(z=1), None)
640
+ (x, y, None)
641
+ sage: R.<x,y,z,t> = QQ[]
642
+ sage: cubic = x^3 + y^3 + z^3 + t*x*y*z
643
+ sage: _check_polynomial_P2(cubic, [x,y,z])
644
+ (x, y, z)
645
+ sage: _check_polynomial_P2(cubic, [x,y,t])
646
+ Traceback (most recent call last):
647
+ ...
648
+ ValueError: the polynomial is not homogeneous with weights (1, 1, 1)
649
+ """
650
+ if variables is None:
651
+ variables = cubic.variables()
652
+ if len(variables) == 3:
653
+ x, y, z = variables
654
+ _check_homogeneity(cubic, [x, y, z], (1, 1, 1), 3)
655
+ elif len(variables) == 2:
656
+ x, y = variables
657
+ z = None
658
+ else:
659
+ raise ValueError(f'need two or three variables, got {variables}')
660
+ return (x, y, z)
661
+
662
+
663
+ ######################################################################
664
+ def WeierstrassForm_P2(polynomial, variables=None):
665
+ r"""
666
+ Bring a cubic into Weierstrass form.
667
+
668
+ Input/output is the same as :func:`WeierstrassForm`, except that
669
+ the input polynomial must be a standard cubic in `\mathbb{P}^2`,
670
+
671
+ .. MATH::
672
+
673
+ \begin{split}
674
+ p(x,y) =&\;
675
+ a_{30} x^{3} + a_{21} x^{2} y + a_{12} x y^{2} +
676
+ a_{03} y^{3} + a_{20} x^{2} +
677
+ \\ &\;
678
+ a_{11} x y +
679
+ a_{02} y^{2} + a_{10} x + a_{01} y + a_{00}
680
+ \end{split}
681
+
682
+ EXAMPLES::
683
+
684
+ sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2
685
+ sage: R.<x,y,z> = QQ[]
686
+ sage: WeierstrassForm_P2(x^3 + y^3 + z^3)
687
+ (0, -27/4)
688
+
689
+ sage: R.<x,y,z, a,b> = QQ[]
690
+ sage: WeierstrassForm_P2(-y^2*z + x^3 + a*x*z^2 + b*z^3, [x,y,z])
691
+ (a, b)
692
+
693
+ TESTS::
694
+
695
+ sage: R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[]
696
+ sage: p = ( a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z +
697
+ ....: a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3 )
698
+ sage: WeierstrassForm_P2(p, [x,y,z])
699
+ (-1/48*a11^4 + 1/6*a20*a11^2*a02 - 1/3*a20^2*a02^2 - 1/2*a03*a20*a11*a10
700
+ + 1/6*a12*a11^2*a10 + 1/3*a12*a20*a02*a10 - 1/2*a21*a11*a02*a10
701
+ + a30*a02^2*a10 - 1/3*a12^2*a10^2 + a21*a03*a10^2 + a03*a20^2*a01
702
+ - 1/2*a12*a20*a11*a01 + 1/6*a21*a11^2*a01 + 1/3*a21*a20*a02*a01
703
+ - 1/2*a30*a11*a02*a01 + 1/3*a21*a12*a10*a01 - 3*a30*a03*a10*a01
704
+ - 1/3*a21^2*a01^2 + a30*a12*a01^2 + a12^2*a20*a00 - 3*a21*a03*a20*a00
705
+ - 1/2*a21*a12*a11*a00 + 9/2*a30*a03*a11*a00 + a21^2*a02*a00
706
+ - 3*a30*a12*a02*a00,
707
+ 1/864*a11^6 - 1/72*a20*a11^4*a02 + 1/18*a20^2*a11^2*a02^2
708
+ - 2/27*a20^3*a02^3 + 1/24*a03*a20*a11^3*a10 - 1/72*a12*a11^4*a10
709
+ - 1/6*a03*a20^2*a11*a02*a10 + 1/36*a12*a20*a11^2*a02*a10
710
+ + 1/24*a21*a11^3*a02*a10 + 1/9*a12*a20^2*a02^2*a10
711
+ - 1/6*a21*a20*a11*a02^2*a10 - 1/12*a30*a11^2*a02^2*a10
712
+ + 1/3*a30*a20*a02^3*a10 + 1/4*a03^2*a20^2*a10^2
713
+ - 1/6*a12*a03*a20*a11*a10^2 + 1/18*a12^2*a11^2*a10^2
714
+ - 1/12*a21*a03*a11^2*a10^2 + 1/9*a12^2*a20*a02*a10^2
715
+ - 1/6*a21*a03*a20*a02*a10^2 - 1/6*a21*a12*a11*a02*a10^2
716
+ + a30*a03*a11*a02*a10^2 + 1/4*a21^2*a02^2*a10^2
717
+ - 2/3*a30*a12*a02^2*a10^2 - 2/27*a12^3*a10^3 + 1/3*a21*a12*a03*a10^3
718
+ - a30*a03^2*a10^3 - 1/12*a03*a20^2*a11^2*a01 + 1/24*a12*a20*a11^3*a01
719
+ - 1/72*a21*a11^4*a01 + 1/3*a03*a20^3*a02*a01 - 1/6*a12*a20^2*a11*a02*a01
720
+ + 1/36*a21*a20*a11^2*a02*a01 + 1/24*a30*a11^3*a02*a01
721
+ + 1/9*a21*a20^2*a02^2*a01 - 1/6*a30*a20*a11*a02^2*a01
722
+ - 1/6*a12*a03*a20^2*a10*a01 - 1/6*a12^2*a20*a11*a10*a01
723
+ + 5/6*a21*a03*a20*a11*a10*a01 + 1/36*a21*a12*a11^2*a10*a01
724
+ - 3/4*a30*a03*a11^2*a10*a01 + 1/18*a21*a12*a20*a02*a10*a01
725
+ - 3/2*a30*a03*a20*a02*a10*a01 - 1/6*a21^2*a11*a02*a10*a01
726
+ + 5/6*a30*a12*a11*a02*a10*a01 - 1/6*a30*a21*a02^2*a10*a01
727
+ + 1/9*a21*a12^2*a10^2*a01 - 2/3*a21^2*a03*a10^2*a01
728
+ + a30*a12*a03*a10^2*a01 + 1/4*a12^2*a20^2*a01^2
729
+ - 2/3*a21*a03*a20^2*a01^2 - 1/6*a21*a12*a20*a11*a01^2
730
+ + a30*a03*a20*a11*a01^2 + 1/18*a21^2*a11^2*a01^2
731
+ - 1/12*a30*a12*a11^2*a01^2 + 1/9*a21^2*a20*a02*a01^2
732
+ - 1/6*a30*a12*a20*a02*a01^2 - 1/6*a30*a21*a11*a02*a01^2
733
+ + 1/4*a30^2*a02^2*a01^2 + 1/9*a21^2*a12*a10*a01^2
734
+ - 2/3*a30*a12^2*a10*a01^2 + a30*a21*a03*a10*a01^2
735
+ - 2/27*a21^3*a01^3 + 1/3*a30*a21*a12*a01^3 - a30^2*a03*a01^3
736
+ - a03^2*a20^3*a00 + a12*a03*a20^2*a11*a00 - 1/12*a12^2*a20*a11^2*a00
737
+ - 3/4*a21*a03*a20*a11^2*a00 + 1/24*a21*a12*a11^3*a00
738
+ + 5/8*a30*a03*a11^3*a00 - 2/3*a12^2*a20^2*a02*a00
739
+ + a21*a03*a20^2*a02*a00 + 5/6*a21*a12*a20*a11*a02*a00
740
+ - 3/2*a30*a03*a20*a11*a02*a00 - 1/12*a21^2*a11^2*a02*a00
741
+ - 3/4*a30*a12*a11^2*a02*a00 - 2/3*a21^2*a20*a02^2*a00
742
+ + a30*a12*a20*a02^2*a00 + a30*a21*a11*a02^2*a00
743
+ - a30^2*a02^3*a00 + 1/3*a12^3*a20*a10*a00
744
+ - 3/2*a21*a12*a03*a20*a10*a00 + 9/2*a30*a03^2*a20*a10*a00
745
+ - 1/6*a21*a12^2*a11*a10*a00 + a21^2*a03*a11*a10*a00
746
+ - 3/2*a30*a12*a03*a11*a10*a00 - 1/6*a21^2*a12*a02*a10*a00
747
+ + a30*a12^2*a02*a10*a00 - 3/2*a30*a21*a03*a02*a10*a00
748
+ - 1/6*a21*a12^2*a20*a01*a00 + a21^2*a03*a20*a01*a00
749
+ - 3/2*a30*a12*a03*a20*a01*a00 - 1/6*a21^2*a12*a11*a01*a00
750
+ + a30*a12^2*a11*a01*a00 - 3/2*a30*a21*a03*a11*a01*a00
751
+ + 1/3*a21^3*a02*a01*a00 - 3/2*a30*a21*a12*a02*a01*a00
752
+ + 9/2*a30^2*a03*a02*a01*a00 + 1/4*a21^2*a12^2*a00^2
753
+ - a30*a12^3*a00^2 - a21^3*a03*a00^2
754
+ + 9/2*a30*a21*a12*a03*a00^2 - 27/4*a30^2*a03^2*a00^2)
755
+ """
756
+ x, y, z = _check_polynomial_P2(polynomial, variables)
757
+ cubic = invariant_theory.ternary_cubic(polynomial, x, y, z)
758
+ F = polynomial.base_ring()
759
+ S = cubic.S_invariant()
760
+ T = cubic.T_invariant()
761
+ return (27 * S, -27 / F(4) * T)
762
+
763
+
764
+ ######################################################################
765
+ #
766
+ # Weierstrass form of biquadric in P1 x P1
767
+ #
768
+ ######################################################################
769
+ def _check_polynomial_P1xP1(biquadric, variables):
770
+ """
771
+ Check the polynomial is weighted homogeneous in standard variables.
772
+
773
+ INPUT:
774
+
775
+ - ``biquadric`` -- the input polynomial; see
776
+ :func:`WeierstrassForm` for details
777
+
778
+ - ``variables`` -- the variables or ``None``; see
779
+ :func:`WeierstrassForm` for details
780
+
781
+ OUTPUT:
782
+
783
+ This functions returns ``variables``, potentially guessed from the
784
+ polynomial ring. A :exc:`ValueError` is raised if the polynomial is
785
+ not homogeneous.
786
+
787
+ EXAMPLES::
788
+
789
+ sage: from sage.schemes.toric.weierstrass import _check_polynomial_P1xP1
790
+ sage: R.<x0,x1,y0,y1> = QQ[]
791
+ sage: biquadric = (x0^2*y0^2 + x0*x1*y0^2*2 + x1^2*y0^2*3
792
+ ....: + x0^2*y0*y1*4 + x0*x1*y0*y1*5 + x1^2*y0*y1*6
793
+ ....: + x0^2*y1^2*7 + x0*x1*y1^2*8)
794
+ sage: _check_polynomial_P1xP1(biquadric, [x0,x1,y0,y1])
795
+ [x0, x1, y0, y1]
796
+ sage: _check_polynomial_P1xP1(biquadric, None)
797
+ (x0, x1, y0, y1)
798
+ sage: _check_polynomial_P1xP1(biquadric.subs(y0=1, y1=1), None)
799
+ [x0, None, x1, None]
800
+ sage: _check_polynomial_P1xP1(biquadric, [x0,y0,x1,y1])
801
+ Traceback (most recent call last):
802
+ ...
803
+ ValueError: the polynomial is not homogeneous with weights (1, 1, 0, 0)
804
+ """
805
+ if variables is None:
806
+ variables = biquadric.variables()
807
+ if len(variables) == 4:
808
+ _check_homogeneity(biquadric, variables, (1, 1, 0, 0), 2)
809
+ _check_homogeneity(biquadric, variables, (0, 0, 1, 1), 2)
810
+ elif len(variables) == 2:
811
+ variables = [variables[0], None, variables[1], None]
812
+ else:
813
+ raise ValueError(f'need two or four variables, got {variables}')
814
+ return variables
815
+
816
+
817
+ ######################################################################
818
+ def _partial_discriminant(quadric, y0, y1=None):
819
+ """
820
+ Return the partial discriminant wrt. `(y_0, y_1)`.
821
+
822
+ INPUT:
823
+
824
+ - ``quadric`` -- a biquadric
825
+
826
+ - ``y_0``, ``y_1`` -- the variables of the quadric; the ``y_1``
827
+ variable can be omitted if the quadric is inhomogeneous
828
+
829
+ OUTPUT: a plane quartic in ``x0``, ``x1``
830
+
831
+ EXAMPLES::
832
+
833
+ sage: R.<x0,x1,y0,y1,a00,a10,a20,a01,a11,a21,a02,a12,a22> = QQ[]
834
+ sage: biquadric = (x0^2*y0^2*a00 + x0*x1*y0^2*a10 + x1^2*y0^2*a20
835
+ ....: + x0^2*y0*y1*a01 + x0*x1*y0*y1*a11 + x1^2*y0*y1*a21
836
+ ....: + x0^2*y1^2*a02 + x0*x1*y1^2*a12 + x1^2*y1^2*a22)
837
+ sage: from sage.schemes.toric.weierstrass import _partial_discriminant
838
+ sage: _partial_discriminant(biquadric, y0, y1)
839
+ x0^4*a01^2 + 2*x0^3*x1*a01*a11 + x0^2*x1^2*a11^2
840
+ + 2*x0^2*x1^2*a01*a21 + 2*x0*x1^3*a11*a21 + x1^4*a21^2
841
+ - 4*x0^4*a00*a02 - 4*x0^3*x1*a10*a02 - 4*x0^2*x1^2*a20*a02
842
+ - 4*x0^3*x1*a00*a12 - 4*x0^2*x1^2*a10*a12 - 4*x0*x1^3*a20*a12
843
+ - 4*x0^2*x1^2*a00*a22 - 4*x0*x1^3*a10*a22 - 4*x1^4*a20*a22
844
+ sage: _partial_discriminant(biquadric, x0, x1)
845
+ y0^4*a10^2 - 4*y0^4*a00*a20 - 4*y0^3*y1*a20*a01
846
+ + 2*y0^3*y1*a10*a11 + y0^2*y1^2*a11^2 - 4*y0^3*y1*a00*a21
847
+ - 4*y0^2*y1^2*a01*a21 - 4*y0^2*y1^2*a20*a02 - 4*y0*y1^3*a21*a02
848
+ + 2*y0^2*y1^2*a10*a12 + 2*y0*y1^3*a11*a12 + y1^4*a12^2
849
+ - 4*y0^2*y1^2*a00*a22 - 4*y0*y1^3*a01*a22 - 4*y1^4*a02*a22
850
+ """
851
+ if y1 is None:
852
+ monomials = (quadric.parent().one(), y0, y0**2)
853
+ variables = [y0]
854
+ else:
855
+ monomials = (y1**2, y0 * y1, y0**2)
856
+ variables = [y0, y1]
857
+ c = _extract_coefficients(quadric, monomials, variables)
858
+ return c[1]**2 - 4*c[0]*c[2]
859
+
860
+
861
+ ######################################################################
862
+ def WeierstrassForm_P1xP1(biquadric, variables=None):
863
+ r"""
864
+ Bring a biquadric into Weierstrass form.
865
+
866
+ Input/output is the same as :func:`WeierstrassForm`, except that
867
+ the input polynomial must be a standard biquadric in `\mathbb{P}^2`,
868
+
869
+ .. MATH::
870
+
871
+ \begin{split}
872
+ p(x,y) =&\;
873
+ a_{40} x^4 +
874
+ a_{30} x^3 +
875
+ a_{21} x^2 y +
876
+ a_{20} x^2 +
877
+ \\ &\;
878
+ a_{11} x y +
879
+ a_{02} y^2 +
880
+ a_{10} x +
881
+ a_{01} y +
882
+ a_{00}
883
+ \end{split}
884
+
885
+ EXAMPLES::
886
+
887
+ sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P1xP1
888
+ sage: R.<x0,x1,y0,y1> = QQ[]
889
+ sage: biquadric = (x0^2*y0^2 + x0*x1*y0^2*2 + x1^2*y0^2*3
890
+ ....: + x0^2*y0*y1*4 + x0*x1*y0*y1*5 + x1^2*y0*y1*6
891
+ ....: + x0^2*y1^2*7 + x0*x1*y1^2*8)
892
+ sage: WeierstrassForm_P1xP1(biquadric, [x0, x1, y0, y1])
893
+ (1581/16, -3529/32)
894
+
895
+ Since there is no `x_1^2 y_1^2` term in ``biquadric``, we can
896
+ dehomogenize it and get a cubic::
897
+
898
+ sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2
899
+ sage: WeierstrassForm_P2(biquadric(x0=1,y0=1))
900
+ (1581/16, -3529/32)
901
+
902
+ TESTS::
903
+
904
+ sage: R.<x0,x1,y0,y1,a00,a10,a20,a01,a11,a21,a02,a12,a22> = QQ[]
905
+ sage: biquadric = (x0^2*y0^2*a00 + x0*x1*y0^2*a10 + x1^2*y0^2*a20
906
+ ....: + x0^2*y0*y1*a01 + x0*x1*y0*y1*a11 + x1^2*y0*y1*a21
907
+ ....: + x0^2*y1^2*a02 + x0*x1*y1^2*a12)
908
+ sage: WeierstrassForm_P1xP1(biquadric, [x0, x1, y0, y1])
909
+ (-1/48*a11^4 + 1/6*a01*a11^2*a21 - 1/3*a01^2*a21^2
910
+ + 1/6*a20*a11^2*a02 + 1/3*a20*a01*a21*a02 - 1/2*a10*a11*a21*a02
911
+ + a00*a21^2*a02 - 1/3*a20^2*a02^2 - 1/2*a20*a01*a11*a12
912
+ + 1/6*a10*a11^2*a12 + 1/3*a10*a01*a21*a12 - 1/2*a00*a11*a21*a12
913
+ + 1/3*a10*a20*a02*a12 - 1/3*a10^2*a12^2 + a00*a20*a12^2, 1/864*a11^6
914
+ - 1/72*a01*a11^4*a21 + 1/18*a01^2*a11^2*a21^2 - 2/27*a01^3*a21^3
915
+ - 1/72*a20*a11^4*a02 + 1/36*a20*a01*a11^2*a21*a02
916
+ + 1/24*a10*a11^3*a21*a02 + 1/9*a20*a01^2*a21^2*a02
917
+ - 1/6*a10*a01*a11*a21^2*a02 - 1/12*a00*a11^2*a21^2*a02
918
+ + 1/3*a00*a01*a21^3*a02 + 1/18*a20^2*a11^2*a02^2
919
+ + 1/9*a20^2*a01*a21*a02^2 - 1/6*a10*a20*a11*a21*a02^2
920
+ + 1/4*a10^2*a21^2*a02^2 - 2/3*a00*a20*a21^2*a02^2 - 2/27*a20^3*a02^3
921
+ + 1/24*a20*a01*a11^3*a12 - 1/72*a10*a11^4*a12
922
+ - 1/6*a20*a01^2*a11*a21*a12 + 1/36*a10*a01*a11^2*a21*a12
923
+ + 1/24*a00*a11^3*a21*a12 + 1/9*a10*a01^2*a21^2*a12
924
+ - 1/6*a00*a01*a11*a21^2*a12 - 1/6*a20^2*a01*a11*a02*a12
925
+ + 1/36*a10*a20*a11^2*a02*a12 + 1/18*a10*a20*a01*a21*a02*a12
926
+ - 1/6*a10^2*a11*a21*a02*a12 + 5/6*a00*a20*a11*a21*a02*a12
927
+ - 1/6*a00*a10*a21^2*a02*a12 + 1/9*a10*a20^2*a02^2*a12
928
+ + 1/4*a20^2*a01^2*a12^2 - 1/6*a10*a20*a01*a11*a12^2
929
+ + 1/18*a10^2*a11^2*a12^2 - 1/12*a00*a20*a11^2*a12^2
930
+ + 1/9*a10^2*a01*a21*a12^2 - 1/6*a00*a20*a01*a21*a12^2
931
+ - 1/6*a00*a10*a11*a21*a12^2 + 1/4*a00^2*a21^2*a12^2
932
+ + 1/9*a10^2*a20*a02*a12^2 - 2/3*a00*a20^2*a02*a12^2
933
+ - 2/27*a10^3*a12^3 + 1/3*a00*a10*a20*a12^3)
934
+
935
+ sage: _ == WeierstrassForm_P1xP1(biquadric.subs(x1=1, y1=1), [x0, y0])
936
+ True
937
+ """
938
+ x, y, s, t = _check_polynomial_P1xP1(biquadric, variables)
939
+ delta = _partial_discriminant(biquadric, s, t)
940
+ Q = invariant_theory.binary_quartic(delta, x, y)
941
+ g2 = Q.EisensteinD()
942
+ g3 = -Q.EisensteinE()
943
+ return (-g2 / 4, -g3 / 4)
944
+
945
+
946
+ ######################################################################
947
+ #
948
+ # Weierstrass form of anticanonical hypersurface in WP2[1,1,2]
949
+ #
950
+ ######################################################################
951
+ def _check_polynomial_P2_112(polynomial, variables):
952
+ """
953
+ Check the polynomial is weighted homogeneous in standard variables.
954
+
955
+ INPUT:
956
+
957
+ - ``polynomial`` -- the input polynomial; see
958
+ :func:`WeierstrassForm` for details
959
+
960
+ - ``variables`` -- the variables or ``None``; see
961
+ :func:`WeierstrassForm` for details
962
+
963
+ OUTPUT:
964
+
965
+ This functions returns ``variables``, potentially guessed from the
966
+ polynomial ring. A :exc:`ValueError` is raised if the polynomial is
967
+ not homogeneous.
968
+
969
+ EXAMPLES::
970
+
971
+ sage: from sage.schemes.toric.weierstrass import _check_polynomial_P2_112
972
+ sage: R.<x,y,z,t> = QQ[]
973
+ sage: polynomial = z^4*t^2 + x*z^3*t^2 + x^2*z^2*t^2 + x^3*z*t^2 + \
974
+ ....: x^4*t^2 + y*z^2*t + x*y*z*t + x^2*y*t + y^2
975
+ sage: _check_polynomial_P2_112(polynomial, [x,y,z,t])
976
+ (x, y, z, t)
977
+ sage: _check_polynomial_P2_112(polynomial, None)
978
+ (x, y, z, t)
979
+ sage: _check_polynomial_P2_112(polynomial(z=1, t=1), None)
980
+ (x, y, None, None)
981
+ sage: _check_polynomial_P2_112(polynomial, [x,y,t,z])
982
+ Traceback (most recent call last):
983
+ ...
984
+ ValueError: the polynomial is not homogeneous with weights (1, 0, 1, -2)
985
+ """
986
+ if variables is None:
987
+ variables = polynomial.variables()
988
+ else:
989
+ variables = tuple(variables)
990
+ if len(variables) == 4:
991
+ _check_homogeneity(polynomial, variables, (1, 0, 1, -2), 0)
992
+ _check_homogeneity(polynomial, variables, (0, 1, 0, 1), 2)
993
+ elif len(variables) == 2:
994
+ variables = (variables[0], variables[1], None, None)
995
+ else:
996
+ raise ValueError(f'need two or four variables, got {variables}')
997
+ return variables
998
+
999
+
1000
+ def WeierstrassForm_P2_112(polynomial, variables=None):
1001
+ r"""
1002
+ Bring an anticanonical hypersurface in `\mathbb{P}^2[1,1,2]` into Weierstrass form.
1003
+
1004
+ Input/output is the same as :func:`WeierstrassForm`, except that
1005
+ the input polynomial must be a standard anticanonical hypersurface
1006
+ in weighted projective space `\mathbb{P}^2[1,1,2]`:
1007
+
1008
+ .. MATH::
1009
+
1010
+ \begin{split}
1011
+ p(x,y) =&\;
1012
+ a_{40} x^4 +
1013
+ a_{30} x^3 +
1014
+ a_{21} x^2 y +
1015
+ a_{20} x^2 +
1016
+ \\ &\;
1017
+ a_{11} x y +
1018
+ a_{02} y^2 +
1019
+ a_{10} x +
1020
+ a_{01} y +
1021
+ a_{00}
1022
+ \end{split}
1023
+
1024
+ EXAMPLES::
1025
+
1026
+ sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2_112
1027
+ sage: fan = Fan(rays=[(1,0),(0,1),(-1,-2),(0,-1)],
1028
+ ....: cones=[[0,1],[1,2],[2,3],[3,0]])
1029
+ sage: P112.<x,y,z,t> = ToricVariety(fan)
1030
+ sage: (-P112.K()).sections_monomials()
1031
+ (z^4*t^2, x*z^3*t^2, x^2*z^2*t^2, x^3*z*t^2,
1032
+ x^4*t^2, y*z^2*t, x*y*z*t, x^2*y*t, y^2)
1033
+ sage: WeierstrassForm_P2_112(sum(_), [x,y,z,t])
1034
+ (-97/48, 17/864)
1035
+
1036
+ TESTS::
1037
+
1038
+ sage: R.<x,y,z,t,a40,a30,a20,a10,a00,a21,a11,a01,a02> = QQ[]
1039
+ sage: p = (a40*x^4*t^2 + a30*x^3*z*t^2 + a20*x^2*z^2*t^2 + a10*x*z^3*t^2 +
1040
+ ....: a00*z^4*t^2 + a21*x^2*y*t + a11*x*y*z*t + a01*y*z^2*t + a02*y^2)
1041
+ sage: WeierstrassForm_P2_112(p, [x,y,z,t])
1042
+ (-1/48*a11^4 + 1/6*a21*a11^2*a01 - 1/3*a21^2*a01^2 + a00*a21^2*a02
1043
+ - 1/2*a10*a21*a11*a02 + 1/6*a20*a11^2*a02 + 1/3*a20*a21*a01*a02
1044
+ - 1/2*a30*a11*a01*a02 + a40*a01^2*a02 - 1/3*a20^2*a02^2 + a30*a10*a02^2
1045
+ - 4*a40*a00*a02^2, 1/864*a11^6 - 1/72*a21*a11^4*a01
1046
+ + 1/18*a21^2*a11^2*a01^2 - 2/27*a21^3*a01^3 - 1/12*a00*a21^2*a11^2*a02
1047
+ + 1/24*a10*a21*a11^3*a02 - 1/72*a20*a11^4*a02 + 1/3*a00*a21^3*a01*a02
1048
+ - 1/6*a10*a21^2*a11*a01*a02 + 1/36*a20*a21*a11^2*a01*a02
1049
+ + 1/24*a30*a11^3*a01*a02 + 1/9*a20*a21^2*a01^2*a02
1050
+ - 1/6*a30*a21*a11*a01^2*a02 - 1/12*a40*a11^2*a01^2*a02
1051
+ + 1/3*a40*a21*a01^3*a02 + 1/4*a10^2*a21^2*a02^2
1052
+ - 2/3*a20*a00*a21^2*a02^2 - 1/6*a20*a10*a21*a11*a02^2
1053
+ + a30*a00*a21*a11*a02^2 + 1/18*a20^2*a11^2*a02^2
1054
+ - 1/12*a30*a10*a11^2*a02^2 - 2/3*a40*a00*a11^2*a02^2
1055
+ + 1/9*a20^2*a21*a01*a02^2 - 1/6*a30*a10*a21*a01*a02^2
1056
+ - 4/3*a40*a00*a21*a01*a02^2 - 1/6*a30*a20*a11*a01*a02^2
1057
+ + a40*a10*a11*a01*a02^2 + 1/4*a30^2*a01^2*a02^2
1058
+ - 2/3*a40*a20*a01^2*a02^2 - 2/27*a20^3*a02^3
1059
+ + 1/3*a30*a20*a10*a02^3 - a40*a10^2*a02^3 - a30^2*a00*a02^3
1060
+ + 8/3*a40*a20*a00*a02^3)
1061
+
1062
+ sage: _ == WeierstrassForm_P2_112(p.subs(z=1, t=1), [x,y])
1063
+ True
1064
+
1065
+ sage: cubic = p.subs(a40=0)
1066
+ sage: a,b = WeierstrassForm_P2_112(cubic, [x,y,z,t])
1067
+ sage: a = a.subs(t=1, z=1)
1068
+ sage: b = b.subs(t=1, z=1)
1069
+ sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2
1070
+ sage: (a,b) == WeierstrassForm_P2(cubic.subs(t=1, z=1), [x,y])
1071
+ True
1072
+ """
1073
+ x, y, z, t = _check_polynomial_P2_112(polynomial, variables)
1074
+ delta = _partial_discriminant(polynomial, y, t)
1075
+ Q = invariant_theory.binary_quartic(delta, x, z)
1076
+ g2 = Q.EisensteinD()
1077
+ g3 = -Q.EisensteinE()
1078
+ return (-g2 / 4, -g3 / 4)