passagemath-polyhedra 10.6.31rc3__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.

Potentially problematic release.


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

Files changed (208) hide show
  1. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +367 -0
  2. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +369 -0
  3. passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +208 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.libs/libgcc_s-0cd532bd.so.1 +0 -0
  7. passagemath_polyhedra.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  8. passagemath_polyhedra.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
  9. passagemath_polyhedra.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
  10. sage/all__sagemath_polyhedra.py +50 -0
  11. sage/game_theory/all.py +8 -0
  12. sage/game_theory/catalog.py +6 -0
  13. sage/game_theory/catalog_normal_form_games.py +923 -0
  14. sage/game_theory/cooperative_game.py +844 -0
  15. sage/game_theory/matching_game.py +1181 -0
  16. sage/game_theory/normal_form_game.py +2697 -0
  17. sage/game_theory/parser.py +275 -0
  18. sage/geometry/all__sagemath_polyhedra.py +22 -0
  19. sage/geometry/cone.py +6940 -0
  20. sage/geometry/cone_catalog.py +847 -0
  21. sage/geometry/cone_critical_angles.py +1027 -0
  22. sage/geometry/convex_set.py +1119 -0
  23. sage/geometry/fan.py +3743 -0
  24. sage/geometry/fan_isomorphism.py +389 -0
  25. sage/geometry/fan_morphism.py +1884 -0
  26. sage/geometry/hasse_diagram.py +202 -0
  27. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  28. sage/geometry/hyperplane_arrangement/all.py +1 -0
  29. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  30. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  31. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  32. sage/geometry/hyperplane_arrangement/library.py +825 -0
  33. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  34. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  35. sage/geometry/integral_points.py +35 -0
  36. sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
  37. sage/geometry/integral_points_generic_dense.pyx +7 -0
  38. sage/geometry/lattice_polytope.py +5894 -0
  39. sage/geometry/linear_expression.py +773 -0
  40. sage/geometry/newton_polygon.py +767 -0
  41. sage/geometry/point_collection.cpython-314-x86_64-linux-musl.so +0 -0
  42. sage/geometry/point_collection.pyx +1008 -0
  43. sage/geometry/polyhedral_complex.py +2616 -0
  44. sage/geometry/polyhedron/all.py +8 -0
  45. sage/geometry/polyhedron/backend_cdd.py +460 -0
  46. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  47. sage/geometry/polyhedron/backend_field.py +347 -0
  48. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  49. sage/geometry/polyhedron/backend_number_field.py +168 -0
  50. sage/geometry/polyhedron/backend_polymake.py +765 -0
  51. sage/geometry/polyhedron/backend_ppl.py +582 -0
  52. sage/geometry/polyhedron/base.py +1206 -0
  53. sage/geometry/polyhedron/base0.py +1444 -0
  54. sage/geometry/polyhedron/base1.py +886 -0
  55. sage/geometry/polyhedron/base2.py +812 -0
  56. sage/geometry/polyhedron/base3.py +1845 -0
  57. sage/geometry/polyhedron/base4.py +1262 -0
  58. sage/geometry/polyhedron/base5.py +2700 -0
  59. sage/geometry/polyhedron/base6.py +1741 -0
  60. sage/geometry/polyhedron/base7.py +997 -0
  61. sage/geometry/polyhedron/base_QQ.py +1258 -0
  62. sage/geometry/polyhedron/base_RDF.py +98 -0
  63. sage/geometry/polyhedron/base_ZZ.py +934 -0
  64. sage/geometry/polyhedron/base_mutable.py +215 -0
  65. sage/geometry/polyhedron/base_number_field.py +122 -0
  66. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-musl.so +0 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-musl.so +0 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-musl.so +0 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-musl.so +0 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  87. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-musl.so +0 -0
  88. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  89. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  90. sage/geometry/polyhedron/constructor.py +773 -0
  91. sage/geometry/polyhedron/double_description.py +753 -0
  92. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  93. sage/geometry/polyhedron/face.py +1060 -0
  94. sage/geometry/polyhedron/generating_function.py +1810 -0
  95. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  96. sage/geometry/polyhedron/library.py +3502 -0
  97. sage/geometry/polyhedron/misc.py +121 -0
  98. sage/geometry/polyhedron/modules/all.py +1 -0
  99. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  100. sage/geometry/polyhedron/palp_database.py +447 -0
  101. sage/geometry/polyhedron/parent.py +1279 -0
  102. sage/geometry/polyhedron/plot.py +1986 -0
  103. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  104. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  105. sage/geometry/polyhedron/representation.py +1723 -0
  106. sage/geometry/pseudolines.py +515 -0
  107. sage/geometry/relative_interior.py +445 -0
  108. sage/geometry/toric_plotter.py +1103 -0
  109. sage/geometry/triangulation/all.py +2 -0
  110. sage/geometry/triangulation/base.cpython-314-x86_64-linux-musl.so +0 -0
  111. sage/geometry/triangulation/base.pyx +963 -0
  112. sage/geometry/triangulation/data.h +147 -0
  113. sage/geometry/triangulation/data.pxd +4 -0
  114. sage/geometry/triangulation/element.py +914 -0
  115. sage/geometry/triangulation/functions.h +10 -0
  116. sage/geometry/triangulation/functions.pxd +4 -0
  117. sage/geometry/triangulation/point_configuration.py +2256 -0
  118. sage/geometry/triangulation/triangulations.h +49 -0
  119. sage/geometry/triangulation/triangulations.pxd +7 -0
  120. sage/geometry/voronoi_diagram.py +319 -0
  121. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  122. sage/interfaces/polymake.py +2028 -0
  123. sage/numerical/all.py +13 -0
  124. sage/numerical/all__sagemath_polyhedra.py +11 -0
  125. sage/numerical/backends/all.py +1 -0
  126. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  127. sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  129. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  130. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  131. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  132. sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-musl.so +0 -0
  133. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  134. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  135. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  136. sage/numerical/backends/generic_backend_test.py +24 -0
  137. sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  138. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  139. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  140. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  141. sage/numerical/backends/logging_backend.py +391 -0
  142. sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  143. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  144. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  145. sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-musl.so +0 -0
  146. sage/numerical/backends/ppl_backend.pyx +1126 -0
  147. sage/numerical/backends/ppl_backend_test.py +13 -0
  148. sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-musl.so +0 -0
  149. sage/numerical/backends/scip_backend.pxd +22 -0
  150. sage/numerical/backends/scip_backend.pyx +1289 -0
  151. sage/numerical/backends/scip_backend_test.py +13 -0
  152. sage/numerical/interactive_simplex_method.py +5338 -0
  153. sage/numerical/knapsack.py +665 -0
  154. sage/numerical/linear_functions.cpython-314-x86_64-linux-musl.so +0 -0
  155. sage/numerical/linear_functions.pxd +31 -0
  156. sage/numerical/linear_functions.pyx +1648 -0
  157. sage/numerical/linear_tensor.py +470 -0
  158. sage/numerical/linear_tensor_constraints.py +448 -0
  159. sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-musl.so +0 -0
  160. sage/numerical/linear_tensor_element.pxd +6 -0
  161. sage/numerical/linear_tensor_element.pyx +459 -0
  162. sage/numerical/mip.cpython-314-x86_64-linux-musl.so +0 -0
  163. sage/numerical/mip.pxd +40 -0
  164. sage/numerical/mip.pyx +3667 -0
  165. sage/numerical/sdp.cpython-314-x86_64-linux-musl.so +0 -0
  166. sage/numerical/sdp.pxd +39 -0
  167. sage/numerical/sdp.pyx +1433 -0
  168. sage/rings/all__sagemath_polyhedra.py +3 -0
  169. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  170. sage/rings/polynomial/omega.py +982 -0
  171. sage/schemes/all__sagemath_polyhedra.py +2 -0
  172. sage/schemes/toric/all.py +10 -0
  173. sage/schemes/toric/chow_group.py +1248 -0
  174. sage/schemes/toric/divisor.py +2082 -0
  175. sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-musl.so +0 -0
  176. sage/schemes/toric/divisor_class.pyx +322 -0
  177. sage/schemes/toric/fano_variety.py +1606 -0
  178. sage/schemes/toric/homset.py +650 -0
  179. sage/schemes/toric/ideal.py +451 -0
  180. sage/schemes/toric/library.py +1322 -0
  181. sage/schemes/toric/morphism.py +1958 -0
  182. sage/schemes/toric/points.py +1032 -0
  183. sage/schemes/toric/sheaf/all.py +1 -0
  184. sage/schemes/toric/sheaf/constructor.py +302 -0
  185. sage/schemes/toric/sheaf/klyachko.py +921 -0
  186. sage/schemes/toric/toric_subscheme.py +905 -0
  187. sage/schemes/toric/variety.py +3460 -0
  188. sage/schemes/toric/weierstrass.py +1078 -0
  189. sage/schemes/toric/weierstrass_covering.py +457 -0
  190. sage/schemes/toric/weierstrass_higher.py +288 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  193. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  194. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  195. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  204. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  205. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  206. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  207. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  208. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
