Affinoid subdomains of the Berkovich line

Let \(K\) be a field, \(v_K\) a discrete valuation on \(K\) and \(X\) the Berkovich line over \(K\), with respect to \(v_K\).

In this file we realize a Sage class which allows us to create and work with strictly affinoid subdomains of \(X\).

Let \(T\) be a Berkovich tree in \(X\) and let \(r:X\to T\) denote the canonical retraction map. Let \(S\) be a nonempty proper subset of \(V(T)\). We define \(\bar{S}\) as the union of \(S\) and of all edges connecting two points of \(S\). Then the inverse image \(U:=r^{-1}(\bar{S})\) is an affinoid subdomain of \(X\). We use the notation \(U=U(T,S)\).

We say that a Berkovich tree \(T\) supports an affinoid domain \(U\) if there exists a nonempty proper subset \(S\) of \(V(T)\) with \(U=U(T,S)\). If this is the case then \(S\) consists exactly of the vertices of \(T\) which lie in \(U\).

Given any affinoid domain \(U\), there exists a unique minimal tree \(T\) which supports \(U\). Moreover, every tree \(T'\) which contracts to \(T'\) supports \(U\) as well.

AUTHORS:

  • Stefan Wewers (2017-07-29): initial version

EXAMPLES:

<Lots and lots of examples>

TO DO:

  • more doctests
  • add missing functions: intersection, ..
  • see if we can remove some obsolete functions
  • improve point_close_to_boundary
class mclf.berkovich.affinoid_domain.AffinoidDomainOnBerkovichLine(T)

Bases: SageObject

Return the affinoid domain corresponding to the affinoid tree T.

Objects of this class represent (generic) affinoid domains on the Berkovich line.

INPUT:

  • T – an affinoid tree

OUTPUT:

The affinoid corresponding to T.

EXAMPLES:

sage: from mclf import *
sage: K = QQ
sage: vK = K.valuation(2)
sage: F.<x> = FunctionField(K)
sage: X = BerkovichLine(F, vK)

TO DO:

affinoid_subtree(xi0, is_in=None)

Return the affinoid subtree with given root.

This function is used inductively to construct a tree representing the affinoid \(U\), if such a tree is not explicitly given, and the affinoid is defined in some other way (as a rational domain, or as a union of other affinoid domains,..).

INPUT:

  • xi0 - a point of type II
  • is_in – a boolean, or None (default None)

OUTPUT: an affinoid tree with root \(\xi0\) which represents the intersection of \(U\) with \(D_{\xi_0}\), the set of points \(\geq \xi_0\) (a closed discoid with boundary point \(\xi_0\), or the full Berkovich line if \(xi_0\) is the Gauss point).

If is_in is given, we assume it is equal to the truth value of “\(\xi_0\) lies in this affinoid”. This is useful to avoid an extra test for membership.

affinoid_subtree_in_hole(eta)

Return the affinoid subtree with given root.

This is a helper function for affinoid_subtree.

INPUT:

  • eta - a point of type V

OUTPUT:

We assume that \(\eta\) represents a downward hole of this affinoid \(U\). This means that the boundary point of \(\eta\) lies in \(U\) but \(\eta\) does not. We return an affinoid tree \(T\) whose root is the boundary point of \(\eta\), representing the affinoid

