def __init__(self, base, ideal=None): """ The Python constructor. EXAMPLES:: sage: Berkovich_Cp_Projective(3) Projective Berkovich line over Cp(3) of precision 20 """ if base in ZZ: if base.is_prime(): base = ProjectiveSpace(Qp(base), 1) else: raise ValueError("non-prime passed into Berkovich space") if base in NumberFields() or isinstance(base, sage.rings.abc.pAdicField): base = ProjectiveSpace(base, 1) if not is_ProjectiveSpace(base): try: base = ProjectiveSpace(base) except: raise ValueError( "base of projective Berkovich space must be projective space" ) if not isinstance(base.base_ring(), sage.rings.abc.pAdicField): if base.base_ring() not in NumberFields(): raise ValueError("base of projective Berkovich space must be " + \ "projective space over Qp or a number field") else: if ideal is None: raise ValueError('passed a number field but not an ideal') if base.base_ring() is not QQ: if not isinstance(ideal, NumberFieldFractionalIdeal): raise ValueError('ideal was not a number field ideal') if ideal.number_field() != base.base_ring(): raise ValueError('passed number field ' + \ '%s but ideal was an ideal of %s' %(base.base_ring(), ideal.number_field())) prime = ideal.smallest_integer() else: if ideal not in QQ: raise ValueError('ideal was not an element of QQ') prime = ideal if not ideal.is_prime(): raise ValueError('passed non prime ideal') self._base_type = 'number field' else: prime = base.base_ring().prime() ideal = None self._base_type = 'padic field' if base.dimension_relative() != 1: raise ValueError("base of projective Berkovich space must be " + \ "projective space of dimension 1 over Qp or a number field") self._p = prime self._ideal = ideal Parent.__init__(self, base=base, category=TopologicalSpaces())
def generators(self, K, precision) : if K is QQ or K in NumberFields() : return Sequence( [ jacobi_form_by_taylor_expansion(i, self.__index, self.__weight, precision) for i in xrange(self._rank(K)) ], universe = JacobiD1NNFourierExpansionModule(QQ, self.__index) ) raise NotImplementedError
def generator_relations(self, K): """ An ideal `I` in the attach polynomial ring `R`, such that the ring of modular forms is a quotient of `R / I`. This ideal must be unique for `K`. INPUT: - `K` -- A ring or module; The ring of Fourier coefficients. OUTPUT: An ideal in a polynomial ring. TESTS:: sage: from hermitianmodularforms import * sage: HermitianModularFormD2_Gamma(-3).generator_relations(QQ) Ideal (0) of Multivariate Polynomial Ring in HE4, HE6, HE10, HE12, Hphi9 over Rational Field sage: HermitianModularFormD2_Gamma(-3).generator_relations(GF(2)) Traceback (most recent call last): ... NotImplementedError: Only Fourier coefficients in a number fields are implemented. """ if self.__D == -3: if K is QQ or K in NumberFields(): R = PolynomialRing(K, self._generator_names(K)) return R.ideal(0) raise NotImplementedError( "Only Fourier coefficients in a number fields are implemented." ) raise NotImplementedError("Discriminant %s is not implemented." % (self.__D, ))
def _generator_names(self, K): """ Names of the generators returned by :meth:~`.generators` within the attached polynomial ring. INPUT: - `K` -- A ring or module; The ring of Fourier coefficients. OUTPUT: A list of strings. TESTS:: sage: from hermitianmodularforms import * sage: HermitianModularFormD2_Gamma(-3)._generator_names(QQ) ['HE4', 'HE6', 'HE10', 'HE12', 'Hphi9'] sage: HermitianModularFormD2_Gamma(-3)._generator_names(GF(2)) Traceback (most recent call last): ... NotImplementedError: Only Fourier coefficients in a number fields are implemented. """ if self.__D == -3: if K is QQ or K in NumberFields(): return ['HE4', 'HE6', 'HE10', 'HE12', 'Hphi9'] raise NotImplementedError( "Only Fourier coefficients in a number fields are implemented." ) raise NotImplementedError("Discriminant %s is not implemented." % (self.__D, ))
def grading(self, K): """ A grading for the ring or module of modular forms. INPUT: - `K` -- A ring or module; The ring of Fourier coefficients. OUTPUT: A grading class. NOTE: This coincides with the weight grading. TESTS:: sage: from hermitianmodularforms import * sage: HermitianModularFormD2_Gamma(-3).grading(QQ) Degree grading (4, 6, 10, 12, 18) sage: HermitianModularFormD2_Gamma(-3).grading(GF(2)) Traceback (most recent call last): ... NotImplementedError: Only Fourier coefficients in a number fields are implemented. """ if self.__D == -3: if K is QQ or K in NumberFields(): return DegreeGrading([4, 6, 10, 12, 18]) raise NotImplementedError( "Only Fourier coefficients in a number fields are implemented." ) raise NotImplementedError("Discriminant %s is not implemented." % (self.__D, ))
def generators(self, K, precision) : if K is QQ or K in NumberFields() : return Sequence([ self._satoh_I4_I6(precision), self._satoh_I4_I10(precision), self._satoh_I4_I12(precision), self._satoh_I6_I10(precision), self._satoh_I6_I12(precision), self._satoh_I10_I12(precision) ]) raise NotImplementedError
def generators(self, K, precision) : if K is QQ or K in NumberFields() : return Sequence( [ jacobi_form_d1_by_restriction(precision, self.__weight, i) for i in xrange(self._rank(K)) ], universe = JacobiFormD1FourierExpansionModule(QQ, self.__weight, self.__index) ) raise NotImplementedError
def weights(self, K) : r""" A list of integers corresponding to the weights. """ if K is QQ or K in NumberFields() : return [10,14,16,16,18,22] raise NotImplementedError
def weights(self, K): """ A list of integers corresponding to the weights. """ if K is QQ or K in NumberFields(): return self._rank(K) * [self.__weight] raise NotImplementedError
def _generator_by_name(self, K, name): if K is QQ or K in NumberFields(): R = self.generator_relations(K).ring() try: return R.gen(self._generator_names(K).index(name)) except ValueError: raise ValueError, "name %s doesn't exist for %s" % (name, K) raise NotImplementedError
def _generator_names(self, K): if K is QQ or K in NumberFields(): ## We assume that the space is spanned by Gritsenko products ## Introduce new names, as soon as new cases are implemented nmb_gps = len(self._gritsenko_products(None)[0]) return [ "GP_%s" % (i,) for i in xrange(nmb_gps)] + \ [ "SymS_%s" % (i,) for i in xrange(self._rank(K) - nmb_gps) ] raise NotImplementedError
def weights(self, K) : r""" A list of integers corresponding to the weights. """ if K is QQ or K in NumberFields() : return len(self._theta_decomposition_indices()) \ * [(self.__index, self.__weight)] raise NotImplementedError
def _generator_by_name(self, K, name) : if K is QQ or K in NumberFields() : R = self.generator_relations(K).ring() try : return R.gen(self._generator_names(K).index(name)) except ValueError : raise ValueError( "Name {0} does not exist for {1}".format(name, K) ) raise NotImplementedError
def _rank(self, K) : if K is QQ or K in NumberFields() : return len(_jacobi_forms_by_taylor_expansion_coords(self.__index, self.__weight, 0)) ## This is the formula used by Poor and Yuen in Paramodular cusp forms if self.__weight == 2 : delta = len(self.__index.divisors()) // 2 - 1 else : delta = 0 return sum( ModularForms(1, self.__weight + 2 * j).dimension() + j**2 // (4 * self.__index) for j in xrange(self.__index + 1) ) \ + delta ## This is the formula given by Skoruppa in ## Jacobi forms of critical weight and Weil representations ##FIXME: There is some mistake here if self.__weight % 2 != 0 : ## Otherwise the space X(i**(n - 2 k)) is different ## See: Skoruppa, Jacobi forms of critical weight and Weil representations raise NotImplementedError m = self.__index K = CyclotomicField(24 * m, 'zeta') zeta = K.gen(0) quadform = lambda x : 6 * x**2 bilinform = lambda x,y : quadform(x + y) - quadform(x) - quadform(y) T = diagonal_matrix([zeta**quadform(i) for i in xrange(2*m)]) S = sum(zeta**(-quadform(x)) for x in xrange(2 * m)) / (2 * m) \ * matrix([[zeta**(-bilinform(j,i)) for j in xrange(2*m)] for i in xrange(2*m)]) subspace_matrix_1 = matrix( [ [1 if j == i or j == 2*m - i else 0 for j in xrange(m + 1) ] for i in xrange(2*m)] ) subspace_matrix_2 = zero_matrix(ZZ, m + 1, 2*m) subspace_matrix_2.set_block(0,0,identity_matrix(m+1)) T = subspace_matrix_2 * T * subspace_matrix_1 S = subspace_matrix_2 * S * subspace_matrix_1 sqrt3 = (zeta**(4*m) - zeta**(-4*m)) * zeta**(-6*m) rank = (self.__weight - 1/2 - 1) / 2 * (m + 1) \ + 1/8 * ( zeta**(3*m * (2*self.__weight - 1)) * S.trace() + zeta**(3*m * (1 - 2*self.__weight)) * S.trace().conjugate() ) \ + 2/(3*sqrt3) * ( zeta**(4 * m * self.__weight) * (S*T).trace() + zeta**(-4 * m * self.__weight) * (S*T).trace().conjugate() ) \ - sum((j**2 % (m+1))/(m+1) -1/2 for j in range(0,m+1)) if self.__weight > 5 / 2 : return rank else : raise NotImplementedError raise NotImplementedError
def generator_relations(self, K) : r""" An ideal `I` in a polynomial ring `R`, such that the associated ring is `R / I`. This ideal must be unique for `K`. """ if K is QQ or K in NumberFields() : R = PolynomialRing(K, self._generator_names(K)) return R.ideal(0) raise NotImplementedError
def generator_relations(self, K): r""" An ideal I in a polynomial ring R, such that the associated module is (R / I)_1. """ if K is QQ or K in NumberFields(): R = PolynomialRing(K, self._generator_names(K)) return R.ideal(0) raise NotImplementedError
def global_height(self, prec=None): r""" Return the absolute logarithmic height of the point. This function computes the maximum of global height of each component point in the product. Global height of component point is computed using function for projective point. INPUT: - ``prec`` -- desired floating point precision (default: default RealField precision). OUTPUT: - a real number. EXAMPLES:: sage: PP = ProductProjectiveSpaces(QQ, [2,2], 'x') sage: Q = PP([1, 7, 5, 18, 2, 3]) sage: Q.global_height() 1.94591014905531 :: sage: PP = ProductProjectiveSpaces(ZZ, [1,1], 'x') sage: A = PP([-30, 2, 1, 6]) sage: A.global_height() 3.40119738166216 :: sage: R.<x> = PolynomialRing(QQ) sage: k.<w> = NumberField(x^2 + 5) sage: PP = ProductProjectiveSpaces(k, [1, 2], 'y') sage: Q = PP([3, 5*w+1, 1, 7*w, 10]) sage: Q.global_height() 2.30258509299405 :: sage: PP = ProductProjectiveSpaces(QQbar, [1, 1], 'x') sage: Q = PP([1, QQbar(sqrt(2)), QQbar(5^(1/3)), QQbar(3^(1/3))]) sage: Q.global_height() 0.536479304144700 """ K = self.codomain().base_ring() if K not in NumberFields( ) and not is_NumberFieldOrder(K) and K != QQbar: raise TypeError( "must be over a number field or a number field order or QQbar") n = self.codomain().ambient_space().num_components() return max(self[i].global_height(prec=prec) for i in range(n))
def _generator_by_name(self, K, name) : if K is QQ or K in NumberFields() : R = self.generator_relations(K).ring() if name == "I4" : return R.gen(0) elif name == "I6" : return R.gen(1) elif name == "I10" : return R.gen(2) elif name == "I12" : return R.gen(3) raise ValueError, "name %s doesn't exist for %s" % (name, K) raise NotImplementedError
def global_height(self, prec=None): r""" Returns the maximum of the absolute logarithmic heights of the coefficients in any of the coordinate functions of this map. INPUT: - ``prec`` -- desired floating point precision (default: default RealField precision). OUTPUT: - a real number. .. TODO:: Add functionality for `\QQbar`, implement function to convert the map defined over `\QQbar` to map over a number field. EXAMPLES:: sage: P1xP1.<x,y,u,v> = ProductProjectiveSpaces([1, 1], ZZ) sage: H = End(P1xP1) sage: f = H([x^2*u, 3*y^2*v, 5*x*v^2, y*u^2]) sage: f.global_height() 1.60943791243410 :: sage: u = QQ['u'].0 sage: R = NumberField(u^2 - 2, 'v') sage: PP.<x,y,a,b> = ProductProjectiveSpaces([1, 1], R) sage: H = End(PP) sage: O = R.maximal_order() sage: g = H([3*O(u)*x^2, 13*x*y, 7*a*y, 5*b*x + O(u)*a*y]) sage: g.global_height() 2.56494935746154 """ K = self.domain().base_ring() if K in NumberFields() or is_NumberFieldOrder(K): H = 0 for i in range(self.domain().ambient_space().ngens()): C = self[i].coefficients() h = max(c.global_height(prec=prec) for c in C) H = max(H, h) return H elif K == QQbar: raise NotImplementedError("not implemented for QQbar") else: raise TypeError( "Must be over a Numberfield or a Numberfield Order or QQbar")
def generators(self, K, precision) : if K is QQ or K in NumberFields() : gps = self._gritsenko_products(precision)[1] if len(gps) != self._rank(QQ) : syms = self._symmetrised_siegel_modular_forms(precision) em = ExpansionModule(Sequence(gps + syms, universe = ParamodularFormD2FourierExpansionRing(QQ, self.__level) ) ) gens = [e.fourier_expansion() for e in em.pivot_elements()] else : gens = gps if len(gens) == self._rank(QQ) : return Sequence( gens, universe = ParamodularFormD2FourierExpansionRing(QQ, self.__level) ) raise ArithmeticError("Gritsenko products do not span this space.") raise NotImplementedError
def __init__(self, base, ideal=None): """ The Python constructor. EXAMPLES:: sage: Berkovich_Cp_Affine(3) Affine Berkovich line over Cp(3) of precision 20 """ if base in ZZ: if base.is_prime(): base = Qp(base) # change to Qpbar else: raise ValueError("non-prime passed into Berkovich space") if is_AffineSpace(base): base = base.base_ring() if base in NumberFields(): if ideal is None: raise ValueError('passed a number field but not an ideal') if base is not QQ: if not isinstance(ideal, NumberFieldFractionalIdeal): raise ValueError( 'ideal was not an ideal of a number field') if ideal.number_field() != base: raise ValueError('passed number field ' + \ '%s but ideal was an ideal of %s' %(base, ideal.number_field())) prime = ideal.smallest_integer() else: if ideal not in QQ: raise ValueError('ideal was not an element of QQ') prime = ideal if not ideal.is_prime(): raise ValueError('passed non prime ideal') self._base_type = 'number field' elif isinstance(base, sage.rings.abc.pAdicField): # change base to Qpbar prime = base.prime() ideal = None self._base_type = 'padic field' else: raise ValueError("base of Berkovich Space must be a padic field " + \ "or a number field") self._ideal = ideal self._p = prime Parent.__init__(self, base=base, category=TopologicalSpaces())
def local_height(self, v, prec=None): r""" Returns the maximum of the local height of the coefficients in any of the coordinate functions of this map. INPUT: - ``v`` -- a prime or prime ideal of the base ring. - ``prec`` -- desired floating point precision (default: default RealField precision). OUTPUT: - a real number. EXAMPLES:: sage: T.<x,y,z,w,u> = ProductProjectiveSpaces([2, 1], QQ) sage: H = T.Hom(T) sage: f = H([4*x^2+3/100*y^2, 8/210*x*y, 1/10000*z^2, 20*w^2, 1/384*u*w]) sage: f.local_height(2) 4.85203026391962 :: sage: R.<z> = PolynomialRing(QQ) sage: K.<w> = NumberField(z^2-5) sage: P.<x,y,a,b> = ProductProjectiveSpaces([1, 1], K) sage: H = Hom(P,P) sage: f = H([2*x^2 + w/3*y^2, 1/w*y^2, a^2, 6*b^2 + 1/9*a*b]) sage: f.local_height(K.ideal(3)) 2.19722457733622 """ K = FractionField(self.domain().base_ring()) if K not in NumberFields(): raise TypeError( "must be over a number field or a number field order") H = 0 for i in range(self.domain().ambient_space().ngens()): C = self[i].coefficients() h = max(K(c).local_height(v, prec) for c in C) H = max(H, h) return H
def generators(self, K, precision): """ A list of Fourier expansions of forms that generate the ring or module of modular forms. INPUT: - `K` -- A ring or module; The ring of Fourier coefficients. - ``precision`` -- A precision class; The precision of the Fourier expansions. OUTPUT: A sequence of equivariant monoid power series. TESTS:: sage: from hermitianmodularforms import * sage: from hermitianmodularforms.hermitianmodularformd2_fourierexpansion import HermitianModularFormD2Filter_diagonal sage: from hermitianmodularforms.hermitianmodularformd2_fourierexpansion import HermitianModularFormD2FourierExpansionRing sage: HermitianModularFormD2_Gamma(-3).generators(QQ, HermitianModularFormD2Filter_diagonal(2, -3)).universe() == HermitianModularFormD2FourierExpansionRing(QQ, -3) True sage: HermitianModularFormD2_Gamma(-3).generators(GF(2), HermitianModularFormD2Filter_diagonal(2, -3)) Traceback (most recent call last): ... NotImplementedError: Only Fourier coefficients in a number fields are implemented. """ if self.__D == -3: if K is QQ or K in NumberFields(): return Sequence( [ self._e4_D3(precision), self._e6_D3(precision), self._e10_D3(precision), self._e12_D3(precision), self._phi9_D3(precision) ], universe=HermitianModularFormD2FourierExpansionRing( QQ, -3)) raise NotImplementedError( "Only Fourier coefficients in a number fields are implemented." ) raise NotImplementedError("Discriminant %s is not implemented." % (self.__D, ))
def _generator_by_name(self, K, name): """ Return the generator ``name`` as an element of the attached polynomial ring. INPUT: - `K` -- A ring or module; The ring of Fourier coefficients. - ``name`` -- A string; The generator's name. OUTPUT: An element of a polynomial ring. TESTS:: sage: from hermitianmodularforms import * sage: HermitianModularFormD2_Gamma(-3)._generator_by_name(QQ, "HE4") HE4 sage: HermitianModularFormD2_Gamma(-3)._generator_by_name(QQ, "???") Traceback (most recent call last): ... ValueError: Name ??? does not exist for Fourier coefficient domain Rational Field. sage: HermitianModularFormD2_Gamma(-3)._generator_by_name(GF(2), "HE4") Traceback (most recent call last): ... NotImplementedError: Only Fourier coefficients in a number fields are implemented. """ if self.__D == -3: if K is QQ or K in NumberFields(): R = self.generator_relations(K).ring() try: return R.gen(self._generator_names(K).index(name)) except ValueError: raise ValueError, "Name %s does not exist for Fourier coefficient domain %s." % ( name, K) raise NotImplementedError( "Only Fourier coefficients in a number fields are implemented." ) raise NotImplementedError("Discriminant %s is not implemented." % (self.__D, ))
def local_height(self, v, prec=None): r""" Return the maximum of the local height of the coordinates of this point. This function computes the maximum of local height of each component point in the product. Local height of component point is computed using function for projective point. INPUT: - ``v`` -- a prime or prime ideal of the base ring. - ``prec`` -- desired floating point precision (default: default RealField precision). OUTPUT: - a real number. EXAMPLES:: sage: PP = ProductProjectiveSpaces(QQ, [1, 1], 'x') sage: A = PP([11, 5, 10, 2]) sage: A.local_height(5) 1.60943791243410 :: sage: P = ProductProjectiveSpaces(QQ, [1,2], 'x') sage: Q = P([1, 4, 1/2, 2, 32]) sage: Q.local_height(2) 4.15888308335967 """ K = FractionField(self.domain().base_ring()) if K not in NumberFields(): raise TypeError( "must be over a number field or a number field order") n = self.codomain().ambient_space().num_components() return max(self[i].local_height(v, prec=prec) for i in range(n))
def _generator_by_name(self, K, name) : if K is QQ or K in NumberFields() : R = self.generator_relations(K).ring() try : i = self._generator_names(K).index(name) return R.gen(i) except ValueError: raise ValueError, "name %s doesn't exist for %s" % (name, K) #=================================================================== # if name == "I4" : return R.gen(0) # elif name == "I6" : return R.gen(1) # elif name == "I10" : return R.gen(2) # elif name == "I12" : return R.gen(3) # elif name == "SB_I4_I6" : return R.gen(4) # elif name == "SB_I4_I10" : return R.gen(5) # elif name == "SB_I4_I12" : return R.gen(6) # elif name == "SB_I6_I10" : return R.gen(7) # elif name == "SB_I6_I12" : return R.gen(8) # elif name == "SB_I10_I12" : return R.gen(9) #=================================================================== raise NotImplementedError
# * _point_morphism_class -> _morphism # * _homset_class -> _point_homset #***************************************************************************** # Copyright (C) 2011 Volker Braun <*****@*****.**> # Copyright (C) 2006 David Kohel <*****@*****.**> # Copyright (C) 2006 William Stein <*****@*****.**> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** from sage.categories.number_fields import NumberFields _NumberFields = NumberFields() from sage.rings.integer_ring import ZZ from sage.rings.number_field.order import is_NumberFieldOrder from sage.rings.real_mpfr import RealField from sage.schemes.generic.morphism import (SchemeMorphism_point, SchemeMorphism, is_SchemeMorphism) from sage.structure.sequence import Sequence ############################################################################ # Rational points on schemes, which we view as morphisms determined # by coordinates. ############################################################################ class SchemeMorphism_point_affine(SchemeMorphism_point): """
def is_injective(self): """ Return whether or not this morphism is injective. EXAMPLES: This often raises a ``NotImplementedError`` as many homomorphisms do not implement this method:: sage: R.<x> = QQ[] sage: f = R.hom([x + 1]); f Ring endomorphism of Univariate Polynomial Ring in x over Rational Field Defn: x |--> x + 1 sage: f.is_injective() Traceback (most recent call last): ... NotImplementedError If the domain is a field, the homomorphism is injective:: sage: K.<x> = FunctionField(QQ) sage: L.<y> = FunctionField(QQ) sage: f = K.hom([y]); f Function Field morphism: From: Rational function field in x over Rational Field To: Rational function field in y over Rational Field Defn: x |--> y sage: f.is_injective() True Unless the codomain is the zero ring:: sage: codomain = Integers(1) sage: f = QQ.hom([Zmod(1)(0)], check=False) sage: f.is_injective() False Homomorphism from rings of characteristic zero to rings of positive characteristic can not be injective:: sage: R.<x> = ZZ[] sage: f = R.hom([GF(3)(1)]); f Ring morphism: From: Univariate Polynomial Ring in x over Integer Ring To: Finite Field of size 3 Defn: x |--> 1 sage: f.is_injective() False A morphism whose domain is an order in a number field is injective if the codomain has characteristic zero:: sage: K.<x> = FunctionField(QQ) sage: f = ZZ.hom(K); f Composite map: From: Integer Ring To: Rational function field in x over Rational Field Defn: Conversion via FractionFieldElement_1poly_field map: From: Integer Ring To: Fraction Field of Univariate Polynomial Ring in x over Rational Field then Isomorphism: From: Fraction Field of Univariate Polynomial Ring in x over Rational Field To: Rational function field in x over Rational Field sage: f.is_injective() True A coercion to the fraction field is injective:: sage: R = ZpFM(3) sage: R.fraction_field().coerce_map_from(R).is_injective() True """ if self.domain().is_zero(): return True if self.codomain().is_zero(): # the only map to the zero ring that is injective is the map from itself return False from sage.categories.fields import Fields if self.domain() in Fields(): # A ring homomorphism from a field to a ring is injective # (unless the codomain is the zero ring.) Note that ring # homomorphism must send the 1 element to the 1 element return True if self.domain().characteristic() == 0: if self.codomain().characteristic() != 0: return False else: from sage.categories.integral_domains import IntegralDomains if self.domain() in IntegralDomains(): # if all elements of the domain are algebraic over ZZ, # then the homomorphism must be injective (in # particular if the domain is ZZ) from sage.categories.number_fields import NumberFields if self.domain().fraction_field() in NumberFields(): return True if self._is_coercion: try: K = self.domain().fraction_field() except (TypeError, AttributeError, ValueError): pass else: if K is self.codomain(): return True if self.domain().cardinality() > self.codomain().cardinality(): return False raise NotImplementedError
def __init__(self): r""" We create the rational numbers `\QQ`, and call a few functions:: sage: Q = RationalField(); Q Rational Field sage: Q.characteristic() 0 sage: Q.is_field() True sage: Q.category() Join of Category of number fields and Category of quotient fields and Category of metric spaces sage: Q.zeta() -1 We next illustrate arithmetic in `\QQ`. :: sage: Q('49/7') 7 sage: type(Q('49/7')) <type 'sage.rings.rational.Rational'> sage: a = Q('19/374'); a 19/374 sage: b = Q('17/371'); b 17/371 sage: a + b 13407/138754 sage: b + a 13407/138754 sage: a * b 19/8162 sage: b * a 19/8162 sage: a - b 691/138754 sage: b - a -691/138754 sage: a / b 7049/6358 sage: b / a 6358/7049 sage: b < a True sage: a < b False Next finally illustrate arithmetic with automatic coercion. The types that coerce into the rational field include ``str, int, long, Integer``. :: sage: a + Q('17/371') 13407/138754 sage: a * 374 19 sage: 374 * a 19 sage: a/19 1/374 sage: a + 1 393/374 TESTS:: sage: TestSuite(QQ).run() sage: QQ.variable_name() 'x' sage: QQ.variable_names() ('x',) sage: QQ._element_constructor_((2, 3)) 2/3 sage: QQ.is_finite() False sage: QQ.is_field() True """ from sage.categories.basic import QuotientFields from sage.categories.number_fields import NumberFields ParentWithGens.__init__( self, self, category=[QuotientFields().Metric(), NumberFields()]) self._assign_names(('x', ), normalize=False) # ????? self._populate_coercion_lists_(init_no_parent=True)
def points_of_bounded_height(self, bound): r""" Returns an iterator of the points in self of absolute height of at most the given bound. Bound check is strict for the rational field. Requires self to be affine space over a number field. Uses the Doyle-Krumm algorithm for computing algebraic numbers up to a given height [Doyle-Krumm]. INPUT: - ``bound`` - a real number OUTPUT: - an iterator of points in self EXAMPLES:: sage: A.<x,y> = AffineSpace(QQ,2) sage: list(A.points_of_bounded_height(3)) [(0, 0), (1, 0), (-1, 0), (1/2, 0), (-1/2, 0), (2, 0), (-2, 0), (0, 1), (1, 1), (-1, 1), (1/2, 1), (-1/2, 1), (2, 1), (-2, 1), (0, -1), (1, -1), (-1, -1), (1/2, -1), (-1/2, -1), (2, -1), (-2, -1), (0, 1/2), (1, 1/2), (-1, 1/2), (1/2, 1/2), (-1/2, 1/2), (2, 1/2), (-2, 1/2), (0, -1/2), (1, -1/2), (-1, -1/2), (1/2, -1/2), (-1/2, -1/2), (2, -1/2), (-2, -1/2), (0, 2), (1, 2), (-1, 2), (1/2, 2), (-1/2, 2), (2, 2), (-2, 2), (0, -2), (1, -2), (-1, -2), (1/2, -2), (-1/2, -2), (2, -2), (-2, -2)] :: sage: u = QQ['u'].0 sage: A.<x,y> = AffineSpace(NumberField(u^2 - 2,'v'), 2) sage: len(list(A.points_of_bounded_height(6))) 121 """ if (is_RationalField(self.base_ring())): ftype = False # stores whether field is a number field or the rational field elif ( self.base_ring() in NumberFields() ): # true for rational field as well, so check is_RationalField first ftype = True else: raise NotImplementedError( "self must be affine space over a number field.") bound = bound**(1 / self.base_ring().absolute_degree() ) # convert to relative height n = self.dimension_relative() R = self.base_ring() zero = R(0) P = [zero for _ in range(n)] yield self(P) if (ftype == False): iters = [R.range_by_height(bound) for _ in range(n)] else: iters = [R.elements_of_bounded_height(bound) for _ in range(n)] for x in iters: next(x) # put at zero i = 0 while i < n: try: P[i] = next(iters[i]) yield self(P) i = 0 except StopIteration: if (ftype == False): iters[i] = R.range_by_height(bound) # reset else: iters[i] = R.elements_of_bounded_height(bound) next(iters[i]) # put at zero P[i] = zero i += 1