Skip to content

Commit 9eb36fd

Browse files
author
Release Manager
committed
Trac #25743: Speed up iteration of ProjectiveSpace_finite_field
While implementing some algorithm involving projective spaces, I noticed that 90% of the time was simply spent enumerating the points of a projective space. URL: https://trac.sagemath.org/25743 Reported by: jdemeyer Ticket author(s): Frédéric Chapoton, Travis Scrimshaw, John Cremona Reviewer(s): Travis Scrimshaw, Frédéric Chapoton, John Cremona
2 parents 496efa6 + 329f89b commit 9eb36fd

File tree

6 files changed

+221
-208
lines changed

6 files changed

+221
-208
lines changed

src/sage/schemes/affine/affine_space.py

+10-19
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
from sage.categories.fields import Fields
2121
_Fields = Fields()
2222
from sage.categories.number_fields import NumberFields
23-
from sage.misc.all import latex
23+
from sage.misc.all import (latex,
24+
cartesian_product_iterator)
2425
from sage.structure.category_object import normalize_names
2526
from sage.schemes.generic.scheme import AffineScheme
2627
from sage.schemes.generic.ambient_space import AmbientSpace
@@ -208,30 +209,20 @@ def __iter__(self):
208209
[(0), (1), (2)]
209210
sage: AA.<z,w> = AffineSpace(FF, 2)
210211
sage: [ x for x in AA ]
211-
[(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)]
212+
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
212213
213214
AUTHOR:
214215
215216
- David Kohel
216217
"""
217218
n = self.dimension_relative()
218219
R = self.base_ring()
219-
zero = R(0)
220-
P = [ zero for _ in range(n) ]
221-
yield self(P)
222-
iters = [ iter(R) for _ in range(n) ]
223-
for x in iters: next(x) # put at zero
224-
i = 0
225-
while i < n:
226-
try:
227-
P[i] = next(iters[i])
228-
yield self(P)
229-
i = 0
230-
except StopIteration:
231-
iters[i] = iter(R) # reset
232-
next(iters[i]) # put at zero
233-
P[i] = zero
234-
i += 1
220+
AHom = self.point_homset()
221+
C = AHom.codomain()
222+
223+
for v in cartesian_product_iterator([R for _ in range(n)]):
224+
yield C._point(AHom, v, check=False)
225+
235226

236227
def ngens(self):
237228
"""
@@ -261,7 +252,7 @@ def rational_points(self, F=None):
261252
[(0), (b), (b + 1), (2*b + 1), (2), (2*b), (2*b + 2), (b + 2), (1)]
262253
263254
sage: AffineSpace(2, ZZ).rational_points(GF(2))
264-
[(0, 0), (1, 0), (0, 1), (1, 1)]
255+
[(0, 0), (0, 1), (1, 0), (1, 1)]
265256
266257
TESTS::
267258

src/sage/schemes/curves/projective_curve.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -534,14 +534,11 @@ def plane_projection(self, PP=None):
534534
sage: C = P.curve([x^2 - 6*y^2, w*z*u - y^3 + 4*y^2*z, u^2 - x^2])
535535
sage: C.plane_projection()
536536
(Scheme morphism:
537-
From: Projective Curve over Finite Field of size 7 defined by x^2 +
538-
y^2, -y^3 - 3*y^2*z + z*w*u, -x^2 + u^2
537+
From: Projective Curve over Finite Field of size 7 defined by x^2 + y^2, -y^3 - 3*y^2*z + z*w*u, -x^2 + u^2
539538
To: Projective Space of dimension 2 over Finite Field of size 7
540539
Defn: Defined on coordinates by sending (x : y : z : w : u) to
541-
(y : z : -x + w),
542-
Projective Plane Curve over Finite Field of size 7 defined by x0^10 -
543-
2*x0^9*x1 + 3*x0^8*x1^2 - 2*x0^7*x1^3 + x0^6*x1^4 + 2*x0^6*x1^2*x2^2 -
544-
2*x0^5*x1^3*x2^2 - x0^4*x1^4*x2^2 + x0^2*x1^4*x2^4)
540+
(x : z : -y + w),
541+
Projective Plane Curve over Finite Field of size 7 defined by x0^10 + 2*x0^8*x1^2 + 2*x0^6*x1^4 - 3*x0^6*x1^3*x2 + 2*x0^6*x1^2*x2^2 - 2*x0^4*x1^4*x2^2 + x0^2*x1^4*x2^4)
545542
546543
::
547544

src/sage/schemes/generic/homset.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
from sage.categories.homset import HomsetWithBase
4040
from sage.structure.factory import UniqueFactory
41+
from sage.structure.parent import Set_generic
4142

