def can_convert_to_singular(R): """ Returns True if this ring's base field or ring can be represented in Singular, and the polynomial ring has at least one generator. If this is True then this polynomial ring can be represented in Singular. The following base rings are supported: finite fields, rationals, number fields, and real and complex fields. EXAMPLES:: sage: from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular sage: can_convert_to_singular(PolynomialRing(QQ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(QQ, names=[])) False """ if R.ngens() == 0: return False; base_ring = R.base_ring() return ( sage.rings.finite_rings.constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) or (base_ring.is_prime_field() and base_ring.characteristic() <= 2147483647) or is_RealField(base_ring) or is_ComplexField(base_ring) or is_RealDoubleField(base_ring) or is_ComplexDoubleField(base_ring) or number_field.all.is_NumberField(base_ring) or ( sage.rings.fraction_field.is_FractionField(base_ring) and ( base_ring.base_ring().is_prime_field() or base_ring.base_ring() is ZZ ) ) or base_ring is ZZ or is_IntegerModRing(base_ring) )
def is_locally_solvable(self, p): r""" Returns True if and only if ``self`` has a solution over the `p`-adic numbers. Here `p` is a prime number or equals `-1`, infinity, or `\RR` to denote the infinite place. EXAMPLES:: sage: C = Conic(QQ, [1,2,3]) sage: C.is_locally_solvable(-1) False sage: C.is_locally_solvable(2) False sage: C.is_locally_solvable(3) True sage: C.is_locally_solvable(QQ.hom(RR)) False sage: D = Conic(QQ, [1, 2, -3]) sage: D.is_locally_solvable(infinity) True sage: D.is_locally_solvable(RR) True """ from sage.categories.map import Map from sage.categories.all import Rings D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] if abc[2] == 0: return True a = -abc[0] / abc[2] b = -abc[1] / abc[2] if is_RealField(p) or is_InfinityElement(p): p = -1 elif isinstance(p, Map) and p.category_for().is_subcategory(Rings()): # p is a morphism of Rings if p.domain() is QQ and is_RealField(p.codomain()): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " \ "B ( =`QQ`) in is_locally_solvable" % p) if hilbert_symbol(a, b, p) == -1: if self._local_obstruction is None: self._local_obstruction = p return False return True
def is_locally_solvable(self, p): r""" Returns True if and only if ``self`` has a solution over the `p`-adic numbers. Here `p` is a prime number or equals `-1`, infinity, or `\RR` to denote the infinite place. EXAMPLES:: sage: C = Conic(QQ, [1,2,3]) sage: C.is_locally_solvable(-1) False sage: C.is_locally_solvable(2) False sage: C.is_locally_solvable(3) True sage: C.is_locally_solvable(QQ.hom(RR)) False sage: D = Conic(QQ, [1, 2, -3]) sage: D.is_locally_solvable(infinity) True sage: D.is_locally_solvable(RR) True """ from sage.categories.map import Map from sage.categories.all import Rings D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] if abc[2] == 0: return True a = -abc[0]/abc[2] b = -abc[1]/abc[2] if is_RealField(p) or is_InfinityElement(p): p = -1 elif isinstance(p, Map) and p.category_for().is_subcategory(Rings()): # p is a morphism of Rings if p.domain() is QQ and is_RealField(p.codomain()): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " \ "B ( =`QQ`) in is_locally_solvable" % p) if hilbert_symbol(a, b, p) == -1: if self._local_obstruction is None: self._local_obstruction = p return False return True
def _evalf_(self, n, x, **kwds): """ Evaluate :class:`chebyshev_U` numerically with mpmath. EXAMPLES:: sage: chebyshev_U(5,-4+3.*I) 98280.0000000000 - 11310.0000000000*I sage: chebyshev_U(10,3).n(75) 4.661117900000000000000e7 sage: chebyshev_U._evalf_(1.5, Mod(8,9)) Traceback (most recent call last): ... TypeError: cannot evaluate chebyshev_U with parent Ring of integers modulo 9 """ try: real_parent = kwds['parent'] except KeyError: real_parent = parent(x) if not is_RealField(real_parent) and not is_ComplexField( real_parent): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) real_parent = RR elif x in CC: x = CC(x) real_parent = CC if not is_RealField(real_parent) and not is_ComplexField(real_parent): raise TypeError( "cannot evaluate chebyshev_U with parent {}".format( real_parent)) from sage.libs.mpmath.all import call as mpcall from sage.libs.mpmath.all import chebyu as mpchebyu return mpcall(mpchebyu, n, x, parent=real_parent)
def can_convert_to_singular(R): """ Returns True if this ring's base field or ring can be represented in Singular, and the polynomial ring has at least one generator. If this is True then this polynomial ring can be represented in Singular. The following base rings are supported: finite fields, rationals, number fields, and real and complex fields. EXAMPLES:: sage: from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular sage: can_convert_to_singular(PolynomialRing(QQ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(ZZ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(QQ, names=[])) False TESTS: Avoid non absolute number fields (see :trac:`23535`):: sage: K.<a,b> = NumberField([x^2-2,x^2-5]) sage: can_convert_to_singular(K['s,t']) False """ if R.ngens() == 0: return False base_ring = R.base_ring() if (base_ring is ZZ or sage.rings.finite_rings.finite_field_constructor.is_FiniteField( base_ring) or is_RationalField(base_ring) or is_IntegerModRing(base_ring) or is_RealField(base_ring) or is_ComplexField(base_ring) or is_RealDoubleField(base_ring) or is_ComplexDoubleField(base_ring)): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 elif number_field.number_field_base.is_NumberField(base_ring): return base_ring.is_absolute() elif sage.rings.fraction_field.is_FractionField(base_ring): B = base_ring.base_ring() return B.is_prime_field() or B is ZZ or is_FiniteField(B) elif is_RationalFunctionField(base_ring): return base_ring.constant_field().is_prime_field() else: return False
def __init__(self, X, P, codomain=None, check=False): r""" Create the discrete probability space with probabilities on the space X given by the dictionary P with values in the field real_field. EXAMPLES:: sage: S = [ i for i in range(16) ] sage: P = {} sage: for i in range(15): P[i] = 2^(-i-1) sage: P[15] = 2^-16 sage: X = DiscreteProbabilitySpace(S,P) sage: X.domain() (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) sage: X.set() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} sage: X.entropy().n() 1.99972534179688 A probability space can be defined on any list of elements:: sage: AZ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' sage: S = [ AZ[i] for i in range(26) ] sage: P = { 'A':1/2, 'B':1/4, 'C':1/4 } sage: X = DiscreteProbabilitySpace(S,P) sage: X Discrete probability space defined by {'A': 1/2, 'C': 1/4, 'B': 1/4} sage: X.entropy().n() 1.50000000000000 """ if codomain is None: codomain = RealField() if not is_RealField(codomain) and not is_RationalField(codomain): raise TypeError( "Argument codomain (= %s) must be the reals or rationals" % codomain) if check: one = sum([P[x] for x in P.keys()]) if is_RationalField(codomain): if not one == 1: raise TypeError( "Argument P (= %s) does not define a probability function" ) else: if not Abs(one - 1) < 2 ^ (-codomain.precision() + 1): raise TypeError( "Argument P (= %s) does not define a probability function" ) ProbabilitySpace_generic.__init__(self, X, codomain) DiscreteRandomVariable.__init__(self, self, P, codomain, check)
def can_convert_to_singular(R): """ Returns True if this ring's base field or ring can be represented in Singular, and the polynomial ring has at least one generator. If this is True then this polynomial ring can be represented in Singular. The following base rings are supported: finite fields, rationals, number fields, and real and complex fields. EXAMPLES:: sage: from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular sage: can_convert_to_singular(PolynomialRing(QQ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(QQ, names=[])) False TESTS: Avoid non absolute number fields (see :trac:`23535`):: sage: K.<a,b> = NumberField([x^2-2,x^2-5]) sage: can_convert_to_singular(K['s,t']) False """ if R.ngens() == 0: return False; base_ring = R.base_ring() if (base_ring is ZZ or sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) or is_IntegerModRing(base_ring) or is_RealField(base_ring) or is_ComplexField(base_ring) or is_RealDoubleField(base_ring) or is_ComplexDoubleField(base_ring)): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 elif number_field.number_field_base.is_NumberField(base_ring): return base_ring.is_absolute() elif sage.rings.fraction_field.is_FractionField(base_ring): B = base_ring.base_ring() return B.is_prime_field() or B is ZZ or is_FiniteField(B) elif is_RationalFunctionField(base_ring): return base_ring.constant_field().is_prime_field() else: return False
def _evalf_(self, n, x, **kwds): """ Evaluate :class:`chebyshev_U` numerically with mpmath. EXAMPLES:: sage: chebyshev_U(5,-4+3.*I) 98280.0000000000 - 11310.0000000000*I sage: chebyshev_U(10,3).n(75) 4.661117900000000000000e7 sage: chebyshev_U._evalf_(1.5, Mod(8,9)) Traceback (most recent call last): ... TypeError: cannot evaluate chebyshev_U with parent Ring of integers modulo 9 """ try: real_parent = kwds["parent"] except KeyError: real_parent = parent(x) if not is_RealField(real_parent) and not is_ComplexField(real_parent): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) real_parent = RR elif x in CC: x = CC(x) real_parent = CC if not is_RealField(real_parent) and not is_ComplexField(real_parent): raise TypeError("cannot evaluate chebyshev_U with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall from sage.libs.mpmath.all import chebyu as mpchebyu return mpcall(mpchebyu, n, x, parent=real_parent)
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES: First, let us test several values for a given character:: sage: RR = RealField(100) sage: for i in range(5): ....: print("L({}, (-4/.)): {}".format(1+2*i, RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000))) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 This procedure fails for negative special values, as the Dirichlet series does not converge here:: sage: quadratic_L_function__numerical(-3,-4, 10000) Traceback (most recent call last): ... ValueError: the Dirichlet series does not converge here Test for several characters that the result agrees with the exact value, to a given accuracy :: sage: for d in range(-20,0): # long time (2s on sage.math 2014) ....: if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ....: print("Oops! We have a problem at d = {}: exact = {}, numerical = {}".format(d, RR(quadratic_L_function__exact(1, d)), RR(quadratic_L_function__numerical(1, d)))) """ # Set the correct precision if it is given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() if n < 0: raise ValueError('the Dirichlet series does not converge here') d1 = fundamental_discriminant(d) ans = R.zero() for i in range(1,num_terms): ans += R(kronecker_symbol(d1,i) / R(i)**n) return ans
def __init__(self, X, P, codomain = None, check = False): r""" Create the discrete probability space with probabilities on the space X given by the dictionary P with values in the field real_field. EXAMPLES:: sage: S = [ i for i in range(16) ] sage: P = {} sage: for i in range(15): P[i] = 2^(-i-1) sage: P[15] = 2^-16 sage: X = DiscreteProbabilitySpace(S,P) sage: X.domain() (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) sage: X.set() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} sage: X.entropy() 1.9997253418 A probability space can be defined on any list of elements. EXAMPLES:: sage: AZ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' sage: S = [ AZ[i] for i in range(26) ] sage: P = { 'A':1/2, 'B':1/4, 'C':1/4 } sage: X = DiscreteProbabilitySpace(S,P) sage: X Discrete probability space defined by {'A': 1/2, 'C': 1/4, 'B': 1/4} sage: X.entropy() 1.5 """ if codomain is None: codomain = RealField() if not is_RealField(codomain) and not is_RationalField(codomain): raise TypeError("Argument codomain (= %s) must be the reals or rationals" % codomain) if check: one = sum([ P[x] for x in P.keys() ]) if is_RationalField(codomain): if not one == 1: raise TypeError("Argument P (= %s) does not define a probability function") else: if not Abs(one-1) < 2^(-codomain.precision()+1): raise TypeError("Argument P (= %s) does not define a probability function") ProbabilitySpace_generic.__init__(self, X, codomain) DiscreteRandomVariable.__init__(self, self, P, codomain, check)
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES: First, let us test several values for a given character:: sage: RR = RealField(100) sage: for i in range(5): ....: print("L({}, (-4/.)): {}".format(1+2*i, RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000))) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 This procedure fails for negative special values, as the Dirichlet series does not converge here:: sage: quadratic_L_function__numerical(-3,-4, 10000) Traceback (most recent call last): ... ValueError: the Dirichlet series does not converge here Test for several characters that the result agrees with the exact value, to a given accuracy :: sage: for d in range(-20,0): # long time (2s on sage.math 2014) ....: if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ....: print("Oops! We have a problem at d = {}: exact = {}, numerical = {}".format(d, RR(quadratic_L_function__exact(1, d)), RR(quadratic_L_function__numerical(1, d)))) """ # Set the correct precision if it is given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() if n < 0: raise ValueError('the Dirichlet series does not converge here') d1 = fundamental_discriminant(d) ans = R.zero() for i in range(1, num_terms): ans += R(kronecker_symbol(d1, i) / R(i)**n) return ans
def complex_conjugation(self, P=None): """ Return the unique element of self corresponding to complex conjugation, for a specified embedding P into the complex numbers. If P is not specified, use the "standard" embedding, whenever that is well-defined. EXAMPLE:: sage: L = CyclotomicField(7) sage: G = L.galois_group() sage: G.complex_conjugation() (1,6)(2,3)(4,5) An example where the field is not CM, so complex conjugation really depends on the choice of embedding:: sage: L = NumberField(x^6 + 40*x^3 + 1372,'a') sage: G = L.galois_group() sage: [G.complex_conjugation(x) for x in L.places()] [(1,3)(2,6)(4,5), (1,5)(2,4)(3,6), (1,2)(3,4)(5,6)] """ if P is None: Q = self.splitting_field().specified_complex_embedding() if Q is None: raise ValueError, "No default complex embedding specified" P = Q from sage.rings.real_mpfr import is_RealField from sage.rings.qqbar import is_AlgebraicRealField if is_RealField(P.codomain()) or is_AlgebraicRealField(P.codomain()): return self.one() P = refine_embedding(P, infinity) if self._non_galois_not_impl: raise TypeError, "Extension is not Galois" g = self.splitting_field().gen() gconj = P(g).conjugate() elts = [s for s in self if P(s(g)) == gconj] if len(elts) != 1: raise ArithmeticError, "Something has gone very wrong here" return elts[0]
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES:: sage: ## Test several values for a given character sage: RR = RealField(100) sage: for i in range(5): ... print "L(" + str(1+2*i) + ", (-4/.)): ", RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 sage: ## Testing the accuracy of the negative special values sage: ## ---- THIS FAILS SINCE THE DIRICHLET SERIES DOESN'T CONVERGE HERE! ---- sage: ## Test several characters agree with the exact value, to a given accuracy. sage: for d in range(-20,0): ... if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ... print "Oops! We have a problem at d = ", d, " exact = ", RR(quadratic_L_function__exact(1, d)), " numerical = ", RR(quadratic_L_function__numerical(1, d)) ... """ ## Set the correct precision if it's given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() d1 = fundamental_discriminant(d) ans = R(0) for i in range(1, num_terms): ans += R(kronecker_symbol(d1, i) / R(i)**n) return ans
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES:: sage: ## Test several values for a given character sage: RR = RealField(100) sage: for i in range(5): ... print "L(" + str(1+2*i) + ", (-4/.)): ", RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 sage: ## Testing the accuracy of the negative special values sage: ## ---- THIS FAILS SINCE THE DIRICHLET SERIES DOESN'T CONVERGE HERE! ---- sage: ## Test several characters agree with the exact value, to a given accuracy. sage: for d in range(-20,0): ... if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ... print "Oops! We have a problem at d = ", d, " exact = ", RR(quadratic_L_function__exact(1, d)), " numerical = ", RR(quadratic_L_function__numerical(1, d)) ... """ ## Set the correct precision if it's given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() d1 = fundamental_discriminant(d) ans = R(0) for i in range(1,num_terms): ans += R(kronecker_symbol(d1,i) / R(i)**n) return ans
def _singular_init_(self, singular=singular): """ Return a newly created Singular ring matching this ring. EXAMPLES:: sage: PolynomialRing(QQ,'u_ba')._singular_init_() polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 1 // block 1 : ordering lp // : names u_ba // block 2 : ordering C """ if not can_convert_to_singular(self): raise TypeError("no conversion of this ring to a Singular ring defined") if self.ngens()==1: _vars = '(%s)'%self.gen() if "*" in _vars: # 1.000...000*x _vars = _vars.split("*")[1] order = 'lp' else: _vars = str(self.gens()) order = self.term_order().singular_str() base_ring = self.base_ring() if is_RealField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order, check=False) elif is_ComplexField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order, check=False) elif is_RealDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(real,15,0)", _vars, order=order, check=False) elif is_ComplexDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(complex,15,0,I)", _vars, order=order, check=False) elif base_ring.is_prime_field(): self.__singular = singular.ring(self.characteristic(), _vars, order=order, check=False) elif sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring): # not the prime field! gen = str(base_ring.gen()) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (str(base_ring.modulus()).replace("x",gen)).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif number_field.number_field_base.is_NumberField(base_ring) and base_ring.is_absolute(): # not the rationals! gen = str(base_ring.gen()) poly=base_ring.polynomial() poly_gen=str(poly.parent().gen()) poly_str=str(poly).replace(poly_gen,gen) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (poly_str).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif sage.rings.fraction_field.is_FractionField(base_ring) and (base_ring.base_ring() is ZZ or base_ring.base_ring().is_prime_field() or is_FiniteField(base_ring.base_ring())): if base_ring.ngens()==1: gens = str(base_ring.gen()) else: gens = str(base_ring.gens()) if not (not base_ring.base_ring().is_prime_field() and is_FiniteField(base_ring.base_ring())) : self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) else: ext_gen = str(base_ring.base_ring().gen()) _vars = '(' + ext_gen + ', ' + _vars[1:]; R = self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) self.base_ring().__minpoly = (str(base_ring.base_ring().modulus()).replace("x",ext_gen)).replace(" ","") singular.eval('setring '+R._name); from sage.misc.stopgap import stopgap stopgap("Denominators of fraction field elements are sometimes dropped without warning.", 17696) self.__singular = singular("std(ideal(%s))"%(self.base_ring().__minpoly),type='qring') elif sage.rings.function_field.function_field.is_RationalFunctionField(base_ring) and base_ring.constant_field().is_prime_field(): gen = str(base_ring.gen()) self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gen), _vars, order=order, check=False) elif is_IntegerModRing(base_ring): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 self.__singular = singular.ring("(integer,2,%d)"%(exp,), _vars, order=order, check=False) else: self.__singular = singular.ring("(integer,%d)"%(ch,), _vars, order=order, check=False) elif base_ring is ZZ: self.__singular = singular.ring("(integer)", _vars, order=order, check=False) else: raise TypeError("no conversion to a Singular ring defined") return self.__singular
def isogenies_prime_degree(self, l=None, max_l=31): """ Generic code, valid for all fields, for arbitrary prime `l` not equal to the characteristic. INPUT: - ``l`` -- either None, a prime or a list of primes. - ``max_l`` -- a bound on the primes to be tested (ignored unless `l` is None). OUTPUT: (list) All `l`-isogenies for the given `l` with domain self. METHOD: Calls the generic function ``isogenies_prime_degree()``. This requires that certain operations have been implemented over the base field, such as root-finding for univariate polynomials. EXAMPLES:: sage: F = QQbar sage: E = EllipticCurve(F, [1,18]); E Elliptic Curve defined by y^2 = x^3 + x + 18 over Algebraic Field sage: E.isogenies_prime_degree() Traceback (most recent call last): ... NotImplementedError: This code could be implemented for QQbar, but has not been yet. sage: F = CC sage: E = EllipticCurve(F, [1,18]); E Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000 over Complex Field with 53 bits of precision sage: E.isogenies_prime_degree(11) Traceback (most recent call last): ... NotImplementedError: This code could be implemented for general complex fields, but has not been yet. Examples over finite fields:: sage: E = EllipticCurve(GF(next_prime(1000000)), [7,8]) sage: E.isogenies_prime_degree() [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003, Isogeny of degree 17 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 347438*x + 594729 over Finite Field of size 1000003, Isogeny of degree 17 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 674846*x + 7392 over Finite Field of size 1000003, Isogeny of degree 23 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 390065*x + 605596 over Finite Field of size 1000003] sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003] sage: E.isogenies_prime_degree(3) [] sage: E.isogenies_prime_degree(5) [] sage: E.isogenies_prime_degree(7) [] sage: E.isogenies_prime_degree(13) [Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003] sage: E.isogenies_prime_degree([2, 3, 5, 7, 13]) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003] sage: E.isogenies_prime_degree([2, 4]) Traceback (most recent call last): ... ValueError: 4 is not prime. sage: E.isogenies_prime_degree(4) Traceback (most recent call last): ... ValueError: 4 is not prime. sage: E.isogenies_prime_degree(11) [] sage: E = EllipticCurve(GF(17),[2,0]) sage: E.isogenies_prime_degree(3) [] sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17 to Elliptic Curve defined by y^2 = x^3 + 9*x over Finite Field of size 17, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17 to Elliptic Curve defined by y^2 = x^3 + 5*x + 9 over Finite Field of size 17, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17 to Elliptic Curve defined by y^2 = x^3 + 5*x + 8 over Finite Field of size 17] sage: E = EllipticCurve(GF(13^4, 'a'),[2,8]) sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field in a of size 13^4, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + (8*a^3+2*a^2+7*a+5)*x + (12*a^3+3*a^2+4*a+4) over Finite Field in a of size 13^4, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + (5*a^3+11*a^2+6*a+11)*x + (a^3+10*a^2+9*a) over Finite Field in a of size 13^4] sage: E.isogenies_prime_degree(3) [Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field in a of size 13^4] Example to show that separable isogenies of degree equal to the characteristic are now implemented:: sage: E.isogenies_prime_degree(13) [Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + 6*x + 5 over Finite Field in a of size 13^4] Examples over number fields (other than QQ):: sage: QQroot2.<e> = NumberField(x^2-2) sage: E = EllipticCurve(QQroot2, j=8000) sage: E.isogenies_prime_degree() [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 = x^3 + (-602112000)*x + 5035261952000 over Number Field in e with defining polynomial x^2 - 2, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 = x^3 + (903168000*e-1053696000)*x + (14161674240000*e-23288086528000) over Number Field in e with defining polynomial x^2 - 2, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 = x^3 + (-903168000*e-1053696000)*x + (-14161674240000*e-23288086528000) over Number Field in e with defining polynomial x^2 - 2] sage: E = EllipticCurve(QQroot2, [1,0,1,4, -6]); E Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-36)*x + (-70) over Number Field in e with defining polynomial x^2 - 2] sage: E.isogenies_prime_degree(3) [Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-128/3)*x + 5662/27 over Number Field in e with defining polynomial x^2 - 2, Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-171)*x + (-874) over Number Field in e with defining polynomial x^2 - 2] """ F = self.base_ring() if is_RealField(F): raise NotImplementedError("This code could be implemented for general real fields, but has not been yet.") if is_ComplexField(F): raise NotImplementedError("This code could be implemented for general complex fields, but has not been yet.") if F == rings.QQbar: raise NotImplementedError("This code could be implemented for QQbar, but has not been yet.") from isogeny_small_degree import isogenies_prime_degree if l is None: from sage.rings.all import prime_range l = prime_range(max_l+1) if not isinstance(l, list): try: l = rings.ZZ(l) except TypeError: raise ValueError("%s is not prime."%l) if l.is_prime(): return isogenies_prime_degree(self, l) else: raise ValueError("%s is not prime."%l) L = list(set(l)) try: L = [rings.ZZ(l) for l in L] except TypeError: raise ValueError("%s is not a list of primes."%l) L.sort() return sum([isogenies_prime_degree(self,l) for l in L],[])
def _singular_init_(self, singular=singular): """ Return a newly created Singular ring matching this ring. EXAMPLES:: sage: PolynomialRing(QQ,'u_ba')._singular_init_() // characteristic : 0 // number of vars : 1 // block 1 : ordering lp // : names u_ba // block 2 : ordering C """ if not can_convert_to_singular(self): raise TypeError("no conversion of this ring to a Singular ring defined") if self.ngens()==1: _vars = '(%s)'%self.gen() if "*" in _vars: # 1.000...000*x _vars = _vars.split("*")[1] order = 'lp' else: _vars = str(self.gens()) order = self.term_order().singular_str() base_ring = self.base_ring() if is_RealField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order, check=False) elif is_ComplexField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order, check=False) elif is_RealDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(real,15,0)", _vars, order=order, check=False) elif is_ComplexDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(complex,15,0,I)", _vars, order=order, check=False) elif base_ring.is_prime_field(): self.__singular = singular.ring(self.characteristic(), _vars, order=order, check=False) elif sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring): # not the prime field! gen = str(base_ring.gen()) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (str(base_ring.modulus()).replace("x",gen)).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif number_field.number_field_base.is_NumberField(base_ring) and base_ring.is_absolute(): # not the rationals! gen = str(base_ring.gen()) poly=base_ring.polynomial() poly_gen=str(poly.parent().gen()) poly_str=str(poly).replace(poly_gen,gen) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (poly_str).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif sage.rings.fraction_field.is_FractionField(base_ring) and (base_ring.base_ring() is ZZ or base_ring.base_ring().is_prime_field() or is_FiniteField(base_ring.base_ring())): if base_ring.ngens()==1: gens = str(base_ring.gen()) else: gens = str(base_ring.gens()) if not (not base_ring.base_ring().is_prime_field() and is_FiniteField(base_ring.base_ring())) : self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) else: ext_gen = str(base_ring.base_ring().gen()) _vars = '(' + ext_gen + ', ' + _vars[1:]; R = self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) self.base_ring().__minpoly = (str(base_ring.base_ring().modulus()).replace("x",ext_gen)).replace(" ","") singular.eval('setring '+R._name); self.__singular = singular("std(ideal(%s))"%(self.base_ring().__minpoly),type='qring') elif sage.rings.function_field.function_field.is_RationalFunctionField(base_ring) and base_ring.constant_field().is_prime_field(): gen = str(base_ring.gen()) self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gen), _vars, order=order, check=False) elif is_IntegerModRing(base_ring): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 self.__singular = singular.ring("(integer,2,%d)"%(exp,), _vars, order=order, check=False) else: self.__singular = singular.ring("(integer,%d)"%(ch,), _vars, order=order, check=False) elif base_ring is ZZ: self.__singular = singular.ring("(integer)", _vars, order=order, check=False) else: raise TypeError("no conversion to a Singular ring defined") return self.__singular
def has_rational_point(self, point = False, algorithm = 'default', read_cache = True): r""" Returns True if and only if the conic ``self`` has a point over its base field `B`. If ``point`` is True, then returns a second output, which is a rational point if one exists. Points are cached whenever they are found. Cached information is used if and only if ``read_cache`` is True. ALGORITHM: The parameter ``algorithm`` specifies the algorithm to be used: - ``'default'`` -- If the base field is real or complex, use an elementary native Sage implementation. - ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system. EXAMPLES:: sage: Conic(RR, [1, 1, 1]).has_rational_point() False sage: Conic(CC, [1, 1, 1]).has_rational_point() True sage: Conic(RR, [1, 2, -3]).has_rational_point(point = True) (True, (1.73205080756888 : 0.000000000000000 : 1.00000000000000)) Conics over polynomial rings can be solved internally:: sage: R.<t> = QQ[] sage: C = Conic([-2,t^2+1,t^2-1]) sage: C.has_rational_point() True And they can also be solved with Magma:: sage: C.has_rational_point(algorithm='magma') # optional - magma True sage: C.has_rational_point(algorithm='magma', point=True) # optional - magma (True, (-t : 1 : 1)) sage: D = Conic([t,1,t^2]) sage: D.has_rational_point(algorithm='magma') # optional - magma False TESTS: One of the following fields comes with an embedding into the complex numbers, one does not. Check that they are both handled correctly by the Magma interface. :: sage: K.<i> = QuadraticField(-1) sage: K.coerce_embedding() Generic morphism: From: Number Field in i with defining polynomial x^2 + 1 with i = 1*I To: Complex Lazy Field Defn: i -> 1*I sage: Conic(K, [1,1,1]).rational_point(algorithm='magma') # optional - magma (-i : 1 : 0) sage: x = QQ['x'].gen() sage: L.<i> = NumberField(x^2+1, embedding=None) sage: Conic(L, [1,1,1]).rational_point(algorithm='magma') # optional - magma (-i : 1 : 0) sage: L == K False """ if read_cache: if self._rational_point is not None: if point: return True, self._rational_point else: return True B = self.base_ring() if algorithm == 'magma': from sage.interfaces.magma import magma M = magma(self) b = M.HasRationalPoint().sage() if not point: return b if not b: return False, None M_pt = M.HasRationalPoint(nvals=2)[1] # Various attempts will be made to convert `pt` to # a Sage object. The end result will always be checked # by self.point(). pt = [M_pt[1], M_pt[2], M_pt[3]] # The first attempt is to use sequences. This is efficient and # succeeds in cases where the Magma interface fails to convert # number field elements, because embeddings between number fields # may be lost on conversion to and from Magma. # This should deal with all absolute number fields. try: return True, self.point([B(c.Eltseq().sage()) for c in pt]) except TypeError: pass # The second attempt tries to split Magma elements into # numerators and denominators first. This is necessary # for the field of rational functions, because (at the moment of # writing) fraction field elements are not converted automatically # from Magma to Sage. try: return True, self.point( \ [B(c.Numerator().sage()/c.Denominator().sage()) for c in pt]) except (TypeError, NameError): pass # Finally, let the Magma interface handle conversion. try: return True, self.point([B(c.sage()) for c in pt]) except (TypeError, NameError): pass raise NotImplementedError("No correct conversion implemented for converting the Magma point %s on %s to a correct Sage point on self (=%s)" % (M_pt, M, self)) if algorithm != 'default': raise ValueError("Unknown algorithm: %s" % algorithm) if is_ComplexField(B): if point: [_,_,_,d,e,f] = self._coefficients if d == 0: return True, self.point([0,1,0]) return True, self.point([0, ((e**2-4*d*f).sqrt()-e)/(2*d), 1], check = False) return True if is_RealField(B): D, T = self.diagonal_matrix() [a, b, c] = [D[0,0], D[1,1], D[2,2]] if a == 0: ret = True, self.point(T*vector([1,0,0]), check = False) elif a*c <= 0: ret = True, self.point(T*vector([(-c/a).sqrt(),0,1]), check = False) elif b == 0: ret = True, self.point(T*vector([0,1,0]), check = False) elif b*c <= 0: ret = True, self.point(T*vector([0,(-c/b).sqrt(),0,1]), check = False) else: ret = False, None if point: return ret return ret[0] raise NotImplementedError("has_rational_point not implemented for " \ "conics over base field %s" % B)
def _evalf_(self, n, x, **kwds): """ Evaluates :class:`chebyshev_T` numerically with mpmath. EXAMPLES:: sage: chebyshev_T._evalf_(10,3) 2.26195370000000e7 sage: chebyshev_T._evalf_(10,3,parent=RealField(75)) 2.261953700000000000000e7 sage: chebyshev_T._evalf_(10,I) -3363.00000000000 sage: chebyshev_T._evalf_(5,0.3) 0.998880000000000 sage: chebyshev_T(1/2, 0) 0.707106781186548 sage: chebyshev_T(1/2, 3/2) 1.11803398874989 sage: chebyshev_T._evalf_(1.5, Mod(8,9)) Traceback (most recent call last): ... TypeError: cannot evaluate chebyshev_T with parent Ring of integers modulo 9 This simply evaluates using :class:`RealField` or :class:`ComplexField`:: sage: chebyshev_T(1234.5, RDF(2.1)) 5.48174256255782e735 sage: chebyshev_T(1234.5, I) -1.21629397684152e472 - 1.21629397684152e472*I For large values of ``n``, mpmath fails (but the algebraic formula still works):: sage: chebyshev_T._evalf_(10^6, 0.1) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. sage: chebyshev_T(10^6, 0.1) 0.636384327171504 """ try: real_parent = kwds['parent'] except KeyError: real_parent = parent(x) if not is_RealField(real_parent) and not is_ComplexField( real_parent): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) real_parent = RR elif x in CC: x = CC(x) real_parent = CC if not is_RealField(real_parent) and not is_ComplexField(real_parent): raise TypeError( "cannot evaluate chebyshev_T with parent {}".format( real_parent)) from sage.libs.mpmath.all import call as mpcall from sage.libs.mpmath.all import chebyt as mpchebyt return mpcall(mpchebyt, n, x, parent=real_parent)
def canonical_height(self, F, **kwds): r""" Evaluates the (absolute) canonical height of ``self`` with respect to ``F``. Must be over number field or order of a number field. Specify either the number of terms of the series to evaluate or the error bound required. ALGORITHM: The sum of the Green's function at the archimedean places and the places of bad reduction. INPUT: - ``F`` - a projective morphism kwds: - ``badprimes`` - a list of primes of bad reduction - ``N`` - positive integer. number of terms of the series to use in the local green functions - ``prec`` - positive integer, float point or p-adic precision - ``error_bound`` - a positive real number OUTPUT: - a real number EXAMPLES:: sage: P.<x,y> = ProjectiveSpace(ZZ,1) sage: H = Hom(P,P) sage: f = H([x^2+y^2,2*x*y]); sage: Q = P(2,1) sage: f.canonical_height(f(Q)) 2.1965476757927038111992627081 sage: f.canonical_height(Q) 1.0979353871245941198040174712 Notice that preperiodic points may not be exactly 0. :: sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: H = Hom(P,P) sage: f = H([x^2-29/16*y^2,y^2]); sage: Q = P(5,4) sage: f.canonical_height(Q, N=30) 1.4989058602918874235833076226e-9 :: sage: P.<x,y,z> = ProjectiveSpace(QQ,2) sage: X = P.subscheme(x^2-y^2); sage: H = Hom(X,X) sage: f = H([x^2,y^2,30*z^2]); sage: Q = X([4,4,1]) sage: f.canonical_height(Q, badprimes=[2,3,5], prec=200) 2.7054056208276961889784303469356774912979228770208655455481 """ bad_primes = kwds.pop("badprimes", None) prec = kwds.get("prec", 100) error_bound = kwds.get("error_bound", None) K = FractionField(self.codomain().base_ring()) if not K in _NumberFields: raise NotImplementedError("Must be over a NumberField or a NumberField Order") if bad_primes is None: bad_primes = [] for b in self: if K == QQ: bad_primes += b.denominator().prime_factors() else: bad_primes += b.denominator_ideal().prime_factors() bad_primes += K(F.resultant()).support() bad_primes = list(set(bad_primes)) emb = K.places(prec=prec) num_places = len(emb) + len(bad_primes) if not error_bound is None: error_bound /= num_places R = RealField(prec) h = R(0) # Archimedean local heights # :: WARNING: If places is fed the default Sage precision of 53 bits, # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec) # the function is_RealField does not identify RDF as real, so we test for that ourselves. for v in emb: if is_RealField(v.codomain()) or v.codomain() is RDF: dv = R(1) else: dv = R(2) h += dv*self.green_function(F, v, **kwds) #arch Green function # Non-Archimedean local heights for v in bad_primes: if K == QQ: dv = R(1) else: dv = R(v.residue_class_degree() * v.absolute_ramification_index()) h += dv * self.green_function(F, v, **kwds) #non-arch Green functions return h
def isogenies_prime_degree(self, l=None, max_l=31): """ Generic code, valid for all fields, for arbitrary prime `l` not equal to the characteristic. INPUT: - ``l`` -- either None, a prime or a list of primes. - ``max_l`` -- a bound on the primes to be tested (ignored unless `l` is None). OUTPUT: (list) All `l`-isogenies for the given `l` with domain self. METHOD: Calls the generic function ``isogenies_prime_degree()``. This requires that certain operations have been implemented over the base field, such as root-finding for univariate polynomials. EXAMPLES:: sage: F = QQbar sage: E = EllipticCurve(F, [1,18]); E Elliptic Curve defined by y^2 = x^3 + x + 18 over Algebraic Field sage: E.isogenies_prime_degree() Traceback (most recent call last): ... NotImplementedError: This code could be implemented for QQbar, but has not been yet. sage: F = CC sage: E = EllipticCurve(F, [1,18]); E Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000 over Complex Field with 53 bits of precision sage: E.isogenies_prime_degree(11) Traceback (most recent call last): ... NotImplementedError: This code could be implemented for general complex fields, but has not been yet. Examples over finite fields:: sage: E = EllipticCurve(GF(next_prime(1000000)), [7,8]) sage: E.isogenies_prime_degree() [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003, Isogeny of degree 17 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 347438*x + 594729 over Finite Field of size 1000003, Isogeny of degree 17 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 674846*x + 7392 over Finite Field of size 1000003, Isogeny of degree 23 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 390065*x + 605596 over Finite Field of size 1000003] sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003] sage: E.isogenies_prime_degree(3) [] sage: E.isogenies_prime_degree(5) [] sage: E.isogenies_prime_degree(7) [] sage: E.isogenies_prime_degree(13) [Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003] sage: E.isogenies_prime_degree([2, 3, 5, 7, 13]) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003 to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003] sage: E.isogenies_prime_degree([2, 4]) Traceback (most recent call last): ... ValueError: 4 is not prime. sage: E.isogenies_prime_degree(4) Traceback (most recent call last): ... ValueError: 4 is not prime. sage: E.isogenies_prime_degree(11) [] sage: E = EllipticCurve(GF(17),[2,0]) sage: E.isogenies_prime_degree(3) [] sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17 to Elliptic Curve defined by y^2 = x^3 + 9*x over Finite Field of size 17, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17 to Elliptic Curve defined by y^2 = x^3 + 5*x + 9 over Finite Field of size 17, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17 to Elliptic Curve defined by y^2 = x^3 + 5*x + 8 over Finite Field of size 17] sage: E = EllipticCurve(GF(13^4, 'a'),[2,8]) sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field in a of size 13^4, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + (8*a^3+2*a^2+7*a+5)*x + (12*a^3+3*a^2+4*a+4) over Finite Field in a of size 13^4, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + (5*a^3+11*a^2+6*a+11)*x + (a^3+10*a^2+9*a) over Finite Field in a of size 13^4] sage: E.isogenies_prime_degree(3) [Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field in a of size 13^4] Example to show that separable isogenies of degree equal to the characteristic are now implemented:: sage: E.isogenies_prime_degree(13) [Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in a of size 13^4 to Elliptic Curve defined by y^2 = x^3 + 6*x + 5 over Finite Field in a of size 13^4] Examples over number fields (other than QQ):: sage: QQroot2.<e> = NumberField(x^2-2) sage: E = EllipticCurve(QQroot2, j=8000) sage: E.isogenies_prime_degree() [Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 = x^3 + (-36750)*x + 2401000 over Number Field in e with defining polynomial x^2 - 2, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 = x^3 + (220500*e-257250)*x + (54022500*e-88837000) over Number Field in e with defining polynomial x^2 - 2, Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 = x^3 + (-220500*e-257250)*x + (-54022500*e-88837000) over Number Field in e with defining polynomial x^2 - 2] sage: E = EllipticCurve(QQroot2, [1,0,1,4, -6]); E Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 sage: E.isogenies_prime_degree(2) [Isogeny of degree 2 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-36)*x + (-70) over Number Field in e with defining polynomial x^2 - 2] sage: E.isogenies_prime_degree(3) [Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-1)*x over Number Field in e with defining polynomial x^2 - 2, Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6) over Number Field in e with defining polynomial x^2 - 2 to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-171)*x + (-874) over Number Field in e with defining polynomial x^2 - 2] """ F = self.base_ring() if is_RealField(F): raise NotImplementedError( "This code could be implemented for general real fields, but has not been yet." ) if is_ComplexField(F): raise NotImplementedError( "This code could be implemented for general complex fields, but has not been yet." ) if F == rings.QQbar: raise NotImplementedError( "This code could be implemented for QQbar, but has not been yet." ) from isogeny_small_degree import isogenies_prime_degree if l is None: from sage.rings.all import prime_range l = prime_range(max_l + 1) if not isinstance(l, list): try: l = rings.ZZ(l) except TypeError: raise ValueError("%s is not prime." % l) if l.is_prime(): return isogenies_prime_degree(self, l) else: raise ValueError("%s is not prime." % l) L = list(set(l)) try: L = [rings.ZZ(l) for l in L] except TypeError: raise ValueError("%s is not a list of primes." % l) L.sort() return sum([isogenies_prime_degree(self, l) for l in L], [])
def has_rational_point(self, point = False, algorithm = 'default', read_cache = True): r""" Returns True if and only if the conic ``self`` has a point over its base field `B`. If ``point`` is True, then returns a second output, which is a rational point if one exists. Points are cached whenever they are found. Cached information is used if and only if ``read_cache`` is True. ALGORITHM: The parameter ``algorithm`` specifies the algorithm to be used: - ``'default'`` -- If the base field is real or complex, use an elementary native Sage implementation. - ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system. EXAMPLES: sage: Conic(RR, [1, 1, 1]).has_rational_point() False sage: Conic(CC, [1, 1, 1]).has_rational_point() True sage: Conic(RR, [1, 2, -3]).has_rational_point(point = True) (True, (1.73205080756888 : 0.000000000000000 : 1.00000000000000)) Conics over polynomial rings can not be solved yet without Magma:: sage: R.<t> = QQ[] sage: C = Conic([-2,t^2+1,t^2-1]) sage: C.has_rational_point() Traceback (most recent call last): ... NotImplementedError: has_rational_point not implemented for conics over base field Fraction Field of Univariate Polynomial Ring in t over Rational Field But they can be solved with Magma:: sage: C.has_rational_point(algorithm='magma') # optional - magma True sage: C.has_rational_point(algorithm='magma', point=True) # optional - magma (True, (t : 1 : 1)) sage: D = Conic([t,1,t^2]) sage: D.has_rational_point(algorithm='magma') # optional - magma False TESTS: One of the following fields comes with an embedding into the complex numbers, one does not. Check that they are both handled correctly by the Magma interface. :: sage: K.<i> = QuadraticField(-1) sage: K.coerce_embedding() Generic morphism: From: Number Field in i with defining polynomial x^2 + 1 To: Complex Lazy Field Defn: i -> 1*I sage: Conic(K, [1,1,1]).rational_point(algorithm='magma') # optional - magma (-i : 1 : 0) sage: x = QQ['x'].gen() sage: L.<i> = NumberField(x^2+1, embedding=None) sage: Conic(L, [1,1,1]).rational_point(algorithm='magma') # optional - magma (-i : 1 : 0) sage: L == K False """ if read_cache: if self._rational_point is not None: if point: return True, self._rational_point else: return True B = self.base_ring() if algorithm == 'magma': from sage.interfaces.magma import magma M = magma(self) b = M.HasRationalPoint().sage() if not point: return b if not b: return False, None M_pt = M.HasRationalPoint(nvals=2)[1] # Various attempts will be made to convert `pt` to # a Sage object. The end result will always be checked # by self.point(). pt = [M_pt[1], M_pt[2], M_pt[3]] # The first attempt is to use sequences. This is efficient and # succeeds in cases where the Magma interface fails to convert # number field elements, because embeddings between number fields # may be lost on conversion to and from Magma. # This should deal with all absolute number fields. try: return True, self.point([B(c.Eltseq().sage()) for c in pt]) except TypeError: pass # The second attempt tries to split Magma elements into # numerators and denominators first. This is neccessary # for the field of rational functions, because (at the moment of # writing) fraction field elements are not converted automatically # from Magma to Sage. try: return True, self.point( \ [B(c.Numerator().sage()/c.Denominator().sage()) for c in pt]) except (TypeError, NameError): pass # Finally, let the Magma interface handle conversion. try: return True, self.point([B(c.sage()) for c in pt]) except (TypeError, NameError): pass raise NotImplementedError("No correct conversion implemented for converting the Magma point %s on %s to a correct Sage point on self (=%s)" % (M_pt, M, self)) if algorithm != 'default': raise ValueError("Unknown algorithm: %s" % algorithm) if is_ComplexField(B): if point: [_,_,_,d,e,f] = self._coefficients if d == 0: return True, self.point([0,1,0]) return True, self.point([0, ((e**2-4*d*f).sqrt()-e)/(2*d), 1], check = False) return True if is_RealField(B): D, T = self.diagonal_matrix() [a, b, c] = [D[0,0], D[1,1], D[2,2]] if a == 0: ret = True, self.point(T*vector([1,0,0]), check = False) elif a*c <= 0: ret = True, self.point(T*vector([(-c/a).sqrt(),0,1]), check = False) elif b == 0: ret = True, self.point(T*vector([0,1,0]), check = False) elif b*c <= 0: ret = True, self.point(T*vector([0,(-c/b).sqrt(),0,1]), check = False) else: ret = False, None if point: return ret return ret[0] raise NotImplementedError("has_rational_point not implemented for " \ "conics over base field %s" % B)
def _evalf_(self, n, x, **kwds): """ Evaluates :class:`chebyshev_T` numerically with mpmath. EXAMPLES:: sage: chebyshev_T._evalf_(10,3) 2.26195370000000e7 sage: chebyshev_T._evalf_(10,3,parent=RealField(75)) 2.261953700000000000000e7 sage: chebyshev_T._evalf_(10,I) -3363.00000000000 sage: chebyshev_T._evalf_(5,0.3) 0.998880000000000 sage: chebyshev_T(1/2, 0) 0.707106781186548 sage: chebyshev_T(1/2, 3/2) 1.11803398874989 sage: chebyshev_T._evalf_(1.5, Mod(8,9)) Traceback (most recent call last): ... TypeError: cannot evaluate chebyshev_T with parent Ring of integers modulo 9 This simply evaluates using :class:`RealField` or :class:`ComplexField`:: sage: chebyshev_T(1234.5, RDF(2.1)) 5.48174256255782e735 sage: chebyshev_T(1234.5, I) -1.21629397684152e472 - 1.21629397684152e472*I For large values of ``n``, mpmath fails (but the algebraic formula still works):: sage: chebyshev_T._evalf_(10^6, 0.1) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. sage: chebyshev_T(10^6, 0.1) 0.636384327171504 """ try: real_parent = kwds["parent"] except KeyError: real_parent = parent(x) if not is_RealField(real_parent) and not is_ComplexField(real_parent): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) real_parent = RR elif x in CC: x = CC(x) real_parent = CC if not is_RealField(real_parent) and not is_ComplexField(real_parent): raise TypeError("cannot evaluate chebyshev_T with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall from sage.libs.mpmath.all import chebyt as mpchebyt return mpcall(mpchebyt, n, x, parent=real_parent)
def _singular_init_(self, singular=singular_default): """ Return a newly created Singular ring matching this ring. EXAMPLES:: sage: PolynomialRing(QQ,'u_ba')._singular_init_() // characteristic : 0 // number of vars : 1 // block 1 : ordering lp // : names u_ba // block 2 : ordering C """ if not can_convert_to_singular(self): raise TypeError, "no conversion of this ring to a Singular ring defined" if self.ngens()==1: _vars = '(%s)'%self.gen() if "*" in _vars: # 1.000...000*x _vars = _vars.split("*")[1] order = 'lp' else: _vars = str(self.gens()) order = self.term_order().singular_str() base_ring = self.base_ring() if is_RealField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.rings.arith.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order, check=False) elif is_ComplexField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.rings.arith.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order, check=False) elif is_RealDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(real,15,0)", _vars, order=order, check=False) elif is_ComplexDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(complex,15,0,I)", _vars, order=order, check=False) elif base_ring.is_prime_field(): self.__singular = singular.ring(self.characteristic(), _vars, order=order, check=False) elif sage.rings.finite_rings.constructor.is_FiniteField(base_ring): # not the prime field! gen = str(base_ring.gen()) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (str(base_ring.modulus()).replace("x",gen)).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif number_field.all.is_NumberField(base_ring) and base_ring.is_absolute(): # not the rationals! gen = str(base_ring.gen()) poly=base_ring.polynomial() poly_gen=str(poly.parent().gen()) poly_str=str(poly).replace(poly_gen,gen) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (poly_str).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif sage.rings.fraction_field.is_FractionField(base_ring) and (base_ring.base_ring() is ZZ or base_ring.base_ring().is_prime_field()): if base_ring.ngens()==1: gens = str(base_ring.gen()) else: gens = str(base_ring.gens()) self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) elif is_IntegerModRing(base_ring): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 self.__singular = singular.ring("(integer,2,%d)"%(exp,), _vars, order=order, check=False) else: self.__singular = singular.ring("(integer,%d)"%(ch,), _vars, order=order, check=False) elif base_ring is ZZ: self.__singular = singular.ring("(integer)", _vars, order=order, check=False) else: raise TypeError, "no conversion to a Singular ring defined" return self.__singular