passagemath-polyhedra 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-polyhedra might be problematic. Click here for more details.
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +368 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +371 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +205 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.dylibs/libgmp.10.dylib +0 -0
- sage/all__sagemath_polyhedra.py +50 -0
- sage/game_theory/all.py +8 -0
- sage/game_theory/catalog.py +6 -0
- sage/game_theory/catalog_normal_form_games.py +923 -0
- sage/game_theory/cooperative_game.py +844 -0
- sage/game_theory/matching_game.py +1181 -0
- sage/game_theory/normal_form_game.py +2697 -0
- sage/game_theory/parser.py +275 -0
- sage/geometry/all__sagemath_polyhedra.py +22 -0
- sage/geometry/cone.py +6940 -0
- sage/geometry/cone_catalog.py +847 -0
- sage/geometry/cone_critical_angles.py +1027 -0
- sage/geometry/convex_set.py +1119 -0
- sage/geometry/fan.py +3743 -0
- sage/geometry/fan_isomorphism.py +389 -0
- sage/geometry/fan_morphism.py +1884 -0
- sage/geometry/hasse_diagram.py +202 -0
- sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
- sage/geometry/hyperplane_arrangement/all.py +1 -0
- sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
- sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
- sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
- sage/geometry/hyperplane_arrangement/library.py +825 -0
- sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
- sage/geometry/hyperplane_arrangement/plot.py +520 -0
- sage/geometry/integral_points.py +35 -0
- sage/geometry/integral_points_generic_dense.cpython-314-darwin.so +0 -0
- sage/geometry/integral_points_generic_dense.pyx +7 -0
- sage/geometry/lattice_polytope.py +5894 -0
- sage/geometry/linear_expression.py +773 -0
- sage/geometry/newton_polygon.py +767 -0
- sage/geometry/point_collection.cpython-314-darwin.so +0 -0
- sage/geometry/point_collection.pyx +1008 -0
- sage/geometry/polyhedral_complex.py +2616 -0
- sage/geometry/polyhedron/all.py +8 -0
- sage/geometry/polyhedron/backend_cdd.py +460 -0
- sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
- sage/geometry/polyhedron/backend_field.py +347 -0
- sage/geometry/polyhedron/backend_normaliz.py +2503 -0
- sage/geometry/polyhedron/backend_number_field.py +168 -0
- sage/geometry/polyhedron/backend_polymake.py +765 -0
- sage/geometry/polyhedron/backend_ppl.py +582 -0
- sage/geometry/polyhedron/base.py +1206 -0
- sage/geometry/polyhedron/base0.py +1444 -0
- sage/geometry/polyhedron/base1.py +886 -0
- sage/geometry/polyhedron/base2.py +812 -0
- sage/geometry/polyhedron/base3.py +1845 -0
- sage/geometry/polyhedron/base4.py +1262 -0
- sage/geometry/polyhedron/base5.py +2700 -0
- sage/geometry/polyhedron/base6.py +1741 -0
- sage/geometry/polyhedron/base7.py +997 -0
- sage/geometry/polyhedron/base_QQ.py +1258 -0
- sage/geometry/polyhedron/base_RDF.py +98 -0
- sage/geometry/polyhedron/base_ZZ.py +934 -0
- sage/geometry/polyhedron/base_mutable.py +215 -0
- sage/geometry/polyhedron/base_number_field.py +122 -0
- sage/geometry/polyhedron/cdd_file_format.py +155 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-darwin.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-darwin.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-darwin.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-darwin.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-darwin.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-darwin.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-darwin.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
- sage/geometry/polyhedron/constructor.py +773 -0
- sage/geometry/polyhedron/double_description.py +753 -0
- sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
- sage/geometry/polyhedron/face.py +1060 -0
- sage/geometry/polyhedron/generating_function.py +1810 -0
- sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
- sage/geometry/polyhedron/library.py +3502 -0
- sage/geometry/polyhedron/misc.py +121 -0
- sage/geometry/polyhedron/modules/all.py +1 -0
- sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
- sage/geometry/polyhedron/palp_database.py +447 -0
- sage/geometry/polyhedron/parent.py +1279 -0
- sage/geometry/polyhedron/plot.py +1986 -0
- sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
- sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
- sage/geometry/polyhedron/representation.py +1723 -0
- sage/geometry/pseudolines.py +515 -0
- sage/geometry/relative_interior.py +445 -0
- sage/geometry/toric_plotter.py +1103 -0
- sage/geometry/triangulation/all.py +2 -0
- sage/geometry/triangulation/base.cpython-314-darwin.so +0 -0
- sage/geometry/triangulation/base.pyx +963 -0
- sage/geometry/triangulation/data.h +147 -0
- sage/geometry/triangulation/data.pxd +4 -0
- sage/geometry/triangulation/element.py +914 -0
- sage/geometry/triangulation/functions.h +10 -0
- sage/geometry/triangulation/functions.pxd +4 -0
- sage/geometry/triangulation/point_configuration.py +2256 -0
- sage/geometry/triangulation/triangulations.h +49 -0
- sage/geometry/triangulation/triangulations.pxd +7 -0
- sage/geometry/voronoi_diagram.py +319 -0
- sage/interfaces/all__sagemath_polyhedra.py +1 -0
- sage/interfaces/polymake.py +2028 -0
- sage/numerical/all.py +13 -0
- sage/numerical/all__sagemath_polyhedra.py +11 -0
- sage/numerical/backends/all.py +1 -0
- sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
- sage/numerical/backends/cvxopt_backend.cpython-314-darwin.so +0 -0
- sage/numerical/backends/cvxopt_backend.pyx +1006 -0
- sage/numerical/backends/cvxopt_backend_test.py +19 -0
- sage/numerical/backends/cvxopt_sdp_backend.cpython-314-darwin.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-darwin.so +0 -0
- sage/numerical/backends/cvxpy_backend.pxd +41 -0
- sage/numerical/backends/cvxpy_backend.pyx +934 -0
- sage/numerical/backends/cvxpy_backend_test.py +13 -0
- sage/numerical/backends/generic_backend_test.py +24 -0
- sage/numerical/backends/interactivelp_backend.cpython-314-darwin.so +0 -0
- sage/numerical/backends/interactivelp_backend.pxd +36 -0
- sage/numerical/backends/interactivelp_backend.pyx +1231 -0
- sage/numerical/backends/interactivelp_backend_test.py +12 -0
- sage/numerical/backends/logging_backend.py +391 -0
- sage/numerical/backends/matrix_sdp_backend.cpython-314-darwin.so +0 -0
- sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
- sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
- sage/numerical/backends/ppl_backend.cpython-314-darwin.so +0 -0
- sage/numerical/backends/ppl_backend.pyx +1126 -0
- sage/numerical/backends/ppl_backend_test.py +13 -0
- sage/numerical/backends/scip_backend.cpython-314-darwin.so +0 -0
- sage/numerical/backends/scip_backend.pxd +22 -0
- sage/numerical/backends/scip_backend.pyx +1289 -0
- sage/numerical/backends/scip_backend_test.py +13 -0
- sage/numerical/interactive_simplex_method.py +5338 -0
- sage/numerical/knapsack.py +665 -0
- sage/numerical/linear_functions.cpython-314-darwin.so +0 -0
- sage/numerical/linear_functions.pxd +31 -0
- sage/numerical/linear_functions.pyx +1648 -0
- sage/numerical/linear_tensor.py +470 -0
- sage/numerical/linear_tensor_constraints.py +448 -0
- sage/numerical/linear_tensor_element.cpython-314-darwin.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-darwin.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-darwin.so +0 -0
- sage/numerical/sdp.pxd +39 -0
- sage/numerical/sdp.pyx +1433 -0
- sage/rings/all__sagemath_polyhedra.py +3 -0
- sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
- sage/rings/polynomial/omega.py +982 -0
- sage/schemes/all__sagemath_polyhedra.py +2 -0
- sage/schemes/toric/all.py +10 -0
- sage/schemes/toric/chow_group.py +1248 -0
- sage/schemes/toric/divisor.py +2082 -0
- sage/schemes/toric/divisor_class.cpython-314-darwin.so +0 -0
- sage/schemes/toric/divisor_class.pyx +322 -0
- sage/schemes/toric/fano_variety.py +1606 -0
- sage/schemes/toric/homset.py +650 -0
- sage/schemes/toric/ideal.py +451 -0
- sage/schemes/toric/library.py +1322 -0
- sage/schemes/toric/morphism.py +1958 -0
- sage/schemes/toric/points.py +1032 -0
- sage/schemes/toric/sheaf/all.py +1 -0
- sage/schemes/toric/sheaf/constructor.py +302 -0
- sage/schemes/toric/sheaf/klyachko.py +921 -0
- sage/schemes/toric/toric_subscheme.py +905 -0
- sage/schemes/toric/variety.py +3460 -0
- sage/schemes/toric/weierstrass.py +1078 -0
- sage/schemes/toric/weierstrass_covering.py +457 -0
- sage/schemes/toric/weierstrass_higher.py +288 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
|
@@ -0,0 +1,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
|