def ideal(self, *gens, **kwds): """ Create an ideal in this polynomial ring. """ do_coerce = False if len(gens) == 1: from sage.rings.ideal import is_Ideal if is_Ideal(gens[0]): if gens[0].ring() is self: return gens[0] gens = gens[0].gens() elif isinstance(gens[0], (list, tuple)): gens = gens[0] if not self._has_singular: # pass through MPolynomialRing_generic.ideal(self,gens,**kwds) if is_SingularElement(gens): gens = list(gens) do_coerce = True if is_Macaulay2Element(gens): gens = list(gens) do_coerce = True elif not isinstance(gens, (list, tuple)): gens = [gens] if ('coerce' in kwds and kwds['coerce']) or do_coerce: gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly! return multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds)
def ideal(self, *gens, **kwds): """ Create an ideal in this polynomial ring. """ do_coerce = False if len(gens) == 1: from sage.rings.ideal import is_Ideal if is_Ideal(gens[0]): if gens[0].ring() is self: return gens[0] gens = gens[0].gens() elif isinstance(gens[0], (list, tuple)): gens = gens[0] if not self._has_singular: # pass through MPolynomialRing_generic.ideal(self, gens, **kwds) if is_SingularElement(gens): gens = list(gens) do_coerce = True if is_Macaulay2Element(gens): gens = list(gens) do_coerce = True elif not isinstance(gens, (list, tuple)): gens = [gens] if ('coerce' in kwds and kwds['coerce']) or do_coerce: gens = [self(x) for x in gens ] # this will even coerce from singular ideals correctly! return multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds)
def _element_constructor_(self, x, coerce=True): """ Construct an element with ``self`` as the parent. EXAMPLES:: sage: R.<x,y> = PolynomialRing(QQ) sage: S = R.quotient_ring(x^2+y^2) sage: S(x) # indirect doctest xbar sage: S(x^2 + y^2) 0 The rings that coerce into the quotient ring canonically, are: - this ring - anything that coerces into the ring of which this is the quotient :: sage: R.<x,y> = PolynomialRing(QQ, 2) sage: S.<a,b> = R.quotient(x^2 + y^2) sage: S.coerce(0) 0 sage: S.coerce(2/3) 2/3 sage: S.coerce(a^2 - b) -b^2 - b sage: S.coerce(GF(7)(3)) Traceback (most recent call last): ... TypeError: no canonical coercion from Finite Field of size 7 to Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2) """ if isinstance(x, quotient_ring_element.QuotientRingElement): if x.parent() is self: return x x = x.lift() if is_SingularElement(x): #self._singular_().set_ring() x = self.element_class(self, x.sage_poly(self.cover_ring())) return x if coerce: R = self.cover_ring() x = R(x) return self.element_class(self, x)
def ideal(self, *gens, **kwds): """ Return the ideal of ``self`` with the given generators. EXAMPLES:: sage: R.<x,y> = PolynomialRing(QQ) sage: S = R.quotient_ring(x^2+y^2) sage: S.ideal() Ideal (0) of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2) sage: S.ideal(x+y+1) Ideal (xbar + ybar + 1) of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2) TESTS: We create an ideal of a fairly generic integer ring (see :trac:`5666`):: sage: R = Integers(10) sage: R.ideal(1) Principal ideal (1) of Ring of integers modulo 10 """ if len(gens) == 1: gens = gens[0] from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular if not isinstance(self.__R, MPolynomialRing_libsingular) and \ (not hasattr(self.__R, '_has_singular') or not self.__R._has_singular): # pass through return commutative_ring.CommutativeRing.ideal(self, gens, **kwds) if is_SingularElement(gens): gens = list(gens) coerce = True elif not isinstance(gens, (list, tuple)): gens = [gens] if kwds.has_key('coerce') and kwds['coerce']: gens = [self(x) for x in gens ] # this will even coerce from singular ideals correctly! return sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal( self, gens, **kwds)
def ideal(self, *gens, **kwds): """ Return the ideal of self with the given generators. EXAMPLES:: sage: R.<x,y> = PolynomialRing(QQ) sage: S = R.quotient_ring(x^2+y^2) sage: S.ideal() Ideal (0) of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2) sage: S.ideal(x+y+1) Ideal (xbar + ybar + 1) of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2) TESTS: We create an ideal of a fairly generic integer ring (see trac 5666):: sage: R = Integers(10) sage: R.ideal(1) Principal ideal (1) of Ring of integers modulo 10 """ if len(gens) == 1: gens = gens[0] from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular if not isinstance(self.__R, MPolynomialRing_libsingular) and ( not hasattr(self.__R, "_has_singular") or not self.__R._has_singular ): # pass through return commutative_ring.CommutativeRing.ideal(self, gens, **kwds) if is_SingularElement(gens): gens = list(gens) coerce = True elif not isinstance(gens, (list, tuple)): gens = [gens] if kwds.has_key("coerce") and kwds["coerce"]: gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly! return sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds)
def __call__(self, x, check=True): """ Convert ``x`` to an element of this multivariate polynomial ring, possibly non-canonically. EXAMPLES: We create a Macaulay2 multivariate polynomial via ideal arithmetic, then convert it into R. :: sage: R.<x,y> = PolynomialRing(QQ, 2) # optional sage: I = R.ideal([x^3 + y, y]) # optional sage: S = I._macaulay2_() # optional sage: T = S*S*S # optional sage: U = T.gens().entries().flatten() # optional sage: f = U[2]; f # optional x^6*y+2*x^3*y^2+y^3 sage: R(repr(f)) # optional x^6*y + 2*x^3*y^2 + y^3 Some other subtle conversions. We create polynomial rings in 2 variables over the rationals, integers, and a finite field. :: sage: R.<x,y> = QQ[] sage: S.<x,y> = ZZ[] sage: T.<x,y> = GF(7)[] We convert from integer polynomials to rational polynomials, and back:: sage: f = R(S.0^2 - 4*S.1^3); f -4*y^3 + x^2 sage: parent(f) Multivariate Polynomial Ring in x, y over Rational Field sage: parent(S(f)) Multivariate Polynomial Ring in x, y over Integer Ring We convert from polynomials over the finite field. :: sage: f = R(T.0^2 - 4*T.1^3); f 3*y^3 + x^2 sage: parent(f) Multivariate Polynomial Ring in x, y over Rational Field We dump and load the polynomial ring S:: sage: S2 = loads(dumps(S)) sage: S2 == S True Coerce works and gets the right parent. :: sage: parent(S2._coerce_(S.0)) is S2 True Conversion to reduce modulo a prime between rings with different variable names:: sage: R.<x,y> = PolynomialRing(QQ,2) sage: S.<a,b> = PolynomialRing(GF(7),2) sage: f = x^2 + 2/3*y^3 sage: S(f) 3*b^3 + a^2 Conversion from symbolic variables:: sage: x,y,z = var('x,y,z') sage: R = QQ[x,y,z] sage: type(x) <type 'sage.symbolic.expression.Expression'> sage: type(R(x)) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'> sage: f = R(x^3 + y^3 - z^3); f x^3 + y^3 - z^3 sage: type(f) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'> sage: parent(f) Multivariate Polynomial Ring in x, y, z over Rational Field A more complicated symbolic and computational mix. Behind the scenes Singular and Maxima are doing the real work. :: sage: R = QQ[x,y,z] sage: f = (x^3 + y^3 - z^3)^10; f (x^3 + y^3 - z^3)^10 sage: g = R(f); parent(g) Multivariate Polynomial Ring in x, y, z over Rational Field sage: (f - g).expand() 0 It intelligently handles conversions from polynomial rings in a subset of the variables too. :: sage: R = GF(5)['x,y,z'] sage: S = ZZ['y'] sage: R(7*S.0) 2*y sage: T = ZZ['x,z'] sage: R(2*T.0 + 6*T.1 + T.0*T.1^2) x*z^2 + 2*x + z :: sage: R = QQ['t,x,y,z'] sage: S.<x> = ZZ['x'] sage: T.<z> = S['z'] sage: T Univariate Polynomial Ring in z over Univariate Polynomial Ring in x over Integer Ring sage: f = (x+3*z+5)^2; f 9*z^2 + (6*x + 30)*z + x^2 + 10*x + 25 sage: R(f) x^2 + 6*x*z + 9*z^2 + 10*x + 30*z + 25 Arithmetic with a constant from a base ring:: sage: R.<u,v> = QQ[] sage: S.<x,y> = R[] sage: u^3*x^2 + v*y u^3*x^2 + v*y Stacked polynomial rings convert into constants if possible. First, the univariate case:: sage: R.<x> = QQ[] sage: S.<u,v> = R[] sage: S(u + 2) u + 2 sage: S(u + 2).degree() 1 sage: S(x + 3) x + 3 sage: S(x + 3).degree() 0 Second, the multivariate case:: sage: R.<x,y> = QQ[] sage: S.<u,v> = R[] sage: S(x + 2*y) x + 2*y sage: S(u + 2*v) u + 2*v Conversion from strings:: sage: R.<x,y> = QQ[] sage: R('x+(1/2)*y^2') 1/2*y^2 + x sage: S.<u,v> = ZZ[] sage: S('u^2 + u*v + v^2') u^2 + u*v + v^2 Foreign polynomial rings convert into the highest ring; the point here is that an element of T could convert to an element of R or an element of S; it is anticipated that an element of T is more likely to be "the right thing" and is historically consistent. :: sage: R.<x,y> = QQ[] sage: S.<u,v> = R[] sage: T.<a,b> = QQ[] sage: S(a + b) u + v TESTS: Check if we still allow nonsense :trac:`7951`:: sage: P = PolynomialRing(QQ, 0, '') sage: P('pi') Traceback (most recent call last): ... TypeError: Unable to coerce pi (<class 'sage.symbolic.constants.Pi'>) to Rational Check that it is possible to convert strings to iterated polynomial rings :trac:`13327`:: sage: Rm = QQ["a"]["b, c"] sage: Rm("a*b") a*b sage: parent(_) is Rm True """ from sage.rings.polynomial.multi_polynomial_element import MPolynomial_polydict import sage.rings.polynomial.polynomial_element as polynomial_element # handle constants that coerce into self.base_ring() first, if possible if isinstance(x, Element) and x.parent() is self.base_ring(): # A Constant multi-polynomial return self({self._zero_tuple:x}) try: y = self.base_ring()._coerce_(x) return MPolynomial_polydict(self, {self._zero_tuple:y}) except TypeError: pass from multi_polynomial_libsingular import MPolynomial_libsingular if isinstance(x, MPolynomial_polydict): P = x.parent() if P is self: return x elif P == self: return MPolynomial_polydict(self, x.element().dict()) elif self.base_ring().has_coerce_map_from(P): # it might be in the base ring (i.e. a poly ring over a poly ring) c = self.base_ring()(x) return MPolynomial_polydict(self, {self._zero_tuple:c}) elif len(P.variable_names()) == len(self.variable_names()): # Map the variables in some crazy way (but in order, # of course). This is here since R(blah) is supposed # to be "make an element of R if at all possible with # no guarantees that this is mathematically solid." K = self.base_ring() D = x.element().dict() for i, a in D.iteritems(): D[i] = K(a) return MPolynomial_polydict(self, D) elif set(P.variable_names()).issubset(set(self.variable_names())) and self.base_ring().has_coerce_map_from(P.base_ring()): # If the named variables are a superset of the input, map the variables by name return MPolynomial_polydict(self, self._extract_polydict(x)) else: return MPolynomial_polydict(self, x._mpoly_dict_recursive(self.variable_names(), self.base_ring())) elif isinstance(x, MPolynomial_libsingular): P = x.parent() if P == self: return MPolynomial_polydict(self, x.dict()) elif self.base_ring().has_coerce_map_from(P): # it might be in the base ring (i.e. a poly ring over a poly ring) c = self.base_ring()(x) return MPolynomial_polydict(self, {self._zero_tuple:c}) elif len(P.variable_names()) == len(self.variable_names()): # Map the variables in some crazy way (but in order, # of course). This is here since R(blah) is supposed # to be "make an element of R if at all possible with # no guarantees that this is mathematically solid." K = self.base_ring() D = x.dict() for i, a in D.iteritems(): D[i] = K(a) return MPolynomial_polydict(self, D) elif set(P.variable_names()).issubset(set(self.variable_names())) and self.base_ring().has_coerce_map_from(P.base_ring()): # If the named variables are a superset of the input, map the variables by name return MPolynomial_polydict(self, self._extract_polydict(x)) else: return MPolynomial_polydict(self, x._mpoly_dict_recursive(self.variable_names(), self.base_ring())) elif isinstance(x, polynomial_element.Polynomial): return MPolynomial_polydict(self, x._mpoly_dict_recursive(self.variable_names(), self.base_ring())) elif isinstance(x, PolyDict): return MPolynomial_polydict(self, x) elif isinstance(x, fraction_field_element.FractionFieldElement) and x.parent().ring() == self: if x.denominator() == 1: return x.numerator() else: raise TypeError("unable to coerce since the denominator is not 1") elif is_SingularElement(x) and self._has_singular: self._singular_().set_ring() try: return x.sage_poly(self) except TypeError: raise TypeError("unable to coerce singular object") elif hasattr(x, '_polynomial_'): return x._polynomial_(self) elif isinstance(x, str): try: from sage.misc.sage_eval import sage_eval return self(sage_eval(x, self.gens_dict_recursive())) except NameError as e: raise TypeError("unable to convert string") elif is_Macaulay2Element(x): try: s = x.sage_polystring() if len(s) == 0: raise TypeError # NOTE: It's CRUCIAL to use the eval command as follows, # i.e., with the gen dict as the third arg and the second # empty. Otherwise pickling won't work after calls to this eval!!! # This took a while to figure out! return self(eval(s, {}, self.gens_dict())) except (AttributeError, TypeError, NameError, SyntaxError): raise TypeError("Unable to coerce macaulay2 object") return MPolynomial_polydict(self, x) if isinstance(x, dict): return MPolynomial_polydict(self, x) else: c = self.base_ring()(x) return MPolynomial_polydict(self, {self._zero_tuple:c})
def __call__(self, x, check=True): """ Convert ``x`` to an element of this multivariate polynomial ring, possibly non-canonically. EXAMPLES: We create a Macaulay2 multivariate polynomial via ideal arithmetic, then convert it into R. :: sage: R.<x,y> = PolynomialRing(QQ, 2) # optional sage: I = R.ideal([x^3 + y, y]) # optional sage: S = I._macaulay2_() # optional sage: T = S*S*S # optional sage: U = T.gens().entries().flatten() # optional sage: f = U[2]; f # optional x^6*y+2*x^3*y^2+y^3 sage: R(repr(f)) # optional x^6*y + 2*x^3*y^2 + y^3 Some other subtle conversions. We create polynomial rings in 2 variables over the rationals, integers, and a finite field. :: sage: R.<x,y> = QQ[] sage: S.<x,y> = ZZ[] sage: T.<x,y> = GF(7)[] We convert from integer polynomials to rational polynomials, and back:: sage: f = R(S.0^2 - 4*S.1^3); f -4*y^3 + x^2 sage: parent(f) Multivariate Polynomial Ring in x, y over Rational Field sage: parent(S(f)) Multivariate Polynomial Ring in x, y over Integer Ring We convert from polynomials over the finite field. :: sage: f = R(T.0^2 - 4*T.1^3); f 3*y^3 + x^2 sage: parent(f) Multivariate Polynomial Ring in x, y over Rational Field We dump and load the polynomial ring S:: sage: S2 = loads(dumps(S)) sage: S2 == S True Coerce works and gets the right parent. :: sage: parent(S2._coerce_(S.0)) is S2 True Conversion to reduce modulo a prime between rings with different variable names:: sage: R.<x,y> = PolynomialRing(QQ,2) sage: S.<a,b> = PolynomialRing(GF(7),2) sage: f = x^2 + 2/3*y^3 sage: S(f) 3*b^3 + a^2 Conversion from symbolic variables:: sage: x,y,z = var('x,y,z') sage: R = QQ[x,y,z] sage: type(x) <type 'sage.symbolic.expression.Expression'> sage: type(R(x)) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'> sage: f = R(x^3 + y^3 - z^3); f x^3 + y^3 - z^3 sage: type(f) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'> sage: parent(f) Multivariate Polynomial Ring in x, y, z over Rational Field A more complicated symbolic and computational mix. Behind the scenes Singular and Maxima are doing the real work. :: sage: R = QQ[x,y,z] sage: f = (x^3 + y^3 - z^3)^10; f (x^3 + y^3 - z^3)^10 sage: g = R(f); parent(g) Multivariate Polynomial Ring in x, y, z over Rational Field sage: (f - g).expand() 0 It intelligently handles conversions from polynomial rings in a subset of the variables too. :: sage: R = GF(5)['x,y,z'] sage: S = ZZ['y'] sage: R(7*S.0) 2*y sage: T = ZZ['x,z'] sage: R(2*T.0 + 6*T.1 + T.0*T.1^2) x*z^2 + 2*x + z :: sage: R = QQ['t,x,y,z'] sage: S.<x> = ZZ['x'] sage: T.<z> = S['z'] sage: T Univariate Polynomial Ring in z over Univariate Polynomial Ring in x over Integer Ring sage: f = (x+3*z+5)^2; f 9*z^2 + (6*x + 30)*z + x^2 + 10*x + 25 sage: R(f) x^2 + 6*x*z + 9*z^2 + 10*x + 30*z + 25 Arithmetic with a constant from a base ring:: sage: R.<u,v> = QQ[] sage: S.<x,y> = R[] sage: u^3*x^2 + v*y u^3*x^2 + v*y Stacked polynomial rings convert into constants if possible. First, the univariate case:: sage: R.<x> = QQ[] sage: S.<u,v> = R[] sage: S(u + 2) u + 2 sage: S(u + 2).degree() 1 sage: S(x + 3) x + 3 sage: S(x + 3).degree() 0 Second, the multivariate case:: sage: R.<x,y> = QQ[] sage: S.<u,v> = R[] sage: S(x + 2*y) x + 2*y sage: S(u + 2*v) u + 2*v Conversion from strings:: sage: R.<x,y> = QQ[] sage: R('x+(1/2)*y^2') 1/2*y^2 + x sage: S.<u,v> = ZZ[] sage: S('u^2 + u*v + v^2') u^2 + u*v + v^2 Foreign polynomial rings convert into the highest ring; the point here is that an element of T could convert to an element of R or an element of S; it is anticipated that an element of T is more likely to be "the right thing" and is historically consistent. :: sage: R.<x,y> = QQ[] sage: S.<u,v> = R[] sage: T.<a,b> = QQ[] sage: S(a + b) u + v TESTS: Check if we still allow nonsense :trac:`7951`:: sage: P = PolynomialRing(QQ, 0, '') sage: P('pi') Traceback (most recent call last): ... TypeError: Unable to coerce pi (<class 'sage.symbolic.constants.Pi'>) to Rational Check that it is possible to convert strings to iterated polynomial rings :trac:`13327`:: sage: Rm = QQ["a"]["b, c"] sage: Rm("a*b") a*b sage: parent(_) is Rm True """ from sage.rings.polynomial.multi_polynomial_element import MPolynomial_polydict import sage.rings.polynomial.polynomial_element as polynomial_element # handle constants that coerce into self.base_ring() first, if possible if isinstance(x, Element) and x.parent() is self.base_ring(): # A Constant multi-polynomial return self({self._zero_tuple: x}) try: y = self.base_ring()._coerce_(x) return MPolynomial_polydict(self, {self._zero_tuple: y}) except TypeError: pass from multi_polynomial_libsingular import MPolynomial_libsingular if isinstance(x, MPolynomial_polydict): P = x.parent() if P is self: return x elif P == self: return MPolynomial_polydict(self, x.element().dict()) elif self.base_ring().has_coerce_map_from(P): # it might be in the base ring (i.e. a poly ring over a poly ring) c = self.base_ring()(x) return MPolynomial_polydict(self, {self._zero_tuple: c}) elif len(P.variable_names()) == len(self.variable_names()): # Map the variables in some crazy way (but in order, # of course). This is here since R(blah) is supposed # to be "make an element of R if at all possible with # no guarantees that this is mathematically solid." K = self.base_ring() D = x.element().dict() for i, a in D.iteritems(): D[i] = K(a) return MPolynomial_polydict(self, D) elif set(P.variable_names()).issubset(set(self.variable_names( ))) and self.base_ring().has_coerce_map_from(P.base_ring()): # If the named variables are a superset of the input, map the variables by name return MPolynomial_polydict(self, self._extract_polydict(x)) else: return MPolynomial_polydict( self, x._mpoly_dict_recursive(self.variable_names(), self.base_ring())) elif isinstance(x, MPolynomial_libsingular): P = x.parent() if P == self: return MPolynomial_polydict(self, x.dict()) elif self.base_ring().has_coerce_map_from(P): # it might be in the base ring (i.e. a poly ring over a poly ring) c = self.base_ring()(x) return MPolynomial_polydict(self, {self._zero_tuple: c}) elif len(P.variable_names()) == len(self.variable_names()): # Map the variables in some crazy way (but in order, # of course). This is here since R(blah) is supposed # to be "make an element of R if at all possible with # no guarantees that this is mathematically solid." K = self.base_ring() D = x.dict() for i, a in D.iteritems(): D[i] = K(a) return MPolynomial_polydict(self, D) elif set(P.variable_names()).issubset(set(self.variable_names( ))) and self.base_ring().has_coerce_map_from(P.base_ring()): # If the named variables are a superset of the input, map the variables by name return MPolynomial_polydict(self, self._extract_polydict(x)) else: return MPolynomial_polydict( self, x._mpoly_dict_recursive(self.variable_names(), self.base_ring())) elif isinstance(x, polynomial_element.Polynomial): return MPolynomial_polydict( self, x._mpoly_dict_recursive(self.variable_names(), self.base_ring())) elif isinstance(x, PolyDict): return MPolynomial_polydict(self, x) elif isinstance(x, fraction_field_element.FractionFieldElement ) and x.parent().ring() == self: if x.denominator() == 1: return x.numerator() else: raise TypeError( "unable to coerce since the denominator is not 1") elif is_SingularElement(x) and self._has_singular: self._singular_().set_ring() try: return x.sage_poly(self) except TypeError: raise TypeError("unable to coerce singular object") elif hasattr(x, '_polynomial_'): return x._polynomial_(self) elif isinstance(x, str): try: from sage.misc.sage_eval import sage_eval return self(sage_eval(x, self.gens_dict_recursive())) except NameError as e: raise TypeError("unable to convert string") elif is_Macaulay2Element(x): try: s = x.sage_polystring() if len(s) == 0: raise TypeError # NOTE: It's CRUCIAL to use the eval command as follows, # i.e., with the gen dict as the third arg and the second # empty. Otherwise pickling won't work after calls to this eval!!! # This took a while to figure out! return self(eval(s, {}, self.gens_dict())) except (AttributeError, TypeError, NameError, SyntaxError): raise TypeError("Unable to coerce macaulay2 object") return MPolynomial_polydict(self, x) if isinstance(x, dict): return MPolynomial_polydict(self, x) else: c = self.base_ring()(x) return MPolynomial_polydict(self, {self._zero_tuple: c})