Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
19635: First round of changes from review.
Browse files Browse the repository at this point in the history
  • Loading branch information
Grayson Jorgenson committed May 7, 2016
1 parent 449d073 commit 954bc26
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 108 deletions.
48 changes: 20 additions & 28 deletions src/sage/schemes/product_projective/homset.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from sage.categories.fields import Fields
from sage.categories.number_fields import NumberFields
from sage.misc.mrange import xmrange
from sage.rings.finite_rings.constructor import is_FiniteField
from sage.schemes.generic.homset import SchemeHomset_points

Expand Down Expand Up @@ -46,32 +47,33 @@ def _element_constructor_(self, v, **kwds):
EXAMPLES::
sage: P = ProductProjectiveSpaces([1,1],QQ,'z')
sage: Q = P([1,2,2,3]); Q
(1/2 : 1 , 2/3 : 1)
sage: P = ProductProjectiveSpaces([1,1],ZZ,'z')
sage: Q = P([4,6,6,2]); Q
(2 : 3 , 3 : 1)
sage: type(Q)
<class 'sage.schemes.product_projective.point.ProductProjectiveSpaces_point_field'>
sage: P(QQ)._element_constructor_([1,2,2,0])
(1/2 : 1 , 1 : 0)
<class 'sage.schemes.product_projective.point.ProductProjectiveSpaces_point_ring'>
sage: P(QQ)._element_constructor_([4,2,2,0])
(2 : 1 , 1 : 0)
"""
return self.codomain()._point(self, v, **kwds)

class SchemeHomset_points_product_projective_spaces_field(SchemeHomset_points_product_projective_spaces_ring):
def points(self, B=0, prec=53):
r"""
Return some or all rational points of a projective scheme.
Return some or all rational points of a projective scheme. A list of points. Over a finite field,
all points are returned. Over an infinite field, all points satisfying the bound are returned. For
a zero-dimensional subscheme, all points are returned regardless of whether the base ring is a field
or not.
INPUT:
- `B` -- integer (optional, default=0). The bound for the
coordinates.
- ``prec`` - the precision to use to compute the elements of bounded height for number fields
- ``prec`` - the precision to use to compute the elements of bounded height for number fields.
OUTPUT:
A list of points. Over a finite field, all points are
returned. Over an infinite field, all points satisfying the
bound are returned.
- all points with height at most the bound are returned.
.. WARNING::
Expand Down Expand Up @@ -114,7 +116,7 @@ def points(self, B=0, prec=53):
::
sage: P.<x,y,z,u,v> = ProductProjectiveSpaces([2,1],GF(3))
sage: P(P.base_ring()).points()
sage: P(P.base_ring()).points().sort()
[(0 : 0 : 1 , 0 : 1), (0 : 0 : 1 , 1 : 1), (0 : 0 : 1 , 2 : 1), (0 : 0 : 1 , 1 : 0),
(1 : 0 : 1 , 0 : 1), (1 : 0 : 1 , 1 : 1), (1 : 0 : 1 , 2 : 1), (1 : 0 : 1 , 1 : 0),
(2 : 0 : 1 , 0 : 1), (2 : 0 : 1 , 1 : 1), (2 : 0 : 1 , 2 : 1), (2 : 0 : 1 , 1 : 0),
Expand Down Expand Up @@ -142,39 +144,29 @@ def points(self, B=0, prec=53):
if dim_ideal == X.ambient_space().num_components():
points = set()
# find points from all possible affine patches
indices = [[k] for k in range(0,X.ambient_space().dimension_relative_components()[0] + 1)]
for t in range(1,X.ambient_space().num_components()):
tmpL = []
for I in indices:
for k in range(0,X.ambient_space().dimension_relative_components()[t] + 1):
tmpL.append(I+[k])
indices = []
indices = indices + tmpL
for I in indices:
for I in xmrange([n+1 for n in X.ambient_space().dimension_relative_components()]):
[Y,phi] = X.affine_patch(I,True)
aff_points = Y.rational_points()
for PP in aff_points:
points.add(X.ambient_space()(list(phi(PP))))
points.add(phi(PP))
return list(points)
R = self.value_ring()
points = []
if R in NumberFields():
if not B > 0:
raise TypeError("a positive bound B (= %s) must be specified."%B)
bddpts = X.ambient_space().points_of_bounded_height(B,prec)
for P in bddpts:
raise TypeError("a positive bound B (= %s) must be specified"%B)
for P in X.ambient_space().points_of_bounded_height(B,prec):
try:
points.append(X(P))
except TypeError:
pass
return points
if is_FiniteField(R):
tpts = X.ambient_space().rational_points()
for P in tpts:
for P in X.ambient_space().rational_points():
try:
points.append(X(P))
except TypeError:
pass
return points
else:
raise TypeError("unable to enumerate points over %s."%R)
raise TypeError("unable to enumerate points over %s"%R)
64 changes: 22 additions & 42 deletions src/sage/schemes/product_projective/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,13 @@ def __hash__(self):
EXAMPLES::
sage: PP = ProductProjectiveSpaces(Zmod(6),[1,1])
sage: hash(PP([5,1,2,4]))
1266382469 # 32-bit
-855399699883264379 # 64-bit
::
sage: PP = ProductProjectiveSpaces(ZZ,[1,2])
sage: hash(PP([1,1,2,2,2]))
805439612 # 32-bit
Expand All @@ -295,20 +302,25 @@ def __hash__(self):
::
sage: PP = ProductProjectiveSpaces(Zmod(6),[1,1])
sage: hash(PP([5,1,2,4]))
1266382469 # 32-bit
-855399699883264379 # 64-bit
sage: PP = ProductProjectiveSpaces(QQ, [1,1])
sage: hash(PP([1/7,1,2,1]))
-7585172175017137916 # 64-bit
::
sage: PP = ProductProjectiveSpaces(GF(7), [1,1,1])
sage: hash(PP([4,1,5,4,6,1]))
-4539377540667874085
"""
R = self.codomain().base_ring()
#if there is a fraction field normalize the point so that
#equal points have equal hash values
# if there is a fraction field normalize the point so that
# equal points have equal hash values
if R in IntegralDomains():
P = self.change_ring(FractionField(R))
P.normalize_coordinates()
return hash(tuple(P))
#if there is no good way to normalize return
#a constant value
# if there is no good way to normalize return
# a constant value
return hash(self.codomain())

def normalize_coordinates(self):
Expand Down Expand Up @@ -526,39 +538,7 @@ def orbit(self,f,N,**kwds):
return(Orb)

class ProductProjectiveSpaces_point_field(ProductProjectiveSpaces_point_ring):
def __hash__(self):
"""
Computes the hash value of ``self``.
OUTPUT: Integer.
EXAMPLES::
sage: PP = ProductProjectiveSpaces(QQ, [1,1])
sage: hash(PP([1/7,1,2,1]))
1139616004 # 32-bit
-7585172175017137916 # 64-bit
sage: hash(PP([1,7,1,1/2]))
1139616004 # 32-bit
-7585172175017137916 # 64-bit
"""
P = copy(self)
P.normalize_coordinates()
return hash(tuple(P))
pass

class ProductProjectiveSpaces_point_finite_field(ProductProjectiveSpaces_point_field):
def __hash__(self):
"""
Computes the hash value of ``self``.
OUTPUT: Integer.
EXAMPLES::
sage: PP = ProductProjectiveSpaces(GF(7), [1,1,1])
sage: hash(PP([4,1,5,4,6,1]))
34
"""
P = copy(self)
P.normalize_coordinates()
return sum(hash(P[i]) for i in range(self.codomain().num_components()))
pass
110 changes: 72 additions & 38 deletions src/sage/schemes/product_projective/space.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

import six
from sage.misc.cachefunc import cached_method
from copy import copy
from sage.misc.mrange import xmrange

from sage.rings.all import (PolynomialRing, ZZ, QQ, Integer)
from sage.rings.commutative_ring import is_CommutativeRing
Expand Down Expand Up @@ -971,10 +973,10 @@ def _point_homset(self, *args, **kwds):

def points_of_bounded_height(self,bound, prec=53):
r"""
Returns an iterator of the points in self with the absolute heights of the components of at most the given
bound. Bound check is strict for the rational field. Requires self to be a product of projective spaces over
a number field. Uses the Doyle-Krumm algorithm for computing algebraic numbers up to a given height
[Doyle-Krumm].
Returns an iterator of the points in this product of projective spaces with the absolute heights of the
components of at most the given bound. Bound check is strict for the rational field. Requires the base
field of this space to be a number field. Uses the Doyle-Krumm algorithm for computing algebraic numbers
up to a given height [Doyle-Krumm]_.
INPUT:
Expand All @@ -984,11 +986,11 @@ def points_of_bounded_height(self,bound, prec=53):
OUTPUT:
- an iterator of points in self
- an iterator of points in this space
.. WARNING::
In the current implementation, the output of the [Doyle-Krumm] algorithm
In the current implementation, the output of the [Doyle-Krumm]_ algorithm
cannot be guaranteed to be correct due to the necessity of floating point
computations. In some cases, the default 53-bit precision is
considerably lower than would be required for the algorithm to
Expand Down Expand Up @@ -1032,22 +1034,14 @@ def points_of_bounded_height(self,bound, prec=53):
(1 : 0 , -1 : 1), (1 : 0 , 1 : 1), (1 : 0 , -1/2*v : 1), (1 : 0 , -v : 1), (1 : 0 , 1/2*v : 1),
(1 : 0 , v : 1), (1 : 0 , 1 : 0)]
"""
comp_points = [list(self._components[i].points_of_bounded_height(bound,prec)) for i in range(self.num_components())]
indices = []
indices = [[k] for k in range(len(comp_points[0]))]
for t in range(1,self.num_components()):
tmpL = []
for I in indices:
for k in range(0,len(comp_points[t])):
tmpL.append(I+[k])
indices = []
indices = indices + tmpL

return iter([self([comp_points[t][I[t]] for t in range(self.num_components())]) for I in indices])
m = self.num_components()
comp_points = [list(self._components[i].points_of_bounded_height(bound,prec)) for i in range(m)]
indices = xmrange([len(comp_points[i]) for i in range(m)])
return iter([self([comp_points[t][I[t]] for t in range(m)]) for I in indices])

class ProductProjectiveSpaces_finite_field(ProductProjectiveSpaces_field):
def _point(self, *args, **kwds):
"""
r"""
Construct a point.
For internal use only. See :mod:`morphism` for details.
Expand All @@ -1060,31 +1054,71 @@ def _point(self, *args, **kwds):
"""
return ProductProjectiveSpaces_point_finite_field(*args, **kwds)

