Skip to content

Commit 83db266

Browse files
author
Release Manager
committed
gh-35778: Return the points in the ring of integers after renormalization <!-- Please provide a concise, informative and self-explanatory title. --> <!-- Don't put issue numbers in the title. Put it in the Description below. --> <!-- For example, instead of "Fixes #12345", use "Add a new method to multiply two integers" --> ### 📚 Description <!-- Describe your changes here in detail. --> <!-- Why is this change required? What problem does it solve? --> <!-- If this PR resolves an open issue, please link to it here. For example "Fixes #12345". --> <!-- If your change requires a documentation PR, please link it appropriately. --> `points_of_bounded_height` function in `proj_bdd_height.py` now returns correct results after renormalization by scaling, if in the ring of integers. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x ]`. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - #12345: short description why this is a dependency - #34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: #35778 Reported by: Jing Guo Reviewer(s):
2 parents fba3ecf + 0ed83e9 commit 83db266

File tree

2 files changed

+345
-140
lines changed

2 files changed

+345
-140
lines changed

src/sage/schemes/projective/proj_bdd_height.py

Lines changed: 120 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,71 +22,143 @@
2222
from math import floor
2323

2424
from sage.schemes.projective.projective_space import ProjectiveSpace
25+
from sage.rings.integer_ring import ZZ
2526
from sage.rings.rational_field import QQ
2627
from sage.rings.real_mpfr import RealField
2728
from sage.rings.number_field.unit_group import UnitGroup
28-
from sage.arith.misc import GCD as gcd
29+
from sage.arith.misc import gcd
30+
from sage.arith.functions import lcm
2931
from sage.matrix.constructor import matrix, column_matrix
3032
from sage.libs.pari.all import pari
3133
from sage.modules.free_module_element import vector
3234
from sage.rings.integer import Integer
3335
from sage.geometry.polyhedron.constructor import Polyhedron
3436

3537

