def __classcall_private__(cls, morphism_or_polys, domain=None, names=None): r""" Return the appropriate dynamical system on a scheme. EXAMPLES:: sage: R.<t> = QQ[] sage: DynamicalSystem(t^2 - 3) Dynamical System of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (X : Y) to (X^2 - 3*Y^2 : Y^2) """ if isinstance(morphism_or_polys, SchemeMorphism_polynomial): domain = morphism_or_polys.domain() if domain is not None: if is_AffineSpace(domain) or isinstance( domain, AlgebraicScheme_subscheme_affine): from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine return DynamicalSystem_affine(morphism_or_polys, domain) if is_Berkovich_Cp(domain): from sage.dynamics.arithmetic_dynamics.berkovich_ds import DynamicalSystem_Berkovich return DynamicalSystem_Berkovich(morphism_or_polys, domain) from sage.dynamics.arithmetic_dynamics.projective_ds import DynamicalSystem_projective return DynamicalSystem_projective(morphism_or_polys, domain, names)
def as_dynamical_system(self): """ Return this endomorphism as a :class:`DynamicalSystem_affine`. OUTPUT: - :class:`DynamicalSystem_affine` EXAMPLES:: sage: A.<x,y,z> = AffineSpace(ZZ, 3) sage: H = End(A) sage: f = H([x^2, y^2, z^2]) sage: type(f.as_dynamical_system()) <class 'sage.dynamics.arithmetic_dynamics.affine_ds.DynamicalSystem_affine'> :: sage: A.<x,y> = AffineSpace(ZZ, 2) sage: H = End(A) sage: f = H([x^2-y^2, y^2]) sage: type(f.as_dynamical_system()) <class 'sage.dynamics.arithmetic_dynamics.affine_ds.DynamicalSystem_affine'> :: sage: A.<x> = AffineSpace(GF(5), 1) sage: H = End(A) sage: f = H([x^2]) sage: type(f.as_dynamical_system()) <class 'sage.dynamics.arithmetic_dynamics.affine_ds.DynamicalSystem_affine_finite_field'> :: sage: P.<x,y> = AffineSpace(RR, 2) sage: f = DynamicalSystem([x^2 + y^2, y^2], P) sage: g = f.as_dynamical_system() sage: g is f True """ from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem if isinstance(self, DynamicalSystem): return self if not self.domain() == self.codomain(): raise TypeError("must be an endomorphism") from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine_field from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine_finite_field R = self.base_ring() if R not in _Fields: return DynamicalSystem_affine(list(self), self.domain()) if is_FiniteField(R): return DynamicalSystem_affine_finite_field(list(self), self.domain()) return DynamicalSystem_affine_field(list(self), self.domain())
def BM_all_minimal(vp, return_transformation=False, D=None): r""" Determine a representative in each `SL(2,\ZZ)` orbit with minimal resultant. This function modifies the Bruin-Molnar algorithm ([BM2012]_) to solve in the inequalities as ``<=`` instead of ``<``. Among the list of solutions is all conjugations that preserve the resultant. From that list the `SL(2,\ZZ)` orbits are identified and one representative from each orbit is returned. This function assumes that the given model is a minimal model. INPUT: - ``vp`` -- a minimal model of a dynamical system on the projective line - ``return_transformation`` -- (default: ``False``) boolean; this signals a return of the ``PGL_2`` transformation to conjugate ``vp`` to the calculated minimal model - ``D`` -- a list of primes, in case one only wants to check minimality at those specific primes OUTPUT: List of pairs ``[f, m]`` where ``f`` is a dynamical system and ``m`` is a `2 \times 2` matrix. EXAMPLES:: sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: f = DynamicalSystem([x^3 - 13^2*y^3, x*y^2]) sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import BM_all_minimal sage: BM_all_minimal(f) [Dynamical System of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^3 - 169*y^3 : x*y^2), Dynamical System of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (13*x^3 - y^3 : x*y^2)] :: sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: f = DynamicalSystem([x^3 - 6^2*y^3, x*y^2]) sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import BM_all_minimal sage: BM_all_minimal(f, D=[3]) [Dynamical System of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^3 - 36*y^3 : x*y^2), Dynamical System of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (3*x^3 - 4*y^3 : x*y^2)] :: sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: f = DynamicalSystem([x^3 - 4^2*y^3, x*y^2]) sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import BM_all_minimal sage: cl = BM_all_minimal(f, return_transformation=True) sage: all(f.conjugate(m) == g for g, m in cl) True """ mp = copy(vp) mp.normalize_coordinates() BR = mp.domain().base_ring() MS = MatrixSpace(QQ, 2) M_Id = MS.one() d = mp.degree() F, G = list(mp) #coordinate polys aff_map = mp.dehomogenize(1) f, g = aff_map[0].numerator(), aff_map[0].denominator() z = aff_map.domain().gen(0) dg = f.parent()(g).degree() Res = mp.resultant() ##### because of how the bound is compute in lemma 3.3 from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine h = f - z * g A = AffineSpace(BR, 1, h.parent().variable_name()) res = DynamicalSystem_affine([h / g], domain=A).homogenize(1).resultant() if D is None: D = ZZ(Res).prime_divisors() # get the conjugations for each prime independently # these are returning (p,k,b) so that the matrix is [p^k,b,0,1] all_pM = [] for p in D: # all_orbits used to scale inequalities to equalities all_pM.append(Min(mp, p, res, M_Id, all_orbits=True)) # need the identity for each prime if [p, 0, 0] not in all_pM[-1]: all_pM[-1].append([p, 0, 0]) #combine conjugations for all primes all_M = [M_Id] for prime_data in all_pM: #these are (p,k,b) so that the matrix is [p^k,b,0,1] new_M = [] if prime_data: p = prime_data[0][0] for m in prime_data: mat = MS([m[0]**m[1], m[2], 0, 1]) new_map = mp.conjugate(mat) new_map.normalize_coordinates() # make sure the resultant didn't change and that it is a different SL(2,ZZ) orbit if (mat == M_Id) or (new_map.resultant().valuation(p) == Res.valuation(p) and mat.det() not in [1, -1]): new_M.append(m) if new_M: all_M = [ m1 * MS([m[0]**m[1], m[2], 0, 1]) for m1 in all_M for m in new_M ] #get all models with same resultant all_maps = [] for M in all_M: new_map = mp.conjugate(M) new_map.normalize_coordinates() if not [new_map, M] in all_maps: all_maps.append([new_map, M]) #Split into conjugacy classes #We just keep track of the two matrices that come from #the original to get the conjugation that goes between these!! classes = [] for funct, mat in all_maps: if not classes: classes.append([funct, mat]) else: found = False for Func, Mat in classes: #get conjugation M = mat.inverse() * Mat assert funct.conjugate(M) == Func if M.det() in [1, -1]: #same SL(2,Z) orbit found = True break if found is False: classes.append([funct, mat]) if return_transformation: return classes else: return [funct for funct, matr in classes]
def affine_minimal(vp, return_transformation=False, D=None, quick=False): r""" Determine if given map is affine minimal. Given vp a scheme morphism on the projective line over the rationals, this procedure determines if `\phi` is minimal. In particular, it determines if the map is affine minimal, which is enough to decide if it is minimal or not. See Proposition 2.10 in [Bruin-Molnar]_. INPUT: - ``vp`` -- dynamical system on the projective line - ``D`` -- a list of primes, in case one only wants to check minimality at those specific primes - ``return_transformation`` -- (default: ``False``) boolean; this signals a return of the `PGL_2` transformation to conjugate this map to the calculated models - ``quick`` -- a boolean value. If true the algorithm terminates once algorithm determines F/G is not minimal, otherwise algorithm only terminates once a minimal model has been found OUTPUT: - ``newvp`` -- dynamical system on the projective line - ``conj`` -- linear fractional transformation which conjugates ``vp`` to ``newvp`` EXAMPLES:: sage: PS.<X,Y> = ProjectiveSpace(QQ, 1) sage: vp = DynamicalSystem_projective([X^2 + 9*Y^2, X*Y]) sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import affine_minimal sage: affine_minimal(vp, True) ( Dynamical System of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (X : Y) to (X^2 + Y^2 : X*Y) , [3 0] [0 1] ) """ from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine BR = vp.domain().base_ring() conj = matrix(BR, 2, 2, 1) flag = True vp.normalize_coordinates() d = vp.degree() Affvp = vp.dehomogenize(1) R = Affvp.coordinate_ring() if R.is_field(): #want the polynomial ring not the fraction field R = R.ring() F = R(Affvp[0].numerator()) G = R(Affvp[0].denominator()) if R(G.degree()) == 0 or R(F.degree()) == 0: raise TypeError( "affine minimality is only considered for maps not of the form f or 1/f for a polynomial f" ) z = F.parent().gen(0) minF, minG = F, G #If the valuation of a prime in the resultant is small enough, we can say the #map is affine minimal at that prime without using the local minimality loop. See #Theorem 3.2.2 in [Molnar, M.Sc. thesis] if d % 2 == 0: g = d else: g = 2 * d Res = vp.resultant() #Some quantities needed for the local minimization loop, but we compute now #since the value is constant, so we do not wish to compute in every local loop. #See Theorem 3.3.3 in [Molnar, M.Sc thesis] H = F - z * minG d1 = F.degree() A = AffineSpace(BR, 1, H.parent().variable_name()) ubRes = DynamicalSystem_affine([H / minG], domain=A).homogenize(1).resultant() #Set the primes to check minimality at, if not already prescribed if D is None: D = ZZ(Res).prime_divisors() #Check minimality at all primes in D. If D is all primes dividing #Res(minF/minG), this is enough to show whether minF/minG is minimal or not. See #Propositions 3.2.1 and 3.3.7 in [Molnar, M.Sc. thesis]. for p in D: while True: if Res.valuation(p) < g: #The model is minimal at p min = True else: #The model may not be minimal at p. newvp, conj = Min(vp, p, ubRes, conj, all_orbits=False) if newvp == vp: min = True else: vp = newvp Affvp = vp.dehomogenize(1) min = False if min: #The model is minimal at p break elif F == Affvp[0].numerator() and G == Affvp[0].denominator(): #The model is minimal at p break else: #The model is not minimal at p flag = False if quick: break if quick and not flag: break if quick: #only return whether the model is minimal return flag if return_transformation: return vp, conj return vp
def chebyshev_polynomial(self, n, kind='first'): """ Generates an endomorphism of this affine line by a Chebyshev polynomial. Chebyshev polynomials are a sequence of recursively defined orthogonal polynomials. Chebyshev of the first kind are defined as `T_0(x) = 1`, `T_1(x) = x`, and `T_{n+1}(x) = 2xT_n(x) - T_{n-1}(x)`. Chebyshev of the second kind are defined as `U_0(x) = 1`, `U_1(x) = 2x`, and `U_{n+1}(x) = 2xU_n(x) - U_{n-1}(x)`. INPUT: - ``n`` -- a non-negative integer. - ``kind`` -- ``first`` or ``second`` specifying which kind of chebyshev the user would like to generate. Defaults to ``first``. OUTPUT: :class:`DynamicalSystem_affine` EXAMPLES:: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(5, 'first') Dynamical System of Affine Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x) to (16*x^5 - 20*x^3 + 5*x) :: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(3, 'second') Dynamical System of Affine Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x) to (8*x^3 - 4*x) :: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(3, 2) Traceback (most recent call last): ... ValueError: keyword 'kind' must have a value of either 'first' or 'second' :: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(-4, 'second') Traceback (most recent call last): ... ValueError: first parameter 'n' must be a non-negative integer :: sage: A = AffineSpace(QQ, 2, 'x') sage: A.chebyshev_polynomial(2) Traceback (most recent call last): ... TypeError: affine space must be of dimension 1 """ if self.dimension_relative() != 1: raise TypeError("affine space must be of dimension 1") n = ZZ(n) if (n < 0): raise ValueError("first parameter 'n' must be a non-negative integer") from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine if kind == 'first': return DynamicalSystem_affine([chebyshev_T(n, self.gen(0))], domain=self) elif kind == 'second': return DynamicalSystem_affine([chebyshev_U(n, self.gen(0))], domain=self) else: raise ValueError("keyword 'kind' must have a value of either 'first' or 'second'")
def __call__(self, x, type_3_pole_check=True): """ Makes dynamical systems on Berkovich space over ``Cp`` callable. INPUT: - ``x`` -- a point of projective Berkovich space over ``Cp``. - type_3_pole_check -- (default ``True``) A bool. WARNING: changing the value of type_3_pole_check can lead to mathematically incorrect answers. Only set to ``False`` if there are NO poles of the dynamical system in the disk corresponding to the type III point ``x``. See Examples. OUTPUT: A point of projective Berkovich space over ``Cp``. EXAMPLES:: sage: P.<x,y> = ProjectiveSpace(Qp(3), 1) sage: g = DynamicalSystem_projective([x^2 + y^2, x*y]) sage: G = DynamicalSystem_Berkovich(g) sage: B = G.domain() sage: Q3 = B(0, 1) sage: G(Q3) Type II point centered at (0 : 1 + O(3^20)) of radius 3^0 :: sage: P.<x,y> = ProjectiveSpace(Qp(3), 1) sage: H = DynamicalSystem_Berkovich([x*y^2, x^3 + 20*y^3]) sage: B = H.domain() sage: Q4 = B(1/9, 1.5) sage: H(Q4, False) Type III point centered at (3^4 + 3^10 + 2*3^11 + 2*3^13 + 2*3^14 + 2*3^15 + 3^17 + 2*3^18 + 2*3^19 + 3^20 + 3^21 + 3^22 + O(3^24) : 1 + O(3^20)) of radius 0.00205761316872428 ALGORITHM: - For type II points, we use the approach outlined in Example 7.37 of [Ben2019]_ - For type III points, we use Proposition 7.6 of [Ben2019]_ """ if not isinstance(x.parent(), Berkovich_Cp_Projective): try: x = self.domain()(x) except: raise TypeError( 'action of dynamical system not defined on %s' % x.parent()) if x.parent().is_padic_base() != self.domain().is_padic_base(): raise ValueError('x was not backed by the same type of field as f') if x.prime() != self.domain().prime(): raise ValueError( 'x and f are defined over Berkovich spaces over Cp for different p' ) if x.type_of_point() == 1: return self.domain()(self._system(x.center())) if x.type_of_point() == 4: raise NotImplementedError( 'action on Type IV points not implemented') f = self._system if x.type_of_point() == 2: if self.domain().is_number_field_base(): ideal = self.domain().ideal() ring_of_integers = self.domain().base_ring().ring_of_integers() field = f.domain().base_ring() M = Matrix([[field(x.prime()**(-1 * x.power())), x.center()[0]], [field(0), field(1)]]) F = list(f * M) R = field['z'] S = f.domain().coordinate_ring() z = R.gen(0) dehomogenize_hom = S.hom([z, 1]) for i in range(len(F)): F[i] = dehomogenize_hom(F[i]) lcm = field(1) for poly in F: for i in poly: if i != 0: lcm = i.denominator().lcm(lcm) for i in range(len(F)): F[i] *= lcm gcd = [i for i in F[0] if i != 0][0] for poly in F: for i in poly: if i != 0: gcd = gcd * i * gcd.lcm(i).inverse_of_unit() for i in range(len(F)): F[i] *= gcd.inverse_of_unit() gcd = F[0].gcd(F[1]) F[0] = F[0].quo_rem(gcd)[0] F[1] = F[1].quo_rem(gcd)[0] fraction = [] for poly in F: new_poly = [] for i in poly: if self.domain().is_padic_base(): new_poly.append(i.residue()) else: new_poly.append(ring_of_integers(i).mod(ideal)) new_poly = R(new_poly) fraction.append((new_poly)) gcd = fraction[0].gcd(fraction[1]) num = fraction[0].quo_rem(gcd)[0] dem = fraction[1].quo_rem(gcd)[0] if dem.is_zero(): f = DynamicalSystem_affine(F[0] / F[1]).homogenize(1) f = f.conjugate(Matrix([[0, 1], [1, 0]])) g = DynamicalSystem_Berkovich(f) return g(self.domain()(QQ(0), QQ(1))).involution_map() # if the reduction is not constant, the image is the Gauss point if not (num.is_constant() and dem.is_constant()): return self.domain()(QQ(0), QQ(1)) if self.domain().is_padic_base(): reduced_value = field(num * dem.inverse_of_unit()).lift_to_precision( field.precision_cap()) else: reduced_value = field(num * dem.inverse_of_unit()) new_num = F[0] - reduced_value * F[1] if self.domain().is_padic_base(): power_of_p = min([i.valuation() for i in new_num]) else: power_of_p = min([i.valuation(ideal) for i in new_num]) inverse_map = field(x.prime()**power_of_p) * z + reduced_value if self.domain().is_padic_base(): return self.domain()(inverse_map(0), (inverse_map(1) - inverse_map(0)).abs()) else: val = (inverse_map(1) - inverse_map(0)).valuation(ideal) if val == Infinity: return self.domain()(inverse_map(0), 0) return self.domain()(inverse_map(0), x.prime()**(-1 * val)) # point is now type III, so we compute using Proposition 7.6 [of Benedetto] affine_system = f.dehomogenize(1) dem = affine_system.defining_polynomials()[0].denominator( ).univariate_polynomial() if type_3_pole_check: if self.domain().is_padic_base(): factorization = [i[0] for i in dem.factor()] for factor in factorization: if factor.degree() >= 2: try: factor_root_field = factor.root_field('a') factor = factor.change_ring(factor_root_field) except: raise NotImplementedError( 'cannot check if poles lie in type III disk') else: factor_root_field = factor.base_ring() center = factor_root_field(x.center()[0]) for pole in [i[0] for i in factor.roots()]: if (center - pole).abs() <= x.radius(): raise NotImplementedError( 'image of type III point not implemented when poles in disk' ) else: dem_splitting_field, embedding = dem.splitting_field('a', True) poles = [i[0] for i in dem.roots(dem_splitting_field)] primes_above = dem_splitting_field.primes_above( self.domain().ideal()) # check if all primes of the extension map the roots to outside # the disk corresponding to the type III point for prime in primes_above: no_poles = True for pole in poles: valuation = (embedding(x.center()[0]) - pole).valuation(prime) if valuation == Infinity: no_poles = False break elif x.prime()**(-1 * valuation / prime.absolute_ramification_index() ) <= x.radius(): no_poles = False break if not no_poles: break if not no_poles: raise NotImplementedError( 'image of type III not implemented when poles in disk') nth_derivative = f.dehomogenize(1).defining_polynomials()[0] variable = nth_derivative.parent().gens()[0] a = x.center()[0] Taylor_expansion = [] from sage.functions.other import factorial for i in range(f.degree() + 1): Taylor_expansion.append(nth_derivative(a) * 1 / factorial(i)) nth_derivative = nth_derivative.derivative(variable) r = x.radius() new_center = f(a) if self.domain().is_padic_base(): new_radius = max([ Taylor_expansion[i].abs() * r**i for i in range(1, len(Taylor_expansion)) ]) else: if prime is None: prime = x.parent().ideal() dem_splitting_field = x.parent().base_ring() p = x.prime() new_radius = 0 for i in range(1, len(Taylor_expansion)): valuation = dem_splitting_field( Taylor_expansion[i]).valuation(prime) new_radius = max( new_radius, p**(-valuation / prime.absolute_ramification_index()) * r**i) return self.domain()(new_center, new_radius)
def __classcall_private__(cls, dynamical_system, domain=None, ideal=None): """ Return the appropriate dynamical system on Berkovich space. EXAMPLES:: sage: R.<t> = Qp(3)[] sage: f = DynamicalSystem_affine(t^2 - 3) sage: DynamicalSystem_Berkovich(f) Dynamical system of Affine Berkovich line over Cp(3) of precision 20 induced by the map Defn: Defined on coordinates by sending ((1 + O(3^20))*t) to ((1 + O(3^20))*t^2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^14 + 2*3^15 + 2*3^16 + 2*3^17 + 2*3^18 + 2*3^19 + 2*3^20 + O(3^21)) """ if not (is_Berkovich_Cp(domain) or domain is None): raise TypeError( 'domain must be a Berkovich space over Cp, not %s' % domain) if isinstance(domain, Berkovich_Cp_Affine): if not isinstance(dynamical_system, DynamicalSystem_affine): try: dynamical_system = DynamicalSystem_affine(dynamical_system) except: raise TypeError('domain was affine Berkovich space, but dynamical_system did not ' + \ 'convert to an affine dynamical system') if isinstance(domain, Berkovich_Cp_Projective): if not isinstance(dynamical_system, DynamicalSystem_projective): try: dynamical_system = DynamicalSystem_projective( dynamical_system) except: raise TypeError('domain was projective Berkovich space, but dynamical_system did not convert ' + \ 'to a projective dynamical system') if not isinstance(dynamical_system, DynamicalSystem): try: dynamical_system = DynamicalSystem(dynamical_system) except: raise TypeError( 'dynamical_system did not convert to a dynamical system') morphism_domain = dynamical_system.domain() if not isinstance(morphism_domain.base_ring(), pAdicBaseGeneric): if morphism_domain.base_ring() in NumberFields(): if domain is None and ideal is not None: if is_AffineSpace(morphism_domain): domain = Berkovich_Cp_Affine( morphism_domain.base_ring(), ideal) else: domain = Berkovich_Cp_Projective( morphism_domain, ideal) else: if ideal is not None: if ideal != domain.ideal(): raise ValueError( 'conflicting inputs for ideal and domain') else: raise ValueError('base ring of domain of dynamical_system must be p-adic or a number field ' + \ 'not %s' %morphism_domain.base_ring()) if is_AffineSpace(morphism_domain): return DynamicalSystem_Berkovich_affine(dynamical_system, domain) return DynamicalSystem_Berkovich_projective(dynamical_system, domain)
def chebyshev_polynomial(self, n, kind='first', monic=False): """ Generates an endomorphism of this affine line by a Chebyshev polynomial. Chebyshev polynomials are a sequence of recursively defined orthogonal polynomials. Chebyshev of the first kind are defined as `T_0(x) = 1`, `T_1(x) = x`, and `T_{n+1}(x) = 2xT_n(x) - T_{n-1}(x)`. Chebyshev of the second kind are defined as `U_0(x) = 1`, `U_1(x) = 2x`, and `U_{n+1}(x) = 2xU_n(x) - U_{n-1}(x)`. INPUT: - ``n`` -- a non-negative integer. - ``kind`` -- ``first`` or ``second`` specifying which kind of chebyshev the user would like to generate. Defaults to ``first``. - ``monic`` -- ``True`` or ``False`` specifying if the polynomial defining the system should be monic or not. Defaults to ``False``. OUTPUT: :class:`DynamicalSystem_affine` EXAMPLES:: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(5, 'first') Dynamical System of Affine Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x) to (16*x^5 - 20*x^3 + 5*x) :: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(3, 'second') Dynamical System of Affine Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x) to (8*x^3 - 4*x) :: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(3, 2) Traceback (most recent call last): ... ValueError: keyword 'kind' must have a value of either 'first' or 'second' :: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(-4, 'second') Traceback (most recent call last): ... ValueError: first parameter 'n' must be a non-negative integer :: sage: A = AffineSpace(QQ, 2, 'x') sage: A.chebyshev_polynomial(2) Traceback (most recent call last): ... TypeError: affine space must be of dimension 1 :: sage: A.<x> = AffineSpace(QQ, 1) sage: A.chebyshev_polynomial(7, monic=True) Dynamical System of Affine Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x) to (x^7 - 7*x^5 + 14*x^3 - 7*x) :: sage: F.<t> = FunctionField(QQ) sage: A.<x> = AffineSpace(F,1) sage: A.chebyshev_polynomial(4, monic=True) Dynamical System of Affine Space of dimension 1 over Rational function field in t over Rational Field Defn: Defined on coordinates by sending (x) to (x^4 + (-4)*x^2 + 2) """ if self.dimension_relative() != 1: raise TypeError("affine space must be of dimension 1") n = ZZ(n) if (n < 0): raise ValueError("first parameter 'n' must be a non-negative integer") from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine if kind == 'first': if monic and self.base().characteristic() != 2: f = DynamicalSystem_affine([chebyshev_T(n, self.gen(0))], domain=self) f = f.homogenize(1) f = f.conjugate(matrix([[1/ZZ(2), 0],[0, 1]])) f = f.dehomogenize(1) return f return DynamicalSystem_affine([chebyshev_T(n, self.gen(0))], domain=self) elif kind == 'second': if monic and self.base().characteristic() != 2: f = DynamicalSystem_affine([chebyshev_T(n, self.gen(0))], domain=self) f = f.homogenize(1) f = f.conjugate(matrix([[1/ZZ(2), 0],[0, 1]])) f = f.dehomogenize(1) return f return DynamicalSystem_affine([chebyshev_U(n, self.gen(0))], domain=self) else: raise ValueError("keyword 'kind' must have a value of either 'first' or 'second'")