예제 #1
0
    def interior(self):
        r"""
        Return the interior of this inertial component.

        OUTPUT:

        an elementary affinoid subdomain of the underlying Berkovich line.

        The **interior** of a base component is the elementary affinoid
        subdomain of the underlying Berkovich line whose canonical reduction
        is an open affine subset of this inertial component of the inertial model
        `\mathcal{X}_0`.

        It is chosen such that the canonical reduction does not contain the
        points of intersection with the other components of `\mathcal{X}_{0,s}`
        and is disjoint from the residue classes of the marked points.

        """
        if not hasattr(self, "_interior"):
            eta_list = []
            subtree = self._subtree
            xi = self._xi
            if subtree.has_parent():
                eta_list.append(
                    TypeVPointOnBerkovichLine(xi,
                                              subtree.parent().root()))
            for child in subtree.children():
                eta_list.append(TypeVPointOnBerkovichLine(xi, child.root()))
            self._interior = ElementaryAffinoidOnBerkovichLine([eta_list])
        return self._interior
def critical_residue_class(xi):
    r""" Return the critical residue class of this point.

    INPUT:

    - ``xi`` -- a point of type II on the Berkovich line

    OUTPUT: the point of type IV corresponding to the critical residue class of
    the discoid with root `\xi`, or ``None`` if it is not defined.

    The critical residue class is defined in [KunzweilerWewers20]_, Remark 3.18.

    .. NOTE::

        This method should be made obsolete by including the functionality in
        ``mclf.berkovich.berkovich_line``.

    """
    from sage.rings.infinity import Infinity
    from mclf.berkovich.type_V_points import TypeVPointOnBerkovichLine
    if not xi.type() == "II" or xi.is_gauss_point():
        return None
    v = xi.pseudovaluation_on_polynomial_ring()
    v0 = v.augmentation_chain()[1]
    if v.E() == v0.E():
        return None
    phi, _ = xi.discoid()
    xi1 = xi.berkovich_line().point_from_discoid(phi, Infinity)
    return TypeVPointOnBerkovichLine(xi, xi1)
예제 #3
0
def open_annuloid(xi0, xi1):
    r""" Return an open annuloid.

    INPUT:

    - ``xi0``, ``xi1`` -- points of type II on the Berkovich line `X`

    OUTPUT:

    the open annuloid `A` with boundary points `xi_0` and `\xi_1`.
    Note that `\xi0` and `\xi_1` are *not* contained in `D`.

    It is assumed that `\xi_0 < \xi_1`. This means that `A` cannot contain the
    Gauss point.

    EXAMPLES::

        sage: from mclf import *
        sage: F.<x> = FunctionField(QQ)
        sage: X = BerkovichLine(F, QQ.valuation(2))
        sage: xi0 = X.point_from_discoid(x-1, 1)
        sage: xi1 = X.point_from_discoid(x+1, 2)
        sage: open_annuloid(xi0, xi1)
        domain defined by
        v(x + 1) > 1
        v(1/(x + 1)) > -2


    """
    from mclf.berkovich.type_V_points import TypeVPointOnBerkovichLine
    assert xi1.type() == "II", "xi1 must be of type II"
    assert xi0.is_leq(xi1) and not xi0.is_equal(xi1), "we must have xi0 < xi1"
    phi0, s0 = TypeVPointOnBerkovichLine(xi0, xi1).open_discoid()
    phi1, s1 = xi1.discoid()
    return Domain(xi0.berkovich_line(), [], [(phi0, s0), (1 / phi1, -s1)])
예제 #4
0
def open_discoid(xi0, xi1):
    r""" Return an open discoid.

    INPUT:

    - ``xi0``, ``xi1`` -- points on the Berkovich line `X`

    OUTPUT:

    the open discoid `D` with boundary point `xi_0` which contains `\xi_1`.
    Note that `\xi0` is *not* contained in `D`.

    It is assumed that `\xi_0 < \xi_1`. This means that `D` cannot contain the
    Gauss point.

    EXAMPLES::

        sage: from mclf import *
        sage: F.<x> = FunctionField(QQ)
        sage: X = BerkovichLine(F, QQ.valuation(2))
        sage: xi0 = X.point_from_discoid(x-1, 1)
        sage: xi1 = X.point_from_discoid(x+1, 2)
        sage: open_discoid(xi0, xi1)
        domain defined by
        v(x + 1) > 1

    """
    from mclf.berkovich.type_V_points import TypeVPointOnBerkovichLine
    assert xi0.is_leq(xi1) and not xi0.is_equal(xi1), "we must have xi0 < xi1"
    phi, s = TypeVPointOnBerkovichLine(xi0, xi1).open_discoid()
    return Domain(xi0.berkovich_line(), [], [(phi, s)])