def rational_points(self, F=None):
def __iter__(self):
r"""
Returns iterator over the elements of this product of projective spaces.
EXAMPLES::
sage: P = ProductProjectiveSpaces([2,1],GF(3))
sage: [x for x in P]
[(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(2 : 1 : 0 , 1 : 0), (1 : 0 : 0 , 1 : 0)]
"""
iters = [ iter(T) for T in self._components ]
L=[]
for x in iters:
L.append(next(x)) # put at zero
yield(copy(self(L)))
j = 0
while j < self.num_components():
try:
L[j] = next(iters[j])
yield(copy(self(L)))
j = 0
except StopIteration:
iters[j] = iter(self[j]) # reset
L[j] = next(iters[j]) # put at zero
j += 1

def rational_points(self, F=None):
r"""
Return the list of `F`-rational points on the affine space self,
where `F` is a given finite field, or the base ring of self.
EXAMPLES::
sage: P = ProductProjectiveSpaces([1,1],GF(5))
sage: P.rational_points()
[(0 : 1 , 0 : 1), (0 : 1 , 1 : 1), (0 : 1 , 2 : 1), (0 : 1 , 3 : 1), (0 : 1 , 4 : 1), (0 : 1 , 1 : 0),
(1 : 1 , 0 : 1), (1 : 1 , 1 : 1), (1 : 1 , 2 : 1), (1 : 1 , 3 : 1), (1 : 1 , 4 : 1), (1 : 1 , 1 : 0),
(2 : 1 , 0 : 1), (2 : 1 , 1 : 1), (2 : 1 , 2 : 1), (2 : 1 , 3 : 1), (2 : 1 , 4 : 1), (2 : 1 , 1 : 0),
(3 : 1 , 0 : 1), (3 : 1 , 1 : 1), (3 : 1 , 2 : 1), (3 : 1 , 3 : 1), (3 : 1 , 4 : 1), (3 : 1 , 1 : 0),
(4 : 1 , 0 : 1), (4 : 1 , 1 : 1), (4 : 1 , 2 : 1), (4 : 1 , 3 : 1), (4 : 1 , 4 : 1), (4 : 1 , 1 : 0),
(1 : 0 , 0 : 1), (1 : 0 , 1 : 1), (1 : 0 , 2 : 1), (1 : 0 , 3 : 1), (1 : 0 , 4 : 1), (1 : 0 , 1 : 0)]
[(0 : 1 , 0 : 1), (1 : 1 , 0 : 1), (2 : 1 , 0 : 1), (3 : 1 , 0 : 1), (4 : 1 , 0 : 1), (1 : 0 , 0 : 1),
(0 : 1 , 1 : 1), (1 : 1 , 1 : 1), (2 : 1 , 1 : 1), (3 : 1 , 1 : 1), (4 : 1 , 1 : 1), (1 : 0 , 1 : 1),
(0 : 1 , 2 : 1), (1 : 1 , 2 : 1), (2 : 1 , 2 : 1), (3 : 1 , 2 : 1), (4 : 1 , 2 : 1), (1 : 0 , 2 : 1),
(0 : 1 , 3 : 1), (1 : 1 , 3 : 1), (2 : 1 , 3 : 1), (3 : 1 , 3 : 1), (4 : 1 , 3 : 1), (1 : 0 , 3 : 1),
(0 : 1 , 4 : 1), (1 : 1 , 4 : 1), (2 : 1 , 4 : 1), (3 : 1 , 4 : 1), (4 : 1 , 4 : 1), (1 : 0 , 4 : 1),
(0 : 1 , 1 : 0), (1 : 1 , 1 : 0), (2 : 1 , 1 : 0), (3 : 1 , 1 : 0), (4 : 1 , 1 : 0), (1 : 0 , 1 : 0)]
"""
comp_points = [list(self._components[i].rational_points(F)) for i in range(self.num_components())]
indices = []
indices = [[k] for k in range(len(comp_points[0]))]
for t in range(1,self.num_components()):
tmpL = []
for I in indices:
for k in range(0,len(comp_points[t])):
tmpL.append(I+[k])
indices = []
indices = indices + tmpL

return [self([comp_points[t][I[t]] for t in range(self.num_components())]) for I in indices]
iters = [ iter(T) for T in self._components ]
L=[]
for x in iters:
L.append(next(x)) # put at zero
points=[copy(self(L))]
j = 0
while j < self.num_components():
try:
L[j] = next(iters[j])
points.append(copy(self(L)))
j = 0
except StopIteration:
iters[j] = iter(self[j]) # reset
L[j] = next(iters[j]) # put at zero
j += 1
return points

0 comments on commit 954bc26

Please sign in to comment.