\[(X\backslash D_\eta)\cup (D_\eta\cap U)`.\]
berkovich_line()

Return the Berkovich line underlying this affinoid.

boundary()

Return the Shilov boundary of the affinoid.

The Shilov boundary is a finite set of type-II-points contained in the affinoid with the property that the valuative function of every rational function which is regular on the affinoid takes a minimum on this set.

The Shilov boundary is simply the union of the boundaries of the connected components.

components()

Return the list of connected components of this affinoid.

connected_component_tree(xi0)

Return the tree of the connected component of this affinoid with given root.

INPUT:

  • xi0 – a point type II or V

OUTPUT:

If \(\xi_0\) is a point of type II, then we return an affinoid tree underlying the connected component of this affinoid \(U\) with minimal point \(\xi_0\).

It is assumed but not checked that \(\xi_0\) lies in this affinoid.

If \(\xi_0\) is of type V then we return the branch of this tree in the direction of \(\xi_0\). This has the effect of “filling in all holes” which do not lie in the open discoid \(D_{\xi_0}\). It does not correspond to the intersection with \(D_{\xi_0}\).

Note:

This is the generic algorithm for the parent class AffinoidDomainOnBerkovichLine. It is assumed that the underlying affinoid tree has already been computed. Otherwise we run into an infinite loop.

intersection(V)

Return the affinoid which is the intersection of self with V.

Not yet implemented.

intersection_with_unit_disk()

Return the intersection of this affinoid with the unit disk.

is_empty()

Return wether this affinoid is the empty set.

is_full_berkovich_line()

Return whether this affinoid is equal to the full Berkovich line.

is_in(xi)

Return whether xi lies on the affinoid.

INPUT:

  • xi – a point of type I, II or V

OUTPUT:

True if xi lies on the affinoid, False otherwise.

minimal_points(xi0=None)

Return the minimal points of this affinoid greater than a given point.

INPUT:

  • xi0 – a point of type II, or None (default None)

OUTPUT:

The list of all minimal points of this affinoid which are \(\geq \xi_0\).

number_of_components()

Return the number of connected components of ths affinoid.

point_close_to_boundary(xi0)

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: F.<x> = FunctionField(QQ)
sage: X = BerkovichLine(F, QQ.valuation(2))
sage: U = rational_domain(X, 2/x/(x+1))
sage: U
Elementary affinoid defined by
v(1/x) >= -1
v(1/(x + 1)) >= -1
<BLANKLINE>

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 = rational_domain(X, 2/(x^2+x+1))
sage: U
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.

The following raised an error in an earlier version

sage: f = (-2/25*x^6 - 4*x^5 - 1351/225*x^4 - 52/225*x^3 - 173/225*x^2 - 2/9*x + 2/3)/(x^2 + 2/3*x)
sage: h = valuative_function(X, f)
sage: U = h.affinoid_domain()
sage: U
Affinoid with 2 components:
Elementary affinoid defined by
v(x) >= 0
v(1/x) >= -1/2
Elementary affinoid defined by
v((2*x^2 + 1)/x^2) >= 2
<BLANKLINE>

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

Todo

  • Use a better strategie to find a point of minimal degree.
simplify()

Simplify this affinoid.

This only changes the internal representation by an “affinoid tree”. Very likely, this is unnecessary because the simplification has already occured when the affinoid was first constructed.

tree()

Return the Berkovich tree representing this affinoid.

union(V)

Return the affinoid which is the union of self with V.

Need new implementation.

class mclf.berkovich.affinoid_domain.AffinoidTree(X, root=None, children=None, parent=None, is_in=False)

Bases: mclf.berkovich.berkovich_trees.BerkovichTree

A marked Berkovich tree representing an affinoid subdomain.

An AffinoidTree is a Berkovich tree \(T\) in which every vertex has an additional flag “is_in” with value True or False. It represents an affinoid subdomain \(U\) in the way explained above.

INPUT:

  • X – a Berkovich line
  • root – a point on X or None (default = None)
  • children – a list of affinoid trees or None (default = None)
  • parent – an affinoid tree or none (default = None)
  • is_in – a boolean or None (default = None)

OUTPUT:

An affinoid tree on X. It is either empty (if only X is given) or it has root, parent, children and the flag is_in as given by the extra parameters.

EXAMPLES:

sage: from mclf import *
sage: K = QQ
sage: vK = K.valuation(2)
sage: F.<x> = FunctionField(K)
sage: X = BerkovichLine(F, vK)
compute_connected_components(comp_list, new_comp)

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)
connected_components(xi0=None)

Return a list of affinoid trees representing the connected components below a given point.

INPUT:

  • xi0 – a point of type II or V

OUTPUT:

A list of affinoid trees representing the connected components of the affinoid corresponding to this tree, which are \(\geq\) to the given point \(\xi_0\). If it is not given, then we ignore this condition.

Note that \(\xi_0\) may be of type V.

copy(parent=None)

Return a copy of self, force parent as parent.

WARNING! something is wrong with this function!!

holes(upward_hole=True)

Return the holes of this affinoid tree.

OUTPUT:

A list of triples \((T_1, T_2, \eta)\), where \(T_1\), \(T_2\) are subtrees of self and \(\eta\) is a point of type V, satisfying the following conditions:

  • \(T_2\) is a child of \(T_1\), or vice versa
  • the root of \(T_1\) is a boundary point of the affinoid underlying self
  • the root of \(T_2\) does not lie in the affinoid
  • \(\eta\) is the direction from the root of \(T_1\) to the root of \(T_2\)

This implies that \(\eta\) is a hole of the affinoid represented by self.

intersection_with_unit_disk()

Return the tree representing the intersection with the unit disk.

is_in(xi)

Return True if xi lies in the affinoid \(U\) represented by self.

INPUT:

  • xi – a point on the Berekovich space underlying this affinoid tree

Note that \(\xi\) may also be a point of type V.

To test this, we compute the image of xi under the retraction map onto the total space of T=self and check whether it lies on a vertex in U or on an edge connecting two vertices in U.

minimal_points(xi0=None)

Return the minimal points of the affinoid corresponding to this tree.

INPUT:

  • xi0 – a point of type II or V, or None (default None)

OUTPUT: the list of all minimal points of the affinoid corresponding to this tree, which are \(\geq \xi_0\). If \(\xi_0\) is not given, this condition is ignored.

Note that \(\xi_0\) may be of type V.

root_is_in()

Return whether the root of self lies in the affinoid.

show()

Display a graphical representation of self.

simplify()

Simplify this tree without changing the represented affinoid.

class mclf.berkovich.affinoid_domain.ClosedUnitDisk(X)

Bases: mclf.berkovich.affinoid_domain.AffinoidDomainOnBerkovichLine

Return the closed unit disk.

The closed unit disk is the affinoid on the Berkovich line with function field \(F=K(x)\) defined by the inequality

\[v(x) >= 0.\]

INPUT:

  • X – a Berkovich line

OUTPUT:

The closed unit disk inside X.

EXAMPLES:

sage: from mclf import *
sage: K = QQ
sage: vK = K.valuation(3)
sage: F.<x> = FunctionField(K)
sage: X = BerkovichLine(F, vK)
sage: ClosedUnitDisk(X)
Elementary affinoid defined by
v(x) >= 0
<BLANKLINE>
class mclf.berkovich.affinoid_domain.ElementaryAffinoidOnBerkovichLine(T)

Bases: mclf.berkovich.affinoid_domain.AffinoidDomainOnBerkovichLine

Return the elementary affinoid corresponding to a boundary list.

An “elementary affinoid” is a connected affinoid subdomain of a Berkovich line \(X\) which is the complement of a finite set of disjoint residue classes in \(X\). It can be represented by a “boundary list” as follows.

A “boundary list” is a list of lists, whose entries at the lowest level are type-V-points on \(X\). Each sublist contains the type-V-points with a common boundary point. The elementary affinoid corresponding to a “boundary list” is the complement of the residue classes corresponding to the type-V-points contained in the sublists. The set of boundary points of the type-V-points is exactly the Shilov boundary of the affinoid.

INPUT:

  • boundary_list – a list of lists containing type-V-points.

OUTPUT:

The elementare affinoid corresponding to comp_list.

TO DO:

  • we need a function which produces an (algebraic) type-I-point inside the affinoid.
inequalities()

Return the inequalities defining the elementary affinoid, as a string.

is_empty()

Return whether this affinoid is the empty set.

is_full_berkovich_line()

Return whether this affinoid is the full Beerkovich line.

class mclf.berkovich.affinoid_domain.UnionOfDomains(affinoid_list)

Bases: mclf.berkovich.affinoid_domain.AffinoidDomainOnBerkovichLine

Return the union of a list of affinoid domains.

INPUT:

  • affinoid_list - a nonempty list of affinoid domains

OUTPUT:

The union of the affinoid domains in affinoid_list

connected_component_tree(xi0)

Return the tree of the connected component of this affinoid with given root.

INPUT:

  • xi0 – a point type II or V

OUTPUT:

If \(\xi_0\) is a point of type II, then we return an affinoid tree underlying the connected component of this affinoid \(U\) with minimal point \(\xi_0\).

It is assumed but not checked that \(\xi_0\) is a minimal point of a connected component of \(U\).

If \(\xi_0\) is of type V then we return the branch of this tree in the direction of \(\xi_0\). This has the effect of ‘filling in all holes’ which do not lie in the open discoid \(D_{\xi_0}\). It does not correspond to the intersection with \(D_{\xi_0}\).

is_in(xi)

Return whether xi lies in this affinoid.

INPUT:

  • xi – a point on the Berkovich line (type V points are allowed)

OUTPUT: True if \(\xi\) lies on this affinoid.

minimal_points(xi0=None)

Return the minimal points of this affinoid greater than a given point.

INPUT:

  • xi0 – a point of type II, or None (default None)

OUTPUT:

The list of all minimal points of this affinoid which are \(\geq \xi_0\).

mclf.berkovich.affinoid_domain.all_polynomials(F, x, d)

List all polynomials in x over F of degree d.

INPUT:

  • F: a finite field F
  • x: generator of a polynomial ring over F

OUTPUT:

an iterator which list all elements of F[x] of degree d.

mclf.berkovich.affinoid_domain.rational_domain(X, f)

Return the rational domain defined by the function f.

INPUT:

  • X – a Berkovich line
  • f – a nonconstant rational function on \(X\)

OUTPUT:

The rational domain

\[U := \{ \xi \in X \mid v_\xi(f) \geq 0 \}.\]

EXAMPLES:

sage: from mclf import *
sage: F.<x> = FunctionField(QQ)
sage: X = BerkovichLine(F, QQ.valuation(2))
sage: rational_domain(X, (x^2+2)/x*(x+1)/2)
Affinoid with 2 components:
Elementary affinoid defined by
v(x^2 + 2) >= 3/2
Elementary affinoid defined by
v(x + 1) >= 1
<BLANKLINE>

f may be nonconstant:

sage: rational_domain(X, F(1/2))
The empty set
sage: rational_domain(X, F(1))
the full berkovich line
mclf.berkovich.affinoid_domain.simplify_tree_at_vertex(T, T1)

Simplify the affinoid tree at a given vertex.

This is now obsolete.

INPUT:

  • T – an affinoid tree
  • T1 – a subtree of \(T\)

OUTPUT: the affinoid tree \(T\) is simplified, starting at the subtree \(T_1\).

We check whether the root of \(T_1\) (which is a vertex of \(T\)) may be contracted, or whether \(T_1\) has a unique child which may be omitted. In the first case, we try to iterate this, if possible.

This may not simplify \(T\) as much as possible. However, if \(T\) has been obtained from a simplified

mclf.berkovich.affinoid_domain.union_of_affinoid_trees(T1, T2)

Return the tree representing the union of the affinoids with given trees.

This is now obsolete.

INPUT:

  • T1, T2 – affinoid trees

OUTPUT: the tree representing the union of the affinoids represented by \(T_1\) and \(T_2\).