passagemath-polyhedra 10.6.37__cp314-cp314-musllinux_1_2_x86_64.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.
- passagemath_polyhedra/__init__.py +3 -0
- passagemath_polyhedra-10.6.37.dist-info/METADATA +367 -0
- passagemath_polyhedra-10.6.37.dist-info/METADATA.bak +369 -0
- passagemath_polyhedra-10.6.37.dist-info/RECORD +209 -0
- passagemath_polyhedra-10.6.37.dist-info/WHEEL +5 -0
- passagemath_polyhedra-10.6.37.dist-info/top_level.txt +3 -0
- passagemath_polyhedra.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_polyhedra.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
- passagemath_polyhedra.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
- sage/all__sagemath_polyhedra.py +50 -0
- sage/game_theory/all.py +8 -0
- sage/game_theory/catalog.py +6 -0
- sage/game_theory/catalog_normal_form_games.py +923 -0
- sage/game_theory/cooperative_game.py +844 -0
- sage/game_theory/matching_game.py +1181 -0
- sage/game_theory/normal_form_game.py +2697 -0
- sage/game_theory/parser.py +275 -0
- sage/geometry/all__sagemath_polyhedra.py +22 -0
- sage/geometry/cone.py +6940 -0
- sage/geometry/cone_catalog.py +847 -0
- sage/geometry/cone_critical_angles.py +1027 -0
- sage/geometry/convex_set.py +1119 -0
- sage/geometry/fan.py +3743 -0
- sage/geometry/fan_isomorphism.py +389 -0
- sage/geometry/fan_morphism.py +1884 -0
- sage/geometry/hasse_diagram.py +202 -0
- sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
- sage/geometry/hyperplane_arrangement/all.py +1 -0
- sage/geometry/hyperplane_arrangement/arrangement.py +3905 -0
- sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
- sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
- sage/geometry/hyperplane_arrangement/library.py +825 -0
- sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
- sage/geometry/hyperplane_arrangement/plot.py +520 -0
- sage/geometry/integral_points.py +35 -0
- sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/integral_points_generic_dense.pyx +7 -0
- sage/geometry/lattice_polytope.py +5894 -0
- sage/geometry/linear_expression.py +773 -0
- sage/geometry/newton_polygon.py +767 -0
- sage/geometry/point_collection.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/point_collection.pyx +1008 -0
- sage/geometry/polyhedral_complex.py +2616 -0
- sage/geometry/polyhedron/all.py +8 -0
- sage/geometry/polyhedron/backend_cdd.py +460 -0
- sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
- sage/geometry/polyhedron/backend_field.py +347 -0
- sage/geometry/polyhedron/backend_normaliz.py +2503 -0
- sage/geometry/polyhedron/backend_number_field.py +168 -0
- sage/geometry/polyhedron/backend_polymake.py +765 -0
- sage/geometry/polyhedron/backend_ppl.py +582 -0
- sage/geometry/polyhedron/base.py +1206 -0
- sage/geometry/polyhedron/base0.py +1444 -0
- sage/geometry/polyhedron/base1.py +886 -0
- sage/geometry/polyhedron/base2.py +812 -0
- sage/geometry/polyhedron/base3.py +1845 -0
- sage/geometry/polyhedron/base4.py +1262 -0
- sage/geometry/polyhedron/base5.py +2700 -0
- sage/geometry/polyhedron/base6.py +1741 -0
- sage/geometry/polyhedron/base7.py +997 -0
- sage/geometry/polyhedron/base_QQ.py +1258 -0
- sage/geometry/polyhedron/base_RDF.py +98 -0
- sage/geometry/polyhedron/base_ZZ.py +934 -0
- sage/geometry/polyhedron/base_mutable.py +215 -0
- sage/geometry/polyhedron/base_number_field.py +122 -0
- sage/geometry/polyhedron/cdd_file_format.py +155 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
- sage/geometry/polyhedron/constructor.py +773 -0
- sage/geometry/polyhedron/double_description.py +753 -0
- sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
- sage/geometry/polyhedron/face.py +1060 -0
- sage/geometry/polyhedron/generating_function.py +1810 -0
- sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
- sage/geometry/polyhedron/library.py +3502 -0
- sage/geometry/polyhedron/misc.py +121 -0
- sage/geometry/polyhedron/modules/all.py +1 -0
- sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
- sage/geometry/polyhedron/palp_database.py +447 -0
- sage/geometry/polyhedron/parent.py +1279 -0
- sage/geometry/polyhedron/plot.py +1986 -0
- sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
- sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
- sage/geometry/polyhedron/representation.py +1723 -0
- sage/geometry/pseudolines.py +515 -0
- sage/geometry/relative_interior.py +445 -0
- sage/geometry/toric_plotter.py +1103 -0
- sage/geometry/triangulation/all.py +2 -0
- sage/geometry/triangulation/base.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/triangulation/base.pyx +963 -0
- sage/geometry/triangulation/data.h +147 -0
- sage/geometry/triangulation/data.pxd +4 -0
- sage/geometry/triangulation/element.py +914 -0
- sage/geometry/triangulation/functions.h +10 -0
- sage/geometry/triangulation/functions.pxd +4 -0
- sage/geometry/triangulation/point_configuration.py +2256 -0
- sage/geometry/triangulation/triangulations.h +49 -0
- sage/geometry/triangulation/triangulations.pxd +7 -0
- sage/geometry/voronoi_diagram.py +319 -0
- sage/interfaces/all__sagemath_polyhedra.py +1 -0
- sage/interfaces/polymake.py +2028 -0
- sage/numerical/all.py +13 -0
- sage/numerical/all__sagemath_polyhedra.py +11 -0
- sage/numerical/backends/all.py +1 -0
- sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
- sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_backend.pyx +1006 -0
- sage/numerical/backends/cvxopt_backend_test.py +19 -0
- sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxpy_backend.pxd +41 -0
- sage/numerical/backends/cvxpy_backend.pyx +934 -0
- sage/numerical/backends/cvxpy_backend_test.py +13 -0
- sage/numerical/backends/generic_backend_test.py +24 -0
- sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/interactivelp_backend.pxd +36 -0
- sage/numerical/backends/interactivelp_backend.pyx +1231 -0
- sage/numerical/backends/interactivelp_backend_test.py +12 -0
- sage/numerical/backends/logging_backend.py +391 -0
- sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
- sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
- sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/ppl_backend.pyx +1126 -0
- sage/numerical/backends/ppl_backend_test.py +13 -0
- sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/scip_backend.pxd +22 -0
- sage/numerical/backends/scip_backend.pyx +1289 -0
- sage/numerical/backends/scip_backend_test.py +13 -0
- sage/numerical/interactive_simplex_method.py +5338 -0
- sage/numerical/knapsack.py +665 -0
- sage/numerical/linear_functions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/linear_functions.pxd +31 -0
- sage/numerical/linear_functions.pyx +1648 -0
- sage/numerical/linear_tensor.py +470 -0
- sage/numerical/linear_tensor_constraints.py +448 -0
- sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/sdp.pxd +39 -0
- sage/numerical/sdp.pyx +1433 -0
- sage/rings/all__sagemath_polyhedra.py +3 -0
- sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
- sage/rings/polynomial/omega.py +982 -0
- sage/schemes/all__sagemath_polyhedra.py +2 -0
- sage/schemes/toric/all.py +10 -0
- sage/schemes/toric/chow_group.py +1248 -0
- sage/schemes/toric/divisor.py +2082 -0
- sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-musl.so +0 -0
- sage/schemes/toric/divisor_class.pyx +322 -0
- sage/schemes/toric/fano_variety.py +1606 -0
- sage/schemes/toric/homset.py +650 -0
- sage/schemes/toric/ideal.py +451 -0
- sage/schemes/toric/library.py +1322 -0
- sage/schemes/toric/morphism.py +1958 -0
- sage/schemes/toric/points.py +1032 -0
- sage/schemes/toric/sheaf/all.py +1 -0
- sage/schemes/toric/sheaf/constructor.py +302 -0
- sage/schemes/toric/sheaf/klyachko.py +921 -0
- sage/schemes/toric/toric_subscheme.py +905 -0
- sage/schemes/toric/variety.py +3460 -0
- sage/schemes/toric/weierstrass.py +1078 -0
- sage/schemes/toric/weierstrass_covering.py +457 -0
- sage/schemes/toric/weierstrass_higher.py +288 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
- 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)
|