passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.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-2d945d6c.so.1 +0 -0
  7. passagemath_polyhedra.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  8. passagemath_polyhedra.libs/libgomp-1ede7ee7.so.1.0.0 +0 -0
  9. passagemath_polyhedra.libs/libstdc++-85f2cd6d.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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-linux-musl.so +0 -0
  131. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  132. sage/numerical/backends/cvxpy_backend.cpython-314-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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-aarch64-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,1032 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ # sage.doctest: needs sage.geometry.polyhedron sage.graphs
3
+ """
4
+ Enumerate points of a toric variety
5
+
6
+ The classes here are not meant to be instantiated manually. Instead,
7
+ you should always use the methods of the :class:`point set
8
+ <sage.schemes.toric.homset.SchemeHomset_points_toric_field>` of the
9
+ variety.
10
+
11
+ In this module, points are always represented by tuples instead of
12
+ Sage's class for points of the toric variety. All Sage library code
13
+ must then convert it to proper point objects before returning it to
14
+ the user.
15
+
16
+ EXAMPLES::
17
+
18
+ sage: P2 = toric_varieties.P2(base_ring=GF(3))
19
+ sage: point_set = P2.point_set()
20
+ sage: point_set.cardinality()
21
+ 13
22
+ sage: next(iter(point_set))
23
+ [0 : 0 : 1]
24
+ sage: list(point_set)[0:5]
25
+ [[0 : 0 : 1], [1 : 0 : 0], [0 : 1 : 0], [0 : 1 : 1], [0 : 1 : 2]]
26
+ """
27
+
28
+ # ****************************************************************************
29
+ # Copyright (C) 2013 Volker Braun <vbraun.name@gmail.com>
30
+ #
31
+ # This program is free software: you can redistribute it and/or modify
32
+ # it under the terms of the GNU General Public License as published by
33
+ # the Free Software Foundation, either version 2 of the License, or
34
+ # (at your option) any later version.
35
+ # https://www.gnu.org/licenses/
36
+ # ****************************************************************************
37
+
38
+ import itertools
39
+ from copy import copy
40
+
41
+ from sage.misc.misc_c import prod
42
+ from sage.misc.cachefunc import cached_method
43
+ from sage.arith.misc import GCD as gcd
44
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
45
+ from sage.parallel.decorate import Parallel
46
+
47
+
48
+ class InfinitePointEnumerator:
49
+
50
+ def __init__(self, fan, ring):
51
+ """
52
+ Point enumerator for infinite fields.
53
+
54
+ INPUT:
55
+
56
+ - ``fan`` -- fan of the toric variety
57
+
58
+ - ``ring`` -- infinite base ring over which to enumerate points
59
+
60
+ TESTS::
61
+
62
+ sage: from sage.schemes.toric.points import InfinitePointEnumerator
63
+ sage: fan = toric_varieties.P2().fan()
64
+ sage: n = InfinitePointEnumerator(fan, QQ)
65
+ sage: ni = iter(n)
66
+ sage: [next(ni) for k in range(10)]
67
+ [(0, 1, 1), (1, 1, 1), (-1, 1, 1), (1/2, 1, 1), (-1/2, 1, 1),
68
+ (2, 1, 1), (-2, 1, 1), (1/3, 1, 1), (-1/3, 1, 1), (3, 1, 1)]
69
+
70
+ sage: X = ToricVariety(Fan([], lattice=ZZ^0))
71
+ sage: X.point_set().cardinality()
72
+ 1
73
+ sage: X.base_ring().is_finite()
74
+ False
75
+ sage: X.point_set().list()
76
+ ([],)
77
+ """
78
+ self.ring = ring
79
+ self.fan = fan
80
+
81
+ def __iter__(self):
82
+ """
83
+ Iterate over the points.
84
+
85
+ OUTPUT: iterator over points
86
+
87
+ EXAMPLES::
88
+
89
+ sage: from sage.schemes.toric.points import InfinitePointEnumerator
90
+ sage: fan = toric_varieties.P2().fan()
91
+ sage: n = InfinitePointEnumerator(fan, QQ)
92
+ sage: ni = iter(n)
93
+ sage: [next(ni) for k in range(5)]
94
+ [(0, 1, 1), (1, 1, 1), (-1, 1, 1), (1/2, 1, 1), (-1/2, 1, 1)]
95
+ """
96
+ rays = self.fan().rays() + self.fan().virtual_rays()
97
+ n = len(rays)
98
+ if n == 0:
99
+ yield ()
100
+ else:
101
+ R = self.ring
102
+ p = [R.one() for k in range(n)]
103
+ for r in R:
104
+ p[0] = r
105
+ yield tuple(p)
106
+
107
+
108
+ class NaiveFinitePointEnumerator:
109
+
110
+ def __init__(self, fan, ring):
111
+ """
112
+ The naive point enumerator.
113
+
114
+ This is very slow.
115
+
116
+ INPUT:
117
+
118
+ - ``fan`` -- fan of the toric variety
119
+
120
+ - ``ring`` -- finite base ring over which to enumerate points
121
+
122
+ EXAMPLES::
123
+
124
+ sage: from sage.schemes.toric.points import NaiveFinitePointEnumerator
125
+ sage: fan = toric_varieties.P2().fan()
126
+ sage: n = NaiveFinitePointEnumerator(fan, GF(3))
127
+ sage: next(iter(n))
128
+ (0, 0, 1)
129
+ """
130
+ assert ring.is_finite()
131
+ self.ring = ring
132
+ self.fan = fan
133
+
134
+ @cached_method
135
+ def rays(self):
136
+ """
137
+ Return all rays (real and virtual).
138
+
139
+ OUTPUT: tuple of rays of the fan
140
+
141
+ EXAMPLES::
142
+
143
+ sage: from sage.schemes.toric.points import NaiveFinitePointEnumerator
144
+ sage: fan = toric_varieties.torus(2).fan()
145
+ sage: fan.rays()
146
+ Empty collection
147
+ in 2-d lattice N
148
+ sage: n = NaiveFinitePointEnumerator(fan, GF(3))
149
+ sage: n.rays()
150
+ N(1, 0),
151
+ N(0, 1)
152
+ in 2-d lattice N
153
+ """
154
+ return self.fan.rays() + self.fan.virtual_rays()
155
+
156
+ @cached_method
157
+ def units(self):
158
+ """
159
+ Return the units in the base field.
160
+
161
+ EXAMPLES::
162
+
163
+ sage: P2 = toric_varieties.P2(base_ring=GF(5))
164
+ sage: ne = P2.point_set()._naive_enumerator()
165
+ sage: ne.units()
166
+ (1, 2, 3, 4)
167
+ """
168
+ return tuple(x for x in self.ring if x != 0)
169
+
170
+ @cached_method
171
+ def roots(self, n):
172
+ """
173
+ Return the `n`-th roots in the base field.
174
+
175
+ INPUT:
176
+
177
+ - ``n`` -- integer
178
+
179
+ OUTPUT:
180
+
181
+ Tuple containing all `n`-th roots (not only the primitive
182
+ ones). In particular, 1 is included.
183
+
184
+ EXAMPLES::
185
+
186
+ sage: P2 = toric_varieties.P2(base_ring=GF(5))
187
+ sage: ne = P2.point_set()._naive_enumerator()
188
+ sage: ne.roots(2)
189
+ (1, 4)
190
+ sage: ne.roots(3)
191
+ (1,)
192
+ sage: ne.roots(4)
193
+ (1, 2, 3, 4)
194
+ """
195
+ return tuple(x for x in self.ring if x**n == self.ring.one())
196
+
197
+ def _Chow_group_free(self):
198
+ r"""
199
+ Return the relations coming from the free part of the Chow group.
200
+
201
+ OUTPUT:
202
+
203
+ A tuple containing the elements of $Hom(A_{d-1,\text{free}},
204
+ F^\times)$, including the identity.
205
+
206
+ EXAMPLES::
207
+
208
+ sage: # needs polytopes_db
209
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
210
+ sage: X = ToricVariety(fan, base_ring=GF(7))
211
+ sage: X.Chow_group().degree(1)
212
+ C3 x Z
213
+ sage: enum = X.point_set()._naive_enumerator()
214
+ sage: enum._Chow_group_free()
215
+ ((1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6))
216
+ """
217
+ units = self.units()
218
+ result = []
219
+ ker = self.rays().matrix().integer_kernel().matrix()
220
+ for phases in itertools.product(units, repeat=ker.nrows()):
221
+ phases = tuple(prod(mu**exponent for mu, exponent in zip(phases, column))
222
+ for column in ker.columns())
223
+ result.append(phases)
224
+ return tuple(sorted(result))
225
+
226
+ def _Chow_group_torsion(self):
227
+ r"""
228
+ Return the relations coming from the torsion part of the Chow group.
229
+
230
+ OUTPUT:
231
+
232
+ A tuple containing the non-identity elements of
233
+ `Hom(A_{d-1,\text{tors}}, F^\times)`
234
+
235
+ EXAMPLES::
236
+
237
+ sage: # needs polytopes_db
238
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
239
+ sage: X = ToricVariety(fan, base_ring=GF(7))
240
+ sage: X.Chow_group().degree(1)
241
+ C3 x Z
242
+ sage: enum = X.point_set()._naive_enumerator()
243
+ sage: enum._Chow_group_torsion()
244
+ ((1, 2, 4), (1, 4, 2))
245
+ """
246
+ if self.fan.is_smooth():
247
+ return ()
248
+ image = self.rays().column_matrix().image()
249
+ torsion = image.saturation().quotient(image)
250
+ result = set()
251
+ for t in torsion:
252
+ t_lift = t.lift()
253
+ for root in self.roots(t.order()):
254
+ phases = tuple(root**exponent for exponent in t_lift)
255
+ result.add(phases)
256
+ result.remove(tuple(self.ring.one() for r in self.rays()))
257
+ return tuple(sorted(result))
258
+
259
+ @cached_method
260
+ def rescalings(self):
261
+ r"""
262
+ Return the rescalings of homogeneous coordinates.
263
+
264
+ OUTPUT:
265
+
266
+ A tuple containing all points that are equivalent to
267
+ `[1:1:\dots:1]`, the distinguished point of the big torus
268
+ orbit.
269
+
270
+ EXAMPLES::
271
+
272
+ sage: P2_123 = toric_varieties.P2_123(base_ring=GF(5))
273
+ sage: ni = P2_123.point_set()._naive_enumerator()
274
+ sage: ni.rescalings()
275
+ ((1, 1, 1), (1, 4, 4), (4, 2, 3), (4, 3, 2))
276
+
277
+ sage: dP8 = toric_varieties.dP8(base_ring=GF(3))
278
+ sage: ni = dP8.point_set()._naive_enumerator()
279
+ sage: ni.rescalings()
280
+ ((1, 1, 1, 1), (1, 2, 2, 2), (2, 1, 2, 1), (2, 2, 1, 2))
281
+
282
+ sage: P1xP1 = toric_varieties.P1xP1(base_ring=GF(3))
283
+ sage: ni = P1xP1.point_set()._naive_enumerator()
284
+ sage: ni.rescalings()
285
+ ((1, 1, 1, 1), (1, 1, 2, 2), (2, 2, 1, 1), (2, 2, 2, 2))
286
+ """
287
+ free = self._Chow_group_free()
288
+ tors = self._Chow_group_torsion()
289
+ if len(tors) == 0: # optimization for smooth fans
290
+ return free
291
+ result = set(free)
292
+ for f in free:
293
+ for t in tors:
294
+ phases = tuple(x * y for x, y in zip(f, t))
295
+ result.add(phases)
296
+ return tuple(sorted(result))
297
+
298
+ def orbit(self, point):
299
+ """
300
+ Return the orbit of homogeneous coordinates under rescalings.
301
+
302
+ OUTPUT: the set of all homogeneous coordinates that are equivalent to ``point``
303
+
304
+ EXAMPLES::
305
+
306
+ sage: P2_123 = toric_varieties.P2_123(base_ring=GF(7))
307
+ sage: ne = P2_123.point_set()._naive_enumerator()
308
+ sage: sorted(ne.orbit([1, 0, 0]))
309
+ [(1, 0, 0), (2, 0, 0), (4, 0, 0)]
310
+ sage: sorted(ne.orbit([0, 1, 0]))
311
+ [(0, 1, 0), (0, 6, 0)]
312
+ sage: sorted(ne.orbit([0, 0, 1]))
313
+ [(0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 0, 5), (0, 0, 6)]
314
+ sage: sorted(ne.orbit([1, 1, 0]))
315
+ [(1, 1, 0), (1, 6, 0), (2, 1, 0), (2, 6, 0), (4, 1, 0), (4, 6, 0)]
316
+ """
317
+ result = set()
318
+ for phases in self.rescalings():
319
+ p = tuple(mu * z for mu, z in zip(point, phases))
320
+ result.add(p)
321
+ return frozenset(result)
322
+
323
+ def cone_iter(self):
324
+ """
325
+ Iterate over all cones of the fan.
326
+
327
+ OUTPUT:
328
+
329
+ Iterator over the cones, starting with the high-dimensional
330
+ ones.
331
+
332
+ EXAMPLES::
333
+
334
+ sage: dP6 = toric_varieties.dP6(base_ring=GF(11))
335
+ sage: ne = dP6.point_set()._naive_enumerator()
336
+ sage: for cone in ne.cone_iter():
337
+ ....: print(cone.ambient_ray_indices())
338
+ (0, 1)
339
+ (1, 2)
340
+ (2, 3)
341
+ (3, 4)
342
+ (4, 5)
343
+ (0, 5)
344
+ (0,)
345
+ (1,)
346
+ (2,)
347
+ (3,)
348
+ (4,)
349
+ (5,)
350
+ ()
351
+ """
352
+ fan = self.fan
353
+ for d in range(fan.dim(), -1, -1):
354
+ yield from fan.cones(d)
355
+
356
+ def coordinate_iter(self):
357
+ """
358
+ Iterate over all distinct homogeneous coordinates.
359
+
360
+ This method does NOT identify homogeneous coordinates that are
361
+ equivalent by a homogeneous rescaling.
362
+
363
+ OUTPUT: an iterator over the points
364
+
365
+ EXAMPLES::
366
+
367
+ sage: P2 = toric_varieties.P2(base_ring=GF(2))
368
+ sage: ni = P2.point_set()._naive_enumerator()
369
+ sage: list(ni.coordinate_iter())
370
+ [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 1, 1),
371
+ (1, 0, 1), (1, 1, 0), (1, 1, 1)]
372
+
373
+ sage: P1xP1 = toric_varieties.P1xP1(base_ring=GF(2))
374
+ sage: ni = P1xP1.point_set()._naive_enumerator()
375
+ sage: list(ni.coordinate_iter())
376
+ [(0, 1, 0, 1), (1, 0, 0, 1), (1, 0, 1, 0),
377
+ (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 1, 1),
378
+ (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)]
379
+
380
+ TESTS::
381
+
382
+ sage: V = ToricVariety(Fan([Cone([(1,1)])]), base_ring=GF(3))
383
+ sage: ni = V.point_set()._naive_enumerator()
384
+ sage: list(ni.coordinate_iter())
385
+ [(0, 1), (0, 2), (1, 1), (1, 2), (2, 1), (2, 2)]
386
+ """
387
+ units = [x for x in self.ring if x != 0]
388
+ zero = self.ring.zero()
389
+ big_torus = [units] * len(self.rays())
390
+ for cone in self.cone_iter():
391
+ patch = copy(big_torus)
392
+ for i in cone.ambient_ray_indices():
393
+ patch[i] = [zero]
394
+ for p in itertools.product(*patch):
395
+ yield tuple(p)
396
+
397
+ def __iter__(self):
398
+ """
399
+ Iterate over the distinct points of the toric variety.
400
+
401
+ This function does identify orbits under the homogeneous
402
+ rescalings, and returns precisely one representative per
403
+ orbit.
404
+
405
+ OUTPUT: an iterator over points
406
+
407
+ EXAMPLES::
408
+
409
+ sage: P2 = toric_varieties.P2(base_ring=GF(2))
410
+ sage: ni = P2.point_set()._naive_enumerator()
411
+ sage: list(ni)
412
+ [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 1, 1),
413
+ (1, 0, 1), (1, 1, 0), (1, 1, 1)]
414
+
415
+ sage: P1xP1 = toric_varieties.P1xP1(base_ring=GF(3))
416
+ sage: ni = P1xP1.point_set()._naive_enumerator()
417
+ sage: list(ni)
418
+ [(0, 1, 0, 1), (1, 0, 0, 1), (1, 0, 1, 0), (0, 1, 1, 0),
419
+ (0, 1, 1, 1), (0, 1, 1, 2), (1, 0, 1, 1), (1, 0, 1, 2),
420
+ (1, 1, 0, 1), (1, 2, 0, 1), (1, 1, 1, 0), (1, 2, 1, 0),
421
+ (1, 1, 1, 1), (1, 1, 1, 2), (1, 2, 1, 1), (1, 2, 1, 2)]
422
+ """
423
+ seen = set()
424
+ for p in self.coordinate_iter():
425
+ if p in seen:
426
+ continue
427
+ seen.update(self.orbit(p))
428
+ yield p
429
+
430
+
431
+ class FiniteFieldPointEnumerator(NaiveFinitePointEnumerator):
432
+
433
+ @cached_method
434
+ def multiplicative_generator(self):
435
+ """
436
+ Return the multiplicative generator of the finite field.
437
+
438
+ OUTPUT: a finite field element
439
+
440
+ EXAMPLES::
441
+
442
+ sage: point_set = toric_varieties.P2(base_ring=GF(5^2, 'a')).point_set() # needs sage.rings.finite_rings
443
+ sage: ffe = point_set._finite_field_enumerator() # needs sage.rings.finite_rings
444
+ sage: ffe.multiplicative_generator() # needs sage.rings.finite_rings
445
+ a
446
+ """
447
+ return self.ring.multiplicative_generator()
448
+
449
+ @cached_method
450
+ def multiplicative_group_order(self):
451
+ return self.ring.multiplicative_generator().multiplicative_order()
452
+
453
+ @cached_method
454
+ def root_generator(self, n):
455
+ """
456
+ Return a generator for :meth:`roots`.
457
+
458
+ INPUT:
459
+
460
+ - ``n`` -- integer
461
+
462
+ OUTPUT: a multiplicative generator for :meth:`roots`
463
+
464
+ EXAMPLES::
465
+
466
+ sage: point_set = toric_varieties.P2(base_ring=GF(5)).point_set()
467
+ sage: ffe = point_set._finite_field_enumerator()
468
+ sage: ffe.root_generator(2)
469
+ 4
470
+ sage: ffe.root_generator(3)
471
+ 1
472
+ sage: ffe.root_generator(4)
473
+ 2
474
+
475
+ TESTS::
476
+
477
+ sage: for p in primes(10): # needs sage.rings.finite_rings
478
+ ....: for k in range(1, 5):
479
+ ....: F = GF(p^k, 'a')
480
+ ....: N = F.cardinality() - 1
481
+ ....: ffe = point_set._finite_field_enumerator(F)
482
+ ....: assert N == ffe.multiplicative_group_order()
483
+ ....: for n in N.divisors():
484
+ ....: x = ffe.root_generator(n)
485
+ ....: assert set(x**i for i in range(N)) == set(ffe.roots(n))
486
+ """
487
+ N = self.multiplicative_group_order()
488
+ k = N // gcd(n, N)
489
+ return self.multiplicative_generator() ** k
490
+
491
+ def _Chow_group_free_generators(self):
492
+ r"""
493
+ Return generators for :meth:`_Chow_group_free_generators`.
494
+
495
+ OUTPUT:
496
+
497
+ A tuple containing generators for $Hom(A_{d-1,\text{free}},
498
+ F^\times)$.
499
+
500
+ EXAMPLES::
501
+
502
+ sage: # needs polytopes_db
503
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
504
+ sage: X = ToricVariety(fan, base_ring=GF(7))
505
+ sage: X.Chow_group().degree(1)
506
+ C3 x Z
507
+ sage: enum = X.point_set()._finite_field_enumerator()
508
+ sage: enum._Chow_group_free()
509
+ ((1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6))
510
+ sage: enum._Chow_group_free_generators()
511
+ ((3, 3, 3),)
512
+ """
513
+ result = []
514
+ null_space = self.rays().matrix().integer_kernel()
515
+ for ker in null_space.basis():
516
+ phases = tuple(self.multiplicative_generator()**exponent
517
+ for exponent in ker)
518
+ result.append(phases)
519
+ return tuple(sorted(result))
520
+
521
+ def _Chow_group_torsion_generators(self):
522
+ r"""
523
+ Return generators for :meth:`Chow_group_torsion`.
524
+
525
+ OUTPUT:
526
+
527
+ A tuple containing generators for
528
+ `Hom(A_{d-1,\text{tors}}, F^\times)`.
529
+
530
+ EXAMPLES::
531
+
532
+ sage: # needs polytopes_db
533
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
534
+ sage: X = ToricVariety(fan, base_ring=GF(7))
535
+ sage: X.Chow_group().degree(1)
536
+ C3 x Z
537
+ sage: enum = X.point_set()._finite_field_enumerator()
538
+ sage: enum._Chow_group_torsion()
539
+ ((1, 2, 4), (1, 4, 2))
540
+ sage: enum._Chow_group_torsion_generators()
541
+ ((1, 2, 4),)
542
+ """
543
+ if self.fan.is_smooth():
544
+ return ()
545
+ image = self.rays().column_matrix().image()
546
+ torsion = image.saturation().quotient(image)
547
+ result = set()
548
+ for t in torsion.gens():
549
+ t_lift = t.lift()
550
+ root = self.root_generator(t.order())
551
+ if root == 1:
552
+ continue
553
+ phases = tuple(root**exponent for exponent in t_lift)
554
+ result.add(phases)
555
+ assert tuple(self.ring.one() for r in self.rays()) not in result # because we excluded 1 as root
556
+ return tuple(sorted(result))
557
+
558
+ def log(self, z):
559
+ """
560
+ Return the component-wise log of ``z``.
561
+
562
+ INPUT:
563
+
564
+ - ``z`` -- list/tuple/iterable of nonzero finite field
565
+ elements
566
+
567
+ OUTPUT:
568
+
569
+ Tuple of integers. The logarithm with base the
570
+ :meth:`multiplicative_generator`.
571
+
572
+ EXAMPLES::
573
+
574
+ sage: # needs sage.rings.finite_rings
575
+ sage: F.<a> = GF(5^2)
576
+ sage: point_set = toric_varieties.P2_123(base_ring=F).point_set()
577
+ sage: ffe = point_set._finite_field_enumerator()
578
+ sage: z = tuple(a^i for i in range(25)); z
579
+ (1, a, a + 3, 4*a + 3, 2*a + 2, 4*a + 1, 2, 2*a, 2*a + 1, 3*a + 1,
580
+ 4*a + 4, 3*a + 2, 4, 4*a, 4*a + 2, a + 2, 3*a + 3, a + 4, 3, 3*a,
581
+ 3*a + 4, 2*a + 4, a + 1, 2*a + 3, 1)
582
+ sage: ffe.log(z)
583
+ (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
584
+ 17, 18, 19, 20, 21, 22, 23, 0)
585
+ sage: ffe.exp(ffe.log(z)) == z
586
+ True
587
+ sage: ffe.log(ffe.exp(range(24))) == tuple(range(24))
588
+ True
589
+ """
590
+ base = self.multiplicative_generator()
591
+ return tuple(zi.log(base) for zi in z)
592
+
593
+ def exp(self, powers):
594
+ """
595
+ Return the component-wise exp of ``z``.
596
+
597
+ INPUT:
598
+
599
+ - ``powers`` -- list/tuple/iterable of integers
600
+
601
+ OUTPUT:
602
+
603
+ Tuple of finite field elements. The powers of the
604
+ :meth:`multiplicative_generator`.
605
+
606
+ EXAMPLES::
607
+
608
+ sage: # needs sage.rings.finite_rings
609
+ sage: F.<a> = GF(5^2)
610
+ sage: point_set = toric_varieties.P2_123(base_ring=F).point_set()
611
+ sage: ffe = point_set._finite_field_enumerator()
612
+ sage: powers = list(range(24))
613
+ sage: ffe.exp(powers)
614
+ (1, a, a + 3, 4*a + 3, 2*a + 2, 4*a + 1, 2, 2*a, 2*a + 1, 3*a + 1,
615
+ 4*a + 4, 3*a + 2, 4, 4*a, 4*a + 2, a + 2, 3*a + 3, a + 4, 3, 3*a,
616
+ 3*a + 4, 2*a + 4, a + 1, 2*a + 3)
617
+ sage: ffe.log(ffe.exp(powers)) == tuple(powers)
618
+ True
619
+ """
620
+ base = self.multiplicative_generator()
621
+ return tuple(base ** i for i in powers)
622
+
623
+ @cached_method
624
+ def rescaling_log_generators(self):
625
+ """
626
+ Return the log generators of :meth:`rescalings`.
627
+
628
+ OUTPUT:
629
+
630
+ A tuple containing the logarithms (see :meth:`log`) of the
631
+ generators of the multiplicative group of :meth:`rescalings`.
632
+
633
+ EXAMPLES::
634
+
635
+ sage: point_set = toric_varieties.P2_123(base_ring=GF(5)).point_set()
636
+ sage: ffe = point_set._finite_field_enumerator()
637
+ sage: ffe.rescalings()
638
+ ((1, 1, 1), (1, 4, 4), (4, 2, 3), (4, 3, 2))
639
+ sage: list(map(ffe.log, ffe.rescalings()))
640
+ [(0, 0, 0), (0, 2, 2), (2, 1, 3), (2, 3, 1)]
641
+ sage: ffe.rescaling_log_generators()
642
+ ((2, 3, 1),)
643
+ """
644
+ free = self._Chow_group_free_generators()
645
+ tors = self._Chow_group_torsion_generators()
646
+ result = map(self.log, free + tors)
647
+ return tuple(sorted(result))
648
+
649
+ def cone_points_iter(self):
650
+ """
651
+ Iterate over the open torus orbits and yield distinct points.
652
+
653
+ OUTPUT:
654
+
655
+ For each open torus orbit (cone): A triple consisting of the
656
+ cone, the nonzero homogeneous coordinates in that orbit (list
657
+ of integers), and the nonzero log coordinates of distinct
658
+ points as a cokernel.
659
+
660
+ EXAMPLES::
661
+
662
+ sage: # needs polytopes_db
663
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
664
+ sage: X = ToricVariety(fan, base_ring=GF(7))
665
+ sage: point_set = X.point_set()
666
+ sage: ffe = point_set._finite_field_enumerator()
667
+ sage: cpi = ffe.cone_points_iter()
668
+ sage: cone, nonzero_points, cokernel = list(cpi)[5]
669
+ sage: cone
670
+ 1-d cone of Rational polyhedral fan in 2-d lattice N
671
+ sage: cone.ambient_ray_indices()
672
+ (2,)
673
+ sage: nonzero_points
674
+ [0, 1]
675
+ sage: cokernel
676
+ Finitely generated module V/W over Integer Ring with invariants (2)
677
+ sage: list(cokernel)
678
+ [(0), (1)]
679
+ sage: [p.lift() for p in cokernel]
680
+ [(0, 0), (0, 1)]
681
+ """
682
+ from sage.matrix.constructor import matrix, block_matrix, identity_matrix
683
+ from sage.rings.integer_ring import ZZ
684
+ nrays = len(self.rays())
685
+ N = self.multiplicative_group_order()
686
+ # Want cokernel of the log rescalings in (ZZ/N)^(#rays). But
687
+ # ZZ/N is not a integral domain. Instead: work over ZZ
688
+ log_generators = self.rescaling_log_generators()
689
+ log_relations = block_matrix(2, 1, [
690
+ matrix(ZZ, len(log_generators), nrays, log_generators),
691
+ N * identity_matrix(ZZ, nrays)])
692
+ for cone in self.cone_iter():
693
+ nrays = self.fan().nrays() + len(self.fan().virtual_rays())
694
+ nonzero_coordinates = [i for i in range(nrays)
695
+ if i not in cone.ambient_ray_indices()]
696
+ log_relations_nonzero = log_relations.matrix_from_columns(nonzero_coordinates)
697
+ image = log_relations_nonzero.image()
698
+ cokernel = image.ambient_module().quotient(image)
699
+ yield cone, nonzero_coordinates, cokernel
700
+
701
+ def __iter__(self):
702
+ """
703
+ Iterate over the distinct points of the toric variety.
704
+
705
+ This function does identify orbits under the homogeneous
706
+ rescalings, and returns precisely one representative per
707
+ orbit.
708
+
709
+ OUTPUT: iterator over points
710
+
711
+ EXAMPLES::
712
+
713
+ sage: point_set = toric_varieties.P2(base_ring=GF(2)).point_set()
714
+ sage: ffe = point_set._finite_field_enumerator()
715
+ sage: list(ffe)
716
+ [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 1, 1),
717
+ (1, 0, 1), (1, 1, 0), (1, 1, 1)]
718
+
719
+ sage: # needs polytopes_db
720
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
721
+ sage: X = ToricVariety(fan, base_ring=GF(7))
722
+ sage: point_set = X.point_set()
723
+ sage: ffe = point_set._finite_field_enumerator()
724
+ sage: list(ffe)
725
+ [(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 1, 1), (0, 1, 3), (1, 0, 1),
726
+ (1, 0, 3), (1, 1, 0), (1, 3, 0), (1, 1, 1), (1, 1, 3), (1, 1, 2),
727
+ (1, 1, 6), (1, 1, 4), (1, 1, 5), (1, 3, 2), (1, 3, 6), (1, 3, 4),
728
+ (1, 3, 5), (1, 3, 1), (1, 3, 3)]
729
+ sage: set(point_set._naive_enumerator()) == set(ffe)
730
+ True
731
+ """
732
+ nrays = len(self.rays())
733
+ for cone, nonzero_coordinates, cokernel in self.cone_points_iter():
734
+ zero = [self.ring.zero()] * nrays
735
+ for v in cokernel:
736
+ z_nonzero = self.exp(v.lift())
737
+ z = copy(zero)
738
+ for i, value in zip(nonzero_coordinates, z_nonzero):
739
+ z[i] = value
740
+ yield tuple(z)
741
+
742
+ def cardinality(self):
743
+ """
744
+ Return the cardinality of the point set.
745
+
746
+ OUTPUT: integer; the number of points
747
+
748
+ EXAMPLES::
749
+
750
+ sage: # needs polytopes_db
751
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
752
+ sage: X = ToricVariety(fan, base_ring=GF(7))
753
+ sage: point_set = X.point_set()
754
+ sage: ffe = point_set._finite_field_enumerator()
755
+ sage: ffe.cardinality()
756
+ 21
757
+ """
758
+ n = 0
759
+ for cone, nonzero_coordinates, cokernel in self.cone_points_iter():
760
+ n += cokernel.cardinality()
761
+ return n
762
+
763
+
764
+ class NaiveSubschemePointEnumerator:
765
+
766
+ def __init__(self, polynomials, ambient):
767
+ """
768
+ Point enumerator for algebraic subschemes of toric varieties.
769
+
770
+ INPUT:
771
+
772
+ - ``polynomials`` -- list/tuple/iterable of polynomials; the
773
+ defining polynomials
774
+
775
+ - ``ambient`` -- enumerator for ambient space points
776
+
777
+ TESTS::
778
+
779
+ sage: P2.<x,y,z> = toric_varieties.P2()
780
+ sage: from sage.schemes.toric.points import NaiveSubschemePointEnumerator
781
+ sage: ne = NaiveSubschemePointEnumerator(
782
+ ....: [x^2 + y^2 - 2*z^2], P2.point_set()._enumerator())
783
+ sage: next(iter(ne))
784
+ (1, 1, 1)
785
+ """
786
+ self.ambient = ambient
787
+ self.polynomials = tuple(polynomials)
788
+
789
+ def __iter__(self):
790
+ """
791
+ Iterate over the distinct points of the toric variety.
792
+
793
+ This function does identify orbits under the homogeneous
794
+ rescalings, and returns precisely one representative per
795
+ orbit.
796
+
797
+ OUTPUT:
798
+
799
+ Iterator over points. Each point is represented by a tuple of
800
+ homogeneous coordinates.
801
+
802
+ EXAMPLES::
803
+
804
+ sage: P2.<x,y,z> = toric_varieties.P2()
805
+ sage: from sage.schemes.toric.points import NaiveSubschemePointEnumerator
806
+ sage: ne = NaiveSubschemePointEnumerator(
807
+ ....: [x^2 + y^2 - 2*z^2], P2.point_set()._enumerator())
808
+ sage: next(iter(ne))
809
+ (1, 1, 1)
810
+ """
811
+ for p in self.ambient:
812
+ if all(eq(p) == 0 for eq in self.polynomials):
813
+ yield p
814
+
815
+
816
+ class FiniteFieldSubschemePointEnumerator(NaiveSubschemePointEnumerator):
817
+
818
+ def inhomogeneous_equations(self, ring, nonzero_coordinates, cokernel):
819
+ """
820
+ Inhomogenize the defining polynomials.
821
+
822
+ INPUT:
823
+
824
+ - ``ring`` -- the polynomial ring for inhomogeneous
825
+ coordinates
826
+
827
+ - ``nonzero_coordinates`` -- list of integers. The indices of
828
+ the nonzero homogeneous coordinates in the patch
829
+
830
+ - ``cokernel`` -- the logs of the nonzero coordinates of
831
+ all distinct points as a cokernel. See
832
+ :meth:`FiniteFieldPointEnumerator.cone_points_iter`.
833
+
834
+ EXAMPLES::
835
+
836
+ sage: R.<s> = QQ[]
837
+ sage: P2.<x,y,z> = toric_varieties.P2(base_ring=GF(7))
838
+ sage: X = P2.subscheme([x^3 + 2*y^3 + 3*z^3, x*y*z + x*y^2])
839
+ sage: point_set = X.point_set()
840
+ sage: ffe = point_set._enumerator()
841
+ sage: cone, nonzero_coordinates, cokernel = list(ffe.ambient.cone_points_iter())[5]
842
+ sage: cone.ambient_ray_indices(), nonzero_coordinates
843
+ ((2,), [0, 1])
844
+ sage: ffe.inhomogeneous_equations(R, nonzero_coordinates, cokernel)
845
+ [2*s^3 + 1, s^2]
846
+ """
847
+ nrays = len(self.ambient.rays())
848
+ z_nonzero = [ring.one()] * len(nonzero_coordinates)
849
+ for t, v in zip(ring.gens(), cokernel.gens()):
850
+ for i, exponent in enumerate(v.lift()):
851
+ z_nonzero[i] *= t**exponent
852
+ z = [ring.zero()] * nrays
853
+ for i, value in zip(nonzero_coordinates, z_nonzero):
854
+ z[i] = value
855
+ return [poly.change_ring(ring)(z) for poly in self.polynomials]
856
+
857
+ def solutions_serial(self, inhomogeneous_equations, log_range):
858
+ """
859
+ Iterate over solutions in a range.
860
+
861
+ INPUT:
862
+
863
+ - ``inhomogeneous_equations`` -- list/tuple/iterable of
864
+ inhomogeneous equations (i.e. output from
865
+ :meth:`inhomogeneous_equations`).
866
+
867
+ - ``log_range`` -- list/tuple/iterable of integer ranges. One
868
+ for each inhomogeneous coordinate. The logarithms of the
869
+ homogeneous coordinates.
870
+
871
+ OUTPUT:
872
+
873
+ All solutions (as tuple of log inhomogeneous coordinates) in
874
+ the Cartesian product of the ranges.
875
+
876
+ EXAMPLES::
877
+
878
+ sage: R.<s> = GF(7)[]
879
+ sage: P2.<x,y,z> = toric_varieties.P2(base_ring=GF(7))
880
+ sage: X = P2.subscheme(1)
881
+ sage: point_set = X.point_set()
882
+ sage: ffe = point_set._enumerator()
883
+ sage: ffe.solutions_serial([s^2 - 1, s^6 - s^2], [range(6)])
884
+ <generator object ...solutions_serial at 0x...>
885
+ sage: list(_)
886
+ [(0,), (3,)]
887
+ """
888
+ from itertools import product
889
+ for log_t in product(*log_range):
890
+ t = self.ambient.exp(log_t)
891
+ if all(poly(t) == 0 for poly in inhomogeneous_equations):
892
+ yield log_t
893
+
894
+ def solutions(self, inhomogeneous_equations, log_range):
895
+ """
896
+ Parallel version of :meth:`solutions_serial`.
897
+
898
+ INPUT/OUTPUT:
899
+
900
+ Same as :meth:`solutions_serial`, except that the output
901
+ points are in random order. Order depends on the number of
902
+ processors and relative speed of separate processes.
903
+
904
+ EXAMPLES::
905
+
906
+ sage: R.<s> = GF(7)[]
907
+ sage: P2.<x,y,z> = toric_varieties.P2(base_ring=GF(7))
908
+ sage: X = P2.subscheme(1)
909
+ sage: point_set = X.point_set()
910
+ sage: ffe = point_set._enumerator()
911
+ sage: ffe.solutions([s^2 - 1, s^6 - s^2], [range(6)])
912
+ <generator object ...solutions at 0x...>
913
+ sage: sorted(_)
914
+ [(0,), (3,)]
915
+ """
916
+ # Do simple cases in one process (this includes most doctests)
917
+ if len(log_range) <= 2:
918
+ for log_t in self.solutions_serial(inhomogeneous_equations, log_range):
919
+ yield log_t
920
+ return
921
+ # Parallelize the outermost loop of the Cartesian product
922
+ work = [([[r]] + log_range[1:],) for r in log_range[0]]
923
+ parallel = Parallel()
924
+
925
+ def partial_solution(work_range):
926
+ return list(self.solutions_serial(inhomogeneous_equations, work_range))
927
+ for partial_result in parallel(partial_solution)(work):
928
+ for log_t in partial_result[-1]:
929
+ yield log_t
930
+
931
+ def homogeneous_coordinates(self, log_t, nonzero_coordinates, cokernel):
932
+ """
933
+ Convert the log of inhomogeneous coordinates back to homogeneous coordinates.
934
+
935
+ INPUT:
936
+
937
+ - ``log_t`` -- log of inhomogeneous coordinates of a point
938
+
939
+ - ``nonzero_coordinates`` -- the nonzero homogeneous
940
+ coordinates in the patch
941
+
942
+ - ``cokernel`` -- the logs of the nonzero coordinates of
943
+ all distinct points as a cokernel. See
944
+ :meth:`FiniteFieldPointEnumerator.cone_points_iter`.
945
+
946
+ OUTPUT: the same point, but as a tuple of homogeneous coordinates
947
+
948
+ EXAMPLES::
949
+
950
+ sage: P2.<x,y,z> = toric_varieties.P2(base_ring=GF(7))
951
+ sage: X = P2.subscheme([x^3 + 2*y^3 + 3*z^3, x*y*z + x*y^2])
952
+ sage: point_set = X.point_set()
953
+ sage: ffe = point_set._enumerator()
954
+ sage: cone, nonzero_coordinates, cokernel = list(ffe.ambient.cone_points_iter())[5]
955
+ sage: cone.ambient_ray_indices(), nonzero_coordinates
956
+ ((2,), [0, 1])
957
+ sage: ffe.homogeneous_coordinates([0], nonzero_coordinates, cokernel)
958
+ (1, 1, 0)
959
+ sage: ffe.homogeneous_coordinates([1], nonzero_coordinates, cokernel)
960
+ (1, 3, 0)
961
+ sage: ffe.homogeneous_coordinates([2], nonzero_coordinates, cokernel)
962
+ (1, 2, 0)
963
+ """
964
+ z = [self.ambient.ring.zero()] * len(self.ambient.rays())
965
+ z_nonzero = self.ambient.exp(
966
+ cokernel.linear_combination_of_smith_form_gens(log_t).lift())
967
+ for i, value in enumerate(z_nonzero):
968
+ z[nonzero_coordinates[i]] = value
969
+ return tuple(z)
970
+
971
+ def __iter__(self):
972
+ """
973
+ Iterate over the distinct points of the toric variety.
974
+
975
+ This function does identify orbits under the homogeneous
976
+ rescalings, and returns precisely one representative per
977
+ orbit.
978
+
979
+ OUTPUT:
980
+
981
+ Iterator over points. Each point is represented by a tuple of
982
+ homogeneous coordinates.
983
+
984
+ EXAMPLES::
985
+
986
+ sage: P2.<x,y,z> = toric_varieties.P2(base_ring=GF(7))
987
+ sage: X = P2.subscheme([x^3 + 2*y^3 + 3*z^3, x*y*z + x*y^2])
988
+ sage: point_set = X.point_set()
989
+ sage: ffe = point_set._enumerator()
990
+ sage: list(ffe) # indirect doctest
991
+ [(1, 1, 6), (1, 2, 5), (1, 4, 3)]
992
+ """
993
+ for cone, nonzero_coordinates, cokernel in self.ambient.cone_points_iter():
994
+ R = PolynomialRing(self.ambient.ring, cokernel.ngens(), 't')
995
+ inhomogeneous = self.inhomogeneous_equations(R, nonzero_coordinates, cokernel)
996
+ log_range = [range(I) for I in cokernel.invariants()]
997
+ for log_t in self.solutions(inhomogeneous, log_range):
998
+ yield self.homogeneous_coordinates(log_t, nonzero_coordinates,
999
+ cokernel)
1000
+
1001
+ def cardinality(self):
1002
+ """
1003
+ Return the cardinality of the point set.
1004
+
1005
+ OUTPUT: integer; the number of points
1006
+
1007
+ EXAMPLES::
1008
+
1009
+ sage: fan = NormalFan(ReflexivePolytope(2, 0))
1010
+ sage: X.<u,v,w> = ToricVariety(fan, base_ring=GF(7))
1011
+ sage: Y = X.subscheme(u^3 + v^3 + w^3 + u*v*w)
1012
+ sage: point_set = Y.point_set()
1013
+ sage: list(point_set) # needs fpylll
1014
+ [[0 : 1 : 3],
1015
+ [1 : 0 : 3],
1016
+ [1 : 3 : 0],
1017
+ [1 : 1 : 6],
1018
+ [1 : 1 : 4],
1019
+ [1 : 3 : 2],
1020
+ [1 : 3 : 5]]
1021
+ sage: ffe = point_set._enumerator() # needs fpylll
1022
+ sage: ffe.cardinality() # needs fpylll
1023
+ 7
1024
+ """
1025
+ n = 0
1026
+ for cone, nonzero_coordinates, cokernel in self.ambient.cone_points_iter():
1027
+ R = PolynomialRing(self.ambient.ring, cokernel.ngens(), 't')
1028
+ inhomogeneous = self.inhomogeneous_equations(R, nonzero_coordinates, cokernel)
1029
+ log_range = [range(I) for I in cokernel.invariants()]
1030
+ for log_t in self.solutions(inhomogeneous, log_range):
1031
+ n += 1
1032
+ return n