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)
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)])
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)])
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
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)
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
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())
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
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)
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
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, [])