예제 #5
0
    def outgoing_edges(self):
        r"""
        Return the list of outgoing edges from this inertial component.

        Here an *edge* is a point on this inertial component where it intersects
        another component; so it corresponds to an edge on the Berkovich tree
        underlying the chosen inertial model. *Outgoing* is defined with respect
        to the natural orientation of the Berkovich tree.

        """
        subtree = self._subtree
        xi0 = self.type_II_point()
        outgoing_edges = []
        for child in subtree.children():
            xi1 = child.root()
            if xi1.type() == "II":
                eta = TypeVPointOnBerkovichLine(xi0, xi1)
                v = eta.minor_valuation()
                outgoing_edges.append(PointOnSmoothProjectiveCurve(self.component(), v))
        return outgoing_edges
예제 #6
0
    def direction(self, s):
        r""" Return the directional vector of ``self`` at position ``s``.

        If `\gamma=[\xi_0,\xi_1]` is a (simple) path, parametrized by `[s_0,s_1]`,
        and `s_0 <= s < s_1`, then the directional vector of `gamma` at 's' is
        a point of type V, with underlying point of type II `\gamma(s)`.
        It corresponds to the residue class of `\xi_1` in the discoid
        corresponding to `\gamma(s)`.
        """

        assert self._s0 <= s and s < self._s1
        return TypeVPointOnBerkovichLine(self.X(), self._phi, s,
                                         self._is_in_unit_disk)
예제 #7
0
    def direction_from_parent(self):
        r""" Return the direction from the parent.

        OUTPUT: the type V point `\eta` representing the direction from the
        root of the parent of ``self`` to the root of ``self``.

        If ``self`` has no parent, an error is raised.

        """
        from mclf.berkovich.type_V_points import TypeVPointOnBerkovichLine
        if not hasattr(self, "_direction_from_parent"):
            eta = TypeVPointOnBerkovichLine(self.parent().root(), self.root())
            self._direction_from_parent = eta
        return self._direction_from_parent
예제 #8
0
    def tangent_vector(self, t):
        r""" Return the tangent vector at a given point.

        INPUT:

        - ``t`` -- a rational number, or `\infty`

        OUTPUT:

        the type-V-point which is the tangent vector at the point
        `\gamma(t)` in the direction of `\gamma`.

        It is assumed that the point `\gamma(t)` does exist and is not the
        terminal point of `\gamma`.

        """
        from mclf.berkovich.type_V_points import TypeVPointOnBerkovichLine
        return TypeVPointOnBerkovichLine(self.point(t), self.terminal_point())
예제 #9
0
    def direction_to_parent(self):
        r""" Return the direction to the parent.

        OUTPUT: the type V point `\eta` representing the direction from the
        root of ``self`` to the root of its parent.

        If ``self`` has no parent, an error is raised.

        The direction is not well defined if the root of ``self`` is a point of
        type I. Therefore, an error is raised in this case.

        """
        from mclf.berkovich.type_V_points import TypeVPointOnBerkovichLine
        assert self.root().type() == "II",\
            "the root must be a point of type II: root = {}, parent = {}".format(self.root(), self.parent().root())
        if not hasattr(self, "_direction_to_parent"):
            eta = TypeVPointOnBerkovichLine(self.root(), self.parent().root())
            self._direction_to_parent = eta
        return self._direction_to_parent
예제 #10
0
 def __init__(self, xi1, xi2):
     from mclf.berkovich.type_V_points import TypeVPointOnBerkovichLine
     assert xi1.is_leq(xi2), "xi1 must be less or equal to xi2"
     self._initial_point = xi1
     self._terminal_point = xi2
     self._initial_point_is_gauss_point = xi1.is_gauss_point()
     if xi2.is_limit_point():
         self._is_limit_path = True
         xi2 = xi2.approximation(xi1, require_maximal_degree=True)
         # we have to make sure that the degree of the polynomial phi
         # does not increase when updating the approximation;
         # otherwise the standard parametrization of the path would change
     else:
         self._is_limit_path = False
     phi = self._make_phi(xi2)
     s2 = xi2.v(phi)
     s1 = xi1.v(phi)
     self._phi = phi
     self._s1 = s1
     self._s2 = s2
     self._initial_tangent_vector = TypeVPointOnBerkovichLine(xi1, xi2)