36-
def QQ_points_of_bounded_height(dim, bound):
38+
def ZZ_points_of_bounded_height(PS, dim, bound):
3739
r"""
3840
Return an iterator of the points in ``self`` of absolute multiplicative
3941
height of at most ``bound`` in the rational field.
4042
4143
INPUT:
4244
45+
- ``PS`` -- a projective space
46+
47+
- ``dim`` -- a positive integer
48+
49+
- ``bound`` -- a positive integer
50+
51+
OUTPUT:
52+
53+
- an iterator of points of bounded height
54+
55+
EXAMPLES:
56+
57+
sage: from sage.schemes.projective.proj_bdd_height import ZZ_points_of_bounded_height
58+
sage: PS = ProjectiveSpace(ZZ, 1)
59+
sage: sorted(list(ZZ_points_of_bounded_height(PS, 1, 1)))
60+
[(-1 : -1), (-1 : 0), (-1 : 1), (0 : -1)]
61+
sage: len(list(ZZ_points_of_bounded_height(PS, 1, 5)))
62+
40
63+
sage: sorted(list(ZZ_points_of_bounded_height(PS, 1, 2)))
64+
[(-2 : -1), (-2 : 1), (-1 : -2), (-1 : -1),
65+
(-1 : 0), (-1 : 1), (-1 : 2), (0 : -1)]
66+
sage: PS = ProjectiveSpace(ZZ, 2)
67+
sage: sorted(list(ZZ_points_of_bounded_height(PS, 2, 1)))
68+
[(-1 : -1 : -1), (-1 : -1 : 0), (-1 : -1 : 1), (-1 : 0 : -1),
69+
(-1 : 0 : 0), (-1 : 0 : 1), (-1 : 1 : -1), (-1 : 1 : 0),
70+
(-1 : 1 : 1), (0 : -1 : -1), (0 : -1 : 0), (0 : -1 : 1),
71+
(0 : 0 : -1)]
72+
73+
There are no points of negative height::
74+
75+
sage: from sage.schemes.projective.proj_bdd_height import ZZ_points_of_bounded_height
76+
sage: PS = ProjectiveSpace(ZZ, 1)
77+
sage: list(ZZ_points_of_bounded_height(PS, 1, -3))
78+
[]
79+
"""
80+
if bound < 1:
81+
return iter(set([]))
82+
83+
points_of_bounded_height = set([])
84+
85+
for t in itertools.product(range(-bound, bound+1), repeat=dim+1):
86+
if gcd(t) == 1:
87+
point = PS(t)
88+
if point not in points_of_bounded_height:
89+
points_of_bounded_height.add(point)
90+
yield point
91+
92+
93+
def QQ_points_of_bounded_height(PS, dim, bound, normalize=False):
94+
r"""
95+
Return an iterator of the points in ``self`` of absolute multiplicative
96+
height of at most ``bound`` in the rational field.
97+
98+
INPUT:
99+
100+
- ``PS`` -- a projective space
101+
43102
- ``dim`` -- a positive integer
44103
45104
- ``bound`` -- a real number
46105
106+
- ``normalize`` -- boolean (optional, default: ``False``); whether to
107+
normalize the coordinates of returned points
108+
47109
OUTPUT:
48110
49111
- an iterator of points of bounded height
50112
51113
EXAMPLES:
52114
53115
sage: from sage.schemes.projective.proj_bdd_height import QQ_points_of_bounded_height
54-
sage: sorted(list(QQ_points_of_bounded_height(1, 1)))
116+
sage: PS = ProjectiveSpace(QQ, 1)
117+
sage: sorted(list(QQ_points_of_bounded_height(PS, 1, 1)))
55118
[(-1 : 1), (0 : 1), (1 : 0), (1 : 1)]
56-
sage: len(list(QQ_points_of_bounded_height(1, 5)))
119+
sage: len(list(QQ_points_of_bounded_height(PS, 1, 5)))
57120
40
121+
sage: sorted(list(QQ_points_of_bounded_height(PS, 1, 2)))
122+
[(-2 : 1), (-1 : 1), (-1/2 : 1), (0 : 1),
123+
(1/2 : 1), (1 : 0), (1 : 1), (2 : 1)]
124+
sage: sorted(list(QQ_points_of_bounded_height(PS, 1, 2, normalize=True)))
125+
[(-2 : 1), (-1 : 1), (-1 : 2), (0 : 1),
126+
(1 : 0), (1 : 1), (1 : 2), (2 : 1)]
58127
59128
There are no points of negative height::
60129
61130
sage: from sage.schemes.projective.proj_bdd_height import QQ_points_of_bounded_height
62-
sage: list(QQ_points_of_bounded_height(1, -3))
131+
sage: PS = ProjectiveSpace(QQ, 1)
132+
sage: list(QQ_points_of_bounded_height(PS, 1, -3))
63133
[]
64134
"""
65135
if bound < 1:
66136
return iter(set([]))
67137

68-
PN = ProjectiveSpace(QQ, dim)
69138
unit_tuples = list(itertools.product([-1, 1], repeat=dim))
70139
points_of_bounded_height = set([])
71140
increasing_tuples = itertools.combinations_with_replacement(range(floor(bound + 1)), dim + 1)
72141
for t in increasing_tuples:
73142
if gcd(t) == 1:
74143
for p in itertools.permutations(t):
75144
for u in unit_tuples:
76-
point = PN([a*b for a, b in zip(u, p)] + [p[dim]])
145+
point = PS([a*b for a, b in zip(u, p)] + [p[dim]])
77146
if point not in points_of_bounded_height:
147+
if normalize:
148+
point.scale_by(lcm([point[i].denominator() for i in range(dim + 1)]))
149+
78150
points_of_bounded_height.add(point)
79151
yield point
80152

81153

