def points(self, B=0): r""" Return some or all rational points of an affine scheme. INPUT: - ``B`` -- integer (optional, default: 0). The bound for the height of the coordinates. OUTPUT: - If the base ring is a finite field: all points of the scheme, given by coordinate tuples. - If the base ring is `\QQ` or `\ZZ`: the subset of points whose coordinates have height ``B`` or less. EXAMPLES: The bug reported at #11526 is fixed:: sage: A2 = AffineSpace(ZZ,2) sage: F = GF(3) sage: A2(F).points() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: R = ZZ sage: A.<x,y> = R[] sage: I = A.ideal(x^2-y^2-1) sage: V = AffineSpace(R,2) sage: X = V.subscheme(I) sage: M = X(R) sage: M.points(1) [(-1, 0), (1, 0)] :: sage: u = QQ['u'].0 sage: K.<v> = NumberField(u^2 + 3) sage: A.<x,y> = AffineSpace(K,2) sage: len(A(K).points(9)) 361 """ R = self.value_ring() if is_RationalField(R) or R == ZZ: if not B > 0: raise TypeError("A positive bound B (= %s) must be specified."%B) from sage.schemes.affine.affine_rational_point import enum_affine_rational_field return enum_affine_rational_field(self,B) if R in NumberFields(): from sage.schemes.affine.affine_rational_point import enum_affine_number_field return enum_affine_number_field(self,B) elif is_FiniteField(R): from sage.schemes.affine.affine_rational_point import enum_affine_finite_field return enum_affine_finite_field(self) else: raise TypeError("Unable to enumerate points over %s."%R)
def points(self, B=0): r""" Return some or all rational points of an affine scheme. INPUT: - ``B`` -- integer (optional, default: 0). The bound for the height of the coordinates. OUTPUT: - If the base ring is a finite field: all points of the scheme, given by coordinate tuples. - If the base ring is `\QQ` or `\ZZ`: the subset of points whose coordinates have height ``B`` or less. EXAMPLES: The bug reported at #11526 is fixed:: sage: A2 = AffineSpace(ZZ, 2) sage: F = GF(3) sage: A2(F).points() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: R = ZZ sage: A.<x,y> = R[] sage: I = A.ideal(x^2-y^2-1) sage: V = AffineSpace(R, 2) sage: X = V.subscheme(I) sage: M = X(R) sage: M.points(1) [(-1, 0), (1, 0)] :: sage: u = QQ['u'].0 sage: K.<v> = NumberField(u^2 + 3) sage: A.<x,y> = AffineSpace(K, 2) sage: len(A(K).points(9)) 361 :: sage: A.<x,y> = AffineSpace(QQ, 2) sage: E = A.subscheme([x^2 + y^2 - 1, y^2 - x^3 + x^2 + x - 1]) sage: E(A.base_ring()).points() [(-1, 0), (0, -1), (0, 1), (1, 0)] """ X = self.codomain() from sage.schemes.affine.affine_space import is_AffineSpace if not is_AffineSpace(X) and X.base_ring() in Fields(): # Then X must be a subscheme dim_ideal = X.defining_ideal().dimension() if dim_ideal < 0: # no points return [] if dim_ideal == 0: # if X zero-dimensional N = len(X.ambient_space().gens()) S = X.defining_polynomials()[0].parent() R = PolynomialRing(S.base_ring(), 's', N, order='lex') phi = S.hom(R.gens(),R) J = R.ideal([phi(t) for t in X.defining_polynomials()]) D = J.variety() points = [] for d in D: P = [d[t] for t in R.gens()] points.append(X(P)) points.sort() return points R = self.value_ring() if is_RationalField(R) or R == ZZ: if not B > 0: raise TypeError("a positive bound B (= %s) must be specified"%B) from sage.schemes.affine.affine_rational_point import enum_affine_rational_field return enum_affine_rational_field(self,B) if R in NumberFields(): if not B > 0: raise TypeError("a positive bound B (= %s) must be specified"%B) from sage.schemes.affine.affine_rational_point import enum_affine_number_field return enum_affine_number_field(self,B) elif is_FiniteField(R): from sage.schemes.affine.affine_rational_point import enum_affine_finite_field return enum_affine_finite_field(self) else: raise TypeError("unable to enumerate points over %s"%R)
def points(self, **kwds): r""" Return some or all rational points of an affine scheme. For dimension 0 subschemes points are determined through a groebner basis calculation. For schemes or subschemes with dimension greater than 1 points are determined through enumeration up to the specified bound. 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 field is infinite or not. For number fields, this uses the Doyle-Krumm algorithm 4 (algorithm 5 for imaginary quadratic) for computing algebraic numbers up to a given height [Doyle-Krumm]_. The algorithm requires floating point arithmetic, so the user is allowed to specify the precision for such calculations. Additionally, due to floating point issues, points slightly larger than the bound may be returned. This can be controlled by lowering the tolerance. INPUT: kwds: - ``bound`` - real number (optional, default: 0). The bound for the height of the coordinates. Only used for subschemes with dimension at least 1. - ``zero_tolerance`` - positive real number (optional, default=10^(-10)). For numerically inexact fields, points are on the subscheme if they satisfy the equations to within tolerance. - ``tolerance`` - a rational number in (0,1] used in doyle-krumm algorithm-4 for enumeration over number fields. - ``precision`` - the precision to use for computing the elements of bounded height of number fields. OUTPUT: - a list of rational points of a affine scheme .. WARNING:: For numerically inexact fields such as ComplexField or RealField the list of points returned is very likely to be incomplete. It may also contain repeated points due to tolerance. EXAMPLES: The bug reported at #11526 is fixed:: sage: A2 = AffineSpace(ZZ, 2) sage: F = GF(3) sage: A2(F).points() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] :: sage: A.<x,y> = ZZ[] sage: I = A.ideal(x^2-y^2-1) sage: V = AffineSpace(ZZ, 2) sage: X = V.subscheme(I) sage: M = X(ZZ) sage: M.points(bound=1) [(-1, 0), (1, 0)] :: sage: u = QQ['u'].0 sage: K.<v> = NumberField(u^2 + 3) sage: A.<x,y> = AffineSpace(K, 2) sage: len(A(K).points(bound=2)) 1849 :: sage: A.<x,y> = AffineSpace(QQ, 2) sage: E = A.subscheme([x^2 + y^2 - 1, y^2 - x^3 + x^2 + x - 1]) sage: E(A.base_ring()).points() [(-1, 0), (0, -1), (0, 1), (1, 0)] :: sage: A.<x,y> = AffineSpace(CC, 2) sage: E = A.subscheme([y^3 - x^3 - x^2, x*y]) sage: E(A.base_ring()).points() verbose 0 (124: affine_homset.py, points) Warning: computations in the numerical fields are inexact;points may be computed partially or incorrectly. [(-1.00000000000000, 0.000000000000000), (0.000000000000000, 0.000000000000000)] :: sage: A.<x1,x2> = AffineSpace(CDF, 2) sage: E = A.subscheme([x1^2 + x2^2 + x1*x2, x1 + x2]) sage: E(A.base_ring()).points() verbose 0 (124: affine_homset.py, points) Warning: computations in the numerical fields are inexact;points may be computed partially or incorrectly. [(0.0, 0.0)] """ from sage.schemes.affine.affine_space import is_AffineSpace X = self.codomain() if not is_AffineSpace(X) and X.base_ring() in Fields(): if hasattr(X.base_ring(), 'precision'): numerical = True verbose("Warning: computations in the numerical fields are inexact;points may be computed partially or incorrectly.", level=0) zero_tol = RR(kwds.pop('zero_tolerance', 10**(-10))) if zero_tol <= 0: raise ValueError("tolerance must be positive") else: numerical = False # Then X must be a subscheme dim_ideal = X.defining_ideal().dimension() if dim_ideal < 0: # no points return [] if dim_ideal == 0: # if X zero-dimensional rat_points = [] AS = X.ambient_space() N = AS.dimension_relative() BR = X.base_ring() #need a lexicographic ordering for elimination R = PolynomialRing(BR, N, AS.gens(), order='lex') I = R.ideal(X.defining_polynomials()) I0 = R.ideal(0) #Determine the points through elimination #This is much faster than using the I.variety() function on each affine chart. G = I.groebner_basis() if G != [1]: P = {} points = [P] #work backwards from solving each equation for the possible #values of the next coordinate for i in range(len(G) - 1, -1, -1): new_points = [] good = 0 for P in points: #substitute in our dictionary entry that has the values #of coordinates known so far. This results in a single #variable polynomial (by elimination) L = G[i].substitute(P) if R(L).degree() > 0: if numerical: for pol in L.univariate_polynomial().roots(multiplicities=False): r = L.variables()[0] varindex = R.gens().index(r) P.update({R.gen(varindex):pol}) new_points.append(copy(P)) good = 1 else: L = L.factor() #the linear factors give the possible rational values of #this coordinate for pol, pow in L: if pol.degree() == 1 and len(pol.variables()) == 1: good = 1 r = pol.variables()[0] varindex = R.gens().index(r) #add this coordinates information to #each dictionary entry P.update({R.gen(varindex):-pol.constant_coefficient() / pol.monomial_coefficient(r)}) new_points.append(copy(P)) else: new_points.append(P) good = 1 if good: points = new_points #the dictionary entries now have values for all coordinates #they are the rational solutions to the equations #make them into affine points for i in range(len(points)): if numerical: if len(points[i]) == N: S = AS([points[i][R.gen(j)] for j in range(N)]) if all([g(list(S)) < zero_tol for g in X.defining_polynomials()]): rat_points.append(S) else: if len(points[i]) == N and I.subs(points[i]) == I0: S = X([points[i][R.gen(j)] for j in range(N)]) rat_points.append(S) rat_points = sorted(rat_points) return rat_points R = self.value_ring() B = kwds.pop('bound', 0) tol = kwds.pop('tolerance', 1e-2) prec = kwds.pop('precision', 53) if is_RationalField(R) or R == ZZ: if not B > 0: raise TypeError("a positive bound B (= %s) must be specified"%B) from sage.schemes.affine.affine_rational_point import enum_affine_rational_field return enum_affine_rational_field(self,B) if R in NumberFields(): if not B > 0: raise TypeError("a positive bound B (= %s) must be specified"%B) from sage.schemes.affine.affine_rational_point import enum_affine_number_field return enum_affine_number_field(self, bound=B, tolerance=tol, precision=prec) elif is_FiniteField(R): from sage.schemes.affine.affine_rational_point import enum_affine_finite_field return enum_affine_finite_field(self) else: raise TypeError("unable to enumerate points over %s"%R)
def points(self, **kwds): r""" Return some or all rational points of an affine scheme. 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 field is infinite or not. For number fields, this uses the Doyle-Krumm algorithm 4 (algorithm 5 for imaginary quadratic) for computing algebraic numbers up to a given height [Doyle-Krumm]_. The algorithm requires floating point arithmetic, so the user is allowed to specify the precision for such calculations. Additionally, due to floating point issues, points slightly larger than the bound may be returned. This can be controlled by lowering the tolerance. INPUT: - ``bound`` - a real number - ``tolerance`` - a rational number in (0,1] used in doyle-krumm algorithm-4 - ``precision`` - the precision to use for computing the elements of bounded height of number fields. OUTPUT: - a list of rational points of a affine scheme EXAMPLES: The bug reported at #11526 is fixed:: sage: A2 = AffineSpace(ZZ, 2) sage: F = GF(3) sage: A2(F).points() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: R = ZZ sage: A.<x,y> = R[] sage: I = A.ideal(x^2-y^2-1) sage: V = AffineSpace(R, 2) sage: X = V.subscheme(I) sage: M = X(R) sage: M.points(bound=1) [(-1, 0), (1, 0)] :: sage: u = QQ['u'].0 sage: K.<v> = NumberField(u^2 + 3) sage: A.<x,y> = AffineSpace(K, 2) sage: len(A(K).points(bound=2)) 1849 :: sage: A.<x,y> = AffineSpace(QQ, 2) sage: E = A.subscheme([x^2 + y^2 - 1, y^2 - x^3 + x^2 + x - 1]) sage: E(A.base_ring()).points() [(-1, 0), (0, -1), (0, 1), (1, 0)] """ B = kwds.pop('bound', 0) tol = kwds.pop('tolerance', 1e-2) prec = kwds.pop('precision', 53) X = self.codomain() from sage.schemes.affine.affine_space import is_AffineSpace if not is_AffineSpace(X) and X.base_ring() in Fields(): # Then X must be a subscheme dim_ideal = X.defining_ideal().dimension() if dim_ideal < 0: # no points return [] if dim_ideal == 0: # if X zero-dimensional N = len(X.ambient_space().gens()) S = X.defining_polynomials()[0].parent() R = PolynomialRing(S.base_ring(), 's', N, order='lex') phi = S.hom(R.gens(), R) J = R.ideal([phi(t) for t in X.defining_polynomials()]) D = J.variety() points = [] for d in D: P = [d[t] for t in R.gens()] points.append(X(P)) points.sort() return points R = self.value_ring() if is_RationalField(R) or R == ZZ: if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) from sage.schemes.affine.affine_rational_point import enum_affine_rational_field return enum_affine_rational_field(self, B) if R in NumberFields(): if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) from sage.schemes.affine.affine_rational_point import enum_affine_number_field return enum_affine_number_field(self, bound=B, tolerance=tol, precision=prec) elif is_FiniteField(R): from sage.schemes.affine.affine_rational_point import enum_affine_finite_field return enum_affine_finite_field(self) else: raise TypeError("unable to enumerate points over %s" % R)
def points(self, B=0): r""" Return some or all rational points of an affine scheme. INPUT: - ``B`` -- integer (optional, default: 0). The bound for the height of the coordinates. OUTPUT: - If the base ring is a finite field: all points of the scheme, given by coordinate tuples. - If the base ring is `\QQ` or `\ZZ`: the subset of points whose coordinates have height ``B`` or less. EXAMPLES: The bug reported at #11526 is fixed:: sage: A2 = AffineSpace(ZZ, 2) sage: F = GF(3) sage: A2(F).points() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: R = ZZ sage: A.<x,y> = R[] sage: I = A.ideal(x^2-y^2-1) sage: V = AffineSpace(R, 2) sage: X = V.subscheme(I) sage: M = X(R) sage: M.points(1) [(-1, 0), (1, 0)] :: sage: u = QQ['u'].0 sage: K.<v> = NumberField(u^2 + 3) sage: A.<x,y> = AffineSpace(K, 2) sage: len(A(K).points(9)) 361 :: sage: A.<x,y> = AffineSpace(QQ, 2) sage: E = A.subscheme([x^2 + y^2 - 1, y^2 - x^3 + x^2 + x - 1]) sage: E(A.base_ring()).points() [(-1, 0), (0, -1), (0, 1), (1, 0)] """ X = self.codomain() from sage.schemes.affine.affine_space import is_AffineSpace if not is_AffineSpace(X) and X.base_ring() in Fields(): # Then X must be a subscheme dim_ideal = X.defining_ideal().dimension() if dim_ideal < 0: # no points return [] if dim_ideal == 0: # if X zero-dimensional N = len(X.ambient_space().gens()) S = X.defining_polynomials()[0].parent() R = PolynomialRing(S.base_ring(), 's', N, order='lex') phi = S.hom(R.gens(), R) J = R.ideal([phi(t) for t in X.defining_polynomials()]) D = J.variety() points = [] for d in D: P = [d[t] for t in R.gens()] points.append(X(P)) points.sort() return points R = self.value_ring() if is_RationalField(R) or R == ZZ: if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) from sage.schemes.affine.affine_rational_point import enum_affine_rational_field return enum_affine_rational_field(self, B) if R in NumberFields(): if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) from sage.schemes.affine.affine_rational_point import enum_affine_number_field return enum_affine_number_field(self, B) elif is_FiniteField(R): from sage.schemes.affine.affine_rational_point import enum_affine_finite_field return enum_affine_finite_field(self) else: raise TypeError("unable to enumerate points over %s" % R)
def points(self, B=0, tolerance=0.9): r""" Return some or all rational points of an affine scheme. INPUT: - ``B`` -- integer (optional, default: 0). The bound for the height of the coordinates. OUTPUT: - If the base ring is a finite field: all points of the scheme, given by coordinate tuples. - If the base ring is `\QQ` or `\ZZ`: the subset of points whose coordinates have height ``B`` or less. EXAMPLES: The bug reported at #11526 is fixed:: sage: A2 = AffineSpace(ZZ, 2) sage: F = GF(3) sage: A2(F).points() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: R = ZZ sage: A.<x,y> = R[] sage: I = A.ideal(x^2-y^2-1) sage: V = AffineSpace(R, 2) sage: X = V.subscheme(I) sage: M = X(R) sage: M.points(1) [(-1, 0), (1, 0)] :: sage: u = QQ['u'].0 sage: K.<v> = NumberField(u^2 + 3) sage: A.<x,y> = AffineSpace(K, 2) sage: len(A(K).points(9)) 361 :: sage: A.<x,y> = AffineSpace(QQ, 2) sage: E = A.subscheme([x^2 + y^2 - 1, y^2 - x^3 + x^2 + x - 1]) sage: E(A.base_ring()).points() [(-1, 0), (0, -1), (0, 1), (1, 0)] :: sage: A.<x,y> = AffineSpace(CC, 2) sage: E = A.subscheme([y^3-x^3-x^2, x*y]) sage: E(A.base_ring()).points() [(-1.00000000000000, 0.000000000000000), (0.000000000000000, 0.000000000000000)] :: sage: A.<x1,x2> = AffineSpace(CDF, 2) sage: E = A.subscheme([x1^2+x2^2+x1*x2, x1+x2]) sage: E(A.base_ring()).points() [(0.0, 0.0)] """ from sage.schemes.affine.affine_space import is_AffineSpace from sage.rings.all import CC, CDF, RR X = self.codomain() tolerance_RR = RR(tolerance) if tolerance_RR.sign() != 1: raise ValueError("Tolerance must be positive") if not is_AffineSpace(X) and X.base_ring() in Fields(): if X.base_ring() == CC or X.base_ring() == CDF: complex = True else: complex = False # Then X must be a subscheme dim_ideal = X.defining_ideal().dimension() if dim_ideal < 0: # no points return [] if dim_ideal == 0: # if X zero-dimensional rat_points = [] PS = X.ambient_space() N = PS.dimension_relative() BR = X.base_ring() #need a lexicographic ordering for elimination R = PolynomialRing(BR, N, PS.gens(), order='lex') I = R.ideal(X.defining_polynomials()) I0 = R.ideal(0) #Determine the points through elimination #This is much faster than using the I.variety() function on each affine chart. G = I.groebner_basis() if G != [1]: P = {} points = [P] #work backwards from solving each equation for the possible #values of the next coordinate for i in range(len(G) - 1, -1, -1): new_points = [] good = 0 for P in points: #substitute in our dictionary entry that has the values #of coordinates known so far. This results in a single #variable polynomial (by elimination) L = G[i].substitute(P) if R(L).degree() > 0: if complex: for pol in L.univariate_polynomial().roots( multiplicities=False): r = L.variables()[0] varindex = R.gens().index(r) P.update({R.gen(varindex): pol}) new_points.append(copy(P)) good = 1 else: L = L.factor() #the linear factors give the possible rational values of #this coordinate for pol, pow in L: if pol.degree() == 1 and len( pol.variables()) == 1: good = 1 r = pol.variables()[0] varindex = R.gens().index(r) #add this coordinates information to #each dictionary entry P.update({ R.gen(varindex): -pol.constant_coefficient() / pol.monomial_coefficient(r) }) new_points.append(copy(P)) else: new_points.append(P) good = 1 if good: points = new_points #the dictionary entries now have values for all coordinates #they are the rational solutions to the equations #make them into projective points for i in range(len(points)): if complex: if len(points[i]) == N: S = X.ambient_space()( [points[i][R.gen(j)] for j in range(N)]) #S.normalize_coordinates() rat_points.append(S) else: if len(points[i]) == N and I.subs(points[i]) == I0: S = X([points[i][R.gen(j)] for j in range(N)]) #S.normalize_coordinates() rat_points.append(S) # remove duplicate element using tolerance if complex: tol = (X.base_ring().precision() * tolerance_RR).floor() dupl_points = list(rat_points) for i in range(len(dupl_points)): u = dupl_points[i] for j in range(i + 1, len(dupl_points)): v = dupl_points[j] if all([(u[k] - v[k]).abs() < 2**(-tol) for k in range(len(u))]): rat_points.remove(u) break rat_points = sorted(rat_points) return rat_points R = self.value_ring() if is_RationalField(R) or R == ZZ: if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) from sage.schemes.affine.affine_rational_point import enum_affine_rational_field return enum_affine_rational_field(self, B) if R in NumberFields(): if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) from sage.schemes.affine.affine_rational_point import enum_affine_number_field return enum_affine_number_field(self, B) elif is_FiniteField(R): from sage.schemes.affine.affine_rational_point import enum_affine_finite_field return enum_affine_finite_field(self) else: raise TypeError("unable to enumerate points over %s" % R)