def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=None, use_sage_types=False): """ A mutable list of elements with a common guaranteed universe, which can be set immutable. A universe is either an object that supports coercion (e.g., a parent), or a category. INPUT: - ``x`` - a list or tuple instance - ``universe`` - (default: None) the universe of elements; if None determined using canonical coercions and the entire list of elements. If list is empty, is category Objects() of all objects. - ``check`` -- (default: True) whether to coerce the elements of x into the universe - ``immutable`` - (default: True) whether or not this sequence is immutable - ``cr`` - (default: False) if True, then print a carriage return after each comma when printing this sequence. - ``cr_str`` - (default: False) if True, then print a carriage return after each comma when calling ``str()`` on this sequence. - ``use_sage_types`` -- (default: False) if True, coerce the built-in Python numerical types int, float, complex to the corresponding Sage types (this makes functions like vector() more flexible) OUTPUT: - a sequence EXAMPLES:: sage: v = Sequence(range(10)) sage: v.universe() <type 'int'> sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] We can request that the built-in Python numerical types be coerced to Sage objects:: sage: v = Sequence(range(10), use_sage_types=True) sage: v.universe() Integer Ring sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] You can also use seq for "Sequence", which is identical to using Sequence:: sage: v = seq([1,2,1/1]); v [1, 2, 1] sage: v.universe() Rational Field Note that assignment coerces if possible,:: sage: v = Sequence(range(10), ZZ) sage: a = QQ(5) sage: v[3] = a sage: parent(v[3]) Integer Ring sage: parent(a) Rational Field sage: v[3] = 2/3 Traceback (most recent call last): ... TypeError: no conversion of this rational to integer Sequences can be used absolutely anywhere lists or tuples can be used:: sage: isinstance(v, list) True Sequence can be immutable, so entries can't be changed:: sage: v = Sequence([1,2,3], immutable=True) sage: v.is_immutable() True sage: v[0] = 5 Traceback (most recent call last): ... ValueError: object is immutable; please change a copy instead. Only immutable sequences are hashable (unlike Python lists), though the hashing is potentially slow, since it first involves conversion of the sequence to a tuple, and returning the hash of that.:: sage: v = Sequence(range(10), ZZ, immutable=True) sage: hash(v) == hash(tuple(range(10))) True If you really know what you are doing, you can circumvent the type checking (for an efficiency gain):: sage: list.__setitem__(v, int(1), 2/3) # bad circumvention sage: v [0, 2/3, 2, 3, 4, 5, 6, 7, 8, 9] sage: list.__setitem__(v, int(1), int(2)) # not so bad circumvention You can make a sequence with a new universe from an old sequence.:: sage: w = Sequence(v, QQ) sage: w [0, 2, 2, 3, 4, 5, 6, 7, 8, 9] sage: w.universe() Rational Field sage: w[1] = 2/3 sage: w [0, 2/3, 2, 3, 4, 5, 6, 7, 8, 9] The default universe for any sequence, if no compatible parent structure can be found, is the universe of all Sage objects. This example illustrates how every element of a list is taken into account when constructing a sequence.:: sage: v = Sequence([1,7,6,GF(5)(3)]); v [1, 2, 1, 3] sage: v.universe() Finite Field of size 5 TESTS:: sage: Sequence(["a"], universe=ZZ) Traceback (most recent call last): ... TypeError: unable to convert a to an element of Integer Ring """ from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal if isinstance(x, Sequence_generic) and universe is None: universe = x.universe() x = list(x) if isinstance(x, MPolynomialIdeal) and universe is None: universe = x.ring() x = x.gens() if universe is None: orig_x = x x = list( x) # make a copy even if x is a list, we're going to change it if len(x) == 0: from sage.categories.objects import Objects universe = Objects() else: import sage.structure.element if use_sage_types: # convert any Python built-in numerical types to Sage objects x = [sage.structure.coerce.py_scalar_to_element(e) for e in x] # start the pairwise coercion for i in range(len(x) - 1): try: x[i], x[i + 1] = sage.structure.element.canonical_coercion( x[i], x[i + 1]) except TypeError: from sage.categories.objects import Objects universe = Objects() x = list(orig_x) check = False # no point break if universe is None: # no type errors raised. universe = sage.structure.element.parent(x[len(x) - 1]) from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.quotient_ring import is_QuotientRing if is_MPolynomialRing(universe) or isinstance( universe, BooleanMonomialMonoid) or (is_QuotientRing(universe) and is_MPolynomialRing( universe.cover_ring())): return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) else: return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types)
def PolynomialSequence(arg1, arg2=None, immutable=False, cr=False, cr_str=None): """ Construct a new polynomial sequence object. INPUT: - ``arg1`` - a multivariate polynomial ring, an ideal or a matrix - ``arg2`` - an iterable object of parts or polynomials (default:``None``) - ``immutable`` - if ``True`` the sequence is immutable (default: ``False``) - ``cr`` - print a line break after each element (default: ``False``) - ``cr_str`` - print a line break after each element if 'str' is called (default: ``None``) EXAMPLES:: sage: P.<a,b,c,d> = PolynomialRing(GF(127),4) sage: I = sage.rings.ideal.Katsura(P) If a list of tuples is provided, those form the parts:: sage: F = Sequence([I.gens(),I.gens()], I.ring()); F # indirect doctest [a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a, 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c, a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a, 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c] sage: F.nparts() 2 If an ideal is provided, the generators are used:: sage: Sequence(I) [a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a, 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c] If a list of polynomials is provided, the system has only one part:: sage: F = Sequence(I.gens(), I.ring()); F [a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a, 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c] sage: F.nparts() 1 """ from sage.matrix.matrix import is_Matrix if is_MPolynomialRing(arg1) or is_QuotientRing(arg1): ring = arg1 gens = arg2 elif is_MPolynomialRing(arg2) or is_QuotientRing(arg2): ring = arg2 gens = arg1 elif is_Matrix(arg1) and arg2 is None: ring = arg1.base_ring() gens = arg1.list() elif isinstance(arg1, MPolynomialIdeal) and arg2 is None: ring = arg1.ring() gens = arg1.gens() elif isinstance(arg1, (list,tuple,GeneratorType)) and arg2 is None: gens = arg1 try: e = iter(gens).next() except StopIteration: raise ValueError("Cannot determine ring from provided information.") if is_MPolynomial(e) or isinstance(e, QuotientRingElement): ring = e.parent() else: ring = iter(e).next().parent() else: raise TypeError("Cannot understand input.") try: e = iter(gens).next() if is_MPolynomial(e) or isinstance(e, QuotientRingElement): gens = tuple(gens) parts = (gens,) if not all(f.parent() is ring for f in gens): parts = ((ring(f) for f in gens),) else: parts = [] _gens = [] for part in gens: _part = [] for gen in part: if not gen.parent() is ring: ring(gen) _part.append(gen) _gens.extend(_part) parts.append(tuple(_part)) gens = _gens except StopIteration: gens = tuple() parts = ((),) k = ring.base_ring() try: c = k.characteristic() except NotImplementedError: c = -1 if c != 2: return PolynomialSequence_generic(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str) elif k.degree() == 1: return PolynomialSequence_gf2(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str) elif k.degree() > 1: return PolynomialSequence_gf2e(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str)
def __classcall_private__(cls, morphism_or_polys, domain=None): r""" Return the appropriate dynamical system on an affine scheme. TESTS:: sage: A.<x> = AffineSpace(ZZ,1) sage: A1.<z> = AffineSpace(CC,1) sage: H = End(A1) sage: f2 = H([z^2+1]) sage: f = DynamicalSystem_affine(f2, A) sage: f.domain() is A False :: sage: P1.<x,y> = ProjectiveSpace(QQ,1) sage: DynamicalSystem_affine([y, 2*x], domain=P1) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme sage: H = End(P1) sage: DynamicalSystem_affine(H([y, 2*x])) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme :: sage: R.<x,y,z> = QQ[] sage: f = DynamicalSystem_affine([x+y+z, y*z]) Traceback (most recent call last): ... ValueError: Number of polys does not match dimension of Affine Space of dimension 3 over Rational Field :: sage: A.<x,y> = AffineSpace(QQ,2) sage: f = DynamicalSystem_affine([CC.0*x^2, y^2], domain=A) Traceback (most recent call last): ... TypeError: coefficients of polynomial not in Rational Field """ if isinstance(morphism_or_polys, SchemeMorphism_polynomial): morphism = morphism_or_polys R = morphism.base_ring() polys = list(morphism) domain = morphism.domain() if not is_AffineSpace(domain) and not isinstance( domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if domain != morphism_or_polys.codomain(): raise ValueError('domain and codomain do not agree') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain) elif isinstance(morphism_or_polys, (list, tuple)): polys = list(morphism_or_polys) else: polys = [morphism_or_polys] PR = get_coercion_model().common_parent(*polys) fraction_field = any(is_FractionField(poly.parent()) for poly in polys) if fraction_field: K = PR.base_ring().fraction_field() # Replace base ring with its fraction field PR = PR.ring().change_ring(K).fraction_field() polys = [PR(poly) for poly in polys] else: quotient_ring = any( is_QuotientRing(poly.parent()) for poly in polys) # If any of the list entries lies in a quotient ring, we try # to lift all entries to a common polynomial ring. if quotient_ring: polys = [PR(poly).lift() for poly in polys] else: polys = [PR(poly) for poly in polys] if domain is None: if PR is SR: raise TypeError("Symbolic Ring cannot be the base ring") if fraction_field: PR = PR.ring() domain = AffineSpace(PR) else: # Check if we can coerce the given polynomials over the given domain PR = domain.ambient_space().coordinate_ring() try: if fraction_field: PR = PR.fraction_field() polys = [PR(poly) for poly in polys] except TypeError: raise TypeError('coefficients of polynomial not in {}'.format( domain.base_ring())) if len(polys) != domain.ambient_space().coordinate_ring().ngens(): raise ValueError( 'Number of polys does not match dimension of {}'.format( domain)) R = domain.base_ring() if R is SR: raise TypeError("Symbolic Ring cannot be the base ring") if not is_AffineSpace(domain) and not isinstance( domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain)
def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=None, use_sage_types=False): """ A mutable list of elements with a common guaranteed universe, which can be set immutable. A universe is either an object that supports coercion (e.g., a parent), or a category. INPUT: - ``x`` - a list or tuple instance - ``universe`` - (default: None) the universe of elements; if None determined using canonical coercions and the entire list of elements. If list is empty, is category Objects() of all objects. - ``check`` -- (default: True) whether to coerce the elements of x into the universe - ``immutable`` - (default: True) whether or not this sequence is immutable - ``cr`` - (default: False) if True, then print a carriage return after each comma when printing this sequence. - ``cr_str`` - (default: False) if True, then print a carriage return after each comma when calling ``str()`` on this sequence. - ``use_sage_types`` -- (default: False) if True, coerce the built-in Python numerical types int, long, float, complex to the corresponding Sage types (this makes functions like vector() more flexible) OUTPUT: - a sequence EXAMPLES:: sage: v = Sequence(range(10)) sage: v.universe() <type 'int'> sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] We can request that the built-in Python numerical types be coerced to Sage objects:: sage: v = Sequence(range(10), use_sage_types=True) sage: v.universe() Integer Ring sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] You can also use seq for "Sequence", which is identical to using Sequence:: sage: v = seq([1,2,1/1]); v [1, 2, 1] sage: v.universe() Rational Field sage: v.parent() Category of sequences in Rational Field sage: v.parent()([3,4/3]) [3, 4/3] Note that assignment coerces if possible,:: sage: v = Sequence(range(10), ZZ) sage: a = QQ(5) sage: v[3] = a sage: parent(v[3]) Integer Ring sage: parent(a) Rational Field sage: v[3] = 2/3 Traceback (most recent call last): ... TypeError: no conversion of this rational to integer Sequences can be used absolutely anywhere lists or tuples can be used:: sage: isinstance(v, list) True Sequence can be immutable, so entries can't be changed:: sage: v = Sequence([1,2,3], immutable=True) sage: v.is_immutable() True sage: v[0] = 5 Traceback (most recent call last): ... ValueError: object is immutable; please change a copy instead. Only immutable sequences are hashable (unlike Python lists), though the hashing is potentially slow, since it first involves conversion of the sequence to a tuple, and returning the hash of that.:: sage: v = Sequence(range(10), ZZ, immutable=True) sage: hash(v) 1591723448 # 32-bit -4181190870548101704 # 64-bit If you really know what you are doing, you can circumvent the type checking (for an efficiency gain):: sage: list.__setitem__(v, int(1), 2/3) # bad circumvention sage: v [0, 2/3, 2, 3, 4, 5, 6, 7, 8, 9] sage: list.__setitem__(v, int(1), int(2)) # not so bad circumvention You can make a sequence with a new universe from an old sequence.:: sage: w = Sequence(v, QQ) sage: w [0, 2, 2, 3, 4, 5, 6, 7, 8, 9] sage: w.universe() Rational Field sage: w[1] = 2/3 sage: w [0, 2/3, 2, 3, 4, 5, 6, 7, 8, 9] Sequences themselves live in a category, the category of all sequences in the given universe.:: sage: w.category() Category of sequences in Rational Field This is also the parent of any sequence:: sage: w.parent() Category of sequences in Rational Field The default universe for any sequence, if no compatible parent structure can be found, is the universe of all Sage objects. This example illustrates how every element of a list is taken into account when constructing a sequence.:: sage: v = Sequence([1,7,6,GF(5)(3)]); v [1, 2, 1, 3] sage: v.universe() Finite Field of size 5 sage: v.parent() Category of sequences in Finite Field of size 5 sage: v.parent()([7,8,9]) [2, 3, 4] """ from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal if isinstance(x, Sequence_generic) and universe is None: universe = x.universe() x = list(x) if isinstance(x, MPolynomialIdeal) and universe is None: universe = x.ring() x = x.gens() if universe is None: if not isinstance(x, (list, tuple)): x = list(x) #raise TypeError("x must be a list or tuple") if len(x) == 0: import sage.categories.all universe = sage.categories.all.Objects() else: import sage.structure.element as coerce y = x x = list(x) # make a copy, or we'd change the type of the elements of x, which would be bad. if use_sage_types: # convert any Python built-in numerical types to Sage objects from sage.rings.integer_ring import ZZ from sage.rings.real_double import RDF from sage.rings.complex_double import CDF for i in range(len(x)): if isinstance(x[i], int) or isinstance(x[i], long): x[i] = ZZ(x[i]) elif isinstance(x[i], float): x[i] = RDF(x[i]) elif isinstance(x[i], complex): x[i] = CDF(x[i]) # start the pairwise coercion for i in range(len(x)-1): try: x[i], x[i+1] = coerce.canonical_coercion(x[i],x[i+1]) except TypeError: import sage.categories.all universe = sage.categories.all.Objects() x = list(y) check = False # no point break if universe is None: # no type errors raised. universe = coerce.parent(x[len(x)-1]) from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.quotient_ring import is_QuotientRing from sage.rings.polynomial.pbori import BooleanMonomialMonoid if is_MPolynomialRing(universe) or \ (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())) or \ isinstance(universe, BooleanMonomialMonoid): from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence try: return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) except (TypeError,AttributeError): return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types) else: return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types)
def __classcall_private__(cls, morphism_or_polys, domain=None): r""" Return the appropriate dynamical system on an affine scheme. TESTS:: sage: A.<x> = AffineSpace(ZZ,1) sage: A1.<z> = AffineSpace(CC,1) sage: H = End(A1) sage: f2 = H([z^2+1]) sage: f = DynamicalSystem_affine(f2, A) sage: f.domain() is A False :: sage: P1.<x,y> = ProjectiveSpace(QQ,1) sage: DynamicalSystem_affine([y, 2*x], domain=P1) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme sage: H = End(P1) sage: DynamicalSystem_affine(H([y, 2*x])) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme """ if isinstance(morphism_or_polys, SchemeMorphism_polynomial): morphism = morphism_or_polys R = morphism.base_ring() polys = list(morphism) domain = morphism.domain() if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if domain != morphism_or_polys.codomain(): raise ValueError('domain and codomain do not agree') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain) elif isinstance(morphism_or_polys,(list, tuple)): polys = list(morphism_or_polys) else: polys = [morphism_or_polys] # We now arrange for all of our list entries to lie in the same ring # Fraction field case first fraction_field = False for poly in polys: P = poly.parent() if is_FractionField(P): fraction_field = True break if fraction_field: K = P.base_ring().fraction_field() # Replace base ring with its fraction field P = P.ring().change_ring(K).fraction_field() polys = [P(poly) for poly in polys] else: # If any of the list entries lies in a quotient ring, we try # to lift all entries to a common polynomial ring. quotient_ring = False for poly in polys: P = poly.parent() if is_QuotientRing(P): quotient_ring = True break if quotient_ring: polys = [P(poly).lift() for poly in polys] else: poly_ring = False for poly in polys: P = poly.parent() if is_PolynomialRing(P) or is_MPolynomialRing(P): poly_ring = True break if poly_ring: polys = [P(poly) for poly in polys] if domain is None: f = polys[0] CR = f.parent() if CR is SR: raise TypeError("Symbolic Ring cannot be the base ring") if fraction_field: CR = CR.ring() domain = AffineSpace(CR) R = domain.base_ring() if R is SR: raise TypeError("Symbolic Ring cannot be the base ring") if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain)
def __classcall_private__(cls, morphism_or_polys, domain=None): r""" Return the appropriate dynamical system on an affine scheme. TESTS:: sage: A.<x> = AffineSpace(ZZ,1) sage: A1.<z> = AffineSpace(CC,1) sage: H = End(A1) sage: f2 = H([z^2+1]) sage: f = DynamicalSystem_affine(f2, A) sage: f.domain() is A False :: sage: P1.<x,y> = ProjectiveSpace(QQ,1) sage: DynamicalSystem_affine([y, 2*x], domain=P1) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme sage: H = End(P1) sage: DynamicalSystem_affine(H([y, 2*x])) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme """ if isinstance(morphism_or_polys, SchemeMorphism_polynomial): morphism = morphism_or_polys R = morphism.base_ring() polys = list(morphism) domain = morphism.domain() if not is_AffineSpace(domain) and not isinstance( domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if domain != morphism_or_polys.codomain(): raise ValueError('domain and codomain do not agree') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain) elif isinstance(morphism_or_polys, (list, tuple)): polys = list(morphism_or_polys) else: polys = [morphism_or_polys] # We now arrange for all of our list entries to lie in the same ring # Fraction field case first fraction_field = False for poly in polys: P = poly.parent() if is_FractionField(P): fraction_field = True break if fraction_field: K = P.base_ring().fraction_field() # Replace base ring with its fraction field P = P.ring().change_ring(K).fraction_field() polys = [P(poly) for poly in polys] else: # If any of the list entries lies in a quotient ring, we try # to lift all entries to a common polynomial ring. quotient_ring = False for poly in polys: P = poly.parent() if is_QuotientRing(P): quotient_ring = True break if quotient_ring: polys = [P(poly).lift() for poly in polys] else: poly_ring = False for poly in polys: P = poly.parent() if is_PolynomialRing(P) or is_MPolynomialRing(P): poly_ring = True break if poly_ring: polys = [P(poly) for poly in polys] if domain is None: f = polys[0] CR = f.parent() if CR is SR: raise TypeError("Symbolic Ring cannot be the base ring") if fraction_field: CR = CR.ring() domain = AffineSpace(CR) R = domain.base_ring() if R is SR: raise TypeError("Symbolic Ring cannot be the base ring") if not is_AffineSpace(domain) and not isinstance( domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain)
def __classcall_private__(cls, morphism_or_polys, domain=None): r""" Return the appropriate dynamical system on an affine scheme. TESTS:: sage: A.<x> = AffineSpace(ZZ,1) sage: A1.<z> = AffineSpace(CC,1) sage: H = End(A1) sage: f2 = H([z^2+1]) sage: f = DynamicalSystem_affine(f2, A) sage: f.domain() is A False :: sage: P1.<x,y> = ProjectiveSpace(QQ,1) sage: DynamicalSystem_affine([y, 2*x], domain=P1) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme sage: H = End(P1) sage: DynamicalSystem_affine(H([y, 2*x])) Traceback (most recent call last): ... ValueError: "domain" must be an affine scheme :: sage: R.<x,y,z> = QQ[] sage: f = DynamicalSystem_affine([x+y+z, y*z]) Traceback (most recent call last): ... ValueError: Number of polys does not match dimension of Affine Space of dimension 3 over Rational Field :: sage: A.<x,y> = AffineSpace(QQ,2) sage: f = DynamicalSystem_affine([CC.0*x^2, y^2], domain=A) Traceback (most recent call last): ... TypeError: coefficients of polynomial not in Rational Field """ if isinstance(morphism_or_polys, SchemeMorphism_polynomial): morphism = morphism_or_polys R = morphism.base_ring() polys = list(morphism) domain = morphism.domain() if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if domain != morphism_or_polys.codomain(): raise ValueError('domain and codomain do not agree') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain) elif isinstance(morphism_or_polys,(list, tuple)): polys = list(morphism_or_polys) else: polys = [morphism_or_polys] PR = get_coercion_model().common_parent(*polys) fraction_field = any(is_FractionField(poly.parent()) for poly in polys) if fraction_field: K = PR.base_ring().fraction_field() # Replace base ring with its fraction field PR = PR.ring().change_ring(K).fraction_field() polys = [PR(poly) for poly in polys] else: quotient_ring = any(is_QuotientRing(poly.parent()) for poly in polys) # If any of the list entries lies in a quotient ring, we try # to lift all entries to a common polynomial ring. if quotient_ring: polys = [PR(poly).lift() for poly in polys] else: polys = [PR(poly) for poly in polys] if domain is None: if PR is SR: raise TypeError("Symbolic Ring cannot be the base ring") if fraction_field: PR = PR.ring() domain = AffineSpace(PR) else: # Check if we can coerce the given polynomials over the given domain PR = domain.ambient_space().coordinate_ring() try: if fraction_field: PR = PR.fraction_field() polys = [PR(poly) for poly in polys] except TypeError: raise TypeError('coefficients of polynomial not in {}'.format(domain.base_ring())) if len(polys) != domain.ambient_space().coordinate_ring().ngens(): raise ValueError('Number of polys does not match dimension of {}'.format(domain)) R = domain.base_ring() if R is SR: raise TypeError("Symbolic Ring cannot be the base ring") if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine): raise ValueError('"domain" must be an affine scheme') if R not in Fields(): return typecall(cls, polys, domain) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(polys, domain) return DynamicalSystem_affine_field(polys, domain)
def ring_defining_ideal(R): R_ideal = R.ideal(0) if is_QuotientRing(R): R_ideal = R.defining_ideal() return R_ideal