82-
def IQ_points_of_bounded_height(PN, K, dim, bound):
154+
def IQ_points_of_bounded_height(PS, K, dim, bound):
83155
r"""
84156
Return an iterator of the points in ``self`` of absolute multiplicative
85157
height of at most ``bound`` in the imaginary quadratic field ``K``.
86158
87159
INPUT:
88160
89-
- ``PN`` -- a projective space
161+
- ``PS`` -- a projective space
90162
91163
- ``K`` -- a number field
92164
@@ -147,13 +219,14 @@ def IQ_points_of_bounded_height(PN, K, dim, bound):
147219
if a == K.ideal(point_coordinates):
148220
for p in itertools.permutations(point_coordinates):
149221
for u in unit_tuples:
150-
point = PN([i*j for i, j in zip(u, p)] + [p[dim]])
222+
point = PS([i*j for i, j in zip(u, p)] + [p[dim]])
223+
151224
if point not in points_in_class_a:
152225
points_in_class_a.add(point)
153226
yield point
154227

155228

156-
def points_of_bounded_height(PN, K, dim, bound, prec=53):
229+
def points_of_bounded_height(PS, K, dim, bound, prec=53):
157230
r"""
158231
Return an iterator of the points in ``K`` with dimension ``dim`` of
159232
absolute multiplicative height of at most ``bound``.
@@ -164,7 +237,7 @@ def points_of_bounded_height(PN, K, dim, bound, prec=53):
164237
165238
INPUT:
166239
167-
- ``PN`` -- a projective space
240+
- ``PS`` -- a projective space
168241
169242
- ``K`` -- a number field
170243
@@ -184,8 +257,39 @@ def points_of_bounded_height(PN, K, dim, bound, prec=53):
184257
sage: x = polygen(ZZ, 'x')
185258
sage: K.<a> = NumberField(x^3 - 7) # optional - sage.rings.number_field
186259
sage: P.<x,y,z> = ProjectiveSpace(K, 2) # optional - sage.rings.number_field
187-
sage: len(list(points_of_bounded_height(P, K, 2, 1))) # optional - sage.rings.number_field
188-
13
260+
sage: sorted(list(points_of_bounded_height(P, K, 2, 1))) # optional - sage.rings.number_field
261+
[(0 : 0 : 1), (0 : 1 : 0), (1 : 0 : 0), (0 : -1 : 1), (0 : 1 : 1),
262+
(-1 : 0 : 1), (1 : 0 : 1), (1 : 1 : 0), (-1 : 1 : 0), (-1 : -1 : 1),
263+
(-1 : 1 : 1), (1 : -1 : 1), (1 : 1 : 1)]
264+
265+
::
266+
267+
sage: R.<x> = QQ[]
268+
sage: K.<a> = NumberField(3*x^2 + 1)
269+
sage: O = K.maximal_order()
270+
sage: P.<z,w> = ProjectiveSpace(O, 1)
271+
sage: len(list(P.points_of_bounded_height(bound=2)))
272+
44
273+
274+
::
275+
276+
sage: R.<x> = QQ[]
277+
sage: K.<a> = NumberField(3*x^2 + 1)
278+
sage: O = K.maximal_order()
279+
sage: P.<z,w> = ProjectiveSpace(O, 1)
280+
sage: sorted(list(P.points_of_bounded_height(bound=1)))
281+
[(-1 : 1), (-3/2*a - 1/2 : 1), (3/2*a - 1/2 : 1), (0 : 1),
282+
(-3/2*a + 1/2 : 0), (-3/2*a + 1/2 : 1), (3/2*a + 1/2 : 1), (1 : 1)]
283+
284+
::
285+
286+
sage: R.<x> = QQ[]
287+
sage: K.<z> = NumberField(x^2 - 2)
288+
sage: R2.<y> = K[]
289+
sage: L.<w> = K.extension(y^2 - 3)
290+
sage: P.<a,b> = ProjectiveSpace(L, 1)
291+
sage: len(list(P.points_of_bounded_height(bound=2)))
292+
256
189293
"""
190294
if bound < 1:
191295
return iter([])
@@ -344,7 +448,8 @@ def points_of_bounded_height(PN, K, dim, bound, prec=53):
344448
if log_arch_height <= log_arch_height_bound and a == K.ideal(point_coordinates):
345449
for p in itertools.permutations(point_coordinates):
346450
for u in unit_tuples:
347-
point = PN([i*j for i, j in zip(u, p)] + [p[dim]])
451+
point = PS([i*j for i, j in zip(u, p)] + [p[dim]])
452+
348453
if point not in points_in_class_a:
349454
points_in_class_a.add(point)
350455
yield point

0 commit comments

Comments
 (0)