예제 #11
0
    def point_close_to_boundary(self, xi0):
        r"""
        Return a type-I-point inside the affinoid, close to ``xi0``.

        INPUT:

        - ``xi0`` -- a boundary point of the affinoid ``self``

        OUTPUT: a type-I-point ``xi1`` on the affinoid `U:=` ``self`` which
        is "close" to the boundary point ``xi0``.

        The latter means that ``xi1`` maps onto the irreducible components
        of the canonical reduction of `U` corresponding to ``xi0``.

        EXAMPLES::

            sage: from mclf import *
            sage: K = QQ
            sage: vK = K.valuation(2)
            sage: F.<x> = FunctionField(K)
            sage: X = BerkovichLine(F, vK)
            sage: U = RationalDomainOnBerkovichLine(X, 2/x/(x+1))
            sage: U
            Affinoid with 1 components:
            Elementary affinoid defined by
            v(1/x) >= -1
            v(1/(x + 1)) >= -1
            sage: xi0 = U.boundary()[0]
            sage: U.point_close_to_boundary(xi0)
            Point of type I on Berkovich line given by x + 2 = 0

        At the moment, our choice of point close to the boundary is not
        optimal, as the following example shows: ::

            sage: U = RationalDomainOnBerkovichLine(X, 2/(x^2+x+1))
            sage: U
            Affinoid with 1 components:
            Elementary affinoid defined by
            v(1/(x^2 + x + 1)) >= -1

            sage: xi0 = U.boundary()[0]
            sage: U.point_close_to_boundary(xi0)
            Point of type I on Berkovich line given by x^2 + 3*x + 1 = 0

        The point at infinity is also inside U and 'close to the boundary',
        and has smaller degree than the point produced above.

        .. TODO::

            Use a better strategie to find a point of minimal degree.

        """
        U = self
        T = U._T
        X = U.berkovich_line()
        F = X.function_field()
        x = F.gen()
        T0 = T.find_point(xi0)
        assert T0 != None and T0._is_in_affinoid, "xi0 is not a boundary point"
        # we only look for point of type I which are larger than xi0
        # but it may be possibleto find other points with smaller degree
        v0 = xi0.pseudovaluation_on_polynomial_ring()
        Rb = v0.residue_ring()
        psi = Rb.one()
        for T1 in T0.children():
            if not T1._is_in_affinoid:
                eta1 = TypeVPointOnBerkovichLine(xi0, T1.root())
                psi1 = eta1.minor_valuation().uniformizer()
                if psi1.denominator().is_one():
                    psi = psi * Rb(psi1.numerator())
        phib = irreducible_polynomial_prime_to(psi)
        phi = v0.lift_to_key(phib)
        if xi0.is_in_unit_disk():
            xi1 = X.point_from_discoid(phi, Infinity)
        else:
            if phi == x:
                xi1 = X.point_from_discoid(1 / x, Infinity)
            else:
                xi1 = X.point_from_discoid(
                    phi(1 / x) * x**phi.degree(), Infinity)
        assert U.is_contained_in(xi1), "error: xi1 is not contained in U"
        return xi1
예제 #12
0
    def compute_connected_components(self, comp_list, new_comp):
        r""" Compute the connected components of the represented affinoid.

        INPUT:

        - ``comp_list`` -- a list (of lists of lists)
        - ``new_comp`` -- a list (of lists)

        OUTPUT:

        - all connected components whose root is a vertex of T=``self`` are
          added to the list ``comp_list``.
        - all boundary_lists which belong to T and to the connected component
          which contains the root of T  are added to ``new_comp`` (in particular,
          if the root of T does not lie in the affinoid then the list is unchanged).

        Here a *boundary list* is a list of type-V-points which represent holes
        of the affinoid with a common boundary point. A *connected component*
        is a list of boundary lists.

        EXAMPLES::

            sage: from mclf import *
            sage: K = QQ
            sage: vK = K.valuation(2)
            sage: F.<x> = FunctionField(K)
            sage: X = BerkovichLine(F, vK)
            sage: xi0 = X.gauss_point()
            sage: xi1 = X.point_from_discoid(x+1, 1)
            sage: xi2 = X.point_from_discoid(x+1, 2)
            sage: xi3 = X.point_from_discoid(1/x, 1)

            sage: U = AffinoidTree(X)
            sage: U = U.add_points([xi0, xi2], [xi1, xi3])
            sage: U
            Affinoid tree with 4 vertices

            sage: component_list = []
            sage: U.compute_connected_components(component_list, [])
            sage: component_list
            [[[Point of type V given by residue class v(1/(x + 1)) > -2]],
            [[Point of type V given by residue class v(x + 1) > 0,
            Point of type V given by residue class v(1/x) > 0]]]

        """
        T = self
        if T._is_in_affinoid:
            if T.parent() == None or T.parent()._is_in_affinoid:
                holes = []
            else:
                # possible source of error: root of T is of type I
                holes = [
                    TypeVPointOnBerkovichLine(T.root(),
                                              T.parent().root())
                ]
            for T1 in T.children():
                if T1._is_in_affinoid:
                    T1.compute_connected_components(comp_list, new_comp)
                else:
                    holes.append(TypeVPointOnBerkovichLine(
                        T.root(), T1.root()))
                    T1.compute_connected_components(comp_list, [])
            if holes != []:
                new_comp.append(holes)

            if T.parent() == None or not T.parent()._is_in_affinoid:
                # T.root() is the root of a component
                comp_list.append(new_comp)
        else:
            # the root of T does not lie in U
            for T1 in T.children():
                T1.compute_connected_components(comp_list, [])