Example #1
0
    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)
Example #2
0
    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())
Example #3
0
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]
Example #4
0
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
Example #5
0
    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'")
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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'")