def _coerce_map_from_(self, P): r"""Return a coercion map from `P` to `self`, or `True`, or `None`. The following rings admit a coercion map to the Puiseux series ring `A((x-a)^(1/e))`: - any ring that admits a coercion map to `A` - any Laurent series ring, power series ring, or polynomial ring in the variable `(x-a)` over a ring admitting a coercion map to `A` - any Puiseux series ring with the same center `a` and ramification index equal to a multiple of `self`'s ramification index. For example, Puiseux series in (x-a)^(1/2) can be interpreted as Puiseux series in (x-a)^(1/4). """ # any ring that has a coercion map to A A = self.base_ring() if A is P: return True f = A.coerce_map_from(P) if f is not None: return self.coerce_map_from(A) * f # Laurent series rings, power series rings, and polynomial rings with # the same variable name and the base rings are coercible if ((is_PuiseuxSeriesRing(P) or is_LaurentSeriesRing(P) or is_PowerSeriesRing(P)) and P.variable_name() == self.variable_name() and A.has_coerce_map_from(P.base_ring())): return True
def _coerce_impl(self, f): """ Return the canonical coercion of ``f`` into this multivariate power series ring, if one is defined, or raise a TypeError. The rings that canonically coerce to this multivariate power series ring are: - this ring itself - a polynomial or power series ring in the same variables or a subset of these variables (possibly empty), over any base ring that canonically coerces into the base ring of this ring EXAMPLES:: sage: R.<t,u,v> = PowerSeriesRing(QQ); R Multivariate Power Series Ring in t, u, v over Rational Field sage: S1.<t,v> = PolynomialRing(ZZ); S1 Multivariate Polynomial Ring in t, v over Integer Ring sage: f1 = -t*v + 2*v^2 + v; f1 -t*v + 2*v^2 + v sage: R(f1) v - t*v + 2*v^2 sage: S2.<u,v> = PowerSeriesRing(ZZ); S2 Multivariate Power Series Ring in u, v over Integer Ring sage: f2 = -2*v^2 + 5*u*v^2 + S2.O(6); f2 -2*v^2 + 5*u*v^2 + O(u, v)^6 sage: R(f2) -2*v^2 + 5*u*v^2 + O(t, u, v)^6 sage: R2 = R.change_ring(GF(2)) sage: R2(f1) v + t*v sage: R2(f2) u*v^2 + O(t, u, v)^6 TESTS:: sage: R.<t,u,v> = PowerSeriesRing(QQ) sage: S1.<t,v> = PolynomialRing(ZZ) sage: f1 = S1.random_element() sage: g1 = R._coerce_impl(f1) sage: f1.parent() == R False sage: g1.parent() == R True """ P = f.parent() if is_MPolynomialRing(P) or is_MPowerSeriesRing(P) \ or is_PolynomialRing(P) or is_PowerSeriesRing(P): if set(P.variable_names()).issubset(set(self.variable_names())): if self.has_coerce_map_from(P.base_ring()): return self(f) else: return self._coerce_try(f,[self.base_ring()])
def _coerce_map_from_(self, P): """ The rings that canonically coerce to this multivariate power series ring are: - this ring itself - a polynomial or power series ring in the same variables or a subset of these variables (possibly empty), over any base ring that canonically coerces into this ring - any ring that coerces into the foreground polynomial ring of this ring TESTS:: sage: M = PowerSeriesRing(ZZ,3,'x,y,z'); sage: M._coerce_map_from_(M) True sage: M._coerce_map_from_(M.remove_var(x)) True sage: M._coerce_map_from_(PowerSeriesRing(ZZ,x)) True sage: M._coerce_map_from_(PolynomialRing(ZZ,'x,z')) True sage: M._coerce_map_from_(PolynomialRing(ZZ,0,'')) True sage: M._coerce_map_from_(ZZ) True sage: M._coerce_map_from_(Zmod(13)) False sage: M._coerce_map_from_(PolynomialRing(ZZ,2,'x,t')) False sage: M._coerce_map_from_(PolynomialRing(Zmod(11),2,'x,y')) False sage: P = PolynomialRing(ZZ,3,'z') sage: H = PowerSeriesRing(P,4,'f'); H Multivariate Power Series Ring in f0, f1, f2, f3 over Multivariate Polynomial Ring in z0, z1, z2 over Integer Ring sage: H._coerce_map_from_(P) True sage: H._coerce_map_from_(P.remove_var(P.gen(1))) True sage: H._coerce_map_from_(PolynomialRing(ZZ,'z2,f0')) True """ if is_MPolynomialRing(P) or is_MPowerSeriesRing(P) \ or is_PolynomialRing(P) or is_PowerSeriesRing(P): if set(P.variable_names()).issubset(set(self.variable_names())): if self.has_coerce_map_from(P.base_ring()): return True return self._poly_ring().has_coerce_map_from(P)
def _coerce_map_from_(self, P): """ Return a coercion map from `P` to ``self``, or True, or None. The following rings admit a coercion map to the Laurent series ring `A((t))`: - any ring that admits a coercion map to `A` (including `A` itself); - any Laurent series ring, power series ring or polynomial ring in the variable `t` over a ring admitting a coercion map to `A`. EXAMPLES:: sage: R.<t> = LaurentSeriesRing(ZZ) sage: S.<t> = PowerSeriesRing(QQ) sage: R.has_coerce_map_from(S) # indirect doctest False sage: R.has_coerce_map_from(R) True sage: R.<t> = LaurentSeriesRing(QQ['x']) sage: R.has_coerce_map_from(S) True sage: R.has_coerce_map_from(QQ['t']) True sage: R.has_coerce_map_from(ZZ['x']['t']) True sage: R.has_coerce_map_from(ZZ['t']['x']) False sage: R.has_coerce_map_from(ZZ['x']) True """ A = self.base_ring() if A is P: return True f = A.coerce_map_from(P) if f is not None: return self.coerce_map_from(A) * f from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing if ((is_LaurentSeriesRing(P) or is_PowerSeriesRing(P) or is_PolynomialRing(P)) and P.variable_name() == self.variable_name() and A.has_coerce_map_from(P.base_ring())): return True
def __classcall__(cls, *args, **kwds): r""" TESTS:: sage: L = LaurentSeriesRing(QQ, 'q') sage: L is LaurentSeriesRing(QQ, name='q') True sage: loads(dumps(L)) is L True sage: L.variable_names() ('q',) sage: L.variable_name() 'q' """ from .power_series_ring import PowerSeriesRing, is_PowerSeriesRing if not kwds and len(args) == 1 and is_PowerSeriesRing(args[0]): power_series = args[0] else: power_series = PowerSeriesRing(*args, **kwds) return UniqueRepresentation.__classcall__(cls, power_series)
def _is_valid_homomorphism_(self, codomain, im_gens): """ EXAMPLES:: sage: R.<x> = LaurentSeriesRing(GF(17)) sage: S.<y> = LaurentSeriesRing(GF(19)) sage: R.hom([y], S) # indirect doctest Traceback (most recent call last): ... TypeError: images do not define a valid homomorphism sage: f = R.hom(x+x^3,R) sage: f(x^2) x^2 + 2*x^4 + x^6 """ ## NOTE: There are no ring homomorphisms from the ring of ## all formal power series to most rings, e.g, the p-adic ## field, since you can always (mathematically!) construct ## some power series that doesn't converge. ## Note that 0 is not a *ring* homomorphism. from power_series_ring import is_PowerSeriesRing if is_PowerSeriesRing(codomain) or is_LaurentSeriesRing(codomain): return im_gens[0].valuation() > 0 and codomain.has_coerce_map_from(self.base_ring()) return False
def _is_valid_homomorphism_(self, codomain, im_gens): """ Replacement for method of PowerSeriesRing_generic. To be valid, a homomorphism must send generators to elements of positive valuation or to nilpotent elements. Note that the method is_nilpotent doesn't (as of sage 4.4) seem to be defined for obvious examples (matrices, quotients of polynomial rings). EXAMPLES:: sage: R.<a,b,c> = PowerSeriesRing(Zmod(8)); R Multivariate Power Series Ring in a, b, c over Ring of integers modulo 8 sage: M = PowerSeriesRing(ZZ,3,'x,y,z'); sage: M._is_valid_homomorphism_(R,[a,c,b]) True sage: M._is_valid_homomorphism_(R,[0,c,b]) True 2 is nilpotent in `ZZ/8`, but 3 is not:: sage: M._is_valid_homomorphism_(R,[2,c,b]) True sage: M._is_valid_homomorphism_(R,[3,c,b]) False Over `ZZ`, 2 is not nilpotent:: sage: S = R.change_ring(ZZ); S Multivariate Power Series Ring in a, b, c over Integer Ring sage: M._is_valid_homomorphism_(S,[a,c,b]) True sage: M._is_valid_homomorphism_(S,[0,c,b]) True sage: M._is_valid_homomorphism_(S,[2,c,b]) False sage: g = [S.random_element(10)*v for v in S.gens()] sage: M._is_valid_homomorphism_(S,g) True """ try: im_gens = [codomain(v) for v in im_gens] except TypeError: raise TypeError("The given generator images do not coerce to codomain.") if len(im_gens) is not self.ngens(): raise ValueError("You must specify the image of each generator.") if all(v == 0 for v in im_gens): return True if is_MPowerSeriesRing(codomain) or is_PowerSeriesRing(codomain): try: B = all(v.valuation() > 0 or v.is_nilpotent() for v in im_gens) except NotImplementedError: B = all(v.valuation() > 0 for v in im_gens) return B if is_CommutativeRing(codomain): return all(v.is_nilpotent() for v in im_gens)
def __init__(self, parent, x=0, prec=infinity, is_gen=False, check=False): """ input x can be an MPowerSeries, or an element of - the background univariate power series ring - the foreground polynomial ring - a ring that coerces to one of the above two TESTS:: sage: S.<s,t> = PowerSeriesRing(ZZ) sage: f = s + 4*t + 3*s*t sage: f in S True sage: f = f.add_bigoh(4); f s + 4*t + 3*s*t + O(s, t)^4 sage: g = 1 + s + t - s*t + S.O(5); g 1 + s + t - s*t + O(s, t)^5 sage: B.<s, t> = PowerSeriesRing(QQ) sage: C.<z> = PowerSeriesRing(QQ) sage: B(z) Traceback (most recent call last): ... TypeError: Cannot coerce input to polynomial ring. sage: D.<s> = PowerSeriesRing(QQ) sage: s.parent() is D True sage: B(s) in B True sage: d = D.random_element(20) sage: b = B(d) # test coercion from univariate power series ring sage: b in B True """ PowerSeries.__init__(self, parent, prec, is_gen=is_gen) self._PowerSeries__is_gen = is_gen try: prec = min(prec, x.prec()) # use precision of input, if defined except AttributeError: pass # set the correct background value, depending on what type of input x is try: xparent = x.parent() # 'int' types have no parent except AttributeError: xparent = None # test whether x coerces to background univariate # power series ring of parent from sage.rings.multi_power_series_ring import is_MPowerSeriesRing if is_PowerSeriesRing(xparent) or is_MPowerSeriesRing(xparent): # x is either a multivariate or univariate power series # # test whether x coerces directly to designated parent if is_MPowerSeries(x): try: self._bg_value = parent._bg_ps_ring(x._bg_value) except TypeError: raise TypeError("Unable to coerce into background ring.") # test whether x coerces to background univariate # power series ring of parent elif xparent == parent._bg_ps_ring(): self._bg_value = x elif parent._bg_ps_ring().has_coerce_map_from(xparent): # previous test may fail if precision or term orderings of # base rings do not match self._bg_value = parent._bg_ps_ring(x) else: # x is a univariate power series, but not from the # background power series ring # # convert x to a polynomial and send to background # ring of parent x = x.polynomial() self._bg_value = parent._send_to_bg(x).add_bigoh(prec) # test whether x coerces to underlying polynomial ring of parent elif is_PolynomialRing(xparent): self._bg_value = parent._send_to_bg(x).add_bigoh(prec) else: try: x = parent._poly_ring(x) #self._value = x self._bg_value = parent._send_to_bg(x).add_bigoh(prec) except (TypeError, AttributeError): raise TypeError("Input does not coerce to any of the expected rings.") self._go_to_fg = parent._send_to_fg self._prec = self._bg_value.prec() # self._parent is used a lot by the class PowerSeries self._parent = self.parent()
def _element_constructor_(self, x): r""" Return ``x`` coerced into this forms space. EXAMPLES:: sage: from graded_ring import MModularFormsRing sage: from space import ModularForms sage: MF = ModularForms(k=12, ep=1) sage: (x,y,z,d) = MF.pol_ring().gens() sage: Delta = MModularFormsRing().Delta() sage: Delta.parent() MeromorphicModularFormsRing(n=3) over Integer Ring sage: MF(Delta) q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5) sage: MF(Delta).parent() == MF True sage: MF(x^3) 1 + 720*q + 179280*q^2 + 16954560*q^3 + 396974160*q^4 + O(q^5) sage: MF(x^3).parent() == MF True sage: qexp = Delta.q_expansion(prec=2) sage: qexp q + O(q^2) sage: qexp.parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MF(qexp) q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5) sage: MF(qexp) == MF(Delta) True sage: MF([0,1]) == MF(Delta) True sage: MF([1,0]) == MF(x^3) - 720*MF(Delta) # todo: this should give True, the result is False because d!=1/1728 but a formal parameter False sage: vec = MF(Delta).coordinate_vector() sage: vec (0, 1) sage: vec.parent() Vector space of dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: vec in MF.module() True sage: MF(vec) == MF(Delta) True sage: subspace = MF.subspace([MF(Delta)]) sage: subspace Subspace of dimension 1 of ModularForms(n=3, k=12, ep=1) over Integer Ring sage: subspace(MF(Delta)) == subspace(d*(x^3-y^2)) == subspace(qexp) == subspace([0,1]) == subspace(vec) == subspace.gen() True sage: subspace(MF(Delta)).parent() == subspace(d*(x^3-y^2)).parent() == subspace(qexp).parent() == subspace([0,1]).parent() == subspace(vec).parent() True sage: subspace([1]) == subspace.gen() True sage: ssvec = subspace(vec).coordinate_vector() sage: ssvec (1) sage: ssvec.parent() Vector space of dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: ambvec = subspace(vec).ambient_coordinate_vector() sage: ambvec (0, 1) sage: ambvec.parent() Vector space of degree 2 and dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring Basis matrix: [0 1] sage: subspace(ambvec) == subspace(vec) and subspace(ambvec).parent() == subspace(vec).parent() True """ from graded_ring_element import FormsRingElement if isinstance(x, FormsRingElement): return self.element_class(self, x._rat) if hasattr(x, 'parent') and (is_LaurentSeriesRing(x.parent()) or is_PowerSeriesRing(x.parent())): # This assumes that the series corresponds to a weakly holomorphic modular form! # But the construction method (with the assumption) may also be used for more general form spaces... return self.construct_form(x) if is_FreeModuleElement(x) and (self.module() == x.parent() or self.ambient_module() == x.parent()): return self.element_from_ambient_coordinates(x) if (not self.is_ambient()) and (isinstance(x, list) or isinstance(x, tuple) or is_FreeModuleElement(x)) and len(x) == self.rank(): try: return self.element_from_coordinates(x) except ArithmeticError, TypeError: pass
def _is_valid_homomorphism_(self, codomain, im_gens): """ Replacement for method of PowerSeriesRing_generic. To be valid, a homomorphism must send generators to elements of positive valuation or to nilpotent elements. Note that the method is_nilpotent doesn't (as of sage 4.4) seem to be defined for obvious examples (matrices, quotients of polynomial rings). EXAMPLES:: sage: R.<a,b,c> = PowerSeriesRing(Zmod(8)); R Multivariate Power Series Ring in a, b, c over Ring of integers modulo 8 sage: M = PowerSeriesRing(ZZ,3,'x,y,z'); sage: M._is_valid_homomorphism_(R,[a,c,b]) True sage: M._is_valid_homomorphism_(R,[0,c,b]) True 2 is nilpotent in `ZZ/8`, but 3 is not:: sage: M._is_valid_homomorphism_(R,[2,c,b]) True sage: M._is_valid_homomorphism_(R,[3,c,b]) False Over `ZZ`, 2 is not nilpotent:: sage: S = R.change_ring(ZZ); S Multivariate Power Series Ring in a, b, c over Integer Ring sage: M._is_valid_homomorphism_(S,[a,c,b]) True sage: M._is_valid_homomorphism_(S,[0,c,b]) True sage: M._is_valid_homomorphism_(S,[2,c,b]) False sage: g = [S.random_element(10)*v for v in S.gens()] sage: M._is_valid_homomorphism_(S,g) True """ try: im_gens = [codomain(v) for v in im_gens] except TypeError: raise TypeError( "The given generator images do not coerce to codomain.") if len(im_gens) is not self.ngens(): raise ValueError("You must specify the image of each generator.") if all(v == 0 for v in im_gens): return True if is_MPowerSeriesRing(codomain) or is_PowerSeriesRing(codomain): try: B = all(v.valuation() > 0 or v.is_nilpotent() for v in im_gens) except NotImplementedError: B = all(v.valuation() > 0 for v in im_gens) return B if isinstance(codomain, CommutativeRing): return all(v.is_nilpotent() for v in im_gens)
def _coerce_map_from_(self, P): """ Return a coercion map from `P` to ``self``, or True, or None. The following rings admit a coercion map to the Laurent series ring `A((t))`: - any ring that admits a coercion map to `A` (including `A` itself); - any Laurent series ring, power series ring or polynomial ring in the variable `t` over a ring admitting a coercion map to `A`. EXAMPLES:: sage: S.<t> = LaurentSeriesRing(ZZ) sage: S.has_coerce_map_from(ZZ) True sage: S.has_coerce_map_from(PolynomialRing(ZZ, 't')) True sage: S.has_coerce_map_from(LaurentPolynomialRing(ZZ, 't')) True sage: S.has_coerce_map_from(PowerSeriesRing(ZZ, 't')) True sage: S.has_coerce_map_from(S) True sage: S.has_coerce_map_from(QQ) False sage: S.has_coerce_map_from(PolynomialRing(QQ, 't')) False sage: S.has_coerce_map_from(LaurentPolynomialRing(QQ, 't')) False sage: S.has_coerce_map_from(PowerSeriesRing(QQ, 't')) False sage: S.has_coerce_map_from(LaurentSeriesRing(QQ, 't')) False sage: R.<t> = LaurentSeriesRing(QQ['x']) sage: R.has_coerce_map_from(QQ[['t']]) True sage: R.has_coerce_map_from(QQ['t']) True sage: R.has_coerce_map_from(ZZ['x']['t']) True sage: R.has_coerce_map_from(ZZ['t']['x']) False sage: R.has_coerce_map_from(ZZ['x']) True """ A = self.base_ring() if A is P: return True f = A.coerce_map_from(P) if f is not None: return self.coerce_map_from(A) * f from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing from sage.rings.polynomial.laurent_polynomial_ring import is_LaurentPolynomialRing if ((is_LaurentSeriesRing(P) or is_LaurentPolynomialRing(P) or is_PowerSeriesRing(P) or is_PolynomialRing(P)) and P.variable_name() == self.variable_name() and A.has_coerce_map_from(P.base_ring())): return True
def parent_to_repr_short(P): r""" Helper method which generates a short(er) representation string out of a parent. INPUT: - ``P`` -- a parent. OUTPUT: A string. EXAMPLES:: sage: from sage.rings.asymptotic.misc import parent_to_repr_short sage: parent_to_repr_short(ZZ) 'ZZ' sage: parent_to_repr_short(QQ) 'QQ' sage: parent_to_repr_short(SR) 'SR' sage: parent_to_repr_short(RR) 'RR' sage: parent_to_repr_short(CC) 'CC' sage: parent_to_repr_short(ZZ['x']) 'ZZ[x]' sage: parent_to_repr_short(QQ['d, k']) 'QQ[d, k]' sage: parent_to_repr_short(QQ['e']) 'QQ[e]' sage: parent_to_repr_short(SR[['a, r']]) 'SR[[a, r]]' sage: parent_to_repr_short(Zmod(3)) 'Ring of integers modulo 3' sage: parent_to_repr_short(Zmod(3)['g']) 'Univariate Polynomial Ring in g over Ring of integers modulo 3' """ from sage.rings.all import RR, CC, RIF, CIF, RBF, CBF from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.symbolic.ring import SR from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing def abbreviate(P): try: return P._repr_short_() except AttributeError: pass abbreviations = {ZZ: 'ZZ', QQ: 'QQ', SR: 'SR', RR: 'RR', CC: 'CC', RIF: 'RIF', CIF: 'CIF', RBF: 'RBF', CBF: 'CBF'} try: return abbreviations[P] except KeyError: pass raise ValueError('Cannot abbreviate %s.' % (P,)) poly = is_PolynomialRing(P) or is_MPolynomialRing(P) from sage.rings import multi_power_series_ring power = is_PowerSeriesRing(P) or \ multi_power_series_ring.is_MPowerSeriesRing(P) if poly or power: if poly: op, cl = ('[', ']') else: op, cl = ('[[', ']]') try: s = abbreviate(P.base_ring()) + op + ', '.join(P.variable_names()) + cl except ValueError: s = str(P) else: try: s = abbreviate(P) except ValueError: s = str(P) return s
def __init__(self, parent, x=0, prec=infinity, is_gen=False, check=False): """ input x can be an MPowerSeries, or an element of - the background univariate power series ring - the foreground polynomial ring - a ring that coerces to one of the above two TESTS:: sage: S.<s,t> = PowerSeriesRing(ZZ) sage: f = s + 4*t + 3*s*t sage: f in S True sage: f = f.add_bigoh(4); f s + 4*t + 3*s*t + O(s, t)^4 sage: g = 1 + s + t - s*t + S.O(5); g 1 + s + t - s*t + O(s, t)^5 sage: B.<s, t> = PowerSeriesRing(QQ) sage: C.<z> = PowerSeriesRing(QQ) sage: B(z) Traceback (most recent call last): ... TypeError: Cannot coerce input to polynomial ring. sage: D.<s> = PowerSeriesRing(QQ) sage: s.parent() is D True sage: B(s) in B True sage: d = D.random_element(20) sage: b = B(d) # test coercion from univariate power series ring sage: b in B True """ PowerSeries.__init__(self, parent, prec, is_gen=is_gen) self._PowerSeries__is_gen = is_gen try: prec = min(prec, x.prec()) # use precision of input, if defined except AttributeError: pass # set the correct background value, depending on what type of input x is try: xparent = x.parent() # 'int' types have no parent except AttributeError: xparent = None # test whether x coerces to background univariate # power series ring of parent from sage.rings.multi_power_series_ring import is_MPowerSeriesRing if is_PowerSeriesRing(xparent) or is_MPowerSeriesRing(xparent): # x is either a multivariate or univariate power series # # test whether x coerces directly to designated parent if is_MPowerSeries(x): try: self._bg_value = parent._bg_ps_ring(x._bg_value) except TypeError: raise TypeError("Unable to coerce into background ring.") # test whether x coerces to background univariate # power series ring of parent elif xparent == parent._bg_ps_ring(): self._bg_value = x elif parent._bg_ps_ring().has_coerce_map_from(xparent): # previous test may fail if precision or term orderings of # base rings do not match self._bg_value = parent._bg_ps_ring(x) else: # x is a univariate power series, but not from the # background power series ring # # convert x to a polynomial and send to background # ring of parent x = x.polynomial() self._bg_value = parent._send_to_bg(x).add_bigoh(prec) # test whether x coerces to underlying polynomial ring of parent elif is_PolynomialRing(xparent): self._bg_value = parent._send_to_bg(x).add_bigoh(prec) else: try: x = parent._poly_ring(x) #self._value = x self._bg_value = parent._send_to_bg(x).add_bigoh(prec) except (TypeError, AttributeError): raise TypeError( "Input does not coerce to any of the expected rings.") self._go_to_fg = parent._send_to_fg self._prec = self._bg_value.prec() # self._parent is used a lot by the class PowerSeries self._parent = self.parent()
def _coerce_map_from_(self, P): """ The rings that canonically coerce to this multivariate power series ring are: - this ring itself - a polynomial or power series ring in the same variables or a subset of these variables (possibly empty), over any base ring that canonically coerces into this ring - any ring that coerces into the foreground polynomial ring of this ring EXAMPLES:: sage: A = GF(17)[['x','y']] sage: A.has_coerce_map_from(ZZ) True sage: A.has_coerce_map_from(ZZ['x']) True sage: A.has_coerce_map_from(ZZ['y','x']) True sage: A.has_coerce_map_from(ZZ[['x']]) True sage: A.has_coerce_map_from(ZZ[['y','x']]) True sage: A.has_coerce_map_from(ZZ['x','z']) False sage: A.has_coerce_map_from(GF(3)['x','y']) False sage: A.has_coerce_map_from(Frac(ZZ['y','x'])) False TESTS:: sage: M = PowerSeriesRing(ZZ,3,'x,y,z') sage: M._coerce_map_from_(M) True sage: M._coerce_map_from_(M.remove_var(x)) True sage: M._coerce_map_from_(PowerSeriesRing(ZZ,x)) True sage: M._coerce_map_from_(PolynomialRing(ZZ,'x,z')) True sage: M._coerce_map_from_(PolynomialRing(ZZ,0,'')) True sage: M._coerce_map_from_(ZZ) True sage: M._coerce_map_from_(Zmod(13)) False sage: M._coerce_map_from_(PolynomialRing(ZZ,2,'x,t')) False sage: M._coerce_map_from_(PolynomialRing(Zmod(11),2,'x,y')) False sage: P = PolynomialRing(ZZ,3,'z') sage: H = PowerSeriesRing(P,4,'f'); H Multivariate Power Series Ring in f0, f1, f2, f3 over Multivariate Polynomial Ring in z0, z1, z2 over Integer Ring sage: H._coerce_map_from_(P) True sage: H._coerce_map_from_(P.remove_var(P.gen(1))) True sage: H._coerce_map_from_(PolynomialRing(ZZ,'z2,f0')) True """ if is_MPolynomialRing(P) or is_MPowerSeriesRing(P) \ or is_PolynomialRing(P) or is_PowerSeriesRing(P): if set(P.variable_names()).issubset(set(self.variable_names())): if self.has_coerce_map_from(P.base_ring()): return True return self._poly_ring().has_coerce_map_from(P)
def _is_valid_homomorphism_(self, codomain, im_gens, base_map=None): """ Replacement for method of PowerSeriesRing_generic. To be valid, a homomorphism must send generators to elements of positive valuation or to nilpotent elements. Note that the method is_nilpotent doesn't (as of sage 4.4) seem to be defined for obvious examples (matrices, quotients of polynomial rings). EXAMPLES:: sage: R.<a,b,c> = PowerSeriesRing(Zmod(8)); R Multivariate Power Series Ring in a, b, c over Ring of integers modulo 8 sage: M = PowerSeriesRing(ZZ,3,'x,y,z') sage: M._is_valid_homomorphism_(R,[a,c,b]) True sage: M._is_valid_homomorphism_(R,[0,c,b]) True 2 is nilpotent in `ZZ/8`, but 3 is not:: sage: M._is_valid_homomorphism_(R,[2,c,b]) True sage: M._is_valid_homomorphism_(R,[3,c,b]) False Over `ZZ`, 2 is not nilpotent:: sage: S = R.change_ring(ZZ); S Multivariate Power Series Ring in a, b, c over Integer Ring sage: M._is_valid_homomorphism_(S,[a,c,b]) True sage: M._is_valid_homomorphism_(S,[0,c,b]) True sage: M._is_valid_homomorphism_(S,[2,c,b]) False sage: g = [S.random_element(10)*v for v in S.gens()] sage: M._is_valid_homomorphism_(S,g) True You must either give a base map or there must be a coercion from the base ring to the codomain:: sage: T.<t> = ZZ[] sage: K.<i> = NumberField(t^2 + 1) sage: Q8.<z> = CyclotomicField(8) sage: X.<x> = PowerSeriesRing(Q8) sage: M.<a,b,c> = PowerSeriesRing(K) sage: M._is_valid_homomorphism_(X, [x,x,x+x^2]) # no coercion False sage: M._is_valid_homomorphism_(X, [x,x,x+x^2], base_map=K.hom([z^2])) True """ try: im_gens = [codomain(v) for v in im_gens] except TypeError: raise TypeError("The given generator images do not coerce to codomain.") if len(im_gens) is not self.ngens(): raise ValueError("You must specify the image of each generator.") if base_map is None and not codomain.has_coerce_map_from(self.base_ring()): return False if all(v == 0 for v in im_gens): return True from .laurent_series_ring import is_LaurentSeriesRing if is_MPowerSeriesRing(codomain) or is_PowerSeriesRing(codomain) or is_LaurentSeriesRing(codomain): try: B = all(v.valuation() > 0 or v.is_nilpotent() for v in im_gens) except NotImplementedError: B = all(v.valuation() > 0 for v in im_gens) return B try: return all(v.is_nilpotent() for v in im_gens) except NotImplementedError: pass return False
def parent_to_repr_short(P): r""" Helper method which generates a short(er) representation string out of a parent. INPUT: - ``P`` -- a parent. OUTPUT: A string. EXAMPLES:: sage: from sage.rings.asymptotic.misc import parent_to_repr_short sage: parent_to_repr_short(ZZ) 'ZZ' sage: parent_to_repr_short(QQ) 'QQ' sage: parent_to_repr_short(SR) 'SR' sage: parent_to_repr_short(ZZ['x']) 'ZZ[x]' sage: parent_to_repr_short(QQ['d, k']) 'QQ[d, k]' sage: parent_to_repr_short(QQ['e']) 'QQ[e]' sage: parent_to_repr_short(SR[['a, r']]) 'SR[[a, r]]' sage: parent_to_repr_short(Zmod(3)) 'Ring of integers modulo 3' sage: parent_to_repr_short(Zmod(3)['g']) 'Univariate Polynomial Ring in g over Ring of integers modulo 3' """ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.symbolic.ring import SR from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.multi_polynomial_ring_generic import is_MPolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing def abbreviate(P): if P is ZZ: return 'ZZ' elif P is QQ: return 'QQ' elif P is SR: return 'SR' raise ValueError('Cannot abbreviate %s.' % (P, )) poly = is_PolynomialRing(P) or is_MPolynomialRing(P) from sage.rings import multi_power_series_ring power = is_PowerSeriesRing(P) or \ multi_power_series_ring.is_MPowerSeriesRing(P) if poly or power: if poly: op, cl = ('[', ']') else: op, cl = ('[[', ']]') try: s = abbreviate(P.base_ring()) + op + ', '.join( P.variable_names()) + cl except ValueError: s = str(P) else: try: s = abbreviate(P) except ValueError: s = str(P) return s
def parent_to_repr_short(P): r""" Helper method which generates a short(er) representation string out of a parent. INPUT: - ``P`` -- a parent. OUTPUT: A string. EXAMPLES:: sage: from sage.rings.asymptotic.misc import parent_to_repr_short sage: parent_to_repr_short(ZZ) 'ZZ' sage: parent_to_repr_short(QQ) 'QQ' sage: parent_to_repr_short(SR) 'SR' sage: parent_to_repr_short(ZZ['x']) 'ZZ[x]' sage: parent_to_repr_short(QQ['d, k']) 'QQ[d, k]' sage: parent_to_repr_short(QQ['e']) 'QQ[e]' sage: parent_to_repr_short(SR[['a, r']]) 'SR[[a, r]]' sage: parent_to_repr_short(Zmod(3)) 'Ring of integers modulo 3' sage: parent_to_repr_short(Zmod(3)['g']) 'Univariate Polynomial Ring in g over Ring of integers modulo 3' """ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.symbolic.ring import SR from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.multi_polynomial_ring_generic import is_MPolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing def abbreviate(P): if P is ZZ: return 'ZZ' elif P is QQ: return 'QQ' elif P is SR: return 'SR' raise ValueError('Cannot abbreviate %s.' % (P,)) poly = is_PolynomialRing(P) or is_MPolynomialRing(P) from sage.rings import multi_power_series_ring power = is_PowerSeriesRing(P) or \ multi_power_series_ring.is_MPowerSeriesRing(P) if poly or power: if poly: op, cl = ('[', ']') else: op, cl = ('[[', ']]') try: s = abbreviate(P.base_ring()) + op + ', '.join(P.variable_names()) + cl except ValueError: s = str(P) else: try: s = abbreviate(P) except ValueError: s = str(P) return s