@@ -0,0 +1,3460 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ # sage.doctest: needs sage.geometry.polyhedron sage.graphs
3
+ r"""
4
+ Toric varieties
5
+
6
+ This module provides support for (normal) toric varieties, corresponding to
7
+ :class:`rational polyhedral fans <sage.geometry.fan.RationalPolyhedralFan>`.
8
+ See also :mod:`~sage.schemes.toric.fano_variety` for a more
9
+ restrictive class of (weak) Fano toric varieties.
10
+
11
+ An **excellent reference on toric varieties** is the book "Toric
12
+ Varieties" by David A. Cox, John B. Little, and Hal Schenck
13
+ [CLS2011]_.
14
+
15
+ The interface to this module is provided through functions
16
+ :func:`AffineToricVariety` and :func:`ToricVariety`, although you may
17
+ also be interested in :func:`normalize_names`.
18
+
19
+ .. NOTE::
20
+
21
+ We do NOT build "general toric varieties" from affine toric varieties.
22
+ Instead, we are using the quotient representation of toric varieties with
23
+ the homogeneous coordinate ring (a.k.a. Cox's ring or the total coordinate
24
+ ring). This description works best for simplicial fans of the full
25
+ dimension.
26
+
27
+ AUTHORS:
28
+
29
+ - Andrey Novoseltsev (2010-05-17): initial version.
30
+
31
+ - Volker Braun (2010-07-24): Cohomology and characteristic classes added.
32
+
33
+ EXAMPLES:
34
+
35
+ We start with constructing the affine plane as an affine toric variety. First,
36
+ we need to have a corresponding cone::
37
+
38
+ sage: quadrant = Cone([(1,0), (0,1)])
39
+
40
+ If you don't care about variable names and the base field, that's all we need
41
+ for now::
42
+
43
+ sage: A2 = AffineToricVariety(quadrant)
44
+ sage: A2
45
+ 2-d affine toric variety
46
+ sage: origin = A2(0,0)
47
+ sage: origin
48
+ [0 : 0]
49
+
50
+ Only affine toric varieties have points whose (homogeneous) coordinates
51
+ are all zero. ::
52
+
53
+ sage: parent(origin)
54
+ Set of rational points of 2-d affine toric variety
55
+
56
+ As you can see, by default toric varieties live over the field of rational
57
+ numbers::
58
+
59
+ sage: A2.base_ring()
60
+ Rational Field
61
+
62
+ While usually toric varieties are considered over the field of complex
63
+ numbers, for computational purposes it is more convenient to work with fields
64
+ that have exact representation on computers. You can also always do ::
65
+
66
+ sage: C2 = AffineToricVariety(quadrant, base_field=CC)
67
+ sage: C2.base_ring()
68
+ Complex Field with 53 bits of precision
69
+ sage: C2(1, 2+i) # needs sage.symbolic
70
+ [1.00000000000000 : 2.00000000000000 + 1.00000000000000*I]
71
+
72
+ or even ::
73
+
74
+ sage: F = CC["a, b"].fraction_field()
75
+ sage: F.inject_variables()
76
+ Defining a, b
77
+ sage: A2 = AffineToricVariety(quadrant, base_field=F)
78
+ sage: A2(a,b)
79
+ [a : b]
80
+
81
+ OK, if you need to work only with affine spaces,
82
+ :func:`~sage.schemes.affine.affine_space.AffineSpace` may be a better way to
83
+ construct them. Our next example is the product of two projective lines
84
+ realized as the toric variety associated to the
85
+ :func:`face fan <sage.geometry.fan.FaceFan>` of the "diamond"::
86
+
87
+ sage: diamond = lattice_polytope.cross_polytope(2)
88
+ sage: diamond.vertices()
89
+ M( 1, 0), M( 0, 1),
90
+ M(-1, 0), M( 0, -1)
91
+ in 2-d lattice M
92
+ sage: fan = FaceFan(diamond)
93
+ sage: P1xP1 = ToricVariety(fan)
94
+ sage: P1xP1
95
+ 2-d toric variety covered by 4 affine patches
96
+ sage: P1xP1.fan().rays()
97
+ M( 1, 0), M( 0, 1),
98
+ M(-1, 0), M( 0, -1)
99
+ in 2-d lattice M
100
+ sage: P1xP1.gens()
101
+ (z0, z1, z2, z3)
102
+
103
+ We got four coordinates - two for each of the projective lines, but their
104
+ names are perhaps not very well chosen. Let's make `(x,y)` to be coordinates
105
+ on the first line and `(s,t)` on the second one::
106
+
107
+ sage: P1xP1 = ToricVariety(fan, coordinate_names="x s y t")
108
+ sage: P1xP1.gens()
109
+ (x, s, y, t)
110
+
111
+ Now, if we want to define subschemes of this variety, the defining polynomials
112
+ must be homogeneous in each of these pairs::
113
+
114
+ sage: P1xP1.inject_variables()
115
+ Defining x, s, y, t
116
+ sage: P1xP1.subscheme(x)
117
+ Closed subscheme of 2-d toric variety covered by 4 affine patches defined by:
118
+ x
119
+ sage: P1xP1.subscheme(x^2 + y^2)
120
+ Closed subscheme of 2-d toric variety covered by 4 affine patches defined by:
121
+ x^2 + y^2
122
+ sage: P1xP1.subscheme(x^2 + s^2)
123
+ Traceback (most recent call last):
124
+ ...
125
+ ValueError: x^2 + s^2 is not homogeneous
126
+ on 2-d toric variety covered by 4 affine patches
127
+ sage: P1xP1.subscheme([x^2*s^2 + x*y*t^2 + y^2*t^2, s^3 + t^3])
128
+ Closed subscheme of 2-d toric variety covered by 4 affine patches defined by:
129
+ x^2*s^2 + x*y*t^2 + y^2*t^2,
130
+ s^3 + t^3
131
+
132
+ While we don't build toric varieties from affine toric varieties, we still can
133
+ access the "building pieces"::
134
+
135
+ sage: patch = P1xP1.affine_patch(2)
136
+ sage: patch
137
+ 2-d affine toric variety
138
+ sage: patch.fan().rays()
139
+ M(1, 0),
140
+ M(0, 1)
141
+ in 2-d lattice M
142
+ sage: patch.embedding_morphism()
143
+ Scheme morphism:
144
+ From: 2-d affine toric variety
145
+ To: 2-d toric variety covered by 4 affine patches
146
+ Defn: Defined on coordinates by sending [x : s] to [x : s : 1 : 1]
147
+
148
+ The patch above was specifically chosen to coincide with our representation of
149
+ the affine plane before, but you can get the other three patches as well.
150
+ (While any cone of a fan will correspond to an affine toric variety, the main
151
+ interest is usually in the generating fans as "the biggest" affine
152
+ subvarieties, and these are precisely the patches that you can get from
153
+ :meth:`~ToricVariety_field.affine_patch`.)
154
+
155
+ All two-dimensional toric varieties are "quite nice" because any
156
+ two-dimensional cone is generated by exactly two rays. From the point of view
157
+ of the corresponding toric varieties, this means that they have at worst
158
+ quotient singularities::
159
+
160
+ sage: P1xP1.is_orbifold()
161
+ True
162
+ sage: P1xP1.is_smooth()
163
+ True
164
+ sage: TV = ToricVariety(NormalFan(diamond))
165
+ sage: TV.fan().rays()
166
+ N( 1, 1), N( 1, -1),
167
+ N(-1, -1), N(-1, 1)
168
+ in 2-d lattice N
169
+ sage: TV.is_orbifold()
170
+ True
171
+ sage: TV.is_smooth()
172
+ False
173
+
174
+ In higher dimensions worse things can happen::
175
+
176
+ sage: TV3 = ToricVariety(NormalFan(lattice_polytope.cross_polytope(3)))
177
+ sage: TV3.fan().rays()
178
+ N( 1, -1, -1), N( 1, 1, -1), N( 1, 1, 1), N( 1, -1, 1),
179
+ N(-1, -1, 1), N(-1, -1, -1), N(-1, 1, -1), N(-1, 1, 1)
180
+ in 3-d lattice N
181
+ sage: TV3.is_orbifold()
182
+ False
183
+
184
+ Fortunately, we can perform a (partial) resolution::
185
+
186
+ sage: TV3_res = TV3.resolve_to_orbifold()
187
+ sage: TV3_res.is_orbifold()
188
+ True
189
+ sage: TV3_res.fan().ngenerating_cones()
190
+ 12
191
+ sage: TV3.fan().ngenerating_cones()
192
+ 6
193
+
194
+ In this example we had to double the number of affine patches. The result is
195
+ still singular::
196
+
197
+ sage: TV3_res.is_smooth()
198
+ False
199
+
200
+ You can resolve it further using :meth:`~ToricVariety_field.resolve` method,
201
+ but (at least for now) you will have to specify which rays should be inserted
202
+ into the fan. See also
203
+ :func:`~sage.schemes.toric.fano_variety.CPRFanoToricVariety`,
204
+ which can construct some other "nice partial resolutions."
205
+
206
+ The intersection theory on toric varieties is very well understood,
207
+ and there are explicit algorithms to compute many quantities of
208
+ interest. The most important tools are the :class:`cohomology ring
209
+ <CohomologyRing>` and the :mod:`Chow group
210
+ <sage.schemes.toric.chow_group>`. For `d`-dimensional compact
211
+ toric varieties with at most orbifold singularities, the rational
212
+ cohomology ring `H^*(X,\QQ)` and the rational Chow ring `A^*(X,\QQ) =
213
+ A_{d-*}(X)\otimes \QQ` are isomorphic except for a doubling in
214
+ degree. More precisely, the Chow group has the same rank
215
+
216
+ .. MATH::
217
+
218
+ A_{d-k}(X) \otimes \QQ \simeq H^{2k}(X,\QQ)
219
+
220
+ and the intersection in of Chow cycles matches the cup product in
221
+ cohomology.
222
+
223
+ In this case, you should work with the cohomology ring description
224
+ because it is much faster. For example, here is a weighted projective
225
+ space with a curve of `\ZZ_3`-orbifold singularities::
226
+
227
+ sage: P4_11133 = toric_varieties.P4_11133()
228
+ sage: P4_11133.is_smooth(), P4_11133.is_orbifold()
229
+ (False, True)
230
+ sage: cone = P4_11133.fan(3)[9]
231
+ sage: cone.is_smooth(), cone.is_simplicial()
232
+ (False, True)
233
+ sage: HH = P4_11133.cohomology_ring(); HH
234
+ Rational cohomology ring of a 4-d CPR-Fano toric variety covered by 5 affine patches
235
+ sage: P4_11133.cohomology_basis() # needs sage.libs.singular
236
+ (([1],), ([z4],), ([z4^2],), ([z4^3],), ([z4^4],))
237
+
238
+ Every cone defines a torus orbit closure, and hence a (co)homology class::
239
+
240
+ sage: # needs sage.libs.singular
241
+ sage: HH.gens()
242
+ ([3*z4], [3*z4], [z4], [z4], [z4])
243
+ sage: list(map(HH, P4_11133.fan(1)))
244
+ [[3*z4], [3*z4], [z4], [z4], [z4]]
245
+ sage: list(map(HH, P4_11133.fan(4)))
246
+ [[9*z4^4], [9*z4^4], [9*z4^4], [9*z4^4], [9*z4^4]]
247
+ sage: HH(cone)
248
+ [3*z4^3]
249
+
250
+ We can compute intersection numbers by integrating top-dimensional
251
+ cohomology classes::
252
+
253
+ sage: # needs sage.libs.singular
254
+ sage: D = P4_11133.divisor(0)
255
+ sage: HH(D)
256
+ [3*z4]
257
+ sage: P4_11133.integrate(HH(D)^4)
258
+ 9
259
+ sage: P4_11133.integrate(HH(D) * HH(cone))
260
+ 1
261
+
262
+ Although computationally less efficient, we can do the same
263
+ computations with the rational Chow group::
264
+
265
+ sage: AA = P4_11133.Chow_group(QQ)
266
+ sage: list(map(AA, P4_11133.fan(1))) # long time (5s on sage.math, 2012)
267
+ [( 0 | 0 | 0 | 3 | 0 ), ( 0 | 0 | 0 | 3 | 0 ),
268
+ ( 0 | 0 | 0 | 1 | 0 ), ( 0 | 0 | 0 | 1 | 0 ), ( 0 | 0 | 0 | 1 | 0 )]
269
+ sage: list(map(AA, P4_11133.fan(4))) # long time (5s on sage.math, 2012)
270
+ [( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 ),
271
+ ( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 )]
272
+ sage: AA(cone).intersection_with_divisor(D) # long time (4s on sage.math, 2013) # needs sage.libs.singular
273
+ ( 1 | 0 | 0 | 0 | 0 )
274
+ sage: AA(cone).intersection_with_divisor(D).count_points() # long time # needs sage.libs.singular
275
+ 1
276
+
277
+ The real advantage of the Chow group is that
278
+
279
+ * it works just as well over `\ZZ`, so torsion information is also
280
+ easily available, and
281
+
282
+ * its combinatorial description also works over worse-than-orbifold
283
+ singularities. By contrast, the cohomology groups can become very
284
+ complicated to compute in this case, and one usually only has a
285
+ spectral sequence but no toric algorithm.
286
+
287
+ Below you will find detailed descriptions of available functions. If you are
288
+ familiar with toric geometry, you will likely see that many important objects
289
+ and operations are unavailable. However, this module is under active
290
+ development and hopefully will improve in future releases of Sage. If there
291
+ are some particular features that you would like to see implemented ASAP,
292
+ please consider reporting them to the Sage Development Team or even
293
+ implementing them on your own as a patch for inclusion!
294
+ """
295
+
296
+ # ****************************************************************************
297
+ # Copyright (C) 2010 Volker Braun <vbraun.name@gmail.com>
298
+ # Copyright (C) 2010 Andrey Novoseltsev <novoselt@gmail.com>
299
+ # Copyright (C) 2010 William Stein <wstein@gmail.com>
300
+ #
301
+ # This program is free software: you can redistribute it and/or modify
302
+ # it under the terms of the GNU General Public License as published by
303
+ # the Free Software Foundation, either version 2 of the License, or
304
+ # (at your option) any later version.
305
+ # https://www.gnu.org/licenses/
306
+ # ****************************************************************************
307
+
308
+ import sys
309
+
310
+ import sage.geometry.abc
311
+
312
+ from sage.categories.fields import Fields
313
+ from sage.geometry.cone import Cone
314
+ from sage.geometry.fan import Fan
315
+ from sage.misc.cachefunc import cached_method
316
+ from sage.misc.latex import latex
317
+ from sage.misc.lazy_import import lazy_import
318
+ from sage.misc.misc_c import prod
319
+ from sage.modules.free_module_element import vector
320
+ from sage.rings.integer_ring import ZZ
321
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
322
+ from sage.rings.quotient_ring import QuotientRing_generic
323
+ from sage.rings.quotient_ring_element import QuotientRingElement
324
+ from sage.rings.rational_field import QQ
325
+ from sage.schemes.affine.affine_space import AffineSpace
326
+ from sage.schemes.generic.ambient_space import AmbientSpace
327
+ from sage.schemes.toric.homset import SchemeHomset_points_toric_field
328
+ from sage.structure.category_object import certify_names
329
+ from sage.structure.unique_representation import UniqueRepresentation
330
+
331
+ lazy_import("sage.functions.all", "factorial")
332
+
333
+ _Fields = Fields()
334
+
335
+
336
+ # Default prefix for indexed coordinates
337
+ DEFAULT_PREFIX = "z"
338
+
339
+
340
+ def is_ToricVariety(x):
341
+ r"""
342
+ Check if ``x`` is a toric variety.
343
+
344
+ INPUT:
345
+
346
+ - ``x`` -- anything
347
+
348
+ OUTPUT:
349
+
350
+ - ``True`` if ``x`` is a :class:`toric variety <ToricVariety_field>` and
351
+ ``False`` otherwise.
352
+
353
+ .. NOTE::
354
+
355
+ While projective spaces are toric varieties mathematically, they are
356
+ not toric varieties in Sage due to efficiency considerations, so this
357
+ function will return ``False``.
358
+
359
+ EXAMPLES::
360
+
361
+ sage: from sage.schemes.toric.variety import is_ToricVariety
362
+ sage: is_ToricVariety(1)
363
+ doctest:warning...
364
+ DeprecationWarning: The function is_ToricVariety is deprecated; use 'isinstance(..., ToricVariety_field)' instead.
365
+ See https://github.com/sagemath/sage/issues/38022 for details.
366
+ False
367
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
368
+ sage: P = ToricVariety(fan)
369
+ sage: P
370
+ 2-d toric variety covered by 4 affine patches
371
+ sage: is_ToricVariety(P)
372
+ True
373
+ sage: is_ToricVariety(ProjectiveSpace(2))
374
+ False
375
+ """
376
+ from sage.misc.superseded import deprecation
377
+ deprecation(38022, "The function is_ToricVariety is deprecated; use 'isinstance(..., ToricVariety_field)' instead.")
378
+ return isinstance(x, ToricVariety_field)
379
+
380
+
381
+ def ToricVariety(fan,
382
+ coordinate_names=None,
383
+ names=None,
384
+ coordinate_indices=None,
385
+ base_ring=QQ, base_field=None):
386
+ r"""
387
+ Construct a toric variety.
388
+
389
+ INPUT:
390
+
391
+ - ``fan`` -- :class:`rational polyhedral fan
392
+ <sage.geometry.fan.RationalPolyhedralFan>`
393
+
394
+ - ``coordinate_names`` -- names of variables for the coordinate ring, see
395
+ :func:`normalize_names` for acceptable formats. If not given, indexed
396
+ variable names will be created automatically.
397
+
398
+ - ``names`` -- an alias of ``coordinate_names`` for internal
399
+ use. You may specify either ``names`` or ``coordinate_names``,
400
+ but not both.
401
+
402
+ - ``coordinate_indices`` -- list of integers, indices for indexed
403
+ variables. If not given, the index of each variable will coincide with
404
+ the index of the corresponding ray of the fan.
405
+
406
+ - ``base_ring`` -- base ring of the toric variety (default:
407
+ `\QQ`); must be a field
408
+
409
+ - ``base_field`` -- alias for ``base_ring``; takes precedence if
410
+ both are specified
411
+
412
+ OUTPUT: a :class:`toric variety <ToricVariety_field>`
413
+
414
+ EXAMPLES:
415
+
416
+ We will create the product of two projective lines::
417
+
418
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
419
+ sage: fan.rays()
420
+ M( 1, 0), M( 0, 1),
421
+ M(-1, 0), M( 0, -1)
422
+ in 2-d lattice M
423
+ sage: P1xP1 = ToricVariety(fan)
424
+ sage: P1xP1.gens()
425
+ (z0, z1, z2, z3)
426
+
427
+ Let's create some points::
428
+
429
+ sage: P1xP1(1,1,1,1)
430
+ [1 : 1 : 1 : 1]
431
+ sage: P1xP1(0,1,1,1)
432
+ [0 : 1 : 1 : 1]
433
+ sage: P1xP1(0,1,0,1)
434
+ Traceback (most recent call last):
435
+ ...
436
+ TypeError: coordinates (0, 1, 0, 1) are in the exceptional set
437
+
438
+ We cannot set to zero both coordinates of the same projective line!
439
+
440
+ Let's change the names of the variables. We have to re-create our toric
441
+ variety::
442
+
443
+ sage: P1xP1 = ToricVariety(fan, "x s y t")
444
+ sage: P1xP1.gens()
445
+ (x, s, y, t)
446
+
447
+ Now `(x, y)` correspond to one line and `(s, t)` to the other one. ::
448
+
449
+ sage: P1xP1.inject_variables()
450
+ Defining x, s, y, t
451
+ sage: P1xP1.subscheme(x*s - y*t)
452
+ Closed subscheme of 2-d toric variety covered by 4 affine patches defined by:
453
+ x*s - y*t
454
+
455
+ Here is a shorthand for defining the toric variety and homogeneous
456
+ coordinates in one go::
457
+
458
+ sage: P1xP1.<a,b,c,d> = ToricVariety(fan)
459
+ sage: (a^2+b^2) * (c+d)
460
+ a^2*c + b^2*c + a^2*d + b^2*d
461
+ """
462
+ if base_field is not None:
463
+ base_ring = base_field
464
+ if names is not None:
465
+ if coordinate_names is not None:
466
+ raise ValueError('you must not specify both coordinate_names and names')
467
+ coordinate_names = names
468
+ if base_ring not in _Fields:
469
+ raise TypeError("need a field to construct a toric variety; got %s"
470
+ % base_ring)
471
+ return ToricVariety_field(fan, coordinate_names, coordinate_indices,
472
+ base_ring)
473
+
474
+
475
+ def AffineToricVariety(cone, *args, **kwds):
476
+ r"""
477
+ Construct an affine toric variety.
478
+
479
+ INPUT:
480
+
481
+ - ``cone`` -- :class:`strictly convex rational polyhedral cone
482
+ <sage.geometry.cone.ConvexRationalPolyhedralCone>`
483
+
484
+ This cone will be used to construct a :class:`rational polyhedral fan
485
+ <sage.geometry.fan.RationalPolyhedralFan>`, which will be passed to
486
+ :func:`ToricVariety` with the rest of positional and keyword arguments.
487
+
488
+ OUTPUT: a :class:`toric variety <ToricVariety_field>`
489
+
490
+ .. NOTE::
491
+
492
+ The generating rays of the fan of this variety are guaranteed to be
493
+ listed in the same order as the rays of the original cone.
494
+
495
+ EXAMPLES:
496
+
497
+ We will create the affine plane as an affine toric variety::
498
+
499
+ sage: quadrant = Cone([(1,0), (0,1)])
500
+ sage: A2 = AffineToricVariety(quadrant)
501
+ sage: origin = A2(0,0)
502
+ sage: origin
503
+ [0 : 0]
504
+ sage: parent(origin)
505
+ Set of rational points of 2-d affine toric variety
506
+
507
+ Only affine toric varieties have points whose (homogeneous) coordinates
508
+ are all zero.
509
+ """
510
+ if not cone.is_strictly_convex():
511
+ raise ValueError("affine toric varieties are defined for strictly "
512
+ "convex cones only")
513
+ # We make sure that Fan constructor does not meddle with the order of
514
+ # rays, this is very important for affine patches construction
515
+ fan = Fan([tuple(range(cone.nrays()))], cone.rays(),
516
+ check=False, normalize=False)
517
+ return ToricVariety(fan, *args, **kwds)
518
+
519
+
520
+ class ToricVariety_field(AmbientSpace):
521
+ r"""
522
+ Construct a toric variety associated to a rational polyhedral fan.
523
+
524
+ .. WARNING::
525
+
526
+ This class does not perform any checks of correctness of input. Use
527
+ :func:`ToricVariety` and :func:`AffineToricVariety` to construct toric
528
+ varieties.
529
+
530
+ INPUT:
531
+
532
+ - ``fan`` -- :class:`rational polyhedral fan
533
+ <sage.geometry.fan.RationalPolyhedralFan>`
534
+
535
+ - ``coordinate_names`` -- names of variables, see :func:`normalize_names`
536
+ for acceptable formats. If ``None``, indexed variable names will be
537
+ created automatically.
538
+
539
+ - ``coordinate_indices`` -- list of integers, indices for indexed
540
+ variables. If ``None``, the index of each variable will coincide with
541
+ the index of the corresponding ray of the fan.
542
+
543
+ - ``base_field`` -- base field of the toric variety
544
+
545
+ OUTPUT: a :class:`toric variety <ToricVariety_field>`
546
+
547
+ TESTS::
548
+
549
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
550
+ sage: P1xP1 = ToricVariety(fan)
551
+ """
552
+
553
+ def __init__(self, fan, coordinate_names, coordinate_indices, base_field):
554
+ r"""
555
+ See :class:`ToricVariety_field` for documentation.
556
+
557
+ TESTS::
558
+
559
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
560
+ sage: P1xP1 = ToricVariety(fan)
561
+ """
562
+ self._fan = fan
563
+ super().__init__(fan.lattice_dim(), base_field)
564
+ self._torus_factor_dim = fan.lattice_dim() - fan.dim()
565
+ coordinate_names = normalize_names(coordinate_names,
566
+ fan.nrays() + self._torus_factor_dim, DEFAULT_PREFIX,
567
+ coordinate_indices, return_prefix=True)
568
+ # Save the prefix for use in resolutions
569
+ self._coordinate_prefix = coordinate_names.pop()
570
+ self._assign_names(names=coordinate_names, normalize=False)
571
+
572
+ def __eq__(self, right):
573
+ r"""
574
+ Check equality of ``self`` and ``right``.
575
+
576
+ INPUT:
577
+
578
+ - ``right`` -- anything
579
+
580
+ OUTPUT: boolean
581
+
582
+ ``True`` if and only if ``right`` is of the same type as ``self``,
583
+ their fans are the same, names of variables are the same and
584
+ stored in the same order, and base fields are the same.
585
+
586
+ TESTS::
587
+
588
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
589
+ sage: P1xP1 = ToricVariety(fan)
590
+ sage: P1xP1a = ToricVariety(fan, "x s y t")
591
+ sage: P1xP1b = ToricVariety(fan)
592
+
593
+ sage: P1xP1 == P1xP1a
594
+ False
595
+ sage: P1xP1a == P1xP1
596
+ False
597
+ sage: P1xP1 == P1xP1b
598
+ True
599
+ sage: P1xP1 is P1xP1b
600
+ False
601
+ """
602
+ if not isinstance(right, ToricVariety_field):
603
+ return False
604
+ return (self.fan() == right.fan() and
605
+ self.variable_names() == right.variable_names() and
606
+ self.base_ring() == right.base_ring())
607
+
608
+ def __ne__(self, other):
609
+ """
610
+ Check not-equality of ``self`` and ``other``.
611
+
612
+ INPUT:
613
+
614
+ - ``other`` -- anything
615
+
616
+ OUTPUT: boolean
617
+
618
+ ``True`` if and only if ``other`` is of the same type as ``self``,
619
+ their fans are the same, names of variables are the same and
620
+ stored in the same order, and base fields are the same.
621
+
622
+ TESTS::
623
+
624
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
625
+ sage: P1xP1 = ToricVariety(fan)
626
+ sage: P1xP1a = ToricVariety(fan, "x s y t")
627
+ sage: P1xP1b = ToricVariety(fan)
628
+
629
+ sage: P1xP1 != P1xP1a
630
+ True
631
+ sage: P1xP1a != P1xP1
632
+ True
633
+ sage: P1xP1 != P1xP1b
634
+ False
635
+ """
636
+ return not (self == other)
637
+
638
+ def __hash__(self):
639
+ """
640
+ Return the hash of ``self``.
641
+
642
+ EXAMPLES::
643
+
644
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
645
+ sage: P1xP1 = ToricVariety(fan)
646
+ sage: h1 = hash(P1xP1)
647
+ sage: h2 = hash(P1xP1)
648
+ sage: h3 = hash(toric_varieties.P(2))
649
+ sage: h1 == h2 and h1 != h3
650
+ True
651
+ """
652
+ return hash((self.fan(), self.variable_names(), self.base_ring()))
653
+
654
+ def _an_element_(self):
655
+ r"""
656
+ Construct an element of ``self``.
657
+
658
+ This function is needed (in particular) for the test framework.
659
+
660
+ OUTPUT: a point of ``self`` with coordinates [1 : 2: ... : n]
661
+
662
+ TESTS::
663
+
664
+ sage: P1xP1 = toric_varieties.P1xP1()
665
+ sage: P1xP1._an_element_()
666
+ [1 : 2 : 3 : 4]
667
+ """
668
+ return self(list(range(1, self.ngens() + 1)))
669
+
670
+ def _check_satisfies_equations(self, coordinates):
671
+ r"""
672
+ Check if ``coordinates`` define a valid point of ``self``.
673
+
674
+ INPUT:
675
+
676
+ - ``coordinates`` -- list of elements of the base field of ``self``
677
+
678
+ OUTPUT:
679
+
680
+ - ``True`` if ``coordinates`` do define a valid point of ``self``,
681
+ otherwise a :exc:`TypeError` or :exc:`ValueError` exception
682
+ is raised.
683
+
684
+ TESTS::
685
+
686
+ sage: P1xP1 = toric_varieties.P1xP1()
687
+ sage: P1xP1._check_satisfies_equations([1,1,1,1])
688
+ True
689
+ sage: P1xP1._check_satisfies_equations([0,1,0,1])
690
+ True
691
+ sage: P1xP1._check_satisfies_equations([0,0,1,1])
692
+ Traceback (most recent call last):
693
+ ...
694
+ TypeError: coordinates (0, 0, 1, 1)
695
+ are in the exceptional set
696
+ sage: P1xP1._check_satisfies_equations([1,1,1])
697
+ Traceback (most recent call last):
698
+ ...
699
+ TypeError: coordinates (1, 1, 1) must have 4 components
700
+ sage: P1xP1._check_satisfies_equations(1)
701
+ Traceback (most recent call last):
702
+ ...
703
+ TypeError: 1 cannot be used as coordinates; use a list or a tuple
704
+ sage: P1xP1._check_satisfies_equations([1,1,1,P1xP1.fan()])
705
+ Traceback (most recent call last):
706
+ ...
707
+ TypeError: coordinate Rational polyhedral fan
708
+ in 2-d lattice N is not an element of Rational Field
709
+ """
710
+ try:
711
+ coordinates = tuple(coordinates)
712
+ except TypeError:
713
+ raise TypeError("%s cannot be used as coordinates; "
714
+ "use a list or a tuple" % coordinates)
715
+ n = self.ngens()
716
+ if len(coordinates) != n:
717
+ raise TypeError("coordinates %s must have %d components"
718
+ % (coordinates, n))
719
+ base_field = self.base_ring()
720
+ for coordinate in coordinates:
721
+ if coordinate not in base_field:
722
+ raise TypeError("coordinate %s is not an element of %s"
723
+ % (coordinate, base_field))
724
+ zero_positions = {position
725
+ for position, coordinate in enumerate(coordinates)
726
+ if coordinate == 0}
727
+ if not zero_positions:
728
+ return True
729
+ for i in range(n - self._torus_factor_dim, n):
730
+ if i in zero_positions:
731
+ raise ValueError("coordinates on the torus factor cannot be "
732
+ "zero; got %s" % str(coordinates))
733
+ if len(zero_positions) == 1:
734
+ return True
735
+ fan = self.fan()
736
+ possible_charts = set(fan._ray_to_cones(zero_positions.pop()))
737
+ for i in zero_positions:
738
+ possible_charts.intersection_update(fan._ray_to_cones(i))
739
+ if possible_charts:
740
+ return True # All zeros are inside one generating cone
741
+ raise TypeError(f"coordinates {coordinates} are in the exceptional set")
742
+
743
+ def _point_homset(self, *args, **kwds):
744
+ r"""
745
+ Construct a Hom-set for ``self``.
746
+
747
+ INPUT:
748
+
749
+ - same as for
750
+ :class:`~sage.schemes.generic.homset.SchemeHomset_points_toric_field`.
751
+
752
+ OUTPUT:
753
+
754
+ -
755
+ :class:`~sage.schemes.generic.homset.SchemeHomset_points_toric_field`.
756
+
757
+ TESTS::
758
+
759
+ sage: P1xA1 = toric_varieties.P1xA1()
760
+ sage: P1xA1._point_homset(Spec(QQ), P1xA1)
761
+ Set of rational points of 2-d toric variety
762
+ covered by 2 affine patches
763
+ """
764
+ return SchemeHomset_points_toric_field(*args, **kwds)
765
+
766
+ def _latex_(self):
767
+ r"""
768
+ Return a LaTeX representation of ``self``.
769
+
770
+ OUTPUT: string
771
+
772
+ TESTS::
773
+
774
+ sage: P1xA1 = toric_varieties.P1xA1()
775
+ sage: print(P1xA1._latex_())
776
+ \mathbb{X}_{\Sigma^{2}}
777
+ """
778
+ return r"\mathbb{X}_{%s}" % latex(self.fan())
779
+
780
+ def _latex_generic_point(self, coordinates=None):
781
+ r"""
782
+ Return a LaTeX representation of a point of ``self``.
783
+
784
+ INPUT:
785
+
786
+ - ``coordinates`` -- list of coordinates of a point of ``self``;
787
+ if not given, names of coordinates of ``self`` will be used
788
+
789
+ OUTPUT: string
790
+
791
+ EXAMPLES::
792
+
793
+ sage: P1xA1 = toric_varieties.P1xA1()
794
+ sage: print(P1xA1._latex_generic_point())
795
+ \left[s : t : z\right]
796
+ sage: print(P1xA1._latex_generic_point([1,2,3]))
797
+ \left[1 : 2 : 3\right]
798
+ """
799
+ if coordinates is None:
800
+ coordinates = self.gens()
801
+ return r"\left[%s\right]" % (" : ".join(str(latex(coord))
802
+ for coord in coordinates))
803
+
804
+ def _point(self, *args, **kwds):
805
+ r"""
806
+ Construct a point of ``self``.
807
+
808
+ INPUT:
809
+
810
+ - same as for
811
+ :class:`~sage.schemes.generic.morphism.SchemeMorphism_point_toric_field`.
812
+
813
+ OUTPUT: :class:`~sage.schemes.generic.morphism.SchemeMorphism_point_toric_field`
814
+
815
+ TESTS::
816
+
817
+ sage: P1xP1 = toric_varieties.P1xP1()
818
+ sage: P1xP1._point(P1xP1, [1,2,3,4])
819
+ [1 : 2 : 3 : 4]
820
+ """
821
+ from sage.schemes.toric.morphism import SchemeMorphism_point_toric_field
822
+ return SchemeMorphism_point_toric_field(*args, **kwds)
823
+
824
+ def _homset(self, *args, **kwds):
825
+ r"""
826
+ Return the homset between two toric varieties.
827
+
828
+ INPUT:
829
+
830
+ Same as :class:`sage.schemes.generic.homset.SchemeHomset_generic`.
831
+
832
+ OUTPUT: a :class:`sage.schemes.toric.homset.SchemeHomset_toric_variety`
833
+
834
+ EXAMPLES::
835
+
836
+ sage: P1xP1 = toric_varieties.P1xP1()
837
+ sage: P1 = toric_varieties.P1()
838
+ sage: hom_set = P1xP1.Hom(P1); hom_set
839
+ Set of morphisms
840
+ From: 2-d CPR-Fano toric variety covered by 4 affine patches
841
+ To: 1-d CPR-Fano toric variety covered by 2 affine patches
842
+ sage: type(hom_set)
843
+ <class 'sage.schemes.toric.homset.SchemeHomset_toric_variety_with_category'>
844
+
845
+ This is also the Hom-set for algebraic subschemes of toric varieties::
846
+
847
+ sage: P1xP1.inject_variables()
848
+ Defining s, t, x, y
849
+ sage: P1 = P1xP1.subscheme(s - t)
850
+ sage: hom_set = P1xP1.Hom(P1)
851
+ sage: hom_set([s,s,x,y])
852
+ Scheme morphism:
853
+ From: 2-d CPR-Fano toric variety covered by 4 affine patches
854
+ To: Closed subscheme of 2-d CPR-Fano toric variety covered by 4 affine patches defined by:
855
+ s - t
856
+ Defn: Defined on coordinates by sending [s : t : x : y] to
857
+ [s : s : x : y]
858
+
859
+ sage: # needs sage.libs.singular
860
+ sage: hom_set = P1.Hom(P1)
861
+ sage: sbar, tbar, xbar, ybar = P1.coordinate_ring().gens()
862
+ sage: hom_set([sbar,sbar,xbar,ybar])
863
+ Scheme endomorphism of Closed subscheme of 2-d CPR-Fano toric
864
+ variety covered by 4 affine patches defined by:
865
+ s - t
866
+ Defn: Defined on coordinates by sending [s : t : x : y] to
867
+ [t : t : x : y]
868
+ """
869
+ from sage.schemes.toric.homset import SchemeHomset_toric_variety
870
+ return SchemeHomset_toric_variety(*args, **kwds)
871
+
872
+ def _repr_(self):
873
+ r"""
874
+ Return a string representation of ``self``.
875
+
876
+ OUTPUT: string
877
+
878
+ TESTS::
879
+
880
+ sage: P1xA1 = toric_varieties.P1xA1()
881
+ sage: print(P1xA1._repr_())
882
+ 2-d toric variety covered by 2 affine patches
883
+ """
884
+ result = "%d-d" % self.dimension_relative()
885
+ if self.fan().ngenerating_cones() == 1:
886
+ result += " affine toric variety"
887
+ else:
888
+ result += (" toric variety covered by %d affine patches"
889
+ % self.fan().ngenerating_cones())
890
+ return result
891
+
892
+ def _repr_generic_point(self, coordinates=None):
893
+ r"""
894
+ Return a string representation of a point of ``self``.
895
+
896
+ INPUT:
897
+
898
+ - ``coordinates`` -- list of coordinates of a point of ``self``;
899
+ if not given, names of coordinates of ``self`` will be used
900
+
901
+ OUTPUT: string
902
+
903
+ EXAMPLES::
904
+
905
+ sage: P1xP1 = toric_varieties.P1xP1()
906
+ sage: print(P1xP1._repr_generic_point())
907
+ [s : t : x : y]
908
+ sage: print(P1xP1._repr_generic_point([1,2,3,4]))
909
+ [1 : 2 : 3 : 4]
910
+ """
911
+ if coordinates is None:
912
+ coordinates = self.gens()
913
+ return "[%s]" % (" : ".join(str(coord) for coord in coordinates))
914
+
915
+ def _validate(self, polynomials):
916
+ """
917
+ Check if ``polynomials`` define valid functions on ``self``.
918
+
919
+ Since this is a toric variety, polynomials must be homogeneous in the
920
+ total coordinate ring of ``self``.
921
+
922
+ INPUT:
923
+
924
+ - ``polynomials`` -- list of polynomials in the coordinate ring of
925
+ ``self`` (this function does not perform any conversions)
926
+
927
+ OUTPUT:
928
+
929
+ - ``polynomials`` -- the input parameter without any modifications if
930
+ ``polynomials`` do define valid polynomial functions on ``self``,
931
+ otherwise a :exc:`ValueError` exception is raised.
932
+
933
+ TESTS:
934
+
935
+ We will use the product of two projective lines with coordinates
936
+ `(x, y)` for one and `(s, t)` for the other::
937
+
938
+ sage: P1xP1 = toric_varieties.P1xP1("x y s t")
939
+ sage: P1xP1.inject_variables()
940
+ Defining x, y, s, t
941
+ sage: P1xP1._validate([x - y, x*s + y*t])
942
+ [x - y, x*s + y*t]
943
+ sage: P1xP1._validate([x + s])
944
+ Traceback (most recent call last):
945
+ ...
946
+ ValueError: x + s is not homogeneous on
947
+ 2-d CPR-Fano toric variety covered by 4 affine patches
948
+ """
949
+ for p in polynomials:
950
+ if not self.is_homogeneous(p):
951
+ raise ValueError("%s is not homogeneous on %s" % (p, self))
952
+ return polynomials
953
+
954
+ def affine_patch(self, i):
955
+ r"""
956
+ Return the ``i``-th affine patch of ``self``.
957
+
958
+ INPUT:
959
+
960
+ - ``i`` -- integer; index of a generating cone of the fan of ``self``
961
+
962
+ OUTPUT:
963
+
964
+ - affine :class:`toric variety <ToricVariety_field>` corresponding to
965
+ the ``i``-th generating cone of the fan of ``self``.
966
+
967
+ The result is cached, so the ``i``-th patch is always the same object
968
+ in memory.
969
+
970
+ See also :meth:`affine_algebraic_patch`, which expresses the
971
+ patches as subvarieties of affine space instead.
972
+
973
+ EXAMPLES::
974
+
975
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
976
+ sage: P1xP1 = ToricVariety(fan, "x s y t")
977
+ sage: patch0 = P1xP1.affine_patch(0)
978
+ sage: patch0
979
+ 2-d affine toric variety
980
+ sage: patch0.embedding_morphism()
981
+ Scheme morphism:
982
+ From: 2-d affine toric variety
983
+ To: 2-d toric variety covered by 4 affine patches
984
+ Defn: Defined on coordinates by sending [y : t] to [1 : 1 : y : t]
985
+ sage: patch1 = P1xP1.affine_patch(1)
986
+ sage: patch1.embedding_morphism()
987
+ Scheme morphism:
988
+ From: 2-d affine toric variety
989
+ To: 2-d toric variety covered by 4 affine patches
990
+ Defn: Defined on coordinates by sending [s : y] to [1 : s : y : 1]
991
+ sage: patch1 is P1xP1.affine_patch(1)
992
+ True
993
+ """
994
+ i = int(i) # implicit type checking
995
+ try:
996
+ return self._affine_patches[i]
997
+ except AttributeError:
998
+ self._affine_patches = {}
999
+ except KeyError:
1000
+ pass
1001
+ cone = self.fan().generating_cone(i)
1002
+ names = self.variable_names()
1003
+ # Number of "honest fan coordinates"
1004
+ n = self.fan().nrays()
1005
+ # Number of "torus factor coordinates"
1006
+ t = self._torus_factor_dim
1007
+ names = ([names[ray] for ray in cone.ambient_ray_indices()]
1008
+ + list(names[n:]))
1009
+ patch = AffineToricVariety(cone, names, base_field=self.base_ring())
1010
+ embedding_coordinates = [1] * n
1011
+ for k, ray in enumerate(cone.ambient_ray_indices()):
1012
+ embedding_coordinates[ray] = patch.gen(k)
1013
+ if t > 0: # Passing "-0" gives unintended result
1014
+ embedding_coordinates.extend(patch.gens()[-t:])
1015
+ patch._embedding_morphism = patch.hom(embedding_coordinates, self)
1016
+ self._affine_patches[i] = patch
1017
+ return patch
1018
+
1019
+ def change_ring(self, F):
1020
+ r"""
1021
+ Return a toric variety over ``F`` and otherwise the same as ``self``.
1022
+
1023
+ INPUT:
1024
+
1025
+ - ``F`` -- field
1026
+
1027
+ OUTPUT: :class:`toric variety <ToricVariety_field>` over ``F``
1028
+
1029
+ .. NOTE::
1030
+
1031
+ There is no need to have any relation between ``F`` and the base
1032
+ field of ``self``. If you do want to have such a relation, use
1033
+ :meth:`base_extend` instead.
1034
+
1035
+ EXAMPLES::
1036
+
1037
+ sage: P1xA1 = toric_varieties.P1xA1()
1038
+ sage: P1xA1.base_ring()
1039
+ Rational Field
1040
+ sage: P1xA1_RR = P1xA1.change_ring(RR)
1041
+ sage: P1xA1_RR.base_ring()
1042
+ Real Field with 53 bits of precision
1043
+ sage: P1xA1_QQ = P1xA1_RR.change_ring(QQ)
1044
+ sage: P1xA1_QQ.base_ring()
1045
+ Rational Field
1046
+ sage: P1xA1_RR.base_extend(QQ)
1047
+ Traceback (most recent call last):
1048
+ ...
1049
+ ValueError: no natural map from the base ring
1050
+ (=Real Field with 53 bits of precision) to R (=Rational Field)!
1051
+ sage: R = PolynomialRing(QQ, 2, 'a')
1052
+ sage: P1xA1.change_ring(R)
1053
+ Traceback (most recent call last):
1054
+ ...
1055
+ TypeError: need a field to construct a toric variety;
1056
+ got Multivariate Polynomial Ring in a0, a1 over Rational Field
1057
+ """
1058
+ if self.base_ring() == F:
1059
+ return self
1060
+ elif F not in _Fields:
1061
+ raise TypeError("need a field to construct a toric variety; got %s"
1062
+ % F)
1063
+ else:
1064
+ return ToricVariety(self.fan(), self.variable_names(),
1065
+ base_field=F)
1066
+
1067
+ def coordinate_ring(self):
1068
+ r"""
1069
+ Return the coordinate ring of ``self``.
1070
+
1071
+ For toric varieties this is the homogeneous coordinate ring (a.k.a.
1072
+ Cox's ring and total ring).
1073
+
1074
+ OUTPUT: a polynomial ring
1075
+
1076
+ EXAMPLES::
1077
+
1078
+ sage: P1xP1 = toric_varieties.P1xP1()
1079
+ sage: P1xP1.coordinate_ring()
1080
+ Multivariate Polynomial Ring in s, t, x, y over Rational Field
1081
+
1082
+ TESTS::
1083
+
1084
+ sage: R = toric_varieties.A1().coordinate_ring(); R
1085
+ Multivariate Polynomial Ring in z over Rational Field
1086
+ sage: type(R) # needs sage.libs.singular
1087
+ <... 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
1088
+ """
1089
+ if "_coordinate_ring" not in self.__dict__:
1090
+ names = self.variable_names()
1091
+ self._coordinate_ring = PolynomialRing(self.base_ring(), len(names), names)
1092
+ return self._coordinate_ring
1093
+
1094
+ def embedding_morphism(self):
1095
+ r"""
1096
+ Return the default embedding morphism of ``self``.
1097
+
1098
+ Such a morphism is always defined for an affine patch of a toric
1099
+ variety (which is also a toric varieties itself).
1100
+
1101
+ OUTPUT:
1102
+
1103
+ - :class:`scheme morphism
1104
+ <sage.schemes.generic.morphism.SchemeMorphism_polynomial_toric_variety>`
1105
+ if the default embedding morphism was defined for ``self``,
1106
+ otherwise a :exc:`ValueError` exception is raised.
1107
+
1108
+ EXAMPLES::
1109
+
1110
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
1111
+ sage: P1xP1 = ToricVariety(fan, "x s y t")
1112
+ sage: P1xP1.embedding_morphism()
1113
+ Traceback (most recent call last):
1114
+ ...
1115
+ ValueError: no default embedding was defined for this toric variety
1116
+ sage: patch = P1xP1.affine_patch(0)
1117
+ sage: patch
1118
+ 2-d affine toric variety
1119
+ sage: patch.embedding_morphism()
1120
+ Scheme morphism:
1121
+ From: 2-d affine toric variety
1122
+ To: 2-d toric variety covered by 4 affine patches
1123
+ Defn: Defined on coordinates by sending [y : t] to [1 : 1 : y : t]
1124
+ """
1125
+ try:
1126
+ return self._embedding_morphism
1127
+ except AttributeError:
1128
+ raise ValueError("no default embedding was defined for this "
1129
+ "toric variety")
1130
+
1131
+ def fan(self, dim=None, codim=None):
1132
+ r"""
1133
+ Return the underlying fan of ``self`` or its cones.
1134
+
1135
+ INPUT:
1136
+
1137
+ - ``dim`` -- dimension of the requested cones
1138
+
1139
+ - ``codim`` -- codimension of the requested cones
1140
+
1141
+ OUTPUT:
1142
+
1143
+ - :class:`rational polyhedral fan
1144
+ <sage.geometry.fan.RationalPolyhedralFan>` if no parameters were
1145
+ given, :class:`tuple` of :class:`cones
1146
+ <sage.geometry.cone.ConvexRationalPolyhedralCone>` otherwise.
1147
+
1148
+ EXAMPLES::
1149
+
1150
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
1151
+ sage: P1xP1 = ToricVariety(fan)
1152
+ sage: P1xP1.fan()
1153
+ Rational polyhedral fan in 2-d lattice M
1154
+ sage: P1xP1.fan() is fan
1155
+ True
1156
+ sage: P1xP1.fan(1)[0]
1157
+ 1-d cone of Rational polyhedral fan in 2-d lattice M
1158
+ """
1159
+ return self._fan(dim, codim)
1160
+
1161
+ def inject_coefficients(self, scope=None, verbose=True):
1162
+ r"""
1163
+ Inject generators of the base field of ``self`` into ``scope``.
1164
+
1165
+ This function is useful if the base field is the field of rational
1166
+ functions.
1167
+
1168
+ INPUT:
1169
+
1170
+ - ``scope`` -- namespace (default: global, not just the scope from
1171
+ which this function was called)
1172
+
1173
+ - ``verbose`` -- if ``True`` (default), names of injected generators
1174
+ will be printed
1175
+
1176
+ OUTPUT: none
1177
+
1178
+ EXAMPLES::
1179
+
1180
+ sage: fan = FaceFan(lattice_polytope.cross_polytope(2))
1181
+ sage: F = QQ["a, b"].fraction_field()
1182
+ sage: P1xP1 = ToricVariety(fan, base_field=F)
1183
+ sage: P1xP1.inject_coefficients()
1184
+ Defining a, b
1185
+
1186
+ We check that we can use names ``a`` and ``b``, :issue:`10498` is fixed::
1187
+
1188
+ sage: a + b
1189
+ a + b
1190
+ sage: a + b in P1xP1.coordinate_ring()
1191
+ True
1192
+ """
1193
+ if scope is None:
1194
+ # scope = globals() does not work well, the above doctest fails.
1195
+ # Instead we "borrow" this code from sage.misc.misc.inject_variable
1196
+ depth = 0
1197
+ while True:
1198
+ scope = sys._getframe(depth).f_globals
1199
+ if (scope["__name__"] == "__main__"
1200
+ and scope.get("__package__", None) is None):
1201
+ break
1202
+ depth += 1
1203
+ try:
1204
+ self.base_ring().inject_variables(scope, verbose)
1205
+ except AttributeError:
1206
+ pass
1207
+
1208
+ @cached_method
1209
+ def dimension_singularities(self):
1210
+ r"""
1211
+ Return the dimension of the singular set.
1212
+
1213
+ OUTPUT:
1214
+
1215
+ Integer. The dimension of the singular set of the toric
1216
+ variety. Often the singular set is a reducible subvariety, and
1217
+ this method will return the dimension of the
1218
+ largest-dimensional component.
1219
+
1220
+ This returns `-1` if the toric variety is smooth.
1221
+
1222
+ EXAMPLES::
1223
+
1224
+ sage: toric_varieties.P4_11169().dimension_singularities()
1225
+ 1
1226
+ sage: toric_varieties.Conifold().dimension_singularities()
1227
+ 0
1228
+ sage: toric_varieties.P2().dimension_singularities()
1229
+ -1
1230
+ """
1231
+ for codim in range(self.dimension() + 1):
1232
+ if any(not cone.is_smooth() for cone in self.fan(codim)):
1233
+ return self.dimension() - codim
1234
+ return -1
1235
+
1236
+ def is_homogeneous(self, polynomial):
1237
+ r"""
1238
+ Check if ``polynomial`` is homogeneous.
1239
+
1240
+ The coordinate ring of a toric variety is multigraded by relations
1241
+ between generating rays of the underlying fan.
1242
+
1243
+ INPUT:
1244
+
1245
+ - ``polynomial`` -- polynomial in the coordinate ring of ``self`` or
1246
+ its quotient
1247
+
1248
+ OUTPUT: ``True`` if ``polynomial`` is homogeneous and ``False`` otherwise
1249
+
1250
+ EXAMPLES:
1251
+
1252
+ We will use the product of two projective lines with coordinates
1253
+ `(x, y)` for one and `(s, t)` for the other::
1254
+
1255
+ sage: P1xP1.<x,y,s,t> = toric_varieties.P1xP1()
1256
+ sage: P1xP1.is_homogeneous(x - y)
1257
+ True
1258
+ sage: P1xP1.is_homogeneous(x*s + y*t)
1259
+ True
1260
+ sage: P1xP1.is_homogeneous(x - t)
1261
+ False
1262
+ sage: P1xP1.is_homogeneous(1)
1263
+ True
1264
+
1265
+ Note that by homogeneous, we mean well-defined with respect to
1266
+ the homogeneous rescalings of ``self``. So a polynomial that you would
1267
+ usually not call homogeneous can be homogeneous if there are
1268
+ no homogeneous rescalings, for example::
1269
+
1270
+ sage: A1.<z> = toric_varieties.A1()
1271
+ sage: A1.is_homogeneous(z^3 + z^7)
1272
+ True
1273
+
1274
+ Finally, the degree group is really the Chow group
1275
+ `A_{d-1}(X)` and can contain torsion. For example, take
1276
+ `\CC^2/\ZZ_2`. Here, the Chow group is `A_{d-1}(\CC^2/\ZZ_2) =
1277
+ \ZZ_2` and distinguishes even-degree homogeneous polynomials
1278
+ from odd-degree homogeneous polynomials::
1279
+
1280
+ sage: A2_Z2.<x,y> = toric_varieties.A2_Z2()
1281
+ sage: A2_Z2.is_homogeneous(x + y + x^3 + y^5 + x^3*y^4)
1282
+ True
1283
+ sage: A2_Z2.is_homogeneous(x^2 + x*y + y^4 + (x*y)^5 + x^4*y^4)
1284
+ True
1285
+ sage: A2_Z2.is_homogeneous(x + y^2)
1286
+ False
1287
+ """
1288
+ if '_homogeneous_degrees_group' not in self.__dict__:
1289
+ fan = self.fan()
1290
+ from sage.modules.free_module import FreeModule
1291
+ rays = fan.rays() + fan.virtual_rays()
1292
+ degrees_group = FreeModule(ZZ, len(rays)).quotient(
1293
+ rays.matrix().columns())
1294
+ self._homogeneous_degrees_group = degrees_group
1295
+ degrees_group = self._homogeneous_degrees_group
1296
+ S = self.coordinate_ring()
1297
+ try:
1298
+ polynomial = S(polynomial)
1299
+ except TypeError:
1300
+ # Then it should be in the quotient corresponding to a subscheme
1301
+ polynomial = S(polynomial.lift())
1302
+ monomials = polynomial.monomials()
1303
+ if not monomials:
1304
+ return True
1305
+ degree = degrees_group(vector(ZZ, monomials[0].degrees()))
1306
+ for monomial in monomials:
1307
+ if degrees_group(vector(ZZ, monomial.degrees())) != degree:
1308
+ return False
1309
+ return True
1310
+
1311
+ def is_isomorphic(self, another):
1312
+ r"""
1313
+ Check if ``self`` is isomorphic to ``another``.
1314
+
1315
+ INPUT:
1316
+
1317
+ - ``another`` -- :class:`toric variety <ToricVariety_field>`
1318
+
1319
+ OUTPUT:
1320
+
1321
+ - ``True`` if ``self`` and ``another`` are isomorphic,
1322
+ ``False`` otherwise.
1323
+
1324
+ EXAMPLES::
1325
+
1326
+ sage: TV1 = toric_varieties.P1xA1()
1327
+ sage: TV2 = toric_varieties.P1xP1()
1328
+
1329
+ Only the most trivial case is implemented so far::
1330
+
1331
+ sage: TV1.is_isomorphic(TV1)
1332
+ True
1333
+ sage: TV1.is_isomorphic(TV2)
1334
+ Traceback (most recent call last):
1335
+ ...
1336
+ NotImplementedError: isomorphism check is not yet implemented
1337
+ """
1338
+ if self is another:
1339
+ return True
1340
+ if not isinstance(another, ToricVariety_field):
1341
+ raise TypeError(
1342
+ "only another toric variety can be checked for isomorphism; "
1343
+ "got %s" % another)
1344
+ raise NotImplementedError("isomorphism check is not yet implemented")
1345
+
1346
+ def is_affine(self):
1347
+ r"""
1348
+ Check if ``self`` is an affine toric variety.
1349
+
1350
+ An affine toric variety is a toric variety whose fan is the
1351
+ face lattice of a single cone. See also
1352
+ :func:`AffineToricVariety`.
1353
+
1354
+ OUTPUT: boolean
1355
+
1356
+ EXAMPLES::
1357
+
1358
+ sage: toric_varieties.A2().is_affine()
1359
+ True
1360
+ sage: toric_varieties.P1xA1().is_affine()
1361
+ False
1362
+ """
1363
+ return self.fan().ngenerating_cones() == 1
1364
+
1365
+ def is_complete(self):
1366
+ r"""
1367
+ Check if ``self`` is complete.
1368
+
1369
+ OUTPUT: ``True`` if ``self`` is complete and ``False`` otherwise
1370
+
1371
+ EXAMPLES::
1372
+
1373
+ sage: P1xP1 = toric_varieties.P1xP1()
1374
+ sage: P1xP1.is_complete()
1375
+ True
1376
+ sage: P1xP1.affine_patch(0).is_complete()
1377
+ False
1378
+ """
1379
+ return self.fan().is_complete()
1380
+
1381
+ def is_orbifold(self):
1382
+ r"""
1383
+ Check if ``self`` has only quotient singularities.
1384
+
1385
+ A toric variety with at most orbifold singularities (in this
1386
+ sense) is often called a simplicial toric variety. In this
1387
+ package, we generally try to avoid this term since it mixes up
1388
+ differential geometry and cone terminology.
1389
+
1390
+ OUTPUT:
1391
+
1392
+ - ``True`` if ``self`` has at most quotient singularities by
1393
+ finite groups, ``False`` otherwise.
1394
+
1395
+ EXAMPLES::
1396
+
1397
+ sage: fan1 = FaceFan(lattice_polytope.cross_polytope(2))
1398
+ sage: P1xP1 = ToricVariety(fan1)
1399
+ sage: P1xP1.is_orbifold()
1400
+ True
1401
+ sage: fan2 = NormalFan(lattice_polytope.cross_polytope(3))
1402
+ sage: TV = ToricVariety(fan2)
1403
+ sage: TV.is_orbifold()
1404
+ False
1405
+ """
1406
+ return self.fan().is_simplicial()
1407
+
1408
+ def is_smooth(self):
1409
+ r"""
1410
+ Check if ``self`` is smooth.
1411
+
1412
+ OUTPUT: ``True`` if ``self`` is smooth and ``False`` otherwise
1413
+
1414
+ EXAMPLES::
1415
+
1416
+ sage: fan1 = FaceFan(lattice_polytope.cross_polytope(2))
1417
+ sage: P1xP1 = ToricVariety(fan1)
1418
+ sage: P1xP1.is_smooth()
1419
+ True
1420
+ sage: fan2 = NormalFan(lattice_polytope.cross_polytope(2))
1421
+ sage: TV = ToricVariety(fan2)
1422
+ sage: TV.is_smooth()
1423
+ False
1424
+ """
1425
+ return self.fan().is_smooth()
1426
+
1427
+ @cached_method
1428
+ def Kaehler_cone(self):
1429
+ r"""
1430
+ Return the closure of the Kähler cone of ``self``.
1431
+
1432
+ OUTPUT: :class:`cone <sage.geometry.cone.ConvexRationalPolyhedralCone>`
1433
+
1434
+ .. NOTE::
1435
+
1436
+ This cone sits in the rational divisor class group of ``self`` and
1437
+ the choice of coordinates agrees with
1438
+ :meth:`rational_class_group`.
1439
+
1440
+ EXAMPLES::
1441
+
1442
+ sage: P1xP1 = toric_varieties.P1xP1()
1443
+ sage: Kc = P1xP1.Kaehler_cone()
1444
+ sage: Kc
1445
+ 2-d cone in 2-d lattice
1446
+ sage: Kc.rays()
1447
+ Divisor class [0, 1],
1448
+ Divisor class [1, 0]
1449
+ in Basis lattice of The toric rational divisor class group
1450
+ of a 2-d CPR-Fano toric variety covered by 4 affine patches
1451
+ sage: [ divisor_class.lift() for divisor_class in Kc.rays() ]
1452
+ [V(y), V(t)]
1453
+ sage: Kc.lattice()
1454
+ Basis lattice of The toric rational divisor class group of a
1455
+ 2-d CPR-Fano toric variety covered by 4 affine patches
1456
+ """
1457
+ fan = self.fan()
1458
+ GT = fan.Gale_transform().columns()
1459
+ from sage.schemes.toric.divisor import \
1460
+ ToricRationalDivisorClassGroup_basis_lattice
1461
+ L = ToricRationalDivisorClassGroup_basis_lattice(
1462
+ self.rational_class_group())
1463
+ n = fan.nrays()
1464
+ K = None
1465
+ for cone in fan:
1466
+ sigma = Cone([GT[i] for i in range(n)
1467
+ if i not in cone.ambient_ray_indices()],
1468
+ lattice=L)
1469
+ K = K.intersection(sigma) if K is not None else sigma
1470
+ return K
1471
+
1472
+ @cached_method
1473
+ def Mori_cone(self):
1474
+ r"""
1475
+ Return the Mori cone of ``self``.
1476
+
1477
+ OUTPUT: :class:`cone <sage.geometry.cone.ConvexRationalPolyhedralCone>`
1478
+
1479
+ .. NOTE::
1480
+
1481
+ * The Mori cone is dual to the Kähler cone.
1482
+
1483
+ * We think of the Mori cone as living inside the row span of the
1484
+ Gale transform matrix (computed by
1485
+ ``self.fan().Gale_transform()``).
1486
+
1487
+ * The points in the Mori cone are the effective curves in the
1488
+ variety.
1489
+
1490
+ * The ``i``-th entry in each Mori vector is the intersection
1491
+ number of the curve corresponding to the generator of the
1492
+ ``i``-th ray of the fan with the corresponding divisor class.
1493
+ The very last entry is associated to the origin of the fan
1494
+ lattice.
1495
+
1496
+ * The Mori vectors are also known as the gauged linear sigma model
1497
+ charge vectors.
1498
+
1499
+ EXAMPLES::
1500
+
1501
+ sage: P4_11169 = toric_varieties.P4_11169_resolved()
1502
+ sage: P4_11169.Mori_cone()
1503
+ 2-d cone in 7-d lattice
1504
+ sage: P4_11169.Mori_cone().rays()
1505
+ (3, 2, 0, 0, 0, 1, -6),
1506
+ (0, 0, 1, 1, 1, -3, 0)
1507
+ in Ambient free module of rank 7 over the principal ideal domain Integer Ring
1508
+ """
1509
+ # Ideally, self.Kaehler_cone().dual() should be it, but
1510
+ # so far this is not the case.
1511
+ rays = (ray * self._fan.Gale_transform()
1512
+ for ray in self.Kaehler_cone().dual().rays())
1513
+ return Cone(rays, lattice=ZZ**(self._fan.nrays() + 1))
1514
+
1515
+ def plot(self, **options):
1516
+ r"""
1517
+ Plot ``self``, i.e. the corresponding fan.
1518
+
1519
+ INPUT:
1520
+
1521
+ - any options for toric plots (see :func:`toric_plotter.options
1522
+ <sage.geometry.toric_plotter.options>`), none are mandatory.
1523
+
1524
+ OUTPUT: a plot
1525
+
1526
+ .. NOTE::
1527
+
1528
+ The difference between ``X.plot()`` and ``X.fan().plot()`` is that
1529
+ in the first case default ray labels correspond to variables of
1530
+ ``X``.
1531
+
1532
+ EXAMPLES::
1533
+
1534
+ sage: X = toric_varieties.Cube_deformation(4)
1535
+ sage: X.plot() # needs sage.plot
1536
+ Graphics3d Object
1537
+ """
1538
+ if "ray_label" not in options:
1539
+ gens = self.coordinate_ring().gens()
1540
+ if self.fan().lattice().degree() <= 2:
1541
+ options["ray_label"] = ["$%s$" % latex(z) for z in gens]
1542
+ else:
1543
+ options["ray_label"] = [str(z) for z in gens]
1544
+ return self.fan().plot(**options)
1545
+
1546
+ def rational_class_group(self):
1547
+ r"""
1548
+ Return the rational divisor class group of ``self``.
1549
+
1550
+ Let `X` be a toric variety.
1551
+
1552
+ The **Weil divisor class group** `\mathop{Cl}(X)` is a finitely
1553
+ generated abelian group and can contain torsion. Its rank equals the
1554
+ number of rays in the fan of `X` minus the dimension of `X`.
1555
+
1556
+ The **rational divisor class group** is
1557
+ `\mathop{Cl}(X) \otimes_\ZZ \QQ` and never includes torsion. If `X` is
1558
+ *smooth*, this equals the **Picard group** of `X`, whose elements are
1559
+ the isomorphism classes of line bundles on `X`. The group law (which
1560
+ we write as addition) is the tensor product of the line bundles. The
1561
+ Picard group of a toric variety is always torsion-free.
1562
+
1563
+ OUTPUT: :class:`rational divisor class group
1564
+ <sage.schemes.toric.divisor.ToricRationalDivisorClassGroup>`.
1565
+
1566
+ .. NOTE::
1567
+
1568
+ * Coordinates correspond to the rows of
1569
+ ``self.fan().gale_transform()``.
1570
+
1571
+ * :meth:`Kaehler_cone` yields a cone in this group.
1572
+
1573
+ EXAMPLES::
1574
+
1575
+ sage: P1xA1 = toric_varieties.P1xA1()
1576
+ sage: P1xA1.rational_class_group()
1577
+ The toric rational divisor class group
1578
+ of a 2-d toric variety covered by 2 affine patches
1579
+ """
1580
+ from sage.schemes.toric.divisor import ToricRationalDivisorClassGroup
1581
+ return ToricRationalDivisorClassGroup(self)
1582
+
1583
+ def Chow_group(self, base_ring=ZZ):
1584
+ r"""
1585
+ Return the toric Chow group.
1586
+
1587
+ INPUT:
1588
+
1589
+ - ``base_ring`` -- either ``ZZ`` (default) or ``QQ``; the
1590
+ coefficient ring of the Chow group
1591
+
1592
+ OUTPUT: a :class:`sage.schemes.toric.chow_group.ChowGroup_class`
1593
+
1594
+ EXAMPLES::
1595
+
1596
+ sage: A = toric_varieties.P2().Chow_group(); A
1597
+ Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches
1598
+ sage: A.gens()
1599
+ (( 0 | 0 | 1 ), ( 0 | 1 | 0 ), ( 1 | 0 | 0 ))
1600
+ """
1601
+ from sage.schemes.toric.chow_group import ChowGroup
1602
+ return ChowGroup(self, base_ring)
1603
+
1604
+ def cartesian_product(self, other,
1605
+ coordinate_names=None, coordinate_indices=None):
1606
+ r"""
1607
+ Return the Cartesian product of ``self`` with ``other``.
1608
+
1609
+ INPUT:
1610
+
1611
+ - ``other`` -- a :class:`toric variety <ToricVariety_field>`
1612
+
1613
+ - ``coordinate_names`` -- names of variables for the coordinate ring,
1614
+ see :func:`normalize_names` for acceptable formats. If not given,
1615
+ indexed variable names will be created automatically.
1616
+
1617
+ - ``coordinate_indices`` -- list of integers, indices for indexed
1618
+ variables. If not given, the index of each variable will coincide
1619
+ with the index of the corresponding ray of the fan.
1620
+
1621
+ OUTPUT: a :class:`toric variety <ToricVariety_field>`
1622
+
1623
+ EXAMPLES::
1624
+
1625
+ sage: P1 = ToricVariety(Fan([Cone([(1,)]), Cone([(-1,)])]))
1626
+ sage: P1xP1 = P1.cartesian_product(P1); P1xP1
1627
+ 2-d toric variety covered by 4 affine patches
1628
+ sage: P1xP1.fan().rays()
1629
+ N+N(-1, 0), N+N( 1, 0),
1630
+ N+N( 0, -1), N+N( 0, 1)
1631
+ in 2-d lattice N+N
1632
+ """
1633
+ return ToricVariety(self.fan().cartesian_product(other.fan()),
1634
+ coordinate_names, coordinate_indices,
1635
+ base_field=self.base_ring())
1636
+
1637
+ def resolve(self, **kwds):
1638
+ r"""
1639
+ Construct a toric variety whose fan subdivides the fan of ``self``.
1640
+
1641
+ The name of this function reflects the fact that usually such
1642
+ subdivisions are done for resolving singularities of the original
1643
+ variety.
1644
+
1645
+ INPUT:
1646
+
1647
+ This function accepts only keyword arguments, none of which are
1648
+ mandatory.
1649
+
1650
+ - ``coordinate_names`` -- names for coordinates of the new variety. If
1651
+ not given, will be constructed from the coordinate names of ``self``
1652
+ and necessary indexed ones. See :func:`normalize_names` for the
1653
+ description of acceptable formats.
1654
+
1655
+ - ``coordinate_indices`` -- coordinate indices which should be used
1656
+ for indexed variables of the new variety
1657
+
1658
+ - all other arguments will be passed to
1659
+ :meth:`~sage.geometry.fan.RationalPolyhedralFan.subdivide` method of
1660
+ the underlying :class:`rational polyhedral fan
1661
+ <sage.geometry.fan.RationalPolyhedralFan>`, see its documentation
1662
+ for the available options.
1663
+
1664
+ OUTPUT: a :class:`toric variety <ToricVariety_field>`
1665
+
1666
+ EXAMPLES:
1667
+
1668
+ First we will "manually" resolve a simple orbifold singularity::
1669
+
1670
+ sage: cone = Cone([(1,1), (-1,1)])
1671
+ sage: fan = Fan([cone])
1672
+ sage: TV = ToricVariety(fan)
1673
+ sage: TV.is_smooth()
1674
+ False
1675
+ sage: TV_res = TV.resolve(new_rays=[(0,1)])
1676
+ sage: TV_res.is_smooth()
1677
+ True
1678
+ sage: TV_res.fan().rays()
1679
+ N( 1, 1),
1680
+ N(-1, 1),
1681
+ N( 0, 1)
1682
+ in 2-d lattice N
1683
+ sage: [cone.ambient_ray_indices() for cone in TV_res.fan()]
1684
+ [(0, 2), (1, 2)]
1685
+
1686
+ Now let's "automatically" partially resolve a more complicated fan::
1687
+
1688
+ sage: fan = NormalFan(lattice_polytope.cross_polytope(3))
1689
+ sage: TV = ToricVariety(fan)
1690
+ sage: TV.is_smooth()
1691
+ False
1692
+ sage: TV.is_orbifold()
1693
+ False
1694
+ sage: TV.fan().nrays()
1695
+ 8
1696
+ sage: TV.fan().ngenerating_cones()
1697
+ 6
1698
+ sage: TV_res = TV.resolve(make_simplicial=True)
1699
+ sage: TV_res.is_smooth()
1700
+ False
1701
+ sage: TV_res.is_orbifold()
1702
+ True
1703
+ sage: TV_res.fan().nrays()
1704
+ 8
1705
+ sage: TV_res.fan().ngenerating_cones()
1706
+ 12
1707
+ sage: TV.gens()
1708
+ (z0, z1, z2, z3, z4, z5, z6, z7)
1709
+ sage: TV_res.gens()
1710
+ (z0, z1, z2, z3, z4, z5, z6, z7)
1711
+ sage: TV_res = TV.resolve(coordinate_names='x+',
1712
+ ....: make_simplicial=True)
1713
+ sage: TV_res.gens()
1714
+ (x0, x1, x2, x3, x4, x5, x6, x7)
1715
+ """
1716
+ # If you are changing this function, check out resolve in Fano toric
1717
+ # varieties to see if it should be changed too
1718
+ #
1719
+ # Currently the resolution of fans works for full-dimensional ones
1720
+ # only, so there is no point to deal with the general case here, since
1721
+ # we will not be able to check that it works.
1722
+ coordinate_names = kwds.pop("coordinate_names", None)
1723
+ coordinate_indices = kwds.pop("coordinate_indices", None)
1724
+ fan = self.fan()
1725
+ if fan.dim() != fan.lattice_dim():
1726
+ raise NotImplementedError("resolution of toric varieties with "
1727
+ "torus factors is not yet implemented")
1728
+ # When it is implemented, should be careful with the torus factor
1729
+ rfan = fan.subdivide(**kwds)
1730
+ if coordinate_names is None:
1731
+ coordinate_names = list(self.variable_names())
1732
+ if coordinate_indices is None:
1733
+ coordinate_indices = list(range(fan.nrays(), rfan.nrays()))
1734
+ else:
1735
+ coordinate_indices = coordinate_indices[fan.nrays():]
1736
+ coordinate_names.extend(normalize_names(
1737
+ ngens=rfan.nrays() - fan.nrays(),
1738
+ indices=coordinate_indices,
1739
+ prefix=self._coordinate_prefix))
1740
+ coordinate_names.append(self._coordinate_prefix + "+")
1741
+ resolution = ToricVariety(rfan, coordinate_names=coordinate_names,
1742
+ coordinate_indices=coordinate_indices,
1743
+ base_field=self.base_ring())
1744
+ R = self.coordinate_ring()
1745
+ R_res = resolution.coordinate_ring()
1746
+ resolution_map = resolution.hom(R.hom(R_res.gens()[:R.ngens()]), self)
1747
+ resolution._resolution_map = resolution_map
1748
+ # The above map does not have (yet) public methods to access it.
1749
+ # While this map is defined correctly, base classes of schemes and
1750
+ # morphisms do not treat it as they should. The plan is to fix this
1751
+ # situation soon and to be able to use this map!
1752
+ return resolution
1753
+
1754
+ def resolve_to_orbifold(self, **kwds):
1755
+ r"""
1756
+ Construct an orbifold whose fan subdivides the fan of ``self``.
1757
+
1758
+ It is a synonym for :meth:`resolve` with ``make_simplicial=True``
1759
+ option.
1760
+
1761
+ INPUT:
1762
+
1763
+ - this function accepts only keyword arguments. See :meth:`resolve`
1764
+ for documentation.
1765
+
1766
+ OUTPUT: a :class:`toric variety <ToricVariety_field>`
1767
+
1768
+ EXAMPLES::
1769
+
1770
+ sage: fan = NormalFan(lattice_polytope.cross_polytope(3))
1771
+ sage: TV = ToricVariety(fan)
1772
+ sage: TV.is_orbifold()
1773
+ False
1774
+ sage: TV.fan().nrays()
1775
+ 8
1776
+ sage: TV.fan().ngenerating_cones()
1777
+ 6
1778
+ sage: TV_res = TV.resolve_to_orbifold()
1779
+ sage: TV_res.is_orbifold()
1780
+ True
1781
+ sage: TV_res.fan().nrays()
1782
+ 8
1783
+ sage: TV_res.fan().ngenerating_cones()
1784
+ 12
1785
+ """
1786
+ return self.resolve(make_simplicial=True, **kwds)
1787
+
1788
+ def subscheme(self, polynomials):
1789
+ r"""
1790
+ Return the subscheme of ``self`` defined by ``polynomials``.
1791
+
1792
+ INPUT:
1793
+
1794
+ - ``polynomials`` -- list of polynomials in the coordinate ring of
1795
+ ``self``
1796
+
1797
+ OUTPUT: a :class:`subscheme of a toric variety
1798
+ <sage.schemes.toric.toric_subscheme.AlgebraicScheme_subscheme_toric>`.
1799
+
1800
+ EXAMPLES:
1801
+
1802
+ We will construct a subscheme of the product of two projective lines
1803
+ with coordinates `(x, y)` for one and `(s, t)` for the other::
1804
+
1805
+ sage: P1xP1.<x,y,s,t> = toric_varieties.P1xP1()
1806
+ sage: X = P1xP1.subscheme([x*s + y*t, x^3 + y^3])
1807
+ sage: X
1808
+ Closed subscheme of 2-d CPR-Fano toric variety
1809
+ covered by 4 affine patches defined by:
1810
+ x*s + y*t,
1811
+ x^3 + y^3
1812
+ sage: X.defining_polynomials()
1813
+ (x*s + y*t, x^3 + y^3)
1814
+ sage: X.defining_ideal()
1815
+ Ideal (x*s + y*t, x^3 + y^3) of
1816
+ Multivariate Polynomial Ring in x, y, s, t over Rational Field
1817
+ sage: X.base_ring()
1818
+ Rational Field
1819
+ sage: X.base_scheme()
1820
+ Spectrum of Rational Field
1821
+ sage: X.structure_morphism()
1822
+ Scheme morphism:
1823
+ From: Closed subscheme of 2-d CPR-Fano toric variety
1824
+ covered by 4 affine patches defined by: x*s + y*t, x^3 + y^3
1825
+ To: Spectrum of Rational Field
1826
+ Defn: Structure map
1827
+ """
1828
+ from sage.schemes.toric.toric_subscheme import\
1829
+ AlgebraicScheme_subscheme_toric, AlgebraicScheme_subscheme_affine_toric
1830
+ if self.is_affine():
1831
+ return AlgebraicScheme_subscheme_affine_toric(self, polynomials)
1832
+ else:
1833
+ return AlgebraicScheme_subscheme_toric(self, polynomials)
1834
+
1835
+ def Stanley_Reisner_ideal(self):
1836
+ r"""
1837
+ Return the Stanley-Reisner ideal.
1838
+
1839
+ OUTPUT:
1840
+
1841
+ - The Stanley-Reisner ideal in the polynomial ring over
1842
+ `\QQ` generated by the homogeneous coordinates.
1843
+
1844
+ EXAMPLES::
1845
+
1846
+ sage: fan = Fan([[0,1,3], [3,4], [2,0], [1,2,4]],
1847
+ ....: [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)])
1848
+ sage: X = ToricVariety(fan, coordinate_names='A B C D E', base_field=GF(5))
1849
+ sage: SR = X.Stanley_Reisner_ideal(); SR
1850
+ Ideal (A*E, C*D, A*B*C, B*D*E) of
1851
+ Multivariate Polynomial Ring in A, B, C, D, E over Rational Field
1852
+ """
1853
+ if "_SR" not in self.__dict__:
1854
+ R = PolynomialRing(QQ, self.variable_names())
1855
+ self._SR = self._fan.Stanley_Reisner_ideal(R)
1856
+ return self._SR
1857
+
1858
+ def linear_equivalence_ideal(self):
1859
+ r"""
1860
+ Return the ideal generated by linear relations.
1861
+
1862
+ OUTPUT:
1863
+
1864
+ - The ideal generated by the linear relations of the rays in
1865
+ the polynomial ring over `\QQ` generated by the homogeneous
1866
+ coordinates.
1867
+
1868
+ EXAMPLES::
1869
+
1870
+ sage: fan = Fan([[0,1,3], [3,4], [2,0], [1,2,4]],
1871
+ ....: [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)])
1872
+ sage: X = ToricVariety(fan, coordinate_names='A B C D E', base_field=GF(5))
1873
+ sage: lin = X.linear_equivalence_ideal(); lin
1874
+ Ideal (-3*A + 3*C - D + E, -2*A - 2*C - D - E, A + B + C + D + E) of
1875
+ Multivariate Polynomial Ring in A, B, C, D, E over Rational Field
1876
+ """
1877
+ if "_linear_equivalence_ideal" not in self.__dict__:
1878
+ R = PolynomialRing(QQ, self.variable_names())
1879
+ self._linear_equivalence_ideal = self._fan.linear_equivalence_ideal(R)
1880
+ return self._linear_equivalence_ideal
1881
+
1882
+ @cached_method
1883
+ def cohomology_ring(self):
1884
+ r"""
1885
+ Return the cohomology ring of the toric variety.
1886
+
1887
+ OUTPUT:
1888
+
1889
+ - If the toric variety is over `\CC` and has at most finite
1890
+ orbifold singularities: `H^\bullet(X,\QQ)` as a polynomial
1891
+ quotient ring.
1892
+
1893
+ - Other cases are not handled yet.
1894
+
1895
+ .. NOTE::
1896
+
1897
+ - Toric varieties over any field of characteristic 0 are
1898
+ treated as if they were varieties over `\CC`.
1899
+
1900
+ - The integral cohomology of smooth toric varieties is
1901
+ torsion-free, so in this case there is no loss of
1902
+ information when going to rational coefficients.
1903
+
1904
+ - ``self.cohomology_ring().gen(i)`` is the divisor class corresponding to
1905
+ the ``i``-th ray of the fan.
1906
+
1907
+ EXAMPLES::
1908
+
1909
+ sage: X = toric_varieties.dP6()
1910
+ sage: X.cohomology_ring()
1911
+ Rational cohomology ring of a 2-d CPR-Fano toric variety covered by 6 affine patches
1912
+ sage: X.cohomology_ring().defining_ideal()
1913
+ Ideal (-u - y + z + w, x - y - v + w, x*y, x*v, x*z, u*v, u*z, u*w, y*z, y*w, v*w)
1914
+ of Multivariate Polynomial Ring in x, u, y, v, z, w over Rational Field
1915
+ sage: X.cohomology_ring().defining_ideal().ring()
1916
+ Multivariate Polynomial Ring in x, u, y, v, z, w over Rational Field
1917
+ sage: X.variable_names()
1918
+ ('x', 'u', 'y', 'v', 'z', 'w')
1919
+ sage: X.cohomology_ring().gens() # needs sage.libs.singular
1920
+ ([y + v - w], [-y + z + w], [y], [v], [z], [w])
1921
+
1922
+ TESTS:
1923
+
1924
+ The cohomology ring is a circular reference that is
1925
+ potentially troublesome on unpickling, see :issue:`15050`
1926
+ and :issue:`15149` ::
1927
+
1928
+ sage: # needs sage.libs.singular
1929
+ sage: variety = toric_varieties.P(1)
1930
+ sage: a = [variety.cohomology_ring(), variety.cohomology_basis(), variety.volume_class()]
1931
+ sage: b = [variety.Todd_class(), variety.Chern_class(), variety.Chern_character(), variety.Kaehler_cone(), variety.Mori_cone()]
1932
+ sage: loads(dumps(variety)) == variety
1933
+ True
1934
+ """
1935
+ if self.base_ring().characteristic() > 0:
1936
+ raise NotImplementedError('only characteristic 0 base fields '
1937
+ 'are implemented')
1938
+ return CohomologyRing(self)
1939
+
1940
+ @cached_method
1941
+ def cohomology_basis(self, d=None):
1942
+ r"""
1943
+ Return a basis for the cohomology of the toric variety.
1944
+
1945
+ INPUT:
1946
+
1947
+ - ``d`` -- (optional) integer
1948
+
1949
+ OUTPUT:
1950
+
1951
+ - Without the optional argument, a list whose `d`-th entry is a
1952
+ basis for `H^{2d}(X,\QQ)`
1953
+
1954
+ - If the argument is an integer ``d``, returns basis for
1955
+ `H^{2d}(X,\QQ)`
1956
+
1957
+ EXAMPLES::
1958
+
1959
+ sage: # needs sage.libs.singular
1960
+ sage: X = toric_varieties.dP8()
1961
+ sage: X.cohomology_basis()
1962
+ (([1],), ([z], [y]), ([y*z],))
1963
+ sage: X.cohomology_basis(1)
1964
+ ([z], [y])
1965
+ sage: X.cohomology_basis(dimension(X))[0] == X.volume_class()
1966
+ True
1967
+ """
1968
+ if d is not None:
1969
+ return self.cohomology_basis()[d]
1970
+
1971
+ H = self.cohomology_ring()
1972
+ # Make an empty list for each d-piece
1973
+ basis = [[] for _ in range(self.dimension() + 1)]
1974
+ # Distribute basis elements into d-pieces
1975
+ for x in H.defining_ideal().normal_basis():
1976
+ basis[x.total_degree()].append(x)
1977
+ # Convert list of lists of polynomials to
1978
+ # tuple of tuples of cohomology classes
1979
+ return tuple(tuple(H(x) for x in dbasis)
1980
+ for dbasis in basis)
1981
+
1982
+ @cached_method
1983
+ def volume_class(self):
1984
+ r"""
1985
+ Return the cohomology class of the volume form on the toric
1986
+ variety.
1987
+
1988
+ Note that we are using cohomology with compact supports. If
1989
+ the variety is non-compact this is dual to homology without
1990
+ any support condition. In particular, for non-compact
1991
+ varieties the volume form `\mathrm{dVol}=\wedge_i(dx_i \wedge
1992
+ dy_i)` does not define a (nonzero) cohomology class.
1993
+
1994
+ OUTPUT:
1995
+
1996
+ A :class:`CohomologyClass`. If it exists, it is the class of
1997
+ the (properly normalized) volume form, that is, it is the
1998
+ Poincaré dual of a single point. If it does not exist, a
1999
+ :exc:`ValueError` is raised.
2000
+
2001
+ EXAMPLES::
2002
+
2003
+ sage: P2 = toric_varieties.P2()
2004
+ sage: P2.volume_class() # needs sage.libs.singular
2005
+ [z^2]
2006
+
2007
+ sage: A2_Z2 = toric_varieties.A2_Z2()
2008
+ sage: A2_Z2.volume_class() # needs sage.libs.singular
2009
+ Traceback (most recent call last):
2010
+ ...
2011
+ ValueError: volume class does not exist
2012
+
2013
+ If none of the maximal cones is smooth things get more
2014
+ tricky. In this case no torus-fixed point is smooth. If we
2015
+ want to count an ordinary point as `1`, then a `G`-orbifold
2016
+ point needs to count as `\frac{1}{|G|}`. For example, take
2017
+ `\mathbb{P}^1\times\mathbb{P}^1` with inhomogeneous
2018
+ coordinates `(t,y)`. Take the quotient by the action
2019
+ `(t,y)\mapsto (-t,-y)`. The `\ZZ_2`-invariant Weil divisors
2020
+ `\{t=0\}` and `\{y=0\}` intersect in a `\ZZ_2`-fixed point, so
2021
+ they ought to have intersection number `\frac{1}{2}`. This
2022
+ means that the cohomology class `[t] \cap [y]` should be
2023
+ `\frac{1}{2}` times the volume class. Note that this is
2024
+ different from the volume normalization chosen in
2025
+ [KS]_::
2026
+
2027
+ sage: P1xP1_Z2 = toric_varieties.P1xP1_Z2()
2028
+ sage: Dt = P1xP1_Z2.divisor(1); Dt
2029
+ V(t)
2030
+ sage: Dy = P1xP1_Z2.divisor(3); Dy
2031
+ V(y)
2032
+ sage: P1xP1_Z2.volume_class() # needs sage.libs.singular
2033
+ [2*t*y]
2034
+
2035
+ sage: HH = P1xP1_Z2.cohomology_ring()
2036
+ sage: HH(Dt) * HH(Dy) == 1/2 * P1xP1_Z2.volume_class() # needs sage.libs.singular
2037
+ True
2038
+
2039
+ The fractional coefficients are also necessary to match the
2040
+ normalization in the rational Chow group for simplicial toric
2041
+ varieties::
2042
+
2043
+ sage: A = P1xP1_Z2.Chow_group(QQ)
2044
+ sage: A(Dt).intersection_with_divisor(Dy).count_points()
2045
+ 1/2
2046
+ """
2047
+ if not self.is_orbifold():
2048
+ raise NotImplementedError('cohomology computations are only '
2049
+ 'implemented for orbifolds')
2050
+ HH = self.cohomology_ring()
2051
+ dim = self.dimension_relative()
2052
+ dVol = HH(self.fan().generating_cone(0)).part_of_degree(dim)
2053
+ if dVol.is_zero():
2054
+ raise ValueError('volume class does not exist')
2055
+ return dVol
2056
+
2057
+ def integrate(self, cohomology_class):
2058
+ """
2059
+ Integrate a cohomology class over the toric variety.
2060
+
2061
+ INPUT:
2062
+
2063
+ - ``cohomology_class`` -- a cohomology class given as a
2064
+ polynomial in ``self.cohomology_ring()``
2065
+
2066
+ OUTPUT:
2067
+
2068
+ The integral of the cohomology class over the variety. The
2069
+ volume normalization is given by :meth:`volume_class`, that
2070
+ is, ``self.integrate(self.volume_class())`` is always one (if
2071
+ the volume class exists).
2072
+
2073
+ EXAMPLES::
2074
+
2075
+ sage: # needs sage.libs.singular
2076
+ sage: dP6 = toric_varieties.dP6()
2077
+ sage: HH = dP6.cohomology_ring()
2078
+ sage: D = [ HH(c) for c in dP6.fan(dim=1) ]
2079
+ sage: matrix([ [ D[i]*D[j] for i in range(0,6) ] for j in range(0,6) ])
2080
+ [ [w^2] [-w^2] [0] [0] [0] [-w^2]]
2081
+ [[-w^2] [w^2] [-w^2] [0] [0] [0]]
2082
+ [ [0] [-w^2] [w^2] [-w^2] [0] [0]]
2083
+ [ [0] [0] [-w^2] [w^2] [-w^2] [0]]
2084
+ [ [0] [0] [0] [-w^2] [w^2] [-w^2]]
2085
+ [[-w^2] [0] [0] [0] [-w^2] [w^2]]
2086
+ sage: matrix([ [ dP6.integrate(D[i]*D[j]) for i in range(0,6) ] for j in range(0,6) ])
2087
+ [-1 1 0 0 0 1]
2088
+ [ 1 -1 1 0 0 0]
2089
+ [ 0 1 -1 1 0 0]
2090
+ [ 0 0 1 -1 1 0]
2091
+ [ 0 0 0 1 -1 1]
2092
+ [ 1 0 0 0 1 -1]
2093
+
2094
+ If the toric variety is an orbifold, the intersection numbers
2095
+ are usually fractional::
2096
+
2097
+ sage: # needs sage.libs.singular
2098
+ sage: P2_123 = toric_varieties.P2_123()
2099
+ sage: HH = P2_123.cohomology_ring()
2100
+ sage: D = [ HH(c) for c in P2_123.fan(dim=1) ]
2101
+ sage: matrix([ [ P2_123.integrate(D[i]*D[j]) for i in range(0,3) ] for j in range(0,3) ])
2102
+ [2/3 1 1/3]
2103
+ [ 1 3/2 1/2]
2104
+ [1/3 1/2 1/6]
2105
+ sage: A = P2_123.Chow_group(QQ)
2106
+ sage: matrix([ [ A(P2_123.divisor(i))
2107
+ ....: .intersection_with_divisor(P2_123.divisor(j))
2108
+ ....: .count_points() for i in range(0,3) ] for j in range(0,3) ])
2109
+ [2/3 1 1/3]
2110
+ [ 1 3/2 1/2]
2111
+ [1/3 1/2 1/6]
2112
+ """
2113
+ assert self.is_complete(), "Can only integrate over compact varieties."
2114
+ top_form = cohomology_class.part_of_degree(self.dimension())
2115
+ if top_form.is_zero():
2116
+ return 0
2117
+ return top_form.lc() / self.volume_class().lc()
2118
+
2119
+ @property
2120
+ def sheaves(self):
2121
+ r"""
2122
+ Return the factory object for sheaves on the toric variety.
2123
+
2124
+ See :class:`sage.schemes.toric.sheaf.constructor.SheafLibrary`
2125
+ for details.
2126
+
2127
+ EXAMPLES::
2128
+
2129
+ sage: dP6 = toric_varieties.dP6()
2130
+ sage: dP6.sheaves
2131
+ Sheaf constructor on 2-d CPR-Fano toric variety covered by 6 affine patches
2132
+ sage: dP6.sheaves.trivial_bundle()
2133
+ Rank 1 bundle on 2-d CPR-Fano toric variety covered by 6 affine patches.
2134
+ """
2135
+ from sage.schemes.toric.sheaf.constructor import SheafLibrary
2136
+ return SheafLibrary(self)
2137
+
2138
+ @cached_method
2139
+ def Chern_class(self, deg=None):
2140
+ """
2141
+ Return Chern classes of the (tangent bundle of the) toric variety.
2142
+
2143
+ INPUT:
2144
+
2145
+ - ``deg`` -- integer (optional); the degree of the Chern class
2146
+
2147
+ OUTPUT: if the degree is specified, the ``deg``-th Chern class
2148
+
2149
+ - If no degree is specified, the total Chern class.
2150
+
2151
+ REFERENCES:
2152
+
2153
+ - :wikipedia:`Chern_class`
2154
+
2155
+ EXAMPLES::
2156
+
2157
+ sage: # needs sage.libs.singular
2158
+ sage: X = toric_varieties.dP6()
2159
+ sage: X.Chern_class()
2160
+ [-6*w^2 + y + 2*v + 2*z + w + 1]
2161
+ sage: X.c()
2162
+ [-6*w^2 + y + 2*v + 2*z + w + 1]
2163
+ sage: X.c(1)
2164
+ [y + 2*v + 2*z + w]
2165
+ sage: X.c(2)
2166
+ [-6*w^2]
2167
+ sage: X.integrate( X.c(2) )
2168
+ 6
2169
+ sage: X.integrate( X.c(2) ) == X.Euler_number()
2170
+ True
2171
+ """
2172
+ assert self.is_orbifold(), "Requires the toric variety to be an orbifold."
2173
+ c = prod([1 + self.cohomology_ring().gen(i)
2174
+ for i in range(self._fan.nrays())])
2175
+ return c if deg is None else c.part_of_degree(deg)
2176
+
2177
+ @cached_method
2178
+ def Chern_character(self, deg=None):
2179
+ """
2180
+ Return the Chern character (of the tangent bundle) of the toric
2181
+ variety.
2182
+
2183
+ INPUT:
2184
+
2185
+ - ``deg`` -- integer (optional); the degree of the Chern
2186
+ character
2187
+
2188
+ OUTPUT:
2189
+
2190
+ - If the degree is specified, the degree-``deg`` part of the
2191
+ Chern character.
2192
+
2193
+ - If no degree is specified, the total Chern character.
2194
+
2195
+ REFERENCES:
2196
+
2197
+ - :wikipedia:`Chern_character#The_Chern_character`
2198
+
2199
+ EXAMPLES::
2200
+
2201
+ sage: # needs sage.libs.singular
2202
+ sage: dP6 = toric_varieties.dP6()
2203
+ sage: dP6.Chern_character()
2204
+ [3*w^2 + y + 2*v + 2*z + w + 2]
2205
+ sage: dP6.ch()
2206
+ [3*w^2 + y + 2*v + 2*z + w + 2]
2207
+ sage: dP6.ch(1) == dP6.c(1)
2208
+ True
2209
+ """
2210
+ assert self.is_orbifold(), "Requires the toric variety to be an orbifold."
2211
+ n_rels = self._fan.nrays() - self.dimension()
2212
+ ch = sum([self.cohomology_ring().gen(i).exp()
2213
+ for i in range(self._fan.nrays())]) - n_rels
2214
+ return ch if deg is None else ch.part_of_degree(deg)
2215
+
2216
+ @cached_method
2217
+ def Todd_class(self, deg=None):
2218
+ """
2219
+ Return the Todd class (of the tangent bundle) of the toric variety.
2220
+
2221
+ INPUT:
2222
+
2223
+ - ``deg`` -- integer (optional); the desired degree part
2224
+
2225
+ OUTPUT:
2226
+
2227
+ - If the degree is specified, the degree-``deg`` part of the
2228
+ Todd class.
2229
+
2230
+ - If no degree is specified, the total Todd class.
2231
+
2232
+ REFERENCES:
2233
+
2234
+ - :wikipedia:`Todd_class`
2235
+
2236
+ EXAMPLES::
2237
+
2238
+ sage: # needs sage.libs.singular
2239
+ sage: dP6 = toric_varieties.dP6()
2240
+ sage: dP6.Todd_class()
2241
+ [-w^2 + 1/2*y + v + z + 1/2*w + 1]
2242
+ sage: dP6.Td()
2243
+ [-w^2 + 1/2*y + v + z + 1/2*w + 1]
2244
+ sage: dP6.integrate( dP6.Td() )
2245
+ 1
2246
+ """
2247
+ Td = QQ.one()
2248
+ dim = self.dimension()
2249
+ if dim >= 1:
2250
+ c1 = self.Chern_class(1)
2251
+ Td += QQ.one() / 2 * c1
2252
+ if dim >= 2:
2253
+ c2 = self.Chern_class(2)
2254
+ Td += QQ.one() / 12 * (c1**2 + c2)
2255
+ if dim >= 3:
2256
+ Td += QQ.one() / 24 * c1 * c2
2257
+ if dim >= 4:
2258
+ c3 = self.Chern_class(3)
2259
+ c4 = self.Chern_class(4)
2260
+ Td += -QQ.one() / 720 * (c1**4 - 4*c1**2*c2 - 3*c2**2 - c1*c3 + c4)
2261
+ if dim >= 5:
2262
+ raise NotImplementedError('Todd class is currently only implemented up to degree 4')
2263
+ return Td if deg is None else Td.part_of_degree(deg)
2264
+
2265
+ c = Chern_class
2266
+ ch = Chern_character
2267
+ Td = Todd_class
2268
+
2269
+ def Euler_number(self):
2270
+ """
2271
+ Return the topological Euler number of the toric variety.
2272
+
2273
+ Sometimes, this is also called the Euler
2274
+ characteristic. :meth:`chi` is a synonym for
2275
+ :meth:`Euler_number`.
2276
+
2277
+ REFERENCES:
2278
+
2279
+ - :wikipedia:`Euler_characteristic`
2280
+
2281
+ EXAMPLES::
2282
+
2283
+ sage: # needs sage.libs.singular
2284
+ sage: P1xP1 = toric_varieties.P1xP1()
2285
+ sage: P1xP1.Euler_number()
2286
+ 4
2287
+ sage: P1xP1.chi()
2288
+ 4
2289
+ """
2290
+ if "_chi" not in self.__dict__:
2291
+ if self.is_complete():
2292
+ chi = self.integrate(self.Chern_class())
2293
+ else:
2294
+ chi = 0
2295
+ H = self.cohomology_basis()
2296
+ for d in range(self.dimension() + 1):
2297
+ chi += (-1)**d * len(H[d])
2298
+ self._chi = chi
2299
+ return self._chi
2300
+
2301
+ chi = Euler_number
2302
+
2303
+ def K(self):
2304
+ r"""
2305
+ Return the canonical divisor of the toric variety.
2306
+
2307
+ EXAMPLES:
2308
+
2309
+ Lets test that the del Pezzo surface `dP_6` has degree 6, as its name implies::
2310
+
2311
+ sage: dP6 = toric_varieties.dP6()
2312
+ sage: HH = dP6.cohomology_ring()
2313
+ sage: dP6.K()
2314
+ -V(x) - V(u) - V(y) - V(v) - V(z) - V(w)
2315
+ sage: dP6.integrate( HH(dP6.K())^2 ) # needs sage.libs.singular
2316
+ 6
2317
+ """
2318
+ from sage.schemes.toric.divisor import ToricDivisor
2319
+ return ToricDivisor(self, [-1] * self._fan.nrays())
2320
+
2321
+ def divisor(self, arg, base_ring=None, check=True, reduce=True):
2322
+ r"""
2323
+ Return a divisor.
2324
+
2325
+ INPUT:
2326
+
2327
+ The arguments are the same as in
2328
+ :func:`sage.schemes.toric.divisor.ToricDivisor`, with the
2329
+ exception of defining a divisor with a single integer: this method
2330
+ considers it to be the index of a ray of the :meth:`fan` of ``self``.
2331
+
2332
+ OUTPUT: a :class:`sage.schemes.toric.divisor.ToricDivisor_generic`
2333
+
2334
+ EXAMPLES::
2335
+
2336
+ sage: dP6 = toric_varieties.dP6()
2337
+ sage: dP6.coordinate_ring()
2338
+ Multivariate Polynomial Ring in x, u, y, v, z, w over Rational Field
2339
+ sage: dP6.divisor(list(range(6)))
2340
+ V(u) + 2*V(y) + 3*V(v) + 4*V(z) + 5*V(w)
2341
+ sage: dP6.inject_variables()
2342
+ Defining x, u, y, v, z, w
2343
+ sage: dP6.divisor(x*u^3)
2344
+ V(x) + 3*V(u)
2345
+
2346
+ You can also construct divisors based on ray indices::
2347
+
2348
+ sage: dP6.divisor(0)
2349
+ V(x)
2350
+ sage: for i in range(dP6.fan().nrays()):
2351
+ ....: print('{} : generated by ray {}'.format(dP6.divisor(i),
2352
+ ....: dP6.fan().ray(i)))
2353
+ V(x) : generated by ray N(0, 1)
2354
+ V(u) : generated by ray N(-1, 0)
2355
+ V(y) : generated by ray N(-1, -1)
2356
+ V(v) : generated by ray N(0, -1)
2357
+ V(z) : generated by ray N(1, 0)
2358
+ V(w) : generated by ray N(1, 1)
2359
+
2360
+ TESTS:
2361
+
2362
+ We check that the issue :issue:`12812` is resolved::
2363
+
2364
+ sage: sum(dP6.divisor(i) for i in range(3))
2365
+ V(x) + V(u) + V(y)
2366
+ """
2367
+ # Divisor by a ray index - must be treated here, see Issue #12812.
2368
+ if arg in ZZ:
2369
+ arg = [(1, self.gen(arg))]
2370
+ check = True # 1 must be coerced into the coefficient ring
2371
+ reduce = False
2372
+ from sage.schemes.toric.divisor import ToricDivisor
2373
+ return ToricDivisor(self, ring=base_ring, arg=arg,
2374
+ check=check, reduce=reduce)
2375
+
2376
+ def divisor_group(self, base_ring=ZZ):
2377
+ r"""
2378
+ Return the group of Weil divisors.
2379
+
2380
+ INPUT:
2381
+
2382
+ - ``base_ring`` -- the coefficient ring, usually ``ZZ``
2383
+ (default) or ``QQ``
2384
+
2385
+ OUTPUT:
2386
+
2387
+ The (free abelian) group of Cartier divisors, that is, formal
2388
+ linear combinations of polynomial equations over the
2389
+ coefficient ring ``base_ring``.
2390
+
2391
+ These need not be toric (=defined by monomials), but allow
2392
+ general polynomials. The output will be an instance of
2393
+ :class:`sage.schemes.generic.divisor_group.DivisorGroup_generic`.
2394
+
2395
+ .. WARNING::
2396
+
2397
+ You almost certainly want the group of toric divisors, see
2398
+ :meth:`toric_divisor_group`. The toric divisor group is
2399
+ generated by the rays of the fan. The general divisor
2400
+ group has no toric functionality implemented.
2401
+
2402
+ EXAMPLES::
2403
+
2404
+ sage: dP6 = toric_varieties.dP6()
2405
+ sage: Div = dP6.divisor_group(); Div
2406
+ Group of ZZ-Divisors on 2-d CPR-Fano toric variety covered by 6 affine patches
2407
+ sage: Div(x) # needs sage.symbolic
2408
+ V(x)
2409
+ """
2410
+ from sage.schemes.generic.divisor_group import DivisorGroup
2411
+ return DivisorGroup(self, base_ring)
2412
+
2413
+ def toric_divisor_group(self, base_ring=ZZ):
2414
+ r"""
2415
+ Return the group of toric (T-Weil) divisors.
2416
+
2417
+ INPUT:
2418
+
2419
+ - ``base_ring`` -- the coefficient ring, usually ``ZZ``
2420
+ (default) or ``QQ``
2421
+
2422
+ OUTPUT:
2423
+
2424
+ The free Abelian agroup of toric Weil divisors, that is,
2425
+ formal ``base_ring``-linear combinations of codimension-one
2426
+ toric subvarieties. The output will be an instance of
2427
+ :class:`sage.schemes.toric.divisor.ToricDivisorGroup`.
2428
+
2429
+ The `i`-th generator of the divisor group is the divisor where
2430
+ the `i`-th homogeneous coordinate vanishes, `\{z_i=0\}`.
2431
+
2432
+ EXAMPLES::
2433
+
2434
+ sage: dP6 = toric_varieties.dP6()
2435
+ sage: TDiv = dP6.toric_divisor_group(); TDiv
2436
+ Group of toric ZZ-Weil divisors on 2-d CPR-Fano toric variety
2437
+ covered by 6 affine patches
2438
+ sage: TDiv == dP6.toric_divisor_group()
2439
+ True
2440
+ sage: TDiv.gens()
2441
+ (V(x), V(u), V(y), V(v), V(z), V(w))
2442
+ sage: dP6.coordinate_ring()
2443
+ Multivariate Polynomial Ring in x, u, y, v, z, w over Rational Field
2444
+ """
2445
+ from sage.schemes.toric.divisor import ToricDivisorGroup
2446
+ return ToricDivisorGroup(self, base_ring)
2447
+
2448
+ def _semigroup_ring(self, cone=None, names=None):
2449
+ r"""
2450
+ Return a presentation of the semigroup ring for the dual of ``cone``.
2451
+
2452
+ INPUT:
2453
+
2454
+ See :meth:`Spec`.
2455
+
2456
+ OUTPUT:
2457
+
2458
+ For the given ``cone`` `\sigma`, return a tuple consisting of
2459
+
2460
+ * a polynomial ring `R`,
2461
+
2462
+ * an ideal `I\in R`,
2463
+
2464
+ * the dual cone `\sigma^\vee`
2465
+
2466
+ such that `R/I \sim k[\sigma^\vee \cap M]`, where `k` is the
2467
+ :meth:`base_ring` of the toric variety.
2468
+
2469
+ EXAMPLES::
2470
+
2471
+ sage: A2Z2 = Cone([(0,1), (2,1)])
2472
+ sage: AffineToricVariety(A2Z2)._semigroup_ring() # needs fpylll sage.libs.singular
2473
+ (Multivariate Polynomial Ring in z0, z1, z2 over Rational Field,
2474
+ Ideal (-z0*z1 + z2^2) of Multivariate Polynomial Ring in z0, z1, z2 over Rational Field,
2475
+ 2-d cone in 2-d lattice M)
2476
+
2477
+ sage: P2 = toric_varieties.P2()
2478
+ sage: cone = P2.fan().generating_cone(0)
2479
+ sage: P2._semigroup_ring(cone) # needs fpylll sage.libs.singular
2480
+ (Multivariate Polynomial Ring in z0, z1 over Rational Field,
2481
+ Ideal (0) of Multivariate Polynomial Ring in z0, z1 over Rational Field,
2482
+ 2-d cone in 2-d lattice M)
2483
+ sage: P2.change_ring(GF(101))._semigroup_ring(cone) # needs fpylll sage.libs.singular
2484
+ (Multivariate Polynomial Ring in z0, z1 over Finite Field of size 101,
2485
+ Ideal (0) of Multivariate Polynomial Ring in z0, z1 over Finite Field of size 101,
2486
+ 2-d cone in 2-d lattice M)
2487
+ """
2488
+ from sage.schemes.toric.ideal import ToricIdeal
2489
+ if cone is None:
2490
+ assert self.is_affine(), \
2491
+ 'You may only omit the cone argument for an affine toric variety!'
2492
+ cone = self.fan().generating_cone(0)
2493
+
2494
+ cone = self.fan().embed(cone)
2495
+ dual = cone.dual()
2496
+ basis = dual.Hilbert_basis()
2497
+ N = len(basis)
2498
+ names = normalize_names(names, N, DEFAULT_PREFIX)
2499
+ A = basis.column_matrix()
2500
+ IA = ToricIdeal(A, names, base_ring=self.base_ring())
2501
+ return (IA.ring(), IA, dual)
2502
+
2503
+ def Spec(self, cone=None, names=None):
2504
+ r"""
2505
+ Return the spectrum associated to the dual cone.
2506
+
2507
+ Let `\sigma \in N_\RR` be a cone and `\sigma^\vee \cap M` the
2508
+ associated semigroup of lattice points in the dual cone. Then
2509
+
2510
+ .. MATH::
2511
+
2512
+ S = \CC[\sigma^\vee \cap M]
2513
+
2514
+ is a `\CC`-algebra. It is spanned over `\CC` by the points of
2515
+ `\sigma \cap N`, addition is formal linear combination of
2516
+ lattice points, and multiplication of lattice points is the
2517
+ semigroup law (that is, addition of lattice points). The
2518
+ `\CC`-algebra `S` then defines a scheme `\mathop{Spec}(S)`.
2519
+
2520
+ For example, if `\sigma=\{(x,y)|x\geq 0,y\geq 0\}` is the
2521
+ first quadrant then `S` is the polynomial ring in two
2522
+ variables. The associated scheme is `\mathop{Spec}(S) =
2523
+ \CC^2`.
2524
+
2525
+ The same construction works over any base field, this
2526
+ introduction only used `\CC` for simplicity.
2527
+
2528
+ INPUT:
2529
+
2530
+ - ``cone`` -- a :class:`Cone
2531
+ <sage.geometry.cone.ConvexRationalPolyhedralCone>`. Can be
2532
+ omitted for an affine toric variety, in which case the
2533
+ (unique) generating cone is used.
2534
+
2535
+ - ``names`` -- (optional). Names of variables for the
2536
+ semigroup ring, see :func:`normalize_names` for acceptable
2537
+ formats. If not given, indexed variable names will be
2538
+ created automatically.
2539
+
2540
+ OUTPUT: the spectrum of the semigroup ring `\CC[\sigma^\vee \cap M]`
2541
+
2542
+ EXAMPLES::
2543
+
2544
+ sage: quadrant = Cone([(1,0), (0,1)])
2545
+ sage: AffineToricVariety(quadrant).Spec()
2546
+ Spectrum of Multivariate Polynomial Ring in z0, z1 over Rational Field
2547
+
2548
+ A more interesting example::
2549
+
2550
+ sage: A2Z2 = Cone([(0,1), (2,1)])
2551
+ sage: AffineToricVariety(A2Z2).Spec(names='u,v,t') # needs fpylll sage.libs.singular
2552
+ Spectrum of Quotient of Multivariate Polynomial Ring
2553
+ in u, v, t over Rational Field by the ideal (-u*v + t^2)
2554
+ """
2555
+ from sage.schemes.generic.spec import Spec
2556
+ R, I, dualcone = self._semigroup_ring(cone, names)
2557
+ return Spec(R.quotient(I))
2558
+
2559
+ def affine_algebraic_patch(self, cone=None, names=None):
2560
+ r"""
2561
+ Return the patch corresponding to ``cone`` as an affine
2562
+ algebraic subvariety.
2563
+
2564
+ INPUT:
2565
+
2566
+ - ``cone`` -- a :class:`Cone
2567
+ <sage.geometry.cone.ConvexRationalPolyhedralCone>` `\sigma`
2568
+ of the fan. It can be omitted for an affine toric variety,
2569
+ in which case the single generating cone is used.
2570
+
2571
+ OUTPUT:
2572
+
2573
+ A :class:`affine algebraic subscheme
2574
+ <sage.schemes.affine.affine_subscheme.AlgebraicScheme_subscheme_affine>`
2575
+ corresponding to the patch `\mathop{Spec}(\sigma^\vee \cap M)`
2576
+ associated to the cone `\sigma`.
2577
+
2578
+ See also :meth:`affine_patch`, which expresses the patches as
2579
+ subvarieties of affine toric varieties instead.
2580
+
2581
+ EXAMPLES::
2582
+
2583
+ sage: cone = Cone([(0,1), (2,1)])
2584
+ sage: A2Z2 = AffineToricVariety(cone)
2585
+ sage: A2Z2.affine_algebraic_patch() # needs fpylll sage.libs.singular
2586
+ Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
2587
+ -z0*z1 + z2^2
2588
+ sage: A2Z2.affine_algebraic_patch(Cone([(0,1)]), names='x, y, t') # needs fpylll sage.libs.singular
2589
+ Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
2590
+ 1
2591
+ """
2592
+ R, I, dualcone = self._semigroup_ring(cone, names)
2593
+ patch_cover = AffineSpace(R)
2594
+ patch = patch_cover.subscheme(I)
2595
+ return patch
2596
+
2597
+ def _orbit_closure_projection(self, cone, x):
2598
+ r"""
2599
+ Return the projection of ``x`` onto the quotient lattice of ``cone``.
2600
+
2601
+ INPUT:
2602
+
2603
+ - ``cone`` -- a :class:`cone
2604
+ <sage.geometry.cone.ConvexRationalPolyhedralCone>` of the :meth:`fan`
2605
+ of ``self``
2606
+
2607
+ - ``x`` -- a lattice point or a cone of the :meth:`fan` of ``self``
2608
+
2609
+ OUTPUT:
2610
+
2611
+ - the projection of ``x`` onto the quotient lattice of ``cone``, which
2612
+ is either a lattice point or a cone depending on the type of ``x``.
2613
+ This quotient lattice is the ambient lattice for the fan of the orbit
2614
+ closure corresponding to ``cone``.
2615
+
2616
+ If ``x`` is a cone not in the star of ``cone``, an :exc:`IndexError`
2617
+ is raised.
2618
+
2619
+ See :meth:`orbit_closure` for more details.
2620
+
2621
+ .. warning::
2622
+
2623
+ Due to incomplete support of quotient lattices (as of 12-07-2011),
2624
+ this function actually operates with a generic toric lattice of the
2625
+ same dimension as the appropriate quotient lattice. This behaviour
2626
+ is likely to change in the future releases of Sage.
2627
+
2628
+ EXAMPLES::
2629
+
2630
+ sage: P2 = toric_varieties.P2()
2631
+ sage: H = P2.fan(1)[0]
2632
+ sage: [P2._orbit_closure_projection(H, p) for p in P2.fan().rays()]
2633
+ [(0), (1), (-1)]
2634
+ sage: P2._orbit_closure_projection(H, P2.fan(2)[0])
2635
+ 1-d cone in 1-d lattice N
2636
+ """
2637
+ cone = self.fan().embed(cone)
2638
+ quot = cone.sublattice_quotient()
2639
+ if x in cone.lattice():
2640
+ result = vector(ZZ, quot(x))
2641
+ result.set_immutable()
2642
+ return result
2643
+
2644
+ assert isinstance(x, sage.geometry.abc.ConvexRationalPolyhedralCone)
2645
+ rays = [vector(quot(r)) for r in x.rays()]
2646
+ return Cone(rays)
2647
+
2648
+ # TODO: make the following work nicely.
2649
+ # if x in cone.lattice():
2650
+ # return quot(x)
2651
+ # assert x is ConvexRationalPolyhedralCone object
2652
+ # return Cone(x.rays(), lattice=quot)
2653
+
2654
+ def orbit_closure(self, cone):
2655
+ r"""
2656
+ Return the orbit closure of ``cone``.
2657
+
2658
+ The cones `\sigma` of a fan `\Sigma` are in one-to-one correspondence
2659
+ with the torus orbits `O(\sigma)` of the corresponding toric variety
2660
+ `X_\Sigma`. Each orbit is isomorphic to a lower dimensional torus (of
2661
+ dimension equal to the codimension of `\sigma`). Just like the toric
2662
+ variety `X_\Sigma` itself, these orbits are (partially) compactified by
2663
+ lower-dimensional orbits. In particular, one can define the closure
2664
+ `V(\sigma)` of the torus orbit `O(\sigma)` in the ambient toric
2665
+ variety `X_\Sigma`, which is again a toric variety.
2666
+
2667
+ See Proposition 3.2.7 of [CLS2011]_ for more details.
2668
+
2669
+ INPUT:
2670
+
2671
+ - ``cone`` -- a :class:`cone
2672
+ <sage.geometry.cone.ConvexRationalPolyhedralCone>` of the fan
2673
+
2674
+ OUTPUT:
2675
+
2676
+ - a torus orbit closure associated to ``cone`` as a
2677
+ :class:`toric variety <ToricVariety_field>`.
2678
+
2679
+ EXAMPLES::
2680
+
2681
+ sage: P1xP1 = toric_varieties.P1xP1()
2682
+ sage: H = P1xP1.fan(1)[0]
2683
+ sage: V = P1xP1.orbit_closure(H); V
2684
+ 1-d toric variety covered by 2 affine patches
2685
+ sage: V.embedding_morphism()
2686
+ Scheme morphism:
2687
+ From: 1-d toric variety covered by 2 affine patches
2688
+ To: 2-d CPR-Fano toric variety covered by 4 affine patches
2689
+ Defn: Defined by embedding the torus closure associated to the 1-d
2690
+ cone of Rational polyhedral fan in 2-d lattice N.
2691
+ sage: V.embedding_morphism().as_polynomial_map()
2692
+ Scheme morphism:
2693
+ From: 1-d toric variety covered by 2 affine patches
2694
+ To: 2-d CPR-Fano toric variety covered by 4 affine patches
2695
+ Defn: Defined on coordinates by sending [z0 : z1] to [0 : 1 : z1 : z0]
2696
+
2697
+ TESTS::
2698
+
2699
+ sage: A2 = toric_varieties.A2()
2700
+ sage: A2.orbit_closure(A2.fan(2)[0])
2701
+ 0-d affine toric variety
2702
+ """
2703
+ from sage.geometry.fan import discard_faces
2704
+ cone = self.fan().embed(cone)
2705
+ cones = [self._orbit_closure_projection(cone, star_cone)
2706
+ for star_cone in cone.star_generators()]
2707
+ fan = Fan(discard_faces(cones), check=False)
2708
+ orbit_closure = ToricVariety(fan)
2709
+
2710
+ star_rays = set()
2711
+ for star_cone in cone.star_generators():
2712
+ star_rays.update(star_cone.rays())
2713
+ ray_map = {ray: self._orbit_closure_projection(cone, ray) for ray in star_rays}
2714
+ from sage.schemes.toric.morphism import SchemeMorphism_orbit_closure_toric_variety
2715
+ orbit_closure._embedding_morphism = \
2716
+ SchemeMorphism_orbit_closure_toric_variety(orbit_closure.Hom(self), cone, ray_map)
2717
+
2718
+ return orbit_closure
2719
+
2720
+ def count_points(self):
2721
+ r"""
2722
+ Return the number of points of ``self``.
2723
+
2724
+ This is an alias for ``point_set().cardinality()``, see
2725
+ :meth:`~sage.schemes.toric.homset.SchemeHomset_points_toric_field.cardinality`
2726
+ for details.
2727
+
2728
+ EXAMPLES::
2729
+
2730
+ sage: o = lattice_polytope.cross_polytope(3)
2731
+ sage: V = ToricVariety(FaceFan(o))
2732
+ sage: V2 = V.change_ring(GF(2))
2733
+ sage: V2.point_set().cardinality()
2734
+ 27
2735
+ sage: V2.count_points()
2736
+ 27
2737
+ """
2738
+ return self.point_set().cardinality()
2739
+
2740
+ @cached_method
2741
+ def Demazure_roots(self):
2742
+ r"""
2743
+ Return the Demazure roots.
2744
+
2745
+ OUTPUT: the roots as points of the `M`-lattice
2746
+
2747
+ REFERENCES:
2748
+
2749
+ - [De1970]_
2750
+ - [Baz2011]_
2751
+
2752
+ EXAMPLES::
2753
+
2754
+ sage: P2 = toric_varieties.P2()
2755
+ sage: P2.Demazure_roots()
2756
+ (M(-1, 0), M(-1, 1), M(0, -1), M(0, 1), M(1, -1), M(1, 0))
2757
+
2758
+ Here are the remaining three examples listed in [Baz2011]_, Example 2.1 and 2.3::
2759
+
2760
+ sage: s = 3
2761
+ sage: cones = [(0,1), (1,2), (2,3), (3,0)]
2762
+ sage: Hs = ToricVariety(Fan(rays=[(1,0), (0,-1), (-1,s), (0,1)], cones=cones))
2763
+ sage: Hs.Demazure_roots()
2764
+ (M(-1, 0), M(1, 0), M(0, 1), M(1, 1), M(2, 1), M(3, 1))
2765
+
2766
+ sage: P11s = ToricVariety(Fan(rays=[(1,0), (0,-1), (-1,s)],
2767
+ ....: cones=[(0,1), (1,2), (2,0)]))
2768
+ sage: P11s.Demazure_roots()
2769
+ (M(-1, 0), M(1, 0), M(0, 1), M(1, 1), M(2, 1), M(3, 1))
2770
+ sage: P11s.Demazure_roots() == Hs.Demazure_roots()
2771
+ True
2772
+
2773
+ sage: Bs = ToricVariety(Fan(rays=[(s,1), (s,-1), (-s,-1), (-s,1)], cones=cones))
2774
+ sage: Bs.Demazure_roots()
2775
+ ()
2776
+
2777
+ TESTS::
2778
+
2779
+ sage: toric_varieties.A1().Demazure_roots()
2780
+ Traceback (most recent call last):
2781
+ ...
2782
+ NotImplementedError: Demazure_roots is only implemented for complete toric varieties
2783
+ """
2784
+ if not self.is_complete():
2785
+ raise NotImplementedError('Demazure_roots is only implemented '
2786
+ 'for complete toric varieties')
2787
+ antiK = -self.K()
2788
+ fan_rays = self.fan().rays()
2789
+ roots = [m for m in antiK.sections()
2790
+ if [ray * m for ray in fan_rays].count(-1) == 1]
2791
+ return tuple(roots)
2792
+
2793
+ def Aut_dimension(self):
2794
+ r"""
2795
+ Return the dimension of the automorphism group.
2796
+
2797
+ There are three kinds of symmetries of toric varieties:
2798
+
2799
+ * Toric automorphisms (rescaling of homogeneous coordinates)
2800
+
2801
+ * Demazure roots. These are translations `x_i \to x_i +
2802
+ \epsilon x^m` of a homogeneous coordinate `x_i` by a
2803
+ monomial `x^m` of the same homogeneous degree.
2804
+
2805
+ * Symmetries of the fan. These yield discrete subgroups.
2806
+
2807
+ OUTPUT:
2808
+
2809
+ An integer. The dimension of the automorphism group. Equals
2810
+ the dimension of the `M`-lattice plus the number of Demazure
2811
+ roots.
2812
+
2813
+ EXAMPLES::
2814
+
2815
+ sage: P2 = toric_varieties.P2()
2816
+ sage: P2.Aut_dimension()
2817
+ 8
2818
+
2819
+ TESTS::
2820
+
2821
+ sage: toric_varieties.A1().Aut_dimension()
2822
+ Traceback (most recent call last):
2823
+ ...
2824
+ NotImplementedError: Aut_dimension is only implemented for complete toric varieties
2825
+ """
2826
+ if not self.is_complete():
2827
+ raise NotImplementedError('Aut_dimension is only implemented '
2828
+ 'for complete toric varieties')
2829
+ return self.fan().lattice_dim() + len(self.Demazure_roots())
2830
+
2831
+
2832
+ def normalize_names(names=None, ngens=None, prefix=None, indices=None,
2833
+ return_prefix=False):
2834
+ r"""
2835
+ Return a list of names in the standard form.
2836
+
2837
+ INPUT:
2838
+
2839
+ All input parameters are optional.
2840
+
2841
+ - ``names`` -- names given either as a single string (with individual
2842
+ names separated by commas or spaces) or a list of strings with each
2843
+ string specifying a name. If the last name ends with the plus sign,
2844
+ "+", this name will be used as ``prefix`` (even if ``prefix`` was
2845
+ given explicitly).
2846
+
2847
+ - ``ngens`` -- number of names to be returned
2848
+
2849
+ - ``prefix`` -- prefix for the indexed names given as a string
2850
+
2851
+ - ``indices`` -- list of integers (default: ``range(ngens)``) used as
2852
+ indices for names with ``prefix``. If given, must be of length
2853
+ ``ngens``.
2854
+
2855
+ - ``return_prefix`` -- if ``True``, the last element of the returned list
2856
+ will contain the prefix determined from ``names`` or given as the
2857
+ parameter ``prefix``. This is useful if you may need more names in the
2858
+ future.
2859
+
2860
+ OUTPUT: list of names given as strings
2861
+
2862
+ These names are constructed in the following way:
2863
+
2864
+ #. If necessary, split ``names`` into separate names.
2865
+ #. If the last name ends with "+", put it into ``prefix``.
2866
+ #. If ``ngens`` was given, add to the names obtained so far as many
2867
+ indexed names as necessary to get this number. If the ``k``-th name of
2868
+ the *total* list of names is indexed, it is
2869
+ ``prefix + str(indices[k])``. If there were already more names than
2870
+ ``ngens``, discard "extra" ones.
2871
+ #. Check if constructed names are valid. See :func:`certify_names` for
2872
+ details.
2873
+ #. If the option ``return_prefix=True`` was given, add ``prefix`` to the
2874
+ end of the list.
2875
+
2876
+ EXAMPLES:
2877
+
2878
+ As promised, all parameters are optional::
2879
+
2880
+ sage: from sage.schemes.toric.variety import normalize_names
2881
+ sage: normalize_names()
2882
+ []
2883
+
2884
+ One of the most common uses is probably this one::
2885
+
2886
+ sage: normalize_names("x+", 4)
2887
+ ['x0', 'x1', 'x2', 'x3']
2888
+
2889
+ Now suppose that you want to enumerate your variables starting with one
2890
+ instead of zero::
2891
+
2892
+ sage: normalize_names("x+", 4, indices=list(range(1,5)))
2893
+ ['x1', 'x2', 'x3', 'x4']
2894
+
2895
+ You may actually have an arbitrary enumeration scheme::
2896
+
2897
+ sage: normalize_names("x+", 4, indices=[1, 10, 100, 1000])
2898
+ ['x1', 'x10', 'x100', 'x1000']
2899
+
2900
+ Now let's add some "explicit" names::
2901
+
2902
+ sage: normalize_names("x y z t+", 4)
2903
+ ['x', 'y', 'z', 't3']
2904
+
2905
+ Note that the "automatic" name is ``t3`` instead of ``t0``. This may seem
2906
+ weird, but the reason for this behaviour is that the fourth name in this
2907
+ list will be the same no matter how many explicit names were given::
2908
+
2909
+ sage: normalize_names("x y t+", 4)
2910
+ ['x', 'y', 't2', 't3']
2911
+
2912
+ This is especially useful if you get ``names`` from a user but want to
2913
+ specify all default names::
2914
+
2915
+ sage: normalize_names("x, y", 4, prefix='t')
2916
+ ['x', 'y', 't2', 't3']
2917
+
2918
+ In this format, the user can easily override your choice for automatic
2919
+ names::
2920
+
2921
+ sage: normalize_names("x y s+", 4, prefix='t')
2922
+ ['x', 'y', 's2', 's3']
2923
+
2924
+ Let's now use all parameters at once::
2925
+
2926
+ sage: normalize_names("x, y, s+", 4, prefix='t',
2927
+ ....: indices=list(range(1,5)), return_prefix=True)
2928
+ ['x', 'y', 's3', 's4', 's']
2929
+
2930
+ Note that you still need to give indices for all names, even if some of
2931
+ the first ones will be "wasted" because of the explicit names. The reason
2932
+ is the same as before - this ensures consistency of automatically
2933
+ generated names, no matter how many explicit names were given.
2934
+
2935
+ The prefix is discarded if ``ngens`` was not given::
2936
+
2937
+ sage: normalize_names("alpha, beta, gamma, zeta+")
2938
+ ['alpha', 'beta', 'gamma']
2939
+
2940
+ Finally, let's take a look at some possible mistakes::
2941
+
2942
+ sage: normalize_names("123")
2943
+ Traceback (most recent call last):
2944
+ ...
2945
+ ValueError: variable name '123' does not start with a letter
2946
+
2947
+ A more subtle one::
2948
+
2949
+ sage: normalize_names("x1", 4, prefix='x')
2950
+ Traceback (most recent call last):
2951
+ ...
2952
+ ValueError: variable name 'x1' appears more than once
2953
+ """
2954
+ if names is None:
2955
+ names = []
2956
+ elif isinstance(names, str):
2957
+ names = names.replace(",", " ").split()
2958
+ else:
2959
+ try:
2960
+ names = list(names)
2961
+ except TypeError:
2962
+ raise TypeError(
2963
+ "names must be a string or a list or tuple of them")
2964
+ for name in names:
2965
+ if not isinstance(name, str):
2966
+ raise TypeError(
2967
+ "names must be a string or a list or tuple of them")
2968
+ if names and names[-1].endswith("+"):
2969
+ prefix = names.pop()[:-1]
2970
+ if ngens is None:
2971
+ ngens = len(names)
2972
+ if len(names) < ngens:
2973
+ if prefix is None:
2974
+ raise IndexError("need %d names but only %d are given"
2975
+ % (ngens, len(names)))
2976
+ if indices is None:
2977
+ indices = list(range(ngens))
2978
+ elif len(indices) != ngens:
2979
+ raise ValueError("need exactly %d indices, but got %d"
2980
+ % (ngens, len(indices)))
2981
+ names += [prefix + str(i) for i in indices[len(names):]]
2982
+ if len(names) > ngens:
2983
+ names = names[:ngens]
2984
+ # Check that all given and constructed names are valid
2985
+ certify_names(names)
2986
+ if return_prefix:
2987
+ names.append(prefix)
2988
+ return names
2989
+
2990
+
2991
+ # *****************************************************************
2992
+ class CohomologyRing(QuotientRing_generic, UniqueRepresentation):
2993
+ r"""
2994
+ The (even) cohomology ring of a toric variety.
2995
+
2996
+ Irregardles of the variety's base ring, we always work with the
2997
+ variety over `\CC` and its topology.
2998
+
2999
+ The cohomology is always the singular cohomology with
3000
+ `\QQ`-coefficients. Note, however, that the cohomology of smooth
3001
+ toric varieties is torsion-free, so there is no loss of
3002
+ information in that case.
3003
+
3004
+ Currently, the toric variety must not be "too singular". See
3005
+ :meth:`ToricVariety_field.cohomology_ring` for a detailed
3006
+ description of which toric varieties are admissible. For such
3007
+ varieties the odd-dimensional cohomology groups vanish.
3008
+
3009
+ .. WARNING::
3010
+
3011
+ You should not create instances of this class manually. Use
3012
+ :meth:`ToricVariety_field.cohomology_ring` to generate the
3013
+ cohomology ring.
3014
+
3015
+ INPUT:
3016
+
3017
+ - ``variety`` -- a toric variety. Currently, the toric variety
3018
+ must be at least an orbifold. See
3019
+ :meth:`ToricVariety_field.cohomology_ring` for a detailed
3020
+ description of which toric varieties are admissible.
3021
+
3022
+ EXAMPLES::
3023
+
3024
+ sage: P2 = toric_varieties.P2()
3025
+ sage: P2.cohomology_ring()
3026
+ Rational cohomology ring of a 2-d CPR-Fano toric variety covered by 3 affine patches
3027
+
3028
+ This is equivalent to::
3029
+
3030
+ sage: from sage.schemes.toric.variety import CohomologyRing
3031
+ sage: CohomologyRing(P2)
3032
+ Rational cohomology ring of a 2-d CPR-Fano toric variety covered by 3 affine patches
3033
+ """
3034
+
3035
+ def __init__(self, variety):
3036
+ r"""
3037
+ See :class:`CohomologyRing` for documentation.
3038
+
3039
+ TESTS::
3040
+
3041
+ sage: P2 = toric_varieties.P2()
3042
+ sage: P2.cohomology_ring()
3043
+ Rational cohomology ring of a 2-d CPR-Fano toric variety covered by 3 affine patches
3044
+
3045
+ ::
3046
+
3047
+ sage: cone1 = Cone([(1,0)]); cone2 = Cone([(1,0)])
3048
+ sage: cone1 is cone2
3049
+ False
3050
+ sage: fan1 = Fan([cone1]); fan2 = Fan([cone2])
3051
+ sage: fan1 is fan2
3052
+ False
3053
+ sage: X1 = ToricVariety(fan1); X2 = ToricVariety(fan2)
3054
+ sage: X1 is X2
3055
+ False
3056
+ sage: X1.cohomology_ring() is X2.cohomology_ring() # see https://github.com/sagemath/sage/issues/10325
3057
+ True
3058
+ sage: TDiv = X1.toric_divisor_group()
3059
+ sage: X1.toric_divisor_group() is TDiv
3060
+ True
3061
+ sage: X2.toric_divisor_group() is TDiv
3062
+ True
3063
+ sage: TDiv.scheme() is X1 # as you expect
3064
+ True
3065
+ sage: TDiv.scheme() is X2 # perhaps less obvious, but toric_divisor_group is unique!
3066
+ False
3067
+ sage: TDiv.scheme() == X2 # isomorphic, but not necessarily identical
3068
+ True
3069
+ sage: TDiv.scheme().cohomology_ring() is X2.cohomology_ring() # this is where it gets tricky
3070
+ True
3071
+ sage: TDiv.gen(0).Chern_character() * X2.cohomology_ring().one() # needs sage.libs.singular
3072
+ [1]
3073
+ """
3074
+ self._variety = variety
3075
+
3076
+ if not variety.is_orbifold():
3077
+ raise NotImplementedError('requires an orbifold toric variety')
3078
+
3079
+ R = PolynomialRing(QQ, variety.variable_names())
3080
+ self._polynomial_ring = R
3081
+
3082
+ I = variety._fan.linear_equivalence_ideal(R) + variety._fan.Stanley_Reisner_ideal(R)
3083
+ super().__init__(R, I, names=variety.variable_names())
3084
+
3085
+ def _repr_(self):
3086
+ r"""
3087
+ Return a string representation of the cohomology ring.
3088
+
3089
+ OUTPUT: string
3090
+
3091
+ EXAMPLES::
3092
+
3093
+ sage: toric_varieties.P2().cohomology_ring()._repr_()
3094
+ 'Rational cohomology ring of a 2-d CPR-Fano toric variety covered by 3 affine patches'
3095
+ """
3096
+ return f'Rational cohomology ring of a {self._variety._repr_()}'
3097
+
3098
+ def _latex_(self):
3099
+ r"""
3100
+ Return a latex representation of the cohomology ring.
3101
+
3102
+ OUTPUT: string
3103
+
3104
+ EXAMPLES::
3105
+
3106
+ sage: cohomology_ring = toric_varieties.P2().cohomology_ring()
3107
+ sage: print(cohomology_ring._latex_()) # needs polytopes_db
3108
+ H^\ast\left(\mathbb{P}_{\Delta^{2}_{15}},\Bold{Q}\right)
3109
+ """
3110
+ return fr'H^\ast\left({self._variety._latex_()},{latex(QQ)}\right)'
3111
+
3112
+ def _element_constructor_(self, x):
3113
+ r"""
3114
+ Construct a :class:`CohomologyClass`.
3115
+
3116
+ INPUT:
3117
+
3118
+ - ``x`` -- something that defines a cohomology class. Either a
3119
+ cohomology class, a cone of the fan, or something that can
3120
+ be converted into a polynomial in the homogeneous
3121
+ coordinates.
3122
+
3123
+ OUTPUT: the :class:`CohomologyClass` defined by ``x``
3124
+
3125
+ EXAMPLES::
3126
+
3127
+ sage: # needs sage.libs.singular
3128
+ sage: dP6 = toric_varieties.dP6()
3129
+ sage: H = dP6.cohomology_ring()
3130
+ sage: cone = dP6.fan().cone_containing(2,3); cone
3131
+ 2-d cone of Rational polyhedral fan in 2-d lattice N
3132
+ sage: H(cone) # indirect doctest
3133
+ [-w^2]
3134
+ sage: H( Cone(cone) )
3135
+ [-w^2]
3136
+ sage: H( dP6.fan(0)[0] ) # trivial cone
3137
+ [1]
3138
+
3139
+ Non-smooth cones are a bit tricky. For such a cone, the
3140
+ intersection of the divisors corresponding to the rays is
3141
+ still proportional to the product of the variables, but the
3142
+ coefficient is a multiple depending on the orbifold
3143
+ singularity. See also [CLS2011]_, Lemma 12.5.2::
3144
+
3145
+ sage: # needs sage.libs.singular
3146
+ sage: P2_123 = toric_varieties.P2_123()
3147
+ sage: HH = P2_123.cohomology_ring()
3148
+ sage: HH(Cone([(1,0)])) * HH(Cone([(-2,-3)]))
3149
+ [2*z2^2]
3150
+ sage: HH(Cone([(1,0), (-2,-3)]))
3151
+ [6*z2^2]
3152
+ sage: [ HH(c) for c in P2_123.fan().generating_cones() ]
3153
+ [[6*z2^2], [6*z2^2], [6*z2^2]]
3154
+ sage: P2_123.volume_class()
3155
+ [6*z2^2]
3156
+ sage: [ HH(c.facets()[0]) * HH(c.facets()[1]) for c in P2_123.fan().generating_cones() ]
3157
+ [[6*z2^2], [3*z2^2], [2*z2^2]]
3158
+
3159
+ Numbers will be converted into the ring::
3160
+
3161
+ sage: # needs sage.libs.singular
3162
+ sage: P2 = toric_varieties.P2()
3163
+ sage: H = P2.cohomology_ring()
3164
+ sage: H._element_constructor_(1)
3165
+ [1]
3166
+ sage: H(1)
3167
+ [1]
3168
+ sage: type( H(1) )
3169
+ <class 'sage.schemes.toric.variety.CohomologyClass'>
3170
+ sage: P2.inject_variables()
3171
+ Defining x, y, z
3172
+ sage: H(1+x*y+z)
3173
+ [z^2 + z + 1]
3174
+ """
3175
+ fan = self._variety.fan()
3176
+ if isinstance(x, CohomologyClass) and x.parent() == self:
3177
+ return x
3178
+ if isinstance(x, QuotientRingElement):
3179
+ x = x.lift()
3180
+ elif isinstance(x, sage.geometry.abc.ConvexRationalPolyhedralCone):
3181
+ cone = fan.embed(x)
3182
+ assert cone.ambient() is fan
3183
+ mult = cone.rays().column_matrix().index_in_saturation()
3184
+ x = prod((self.cover_ring().gen(i) for i in cone.ambient_ray_indices()),
3185
+ z=self.cover_ring().one()) * mult
3186
+ else:
3187
+ try:
3188
+ # divisor, for example, know how to compute their own cohomology class
3189
+ return x.cohomology_class()
3190
+ except AttributeError:
3191
+ # this ensures that rationals are converted to cohomology ring elements
3192
+ x = self.cover_ring()(x)
3193
+ return CohomologyClass(self, x)
3194
+
3195
+ # We definitely should not override __call__, but since our
3196
+ # superclass QuotientRing_generic does not adhere to the coercion
3197
+ # model we cannot either. See
3198
+ # https://github.com/sagemath/sage/issues/9429
3199
+ def __call__(self, x, coerce=True):
3200
+ r"""
3201
+ Turn ``x`` into a ``CohomologyClass``.
3202
+
3203
+ EXAMPLES::
3204
+
3205
+ sage: # needs sage.libs.singular
3206
+ sage: P2 = toric_varieties.P2()
3207
+ sage: H = P2.cohomology_ring()
3208
+ sage: H(1)
3209
+ [1]
3210
+ sage: type( H(1) )
3211
+ <class 'sage.schemes.toric.variety.CohomologyClass'>
3212
+ """
3213
+ return self._element_constructor_(x)
3214
+
3215
+ def gens(self) -> tuple:
3216
+ r"""
3217
+ Return the generators of the cohomology ring.
3218
+
3219
+ OUTPUT:
3220
+
3221
+ A tuple of generators, one for each toric divisor of the toric
3222
+ variety ``X``. The order is the same as the ordering of the
3223
+ rays of the fan ``X.fan().rays()``, which is also the same as
3224
+ the ordering of the one-cones in ``X.fan(1)``
3225
+
3226
+ EXAMPLES::
3227
+
3228
+ sage: P2 = toric_varieties.P2()
3229
+ sage: P2.cohomology_ring().gens() # needs sage.libs.singular
3230
+ ([z], [z], [z])
3231
+ """
3232
+ if "_gens" not in self.__dict__:
3233
+ self._gens = tuple(self.gen(i)
3234
+ for i in range(self._variety.fan().nrays()))
3235
+ return self._gens
3236
+
3237
+ def gen(self, i):
3238
+ r"""
3239
+ Return a generator of the cohomology ring.
3240
+
3241
+ INPUT:
3242
+
3243
+ - ``i`` -- integer
3244
+
3245
+ OUTPUT:
3246
+
3247
+ The ``i``-th generator of the cohomology ring. If we denote
3248
+ the toric variety by ``X``, then this generator is
3249
+ associated to the ray ``X.fan().ray(i)``, which spans the
3250
+ one-cone ``X.fan(1)[i]``
3251
+
3252
+ EXAMPLES::
3253
+
3254
+ sage: P2 = toric_varieties.P2()
3255
+ sage: P2.cohomology_ring().gen(2) # needs sage.libs.singular
3256
+ [z]
3257
+ """
3258
+ return CohomologyClass(self, self._polynomial_ring.gen(i))
3259
+
3260
+
3261
+ # *****************************************************************
3262
+ def is_CohomologyClass(x):
3263
+ r"""
3264
+ Check whether ``x`` is a cohomology class of a toric variety.
3265
+
3266
+ INPUT:
3267
+
3268
+ - ``x`` -- anything
3269
+
3270
+ OUTPUT:
3271
+
3272
+ ``True`` or ``False`` depending on whether ``x`` is an instance of
3273
+ :class:`CohomologyClass`
3274
+
3275
+ EXAMPLES::
3276
+
3277
+ sage: P2 = toric_varieties.P2()
3278
+ sage: HH = P2.cohomology_ring()
3279
+ sage: from sage.schemes.toric.variety import is_CohomologyClass
3280
+ sage: is_CohomologyClass('z')
3281
+ doctest:warning...
3282
+ DeprecationWarning: The function is_CohomologyClass is deprecated;
3283
+ use 'isinstance(..., CohomologyClass)' instead.
3284
+ See https://github.com/sagemath/sage/issues/38277 for details.
3285
+ False
3286
+ sage: is_CohomologyClass( HH.one() ) # needs sage.libs.singular
3287
+ True
3288
+ sage: is_CohomologyClass( HH(P2.fan(1)[0]) ) # needs sage.libs.singular
3289
+ True
3290
+ """
3291
+ from sage.misc.superseded import deprecation
3292
+ deprecation(38277,
3293
+ "The function is_CohomologyClass is deprecated; "
3294
+ "use 'isinstance(..., CohomologyClass)' instead.")
3295
+ return isinstance(x, CohomologyClass)
3296
+
3297
+
3298
+ # *****************************************************************
3299
+ class CohomologyClass(QuotientRingElement):
3300
+ r"""
3301
+ An element of the :class:`CohomologyRing`.
3302
+
3303
+ .. WARNING::
3304
+
3305
+ You should not create instances of this class manually. The
3306
+ generators of the cohomology ring as well as the cohomology
3307
+ classes associated to cones of the fan can be obtained from
3308
+ :meth:`ToricVariety_field.cohomology_ring`.
3309
+
3310
+ EXAMPLES::
3311
+
3312
+ sage: # needs sage.libs.singular
3313
+ sage: P2 = toric_varieties.P2()
3314
+ sage: P2.cohomology_ring().gen(0)
3315
+ [z]
3316
+ sage: HH = P2.cohomology_ring()
3317
+ sage: HH.gen(0)
3318
+ [z]
3319
+ sage: cone = P2.fan(1)[0]; HH(cone)
3320
+ [z]
3321
+ """
3322
+
3323
+ def __init__(self, cohomology_ring, representative):
3324
+ r"""
3325
+ Construct the cohomology class.
3326
+
3327
+ INPUT:
3328
+
3329
+ - ``cohomology_ring`` -- :class:`CohomologyRing`
3330
+
3331
+ - ``representative`` -- a polynomial in the generators of the cohomology ring
3332
+
3333
+ OUTPUT: an instance of :class:`CohomologyClass`
3334
+
3335
+ EXAMPLES::
3336
+
3337
+ sage: P2 = toric_varieties.P2()
3338
+ sage: H = P2.cohomology_ring()
3339
+ sage: from sage.schemes.toric.variety import CohomologyClass
3340
+ sage: CohomologyClass(H, H.defining_ideal().ring().zero() ) # needs sage.libs.singular
3341
+ [0]
3342
+ """
3343
+ assert representative in cohomology_ring.defining_ideal().ring(), \
3344
+ 'The given representative is not in the parent polynomial ring.'
3345
+ super().__init__(cohomology_ring, representative)
3346
+
3347
+ def _repr_(self):
3348
+ r"""
3349
+ Return a string representation of the cohomology class.
3350
+
3351
+ OUTPUT: string
3352
+
3353
+ EXAMPLES::
3354
+
3355
+ sage: toric_varieties.P2().cohomology_ring().gen(0)._repr_() # needs sage.libs.singular
3356
+ '[z]'
3357
+ """
3358
+ return '[' + super()._repr_() + ']'
3359
+
3360
+ def _latex_(self):
3361
+ r"""
3362
+ Return a latex representation of the cohomology class.
3363
+
3364
+ OUTPUT: string
3365
+
3366
+ EXAMPLES::
3367
+
3368
+ sage: cohomology_class = toric_varieties.P2().cohomology_ring().gen(0)^2/2 # needs sage.libs.singular
3369
+ sage: cohomology_class._latex_() # needs sage.libs.singular
3370
+ '\\left[ \\frac{1}{2} z^{2} \\right]'
3371
+ """
3372
+ return r'\left[ %s \right]' % latex(self.lift())
3373
+
3374
+ def deg(self):
3375
+ r"""
3376
+ The degree of the cohomology class.
3377
+
3378
+ OUTPUT:
3379
+
3380
+ An integer `d` such that the cohomology class is in degree
3381
+ `2d`. If the cohomology class is of mixed degree, the highest
3382
+ degree is returned.
3383
+
3384
+ EXAMPLES::
3385
+
3386
+ sage: P2 = toric_varieties.P2()
3387
+ sage: P2.cohomology_ring().gen(0).deg() # needs sage.libs.singular
3388
+ 1
3389
+ sage: P2.cohomology_ring().zero().deg() # needs sage.libs.singular
3390
+ -1
3391
+ """
3392
+ return self.lift().degree()
3393
+
3394
+ def part_of_degree(self, d):
3395
+ r"""
3396
+ Project the (mixed-degree) cohomology class to the given degree.
3397
+
3398
+ .. MATH::
3399
+
3400
+ \mathop{pr}\nolimits_d:~ H^\bullet(X_\Delta,\QQ) \to H^{2d}(X_\Delta,\QQ)
3401
+
3402
+ INPUT:
3403
+
3404
+ - An integer ``d``
3405
+
3406
+ OUTPUT: the degree-``2d`` part of the cohomology class
3407
+
3408
+ EXAMPLES::
3409
+
3410
+ sage: # needs sage.libs.singular
3411
+ sage: P1xP1 = toric_varieties.P1xP1()
3412
+ sage: t = P1xP1.cohomology_ring().gen(0)
3413
+ sage: y = P1xP1.cohomology_ring().gen(2)
3414
+ sage: 3*t + 4*t^2*y + y + t*y + t + 1
3415
+ [t*y + 4*t + y + 1]
3416
+ sage: (3*t + 4*t^2*y + y + t*y + t + 1).part_of_degree(1)
3417
+ [4*t + y]
3418
+ """
3419
+ Q = self.parent()
3420
+ # We iterate over monomials of self.lift()
3421
+ p = [x for x in self.lift() if x[1].total_degree() == d]
3422
+ if not p:
3423
+ return Q.zero()
3424
+ else:
3425
+ return Q.sum(x[0] * x[1] for x in p)
3426
+
3427
+ def exp(self):
3428
+ r"""
3429
+ Exponentiate ``self``.
3430
+
3431
+ .. NOTE::
3432
+
3433
+ The exponential `\exp(x)` of a rational number `x` is
3434
+ usually not rational. Therefore, the cohomology class must
3435
+ not have a constant (degree zero) part. The coefficients
3436
+ in the Taylor series of `\exp` are rational, so any
3437
+ cohomology class without constant term can be
3438
+ exponentiated.
3439
+
3440
+ OUTPUT:
3441
+
3442
+ The cohomology class `\exp(` ``self`` `)` if the constant part
3443
+ vanishes, otherwise a :exc:`ValueError` is raised.
3444
+
3445
+ EXAMPLES::
3446
+
3447
+ sage: # needs sage.libs.singular
3448
+ sage: P2 = toric_varieties.P2()
3449
+ sage: H_class = P2.cohomology_ring().gen(0)
3450
+ sage: H_class
3451
+ [z]
3452
+ sage: H_class.exp()
3453
+ [1/2*z^2 + z + 1]
3454
+ """
3455
+ if not self.part_of_degree(0).is_zero():
3456
+ raise ValueError('must not have a constant part')
3457
+ exp_x = self.parent().one()
3458
+ for d in range(1, self.parent()._variety.dimension() + 1):
3459
+ exp_x += self**d / factorial(d)
3460
+ return exp_x