4243
from sage.rings.all import ZZ
4344
from sage.rings.ring import CommutativeRing
@@ -270,7 +271,6 @@ def __call__(self, *args, **kwds):
270271
(4, 5)
271272
"""
272273
# Homset (base of HomsetWithBase) overrides __call__ @#$
273-
from sage.structure.parent import Set_generic
274274
return Set_generic.__call__(self, *args, **kwds)
275275

276276
def _repr_(self):

src/sage/schemes/generic/morphism.py

+31-2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
from sage.rings.fraction_field import is_FractionField
8686
from sage.categories.map import FormalCompositeMap, Map
8787
from sage.misc.constant_function import ConstantFunction
88+
from sage.misc.lazy_attribute import lazy_attribute
8889
from sage.categories.morphism import SetMorphism
8990
from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme
9091

@@ -167,9 +168,37 @@ def __init__(self, parent, codomain=None):
167168
if not isinstance(parent, Homset):
168169
raise TypeError("parent (=%s) must be a Homspace"%parent)
169170
Element.__init__(self, parent)
170-
self.domain = ConstantFunction(parent.domain())
171171
self._codomain = parent.codomain()
172-
self.codomain = ConstantFunction(self._codomain)
172+
173+
@lazy_attribute
174+
def domain(self):
175+
r"""
176+
The constant function from the domain.
177+
178+
EXAMPLES::
179+
180+
sage: A.<x,y> = AffineSpace(QQ['x,y'])
181+
sage: H = A.Hom(A)
182+
sage: f = H([y,x^2+y])
183+
sage: f.domain() is A
184+
True
185+
"""
186+
return ConstantFunction(self.parent().domain())
187+
188+
@lazy_attribute
189+
def codomain(self):
190+
r"""
191+
The constant function from the codomain.
192+
193+
EXAMPLES::
194+
195+
sage: A.<x,y> = AffineSpace(QQ['x,y'])
196+
sage: H = A.Hom(A)
197+
sage: f = H([y,x^2+y])
198+
sage: f.codomain() is A
199+
True
200+
"""
201+
return ConstantFunction(self._codomain)
173202

174203
# We copy methods of sage.categories.map.Map, to make
175204
# a future transition of SchemeMorphism to a sub-class of Morphism

src/sage/schemes/product_projective/space.py

+7-11
Original file line numberDiff line numberDiff line change
@@ -1255,17 +1255,13 @@ def __iter__(self):
12551255
12561256
sage: P = ProductProjectiveSpaces([2, 1], GF(3))
12571257
sage: [x for x in P]
1258-
[(0 : 0 : 1 , 0 : 1), (1 : 0 : 1 , 0 : 1), (2 : 0 : 1 , 0 : 1), (0 : 1 : 1 , 0 : 1), (1 : 1 : 1 , 0 : 1),
1259-
(2 : 1 : 1 , 0 : 1), (0 : 2 : 1 , 0 : 1), (1 : 2 : 1 , 0 : 1), (2 : 2 : 1 , 0 : 1), (0 : 1 : 0 , 0 : 1),
1260-
(1 : 1 : 0 , 0 : 1), (2 : 1 : 0 , 0 : 1), (1 : 0 : 0 , 0 : 1), (0 : 0 : 1 , 1 : 1), (1 : 0 : 1 , 1 : 1),
1261-
(2 : 0 : 1 , 1 : 1), (0 : 1 : 1 , 1 : 1), (1 : 1 : 1 , 1 : 1), (2 : 1 : 1 , 1 : 1), (0 : 2 : 1 , 1 : 1),
1262-
(1 : 2 : 1 , 1 : 1), (2 : 2 : 1 , 1 : 1), (0 : 1 : 0 , 1 : 1), (1 : 1 : 0 , 1 : 1), (2 : 1 : 0 , 1 : 1),
1263-
(1 : 0 : 0 , 1 : 1), (0 : 0 : 1 , 2 : 1), (1 : 0 : 1 , 2 : 1), (2 : 0 : 1 , 2 : 1), (0 : 1 : 1 , 2 : 1),
1264-
(1 : 1 : 1 , 2 : 1), (2 : 1 : 1 , 2 : 1), (0 : 2 : 1 , 2 : 1), (1 : 2 : 1 , 2 : 1), (2 : 2 : 1 , 2 : 1),
1265-
(0 : 1 : 0 , 2 : 1), (1 : 1 : 0 , 2 : 1), (2 : 1 : 0 , 2 : 1), (1 : 0 : 0 , 2 : 1), (0 : 0 : 1 , 1 : 0),
1266-
(1 : 0 : 1 , 1 : 0), (2 : 0 : 1 , 1 : 0), (0 : 1 : 1 , 1 : 0), (1 : 1 : 1 , 1 : 0), (2 : 1 : 1 , 1 : 0),
1267-
(0 : 2 : 1 , 1 : 0), (1 : 2 : 1 , 1 : 0), (2 : 2 : 1 , 1 : 0), (0 : 1 : 0 , 1 : 0), (1 : 1 : 0 , 1 : 0),
1268-
(2 : 1 : 0 , 1 : 0), (1 : 0 : 0 , 1 : 0)]
1258+
[(0 : 0 : 1 , 0 : 1),
1259+
(0 : 1 : 1 , 0 : 1),
1260+
(0 : 2 : 1 , 0 : 1),
1261+
...
1262+
(1 : 1 : 0 , 1 : 0),
1263+
(2 : 1 : 0 , 1 : 0),
1264+
(1 : 0 : 0 , 1 : 0)]
12691265
"""
12701266
iters = [iter(T) for T in self._components]
12711267
L=[]

0 commit comments

Comments
 (0)