Cluster Pictures

class sage_cluster_pictures.cluster_pictures.BYTree(*args, **kwargs)

Bases: Graph

Construct a BY tree.

EXAMPLES:

__init__(*args, **kwargs)

See BYTree for documentation.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T
BY tree with 0 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges

TESTS:

sage: #C = BYTree()
sage: #TestSuite(C).run()
_repr_()

Return a string representation of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_yellow_vertex('v3')
sage: T.add_yellow_vertex('v4')
sage: T.add_yellow_edge(('v4', 'v1', 1))
sage: T.add_yellow_edge(('v4', 'v2', 1))
sage: T.add_blue_edge(('v3', 'v4', 2))
sage: T
BY tree with 2 yellow vertices, 2 blue vertices, 2 yellow edges, 1 blue edges
add_blue_edge(a)

Adds a blue edge to the BY tree.

INPUT:

  • a - triple of vertices and a weight.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_yellow_vertex('v3')
sage: T.add_yellow_vertex('v4')
sage: T.add_yellow_edge(('v4', 'v1', 1))
sage: T.add_yellow_edge(('v4', 'v2', 1))
sage: T.add_blue_edge(('v3', 'v4', 2))
sage: T
BY tree with 2 yellow vertices, 2 blue vertices, 2 yellow edges, 1 blue edges
add_blue_edges(B)

Adds a sequence of blue edges B to self.

INPUT:

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertices(['b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7'])
sage: T.add_yellow_vertex('Y')
sage: T.add_blue_edges([('b1', 'Y', 2), ('b2', 'Y', 2), ('b5', 'Y', 1), ('b6', 'Y', 4), ('b3', 'b4', 1), ('b7', 'b4', 1)])
sage: T
BY tree with 1 yellow vertices, 7 blue vertices, 0 yellow edges, 6 blue edges
add_blue_vertex(label, genus=0)

Adds a blue vertex to the BY tree.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 0)
sage: T
BY tree with 0 yellow vertices, 1 blue vertices, 0 yellow edges, 0 blue edges
sage: T.add_blue_vertex('v2', 1)
sage: T
BY tree with 0 yellow vertices, 2 blue vertices, 0 yellow edges, 0 blue edges
sage: T.add_blue_vertex('v3')
sage: T.genus('v3')
0
add_blue_vertices(labels, genera=None)

Adds a sequence of blue vertices given by labels to self, optionally with genera.

INPUT:

  • labels - an iterable containing valid inputs for add_blue_vertex().

  • genera (optional) - an iterable containing the same number of inputs as labels, specifying a genus for each vertex.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertices(['b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7'])
sage: T.add_yellow_vertex('Y')
sage: T.add_blue_edges([('b1', 'Y', 2), ('b2', 'Y', 2), ('b5', 'Y', 1), ('b6', 'Y', 4), ('b3', 'b4', 1), ('b7', 'b4', 1)])
sage: T
BY tree with 1 yellow vertices, 7 blue vertices, 0 yellow edges, 6 blue edges
sage: T.add_blue_vertices(['b8', 'b9'], [1, 2])
sage: T
BY tree with 1 yellow vertices, 9 blue vertices, 0 yellow edges, 6 blue edges
add_yellow_edge(a)

Adds a yellow edge to the BY tree.

INPUT:

  • a - triple of vertices and a weight.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_yellow_vertex('v3')
sage: T.add_yellow_vertex('v4')
sage: T.add_yellow_edge(('v4', 'v1', 1))
sage: T.add_yellow_edge(('v4', 'v2', 1))
sage: T.add_blue_edge(('v3', 'v4', 2))
sage: T
BY tree with 2 yellow vertices, 2 blue vertices, 2 yellow edges, 1 blue edges
add_yellow_edges(Y)

Adds a sequence of yellow edges Y to self.

INPUT:

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree(name="Stick person")
sage: T.add_blue_vertices(['b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7'])
sage: T.add_yellow_vertex('Y')
sage: T.add_yellow_edges([('b1', 'Y', 2), ('b2', 'Y', 2), ('b5', 'Y', 1), ('b6', 'Y', 4), ('b3', 'b4', 1), ('b7', 'b4', 1)])
sage: T.add_blue_edge(('b6', 'b4', 1))
sage: T
BY tree with 1 yellow vertices, 7 blue vertices, 6 yellow edges, 1 blue edges
add_yellow_vertex(label)

Adds a yellow vertex to the BY tree.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_yellow_vertex('v1')
sage: T
BY tree with 1 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges
sage: T.add_yellow_vertex('v2')
sage: T
BY tree with 2 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges
add_yellow_vertices(labels)

Adds a sequence of yellow vertices given by labels to self.

INPUT:

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_yellow_vertices(['b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7'])
sage: T.add_yellow_vertex('Y')
sage: T
BY tree with 8 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges
blue_edges()

Return the list of yellow vertices of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_yellow_vertex('v3')
sage: T.add_yellow_vertex('v4')
sage: T.add_yellow_edge(('v4', 'v1', 1))
sage: T.add_yellow_edge(('v4', 'v2', 1))
sage: T.add_blue_edge(('v3', 'v4', 2))
sage: T.blue_edges()
[('v3', 'v4', 2)]
blue_subgraph()

Return the blue subgraph of self.

This is the subgraph consisting of blue edges and vertices. Note that by assumption no blue edge is incident to a yellow vertex.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: T.blue_subgraph()
BY tree with 0 yellow vertices, 2 blue vertices, 0 yellow edges, 0 blue edges
blue_vertices()

Return the list of blue vertices of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 0)
sage: T.add_blue_vertex('v2', 1)
sage: T.add_yellow_vertex('v3')
sage: T.blue_vertices()
['v1', 'v2']
centre()

Gives the centre of a BY tree as a list of one or two vertices. This also outputs the W function on the vertices.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: f = (x^3 - 7^15)*(x^2-7^6)*(x^3-7^3)
sage: BYT = Cluster.from_polynomial(f).BY_tree()
sage: BYT.centre()
([Cluster with 5 roots and 3 children],
 {Cluster with 3 roots and 3 children: 3,
  Cluster with 5 roots and 3 children: 8,
  Cluster with 8 roots and 4 children: 3})
sage: f = 7*(x^2+1)*(x^2+36)*(x^2+64)
sage: BYT = Cluster.from_polynomial(f).BY_tree()
sage: BYT.centre()
([Cluster with 3 roots and 3 children, Cluster with 3 roots and 3 children],
 {Cluster with 3 roots and 3 children: 3,
  Cluster with 3 roots and 3 children: 3})
contract_odd_order_subtree(F)

Returns a BY tree obtained from self by contracting the subtree on which F acts with odd order into a blue vertex, along with the induced BYTreeIsomorphism of F on the new tree. Note that this mutates the original graph.

degree_ge_three_vertices()

Return all degree \ge 3 vertices of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster, BYTree
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: T = Cluster.from_curve(H).BY_tree()
sage: T.degree_ge_three_vertices()
[Cluster with 4 roots and 2 children]
sage: K = Qp(5)
sage: x = polygen(K)
sage: R = Cluster.from_polynomial((x^4-5^4)*(x+1)*(x+2))
sage: T = R.BY_tree()
sage: T.degree_ge_three_vertices()
[]
sage: T = BYTree()
sage: T.add_blue_vertex(1)
sage: T.add_blue_vertex(2)
sage: T.add_blue_vertex(3)
sage: T.add_blue_vertex(4)
sage: T.add_yellow_vertex(5)
sage: T.add_yellow_edge((1, 5, 1))
sage: T.add_yellow_edge((2, 5, 1))
sage: T.add_yellow_edge((3, 5, 1))
sage: T.add_yellow_edge((4, 5, 1))
sage: T.degree_ge_three_vertices()
[5]
delete_vertex(label)

Deletes a vertex and all incident edges from the BY tree.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_yellow_vertex('v1')
sage: T.add_yellow_vertex('v2')
sage: T.add_blue_edge(('v1','v2',2))
sage: T.delete_vertex('v1')
sage: T
BY tree with 1 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges
sage: T = BYTree()
sage: T.add_yellow_vertex('v1')
sage: T.add_yellow_vertex('v2')
sage: T.add_blue_edge(('v2','v1',2))
sage: T.delete_vertex('v1')
sage: T
BY tree with 1 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges
sage: T = BYTree()
sage: T.add_yellow_vertex('v1')
sage: T.add_yellow_vertex('v2')
sage: T.add_yellow_edge(('v1','v2',2))
sage: T.delete_vertex('v1')
sage: T
BY tree with 1 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges
sage: T = BYTree()
sage: T.add_yellow_vertex('v1')
sage: T.add_yellow_vertex('v2')
sage: T.add_yellow_edge(('v2','v1',2))
sage: T.delete_vertex('v1')
sage: T
BY tree with 1 yellow vertices, 0 blue vertices, 0 yellow edges, 0 blue edges
genus(vertex)

Return the genus of a vertex.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 0)
sage: T.genus('v1')
0
sage: T.add_blue_vertex('v2', 1)
sage: T.genus('v2')
1
sage: T.add_yellow_vertex('v3')
sage: T.genus('v3')
0
graphplot(**options)
is_blue(e)

Check if an edge e of self is blue.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_blue_vertex('v3', 2)
sage: T.add_yellow_edge(('v2', 'v1', 1))
sage: T.is_blue(T.edges(sort=False)[0])
False
sage: T.add_blue_edge(('v3', 'v1', 1))
sage: T.is_blue(T.edges_incident('v3')[0])
True
is_yellow(e)

Check if an edge e of self is yellow.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_blue_vertex('v3', 2)
sage: T.add_yellow_edge(('v2', 'v1', 1))
sage: T.is_yellow(T.edges(sort=False)[0])
True
sage: T.add_blue_edge(('v3', 'v1', 1))
sage: T.is_yellow(T.edges_incident('v3')[0])
False
minimal_discriminant(frob=None)

Computes the valuation of the minimal discriminant of the BY tree. In some cases, it is required to give the Frobenius automorphism.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: f = (x^3 - 7^15)*(x^2-7^6)*(x^3-7^3)
sage: BYT = Cluster.from_polynomial(f).BY_tree()
sage: BYT.minimal_discriminant()
24

Example 15.7:

sage: f = 7*(x^2+1)*(x^2+36)*(x^2+64)
sage: BYT, F = Cluster.from_polynomial(f).BY_tree(with_frob = True)
sage: BYT.minimal_discriminant(frob=F)
22

Example 15.6:

sage: p = 11
sage: x = polygen(Qp(p, 200))
sage: C = Cluster.from_polynomial(p*(x^2-p^5)*(x^3-p^3)*((x-1)^3-p^9))
sage: T,F = C.BY_tree(with_frob=True)
sage: T.minimal_discriminant(frob=F)
27
multiway_cuts(vertices)

Return all unordered n-tuples of edges of self such that their removal disconnects the n + 1 vertices provided.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: G = BYTree()
sage: G.add_yellow_vertex(1)
sage: G.add_yellow_vertex(2)
sage: G.add_yellow_edge((1,2,1))
sage: list(G.multiway_cuts([1,2]))
[[(1, 2, 1)]]
sage: G.add_yellow_vertex(3)
sage: G.add_yellow_edge((2,3,1))
sage: list(G.multiway_cuts([1,2,3]))
[[(1, 2, 1), (2, 3, 1)]]
sage: list(G.multiway_cuts([1,3]))
[[(1, 2, 1)], [(2, 3, 1)]]
sage: G.add_yellow_edge((1,3,1))
sage: list(G.multiway_cuts([1,3]))
[]
sage: list(G.multiway_cuts([1,2,3]))
[]
sage: list(G.multiway_cuts([1,2,3]))
[]
sage: G.add_yellow_vertex(4)
sage: G.add_yellow_edge((2,4,1))
sage: list(G.multiway_cuts([1,2,3]))
[]
sage: list(G.multiway_cuts([1,2,4]))
[]
quotient(F)

Quotient self by the automorphism F.

EXAMPLES:

Example 4.11:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qq(11^3, 200, names="a")
sage: a = K.gen()
sage: z = K.teichmuller(10*a^2 + 7*a + 8)
sage: x = polygen(K)
sage: f = prod(x-a for a in [0,1,2,z-11,z+11,z^2 - 11, z^2 +11, z^4 -11, z^4 + 11]).map_coefficients(lambda x: x.trace()/3, new_base_ring=Qp(11, 200))
sage: R = Cluster.from_polynomial(f)
sage: T, F = R.BY_tree(with_frob=True)
sage: T.quotient(F)
BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: R = Cluster.from_curve(H)
sage: T, F = R.BY_tree(with_frob=True)
sage: T.quotient(F)
BY tree with 1 yellow vertices, 3 blue vertices, 3 yellow edges, 0 blue edges
sign_vertex(component)

Return the vertex of self used to compute the sign of the yellow component component in an automorphism.

This is any vertex in the closure of component, which is either yellow or not the parent of a cluster \mathfrak t with v_{\mathfrak t} also in this closure.

NOTE:

This depends on parent child relationships of vertices, so does not work for arbitrary BY trees, only those coming from clusters.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster, BYTree
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: R = Cluster.from_curve(H)
sage: T = R.BY_tree()
sage: T.sign_vertex([T.yellow_edges()[0]])
Cluster with 4 roots and 2 children
subgraph(*args, **options)

Return the subgraph containing the given vertices and edges.

If either vertices or edges are not specified, they are assumed to be all vertices or edges. If edges are not specified, returns the subgraph induced by the vertices.

INPUT:

  • inplace – boolean (default: False); using inplace=True will simply delete the extra vertices and edges from the current graph. This will modify the graph.

  • vertices – a single vertex or an iterable container of vertices, e.g. a list, set, graph, file or numeric array. If not passed (i.e., None), defaults to the entire graph.

  • edges – as with vertices, edges can be a single edge or an iterable container of edges (e.g., a list, set, file, numeric array, etc.). By default (edges=None), all edges are assumed and the returned graph is an induced subgraph. In the case of multiple edges, specifying an edge as (u,v) means to keep all edges (u,v), regardless of the label.

  • vertex_property – function (default: None); a function that inputs a vertex and outputs a boolean value, i.e., a vertex v in vertices is kept if vertex_property(v) == True

  • edge_property – function (default: None); a function that inputs an edge and outputs a boolean value, i.e., a edge e in edges is kept if edge_property(e) == True

  • algorithm – string (default: None); one of the following:

    • If algorithm="delete" or inplace=True, then the graph is constructed by deleting edges and vertices

    • If algorithm="add", then the graph is constructed by building a new graph from the appropriate vertices and edges. Implies inplace=False.

    • If algorithm=None, then the algorithm is chosen based on the number of vertices in the subgraph.

  • immutable – boolean (default: None); whether to create a mutable/immutable subgraph. immutable=None (default) means that the graph and its subgraph will behave the same way.

EXAMPLES:

sage: G = graphs.CompleteGraph(9)
sage: H = G.subgraph([0, 1, 2]); H
Subgraph of (Complete graph): Graph on 3 vertices
sage: G
Complete graph: Graph on 9 vertices
sage: J = G.subgraph(edges=[(0, 1)])
sage: J.edges(sort=True, labels=False)
[(0, 1)]
sage: set(J) == set(G)
True
sage: G.subgraph([0, 1, 2], inplace=True); G
Subgraph of (Complete graph): Graph on 3 vertices
sage: G.subgraph() == G
True
sage: D = digraphs.Complete(9)
sage: H = D.subgraph([0, 1, 2]); H
Subgraph of (Complete digraph): Digraph on 3 vertices
sage: H = D.subgraph(edges=[(0, 1), (0, 2)])
sage: H.edges(sort=True, labels=False)
[(0, 1), (0, 2)]
sage: set(H) == set(D)
True
sage: D
Complete digraph: Digraph on 9 vertices
sage: D.subgraph([0, 1, 2], inplace=True); D
Subgraph of (Complete digraph): Digraph on 3 vertices
sage: D.subgraph() == D
True

A more complicated example involving multiple edges and labels:

sage: G = Graph(multiedges=True, sparse=True)
sage: G.add_edges([(0, 1, 'a'), (0, 1, 'b'), (1, 0, 'c'), (0, 2, 'd'), (0, 2, 'e'), (2, 0, 'f'), (1, 2, 'g')])
sage: G.subgraph(edges=[(0, 1), (0, 2,'d'), (0, 2, 'not in graph')]).edges(sort=True)
[(0, 1, 'a'), (0, 1, 'b'), (0, 1, 'c'), (0, 2, 'd')]
sage: J = G.subgraph(vertices=[0, 1], edges=[(0, 1, 'a'), (0, 2, 'c')])
sage: J.edges(sort=True)
[(0, 1, 'a')]
sage: J.vertices(sort=True)
[0, 1]
sage: G.subgraph(vertices=G) == G
True
sage: D = DiGraph(multiedges=True, sparse=True)
sage: D.add_edges([(0, 1, 'a'), (0, 1, 'b'), (1, 0, 'c'), (0, 2, 'd'), (0, 2, 'e'), (2, 0, 'f'), (1, 2, 'g')])
sage: D.subgraph(edges=[(0, 1), (0, 2, 'd'), (0, 2, 'not in graph')]).edges(sort=True)
[(0, 1, 'a'), (0, 1, 'b'), (0, 2, 'd')]
sage: H = D.subgraph(vertices=[0, 1], edges=[(0, 1, 'a'), (0, 2, 'c')])
sage: H.edges(sort=True)
[(0, 1, 'a')]
sage: H.vertices(sort=True)
[0, 1]

Using the property arguments:

sage: P = graphs.PetersenGraph()
sage: S = P.subgraph(vertex_property=lambda v: not (v % 2))
sage: S.vertices(sort=True)
[0, 2, 4, 6, 8]
sage: C = graphs.CubeGraph(2)
sage: S = C.subgraph(edge_property=(lambda e: e[0][0] == e[1][0]))
sage: C.edges(sort=True)
[('00', '01', None), ('00', '10', None), ('01', '11', None), ('10', '11', None)]
sage: S.edges(sort=True)
[('00', '01', None), ('10', '11', None)]

The algorithm is not specified, then a reasonable choice is made for speed:

sage: g = graphs.PathGraph(1000)
sage: g.subgraph(list(range(10)))  # uses the 'add' algorithm
Subgraph of (Path graph): Graph on 10 vertices

TESTS:

The appropriate properties are preserved:

sage: g = graphs.PathGraph(10)
sage: g.is_planar(set_embedding=True)
True
sage: g.set_vertices({v: 'v%d'%v for v in g})
sage: h = g.subgraph([3..5])
sage: sorted(h.get_pos().keys())
[3, 4, 5]
sage: h.get_vertices()
{3: 'v3', 4: 'v4', 5: 'v5'}
tamagawa_number(F)

Compute the Tamagawa number of self with respect to the automorphism F.

INPUT:

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, Cluster, BYTreeIsomorphism
sage: K = Qp(5,150)
sage: x  = polygen(K)
sage: R = Cluster.from_polynomial((x^4-5^4)*(x+1)*(x+2))
sage: T, F = R.BY_tree(with_frob=True)
sage: T.tamagawa_number(F)
2

We can use symbols even as in Betts 3.3.1:

sage: a, b, c = var('a b c', domain="positive")
sage: R = Cluster([[oo, a/2, 0,  0,  0,  0,   0,  0],
....:             [a/2, oo, 0,  0,  0,  0,   0,  0],
....:             [0,  0,  oo, b/2, 0,  0,   0,  0],
....:             [0,  0,  b/2, oo, 0,  0,   0,  0],
....:             [0,  0,  0,  0,  oo, c/2,  0,  0],
....:             [0,  0,  0,  0,  c/2, oo,  0,  0],
....:             [0,  0,  0,  0,  0,  0,  oo, c/2],
....:             [0,  0,  0,  0,  0,  0,  c/2, oo], ])
sage: R
Cluster with 8 roots and 4 children
sage: C1,C2 = [r for r in R.children() if r.depth() == c/2]
sage: A = [r for r in R.children() if r.depth() == a/2][0]
sage: B = [r for r in R.children() if r.depth() == b/2][0]
sage: T = R.BY_tree()
sage: T
BY tree with 1 yellow vertices, 4 blue vertices, 4 yellow edges, 0 blue edges
sage: F = BYTreeIsomorphism(T, T,
....:     lambda x: {A:A, B:B, C1:C2, C2:C1, R:R}[x],
....:     lambda Y: 1)
sage: T.tamagawa_number(F)
2*a*b + a*c + b*c
sage: F = BYTreeIsomorphism(T, T,
....:     lambda x: {A:A, B:B, C1:C2, C2:C1, R:R}[x],
....:     lambda Y: -1)
sage: #T.tamagawa_number(F) if only TODO

Example 10.5:

sage: a, b, c = var('a b c', domain="positive")
sage: R = Cluster([[oo, a/2, 0,  0,  0,  0, ],
....:              [a/2, oo, 0,  0,  0,  0, ],
....:              [0,  0,  oo, b/2, 0,  0, ],
....:              [0,  0,  b/2, oo, 0,  0, ],
....:              [0,  0,  0,  0,  oo, c/2,],
....:              [0,  0,  0,  0,  c/2, oo,],
....:            ])
sage: R
Cluster with 6 roots and 3 children
sage: C = [r for r in R.children() if r.depth() == c/2][0]
sage: A = [r for r in R.children() if r.depth() == a/2][0]
sage: B = [r for r in R.children() if r.depth() == b/2][0]
sage: T = R.BY_tree()
sage: T
BY tree with 1 yellow vertices, 3 blue vertices, 3 yellow edges, 0 blue edges
sage: F = BYTreeIsomorphism(T, T,
....:     lambda x: {A:A, B:B, C:C, R:R}[x],
....:     lambda Y: 1)
sage: T.tamagawa_number(F)
a*b + a*c + b*c

Example 10.7:

sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: w = 2
sage: a = 7
sage: u = 2
sage: z = 2
sage: f = ((x^(2)+1)^(2)-p^(u))*((x-1)^(2)-p^(z))*(x-p^(w / 2))*(x-p^(w / 2+2))*((x^(2)+p^(w+4))^(2)-p^(2*(w+4)+a))
sage: R = Cluster.from_polynomial(f)
sage: T, F = R.BY_tree(with_frob=True)
sage: F2 = BYTreeIsomorphism(T, T, F, lambda y:-1)
sage: T.tamagawa_number(F2) == a*u*gcd(z, 2)
True
sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: w = 6
sage: a = 12
sage: u = 2
sage: z = 3
sage: f = ((x^(2)+1)^(2)-p^(u))*((x-1)^(2)-p^(z))*(x-p^(w / 2))*(x-p^(w / 2+2))*((x^(2)+p^(w+4))^(2)-p^(2*(w+4)+a))
sage: R = Cluster.from_polynomial(f)
sage: T, F = R.BY_tree(with_frob=True)
sage: F2 = BYTreeIsomorphism(T, T, F, lambda y:-1)
sage: T.tamagawa_number(F2) == a*u*gcd(z, 2)
True
sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: w = 6
sage: a = 12
sage: u = 2
sage: z = 4
sage: f = ((x^(2)+1)^(2)-p^(u))*((x-1)^(2)-p^(z))*(x-p^(w / 2))*(x-p^(w / 2+2))*((x^(2)+p^(w+4))^(2)-p^(2*(w+4)+a))
sage: R = Cluster.from_polynomial(f)
sage: T, F = R.BY_tree(with_frob=True)
sage: F2 = BYTreeIsomorphism(T, T, F, lambda y:-1)
sage: T.tamagawa_number(F2) == a*u*gcd(z, 2)
True
validate()

Checks if self is a valid BY tree, i.e. it is a tree, all vertices / edges are coloured blue or yellow, all edges have a positive weight, all vertices have nonnegative genus, and: (1) yellow vertices have genus 0, degree \ge 3, and only yellow edges; (2) blue vertices of genus 0 have at least one yellow edge; (3) at every vertex, 2g(v) + 2 \ge \# blue edges at v.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, Cluster
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_yellow_vertex('v3')
sage: T.add_yellow_vertex('v4')
sage: T.add_yellow_edge(('v4', 'v1', 1))
sage: T.add_yellow_edge(('v4', 'v2', 1))
sage: T.add_blue_edge(('v3', 'v4', 2))
sage: T.validate()
False

User guide section 10, example 10.4

sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: T.validate()
True

User guide section 10, example 10.5

sage: T = BYTree()
sage: T.add_blue_vertex('v1')
sage: T.add_blue_vertex('v2')
sage: T.add_blue_vertex('v3')
sage: T.add_yellow_vertex('v4')
sage: T.add_blue_vertex('v5')
sage: T.add_blue_vertex('v6')
sage: T.add_blue_vertex('v7')
sage: T.add_blue_vertex('v8')
sage: T.add_yellow_edge(('v1', 'v4', 2))
sage: T.add_yellow_edge(('v2', 'v4', 2))
sage: T.add_yellow_edge(('v6', 'v4', 2))
sage: T.add_yellow_edge(('v7', 'v4', 2))
sage: T.add_blue_edge(('v7', 'v5', 2))
sage: T.add_yellow_edge(('v3', 'v5', 2))
sage: T.add_yellow_edge(('v8', 'v5', 2))
sage: T.validate()
True
sage: p = 3
sage: K = Qp(p)
sage: C = Cluster.from_roots([K(1), K(p), K(2*p), K(2*p + p^2), K(2*p + 2*p^2), K(2*p + 2*p^2+p^3)])
sage: C.BY_tree().validate()
True
weight(v)

Return the weight of a vertex of self, defined by w: V\left(self\right) \rightarrow \mathbb{Z}

w(v)=\left\{\begin{array}{ll}2 g(v)+2-\text { #blue edges at } v & \text { if } v \text { is blue, } \\ 0 & \text { if } v \text { is yellow }\end{array}\right.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster, BYTree
sage: p = 11
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial(p*(x^2 - p^5)*(x^3 - p^2)*((x-1)^3 - p^9))
sage: T = R.BY_tree()
sage: s3 = R.children()[0]
sage: s1 = R.children()[1].children()[3]
sage: T.weight(s1)
2
sage: T.weight(s3)
3
yellow_components()

Return the set of yellow components of self, i.e. the connected components of self \smallsetminus self.blue_subgraph(), as a list of yellow edges in the component.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: T.yellow_components()
[[('v1', 'v2', 2)]]
yellow_edges()

Return the list of yellow edges of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 2)
sage: T.add_yellow_vertex('v3')
sage: T.add_yellow_vertex('v4')
sage: T.add_yellow_edge(('v4', 'v1', 1))
sage: T.add_yellow_edge(('v4', 'v2', 1))
sage: T.add_blue_edge(('v3', 'v4', 2))
sage: T.yellow_edges()
[('v1', 'v4', 1), ('v2', 'v4', 1)]
yellow_vertices()

Return the list of yellow vertices of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 0)
sage: T.add_yellow_vertex('v3')
sage: T.add_blue_vertex('v2', 1)
sage: T.add_yellow_vertex('v4')
sage: T.yellow_vertices()
['v3', 'v4']
class sage_cluster_pictures.cluster_pictures.BYTreeIsomorphism(A, B, f, eps)

Bases: SageObject

Isomorphisms between BY trees, these are graph isomorphisms that preserve the BY tree structure, and additionally assign an sign to each yellow component of the tree.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, BYTreeIsomorphism
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: f = lambda v: {'v1':'v2','v2':'v1'}[v]
sage: eps = lambda c: -1
sage: F = BYTreeIsomorphism(T, T, f, eps)
sage: F
BY tree isomorphism from BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges to BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
__call__(inp)

Return the image of the vertex or edge under self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, BYTreeIsomorphism
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: f = lambda v: {'v1':'v2','v2':'v1'}[v]
sage: eps = lambda c: -1
sage: F = BYTreeIsomorphism(T, T, f, eps)
sage: F('v2')
'v1'
sage: F('v1')
'v2'
sage: F(T.edges(sort=False)[0])
('v2', 'v1', 2)
__init__(A, B, f, eps)

See BYTree for documentation.

INPUT:

  • A, B - BY trees

  • f - a function from vertices of A to vertices of B,

    assumed to be bijective, preserve the colouring and genera, and that the induced map on edges preserves colouring.

  • eps - a function from yellow components of A to \{\pm1\}.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, BYTreeIsomorphism
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: f = lambda v: {'v1':'v2','v2':'v1'}[v]
sage: eps = lambda c: -1
sage: F = BYTreeIsomorphism(T, T, f, eps)
sage: F
BY tree isomorphism from BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges to BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
__weakref__

list of weak references to the object

_repr_()

Return a string representation of self.

OUTPUT:

  • a string

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, BYTreeIsomorphism
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: f = lambda v: {'v1':'v2','v2':'v1'}[v]
sage: eps = lambda c: -1
sage: F = BYTreeIsomorphism(T, T, f, eps)
sage: F
BY tree isomorphism from BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges to BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
_test()

Check that self satisfies the properties assumed of it.

codomain()

Return the codomain of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, BYTreeIsomorphism
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: f = lambda v: {'v1':'v2','v2':'v1'}[v]
sage: eps = lambda c: -1
sage: F = BYTreeIsomorphism(T, T, f, eps)
sage: F.codomain()
BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
domain()

Return the domain of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, BYTreeIsomorphism
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: f = lambda v: {'v1':'v2','v2':'v1'}[v]
sage: eps = lambda c: -1
sage: F = BYTreeIsomorphism(T, T, f, eps)
sage: F.domain()
BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
epsilon(inp)

Evaluate the sign function \epsilon associated to self at the component inp.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import BYTree, BYTreeIsomorphism
sage: T = BYTree()
sage: T.add_blue_vertex('v1', 1)
sage: T.add_blue_vertex('v2', 0)
sage: T.add_yellow_edge(('v1', 'v2', 2))
sage: f = lambda v: {'v1':'v2','v2':'v1'}[v]
sage: eps = lambda c: -1
sage: F = BYTreeIsomorphism(T, T, f, eps)
sage: F.epsilon(T.edges(sort=False))
-1
sage: F.epsilon(T.edges(sort=False)[0])
-1
class sage_cluster_pictures.cluster_pictures.Cluster(M=[], parent=None, top=None, roots=None, depth=None, leading_coefficient=None)

Bases: SageObject

Construct a cluster picture.

INPUT:

  • M – a matrix of valuations of differences of roots

EXAMPLES:

Example 1.2 from M2D2:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: C = Cluster.from_curve(H)
sage: print(ascii_art(C))
((* * *)_2 (* (* * *)_2)_1)_0
BY_tree(with_frob=False, check=True)

Constructs the BY tree associated to the cluster picture, and optionally the associated BYTreeIsomorphism to Frobenius acting on the cluster.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster, BYTree
sage: K = Qp(5)
sage: R = Cluster.from_roots([K(1), K(6), K(2), K(7)])
sage: R.BY_tree()
BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges

Example 4.9 from the users guide:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: T = R.BY_tree()
sage: T
BY tree with 1 yellow vertices, 3 blue vertices, 3 yellow edges, 0 blue edges
sage: sorted([e[2] for e in T.edges(sort=False)])
[3, 6, 10]

Example 4.11 from the users guide:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qq(11^3, 200, names="a")
sage: a = K.gen()
sage: z = K.teichmuller(10*a^2 + 7*a + 8)
sage: x = polygen(K)
sage: f = prod(x-a for a in [0,1,2,z-11,z+11,z^2 - 11, z^2 +11, z^4 -11, z^4 + 11]).map_coefficients(lambda x: x.trace()/3, new_base_ring=Qp(11, 200))
sage: H = HyperellipticCurve(f)
sage: R = Cluster.from_curve(H)
sage: T = R.BY_tree()
sage: T
BY tree with 0 yellow vertices, 4 blue vertices, 3 yellow edges, 0 blue edges
sage: [e[2] for e in T.edges(sort=False)]
[2, 2, 2]
sage: sorted([T.genus(v) for v in T.vertices(sort=False)])
[0, 0, 0, 1]
__eq__(other)

Return self==value.

__hash__()

File: sage/structure/sage_object.pyx (starting at line 363)

Not implemented: mutable objects inherit from this class

EXAMPLES:

sage: hash(SageObject())
Traceback (most recent call last):
...
TypeError: <... 'sage.structure.sage_object.SageObject'> is not hashable
__init__(M=[], parent=None, top=None, roots=None, depth=None, leading_coefficient=None)

See Cluster for documentation.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: C = Cluster([\
           [20, 2, 0],\
           [2, 20, 0],\
           [0, 0, 20],\
        ])
sage: C
Cluster with 3 roots and 2 children

sage: C = Cluster(Matrix(ZZ, 4, 4,[\
           [20, 1, 0, 0 ],\
           [1, 20, 0, 0 ],\
           [0, 0, 20, 1 ],\
           [0, 0, 1, 20 ],\
        ]))
sage: C
Cluster with 4 roots and 2 children
sage: #TestSuite(C).run()
__lt__(other)

Return self<value.

__ne__(other)

Return self!=value.

__weakref__

list of weak references to the object

_ascii_art_()

Return an ascii art representation of self.

EXAMPLES:

Example 3.7 from the users guide:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve(x*(x-1)*(x-2)*(x-3)*(x-5)*(x-8)*(x-13))
sage: R = Cluster.from_curve(H)
sage: print(ascii_art(R))
(* * (* *)_1 (* * *)_1)_0
sage: p = 7
sage: K = Qp(p,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x-1)*(x-2)*(x-p)*(x-2*p)*(x-3*p)*(x-4*p))
sage: R = Cluster.from_curve(H)
sage: print(ascii_art(R))
(* * (* * * *)_1)_0
sage: H = HyperellipticCurve(H.hyperelliptic_polynomials()[0](1/x).numerator())
sage: R = Cluster.from_curve(H)
sage: print(ascii_art(R))
(* * * * (* *)_1)_-1
_latex_()

Return a LaTeX representation of self.

OUTPUT:

  • a string

_repr_()

Return a string representation of self.

OUTPUT:

  • a string

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: Cluster.from_curve(H)
Cluster with 7 roots and 2 children
_unicode_art_()

Return a unicode art representation of self.

all_automorphisms()

Specialisation of all_automorphisms() to self = other and always include roots.

all_descendants()

Return (an iterator over) all descendent clusters of self (including self).

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10), K(35), K(135)])
sage: list(C.all_descendants())
[Cluster with 5 roots and 2 children,
 Cluster with 1 roots and 0 children,
 Cluster with 4 roots and 2 children,
 Cluster with 1 roots and 0 children,
 Cluster with 3 roots and 2 children,
 Cluster with 1 roots and 0 children,
 Cluster with 2 roots and 2 children,
 Cluster with 1 roots and 0 children,
 Cluster with 1 roots and 0 children]
all_isomorphisms(other, include_roots=False)

Construct all isomorphisms from self to other. The parameter ‘include_roots’ indicates whether the clusters of size 1 are also considered.

EXAMPLES:

Example with some symmetry:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: C = Cluster.from_picture('((* *)_1/2 (* *)_1/2 (* *)_1/2)_0')
sage: isoms = C.all_isomorphisms(C)
sage: isoms2 = C.all_isomorphisms(C, include_roots=True)
sage: len(isoms)
6
sage: len(isoms2)
48

An example without depths:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: C = Cluster.from_picture('((* * *) (* * *))')
sage: isoms = C.all_isomorphisms(C)
sage: isoms2 = C.all_isomorphisms(C, include_roots=True)
sage: len(isoms)
2
sage: len(isoms2)
72

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: C = Cluster.from_picture('((* * *)_1 (* * *)_1/2)_0')
sage: isoms = C.all_isomorphisms(C)
sage: isoms2 = C.all_isomorphisms(C, include_roots=True)
sage: len(isoms)
1
sage: len(isoms2)
36
static ascii_to_lmfdb_label(s)

The lmfdb label of the cluster picture, this is defined only for clusters with depths as an alternative representation of the ascii_art.

  • c represents an opening bracket

  • ~ is used in place of /

  • _ closes the previous open bracket and the following number (with negatives and possibly /) is the (relative) depth

  • a number in brackets denotes the number of roots there

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import *
sage: Cluster.ascii_to_lmfdb_label("(● ● (● ● ●)_1/12 (● ● ● (● ●)_1)_1/12)_-1/6")
'c2c3_1~12c3c2_1_1~12_-1~6'
sage: Cluster.ascii_to_lmfdb_label("(* * (* * *)_1/12 (* * * (* *)_1)_1/12)_-1/6")
'c2c3_1~12c3c2_1_1~12_-1~6'
center()

A choice of center of self, i.e. some z_{\mathfrak{s}} \in K^{\mathrm{sep}} with \min _{r \in \mathfrak{s}} v\left(z_{\mathfrak{s}}-r\right)=d_{\mathfrak{s}}.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5)
sage: C = Cluster(Matrix(ZZ, 4, 4,[\
           [20, 1, 0, 0 ],\
           [1, 20, 0, 0 ],\
           [0, 0, 20, 1 ],\
           [0, 0, 1, 20 ],\
        ]))
sage: C.roots()
Traceback (most recent call last):
...
AttributeError: This cluster does not have root information stored.
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.center()
0
sage: C.is_center(C.center())
True

sage: C = Cluster.from_roots([K(1), K(2), K(10), K(35)])
sage: C.center()
0
sage: C.is_center(C.center())
True

sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: a = R.children()[2]
sage: t1 = a.children()[0]
sage: t2 = a.children()[1]
sage: R.is_center(R.center())
True
sage: a.is_center(a.center())
True
sage: t1.is_center(t1.center())
True
sage: t2.is_center(t2.center())
True
sage: R.center()
0
sage: a.center()
0
sage: t1.center()
0
sage: t2.center() == 7^6
True
children()

Returns all children of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.children()
[Cluster with 1 roots and 0 children, Cluster with 2 roots and 2 children]
component_special_fibre()

Compute the component of the special fibre corresponding to self.

EXAMPLES:

Example 6.9

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(5,150))
sage: H = HyperellipticCurve(x*((x+1)^2 - 5)*(x+4)*(x-6))
sage: R = Cluster.from_curve(H)
sage: R.component_special_fibre()
Hyperelliptic Curve over Finite Field of size 5 defined by y^2 = x^3 + 2*x^2 + x
sage: R.red(5)
0

Example 6.10

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve((x^4-p^8)*(x^2+2*x+1-p^2)*(x^2-2*x+1-p))
sage: R = Cluster.from_curve(H)
sage: R.component_special_fibre()
Hyperelliptic Curve over Finite Field of size 5 defined by y^2 = x^2 + 3*x + 1
sage: R.children()[-1].component_special_fibre()
Hyperelliptic Curve over Finite Field of size 5 defined by y^2 = x^4 + 4
conductor_exponent()

Compute the conductor exponent of the Jacobian of the curve associated to self.

EXAMPLES:

Lmfdb curve 2520.c.680400.1:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial( -300*x^6 - 259*x^4 - 74*x^2 - 7)
sage: R.conductor_exponent()
1
curve_genus()

The genus of the curve on the generic fibre, g such that number of roots is 2g+1 or 2g+2.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.curve_genus()
1
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10), K(25)])
sage: C.curve_genus()
2
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10), K(25), K(50)])
sage: C.curve_genus()
2
depth()

Return the depth of the cluster.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.depth()
0
sage: C = Cluster.from_roots([K(5), K(25), K(50)])
sage: C.depth()
1
sage: C = Cluster.from_roots([K(1), K(6), K(26), K(126)])
sage: C.children()[1].children()[1].depth()
3

Example 3.6 from the users guide:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: R.depth()
1
sage: R.children()[2].depth()
6
sage: R.children()[2].relative_depth()
5
sage: R.children()[2].children()[0].depth()
15/2
sage: R.children()[2].children()[1].depth()
9
discriminant()

Computes the valuation of the discriminant of the curve. This is only implemented for semi-stable curves.

EXAMPLES:

Example 1.2 from M2D2:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 3
sage: x = polygen(Qp(p,200))
sage: R = Cluster.from_polynomial((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: R.discriminant()
36

Example 15.6:

sage: p = 11
sage: x = polygen(Qp(p, 200))
sage: C = Cluster.from_polynomial(p*(x^2-p^5)*(x^3-p^3)*((x-1)^3-p^9))
sage: C.discriminant()
55

Example 15.7:

sage: x = polygen(Qp(7,150))
sage: f = 7*(x^2+1)*(x^2+36)*(x^2+64)
sage: C = Cluster.from_polynomial(f)
sage: C.discriminant()
22

Lmfdb curve 336.a.172032.1:

sage: x = polygen(Qp(3, 200))
sage: C = Cluster.from_polynomial(-3*x^6 + 62*x^4 - 299*x^2 - 224)
sage: C.discriminant()
1
dual_graph(with_gal=False, check=True)

Constructs the dual graph of the special fibre of the minimal regular model associated to self.

EXAMPLES:

Example 6.9

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(5,150))
sage: H = HyperellipticCurve(x*((x+1)^2 - 5)*(x+4)*(x-6))
sage: R = Cluster.from_curve(H)
sage: R.dual_graph()
Dual graph of Cluster with 5 roots and 3 children: Looped multi-graph on 2 vertices
sage: len(R.dual_graph().edges(sort=False))
3

Old example 6.6

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve((x+5)*(x-4)*(x-13)*x*(x-3)*(x+4))
sage: R = Cluster.from_curve(H)
sage: R.dual_graph()
Dual graph of Cluster with 6 roots and 3 children: Looped multi-graph on 3 vertices

Old example 6.10

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve((x^4-p^8)*(x^2+2*x+1-p^2)*(x^2-2*x+1-p))
sage: R = Cluster.from_curve(H)
sage: R.dual_graph()
Dual graph of Cluster with 8 roots and 3 children: Looped multi-graph on 6 vertices

Example 1.2 from M2D2

sage: p = 3
sage: x = polygen(Qp(p,200))
sage: R = Cluster.from_polynomial((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: G = R.dual_graph()
sage: G
Dual graph of Cluster with 7 roots and 2 children: Looped multi-graph on 4 vertices
sage: len(G.edges(sort=False))
4

Example 8.4:

sage: p = 5
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(x*(x-p)*(x-2*p)*(x-3*p)*(x-1)*(x-2)*(x-3)*(x-4))
sage: R = Cluster.from_curve(H)
sage: G = R.dual_graph()
sage: G
Dual graph of Cluster with 8 roots and 5 children: Looped multi-graph on 2 vertices
sage: len(G.edges(sort=False))
2

Example 8.5:

sage: p = 5
sage: x = polygen(Qp(p,150))
sage: n = 3
sage: H = HyperellipticCurve((x-1)*(x-2)*(x-3)*(x-p^2)*(x-p^(n+2))*(x+p^(n+2)))
sage: R = Cluster.from_curve(H)
sage: G = R.dual_graph()
sage: G # 2n + 1 vertices
Dual graph of Cluster with 6 roots and 4 children: Looped multi-graph on 7 vertices
sage: len(G.edges(sort=False)) == 2*n + 1
True

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: n = 1
sage: H = HyperellipticCurve((x-1)*(x-2)*(x-3)*(x-p^2)*(x-p^(n+2))*(x+p^(n+2)))
sage: R = Cluster.from_curve(H)
sage: G = R.dual_graph()
sage: G # 2n + 1 vertices
Dual graph of Cluster with 6 roots and 4 children: Looped multi-graph on 3 vertices
sage: len(G.edges(sort=False)) == 2*n + 1
True

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: n = 5
sage: H = HyperellipticCurve((x-1)*(x-2)*(x-3)*(x-p^2)*(x-p^(n+2))*(x+p^(n+2)))
sage: R = Cluster.from_curve(H)
sage: G = R.dual_graph()
sage: G # 2n + 1 vertices
Dual graph of Cluster with 6 roots and 4 children: Looped multi-graph on 11 vertices
sage: len(G.edges(sort=False)) == 2*n + 1
True

Example 13.7 (ii) (multiple twins)

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 23
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(((x^2+1)^2 - 2*x^2*p^4 + 2*p^4 + p^8)*(x-2)*(x-3))
sage: C = Cluster.from_curve(H)
sage: C.dual_graph()
Dual graph of Cluster with 6 roots and 4 children: Looped multi-graph on 7 vertices

A non-principal top cluster:

sage: K = Qp(5,200)
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x-5)*x*(x-3)*(x-3-25)*(x-3-2*25)*(x-3-3*25))
sage: C
Cluster with 6 roots and 2 children
sage: C.dual_graph()
Dual graph of Cluster with 6 roots and 2 children: Looped multi-graph on 6 vertices
sage: C = Cluster.from_polynomial((x-15)*(x-10)*(x-5)*x*(x-3)*(x-3-25)*(x-3-2*25)*(x-3-3*25))
sage: C.dual_graph()
Dual graph of Cluster with 8 roots and 2 children: Looped multi-graph on 6 vertices

Another test:

sage: K = Qp(3,200)
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x-1)*(x-6)*(x-5)*(x-10)*(x-19)*(x-28))
sage: G = C.dual_graph()
sage: G
Dual graph of Cluster with 6 roots and 3 children: Looped multi-graph on 2 vertices
sage: len(G.edges(sort=False)) == 3
True

Plots:

epsilon(sigma, sigmaK, frobenius_reduction=False)

\frac{\sigma\left(\theta_{s^{*}}\right)}{\theta_{\left(\sigma_{\mathfrak{s}}\right)^{*}}} \bmod \mathfrak{m} \in\{\pm 1\} \text { if } \mathfrak{s} \text { even or cotwin, } \epsilon_{\mathfrak{s}}(\sigma)=0 \text { otherwise }

INPUT:

  • sigma an element of Galois acting on clusters

  • sigmaK an element of Galois as a map K \to K

  • optional parameter frobenius_reduction to force the calculation using reductions, assuming the action on the uniformiser is trvial

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5)
sage: C = Cluster.from_roots([K(1), K(5), K(10)], leading_coefficient=1)
sage: C.epsilon(lambda x: x, lambda x: x)
1
sage: C = Cluster.from_roots([K(1), K(2), K(10), K(35)], leading_coefficient=1)
sage: C.children()[0].epsilon(lambda x: x, lambda x: x)
0

Example 3.7 from the users guide:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve(x*(x-1)*(x-2)*(x-3)*(x-8))
sage: R = Cluster.from_curve(H)
sage: t = R.children()[-1]
sage: t.epsilon(lambda x: x.frobenius(), R.field_frobenius())
1

Example 4.11:

sage: K = Qq(11^3, 200, names="a")
sage: a = K.gen()
sage: z = K.teichmuller(10*a^2 + 7*a + 8)
sage: x = polygen(K)
sage: f = prod(x-a for a in [0,1,2,z-11,z+11,z^2 - 11, z^2 +11, z^4 -11, z^4 + 11]).map_coefficients(lambda x: x.trace()/3, new_base_ring=Qp(11, 200))
sage: H = HyperellipticCurve(f)
sage: R = Cluster.from_curve(H)
sage: t1 = R.children()[3]
sage: t2 = R.children()[4]
sage: t4 = R.children()[5]
sage: # t1.center().frobenius() == t2.center() these are true in some order
sage: # t2.center().frobenius() == t4.center()
sage: # t4.center().frobenius() == t1.center()
sage: #t1.epsilon(lambda x: x.frobenius(), R.field_frobenius()) 1
sage: # t2.epsilon(lambda x: x.frobenius(), R.field_frobenius()) 1
sage: # t4.epsilon(lambda x: x.frobenius(), R.field_frobenius()) -1
field_frobenius()

Return the frobenius morphism of the base field of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x-1)*(x-6)*(x-26)*(x-126))
sage: C.field_frobenius()
Identity endomorphism of 5-adic Field with capped relative precision 150
sage: C.children()[0].field_frobenius()
Identity endomorphism of 5-adic Field with capped relative precision 150

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x^2+1)*(x-1)*x)
sage: C.field_frobenius()
Frobenius endomorphism on 7-adic Unramified Extension Field in b defined by x^2 + 6*x + 3 lifting b |--> b^7 on the residue field
sage: C.children()[0].field_frobenius()
Frobenius endomorphism on 7-adic Unramified Extension Field in b defined by x^2 + 6*x + 3 lifting b |--> b^7 on the residue field
field_inertia()

Return the inertia morphism of the base field of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x-1)*(x-6)*(x-26)*(x-126))
sage: C.field_inertia()
Identity endomorphism of 5-adic Field with capped relative precision 150
frobenius()

The action of Frobenius.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: C = Cluster.from_curve(H)
sage: C.children()[0].frobenius() == C.children()[1]
True

Even if we have no roots the Galois action is sometimes implicit in the combinatorial structure of the cluster:

sage: C = Cluster.from_picture("(* (* *))")
sage: C.frobenius() == C
True
sage: C.children()[0].frobenius() == C.children()[0]
True
sage: C.children()[1].frobenius() == C.children()[1]
True
sage: C = Cluster.from_picture("((* *)_1 (* *)_2)_0")
sage: C.frobenius() == C
True
sage: C.children()[0].frobenius() == C.children()[0]
True
sage: C.children()[1].frobenius() == C.children()[1]
True

If the cluster has root data this should be relatively fast:

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(x^(12) + 36*x^(11) + 534*x^(10) + 4094*x^9 + 17667*x^8 + 44018*x^7 + 61093*x^6 + 44018*x^5 + 17667*x^4 + 4094*x^3 + 534*x^2 + 36*x + 1)
sage: C = Cluster.from_curve(H)
sage: C.children()[-1].frobenius() == C.children()[-1]
True
classmethod from_BY_tree(T, R)

Construct a Cluster from a (rooted) BY tree

EXAMPLES:

Going from cluster to tree and back is not a bijection:

sage: from sage_cluster_pictures.cluster_pictures import *
sage: R = Cluster.from_picture("((* *)_4 *)_1")
sage: T = R.BY_tree()
sage: T
BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
sage: R2 = Cluster.from_BY_tree(T, R)
sage: R2
Cluster with 4 roots and 3 children
sage: T2 = R2.BY_tree()
sage: T2
BY tree with 0 yellow vertices, 2 blue vertices, 1 yellow edges, 0 blue edges
classmethod from_curve(H)

Construct a Cluster from a hyperelliptic curve.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: Cluster.from_curve(H)
Cluster with 7 roots and 2 children
classmethod from_lmfdb_label(S)

Construct a Cluster from an lmfdb label.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import *
sage: unicode_art(Cluster.from_lmfdb_label("c2c3c2_1_1~12c3_1~12_-1~6"))
(● ● (● ● ●)_1/12 (● ● ● (● ●)_1)_1/12)_-1/6
classmethod from_picture(S, leading_coefficient=None)

Construct a Cluster from an ascii art cluster picture with depths.

The recommended format is shown in the examples below, however the code will ignore all characters except digits brackets and asterisks, so extra annotations can be included but will currently be ignored.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: Cluster.from_picture("((* *)_1 *)_0")
Cluster with 3 roots and 2 children

A slighly more complicated example:

sage: x = polygen(Qp(3))
sage: F = (1 + 2*3 + 2*3^2 + 2*3^3 + 3^4 + 2*3^6 + 2*3^7 + 3^8 + 2*3^9 + 3^11 + 3^12 + 3^15 + 2*3^16 + 2*3^19 + O(3^20))*x^6 + (2 + 3 + 2*3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 2*3^8 + 3^9 + 2*3^10 + 2*3^11 + 3^12 + 3^13 + 3^15 + 3^16 + 2*3^17 + 2*3^19 + O(3^20))*x^5 + (3 + 2*3^2 + 2*3^3 + 2*3^4 + 3^6 + 3^7 + 3^10 + 3^12 + 2*3^13 + 2*3^14 + 3^15 + 3^16 + 2*3^17 + 3^18 + 3^19 + 3^20 + O(3^21))*x^4 + (3^3 + 2*3^4 + 3^6 + 2*3^10 + 2*3^11 + 3^12 + 3^13 + 3^14 + 2*3^15 + 2*3^16 + 3^18 + 3^19 + 2*3^20 + 2*3^21 + 2*3^22 + O(3^23))*x^3 + (2 + 3 + 3^2 + 2*3^3 + 3^4 + 2*3^7 + 3^9 + 3^11 + 3^12 + 3^13 + 2*3^14 + 2*3^15 + 3^16 + 2*3^17 + 2*3^18 + 2*3^19 + O(3^20))*x^2 + (3 + 2*3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 3^8 + 2*3^9 + 3^10 + 3^11 + 3^12 + 3^13 + 2*3^14 + 3^15 + 3^16 + 2*3^17 + 2*3^18 + 3^19 + 3^20 + O(3^21))*x + 2 + 2*3^4 + 2*3^6 + 3^8 + 3^9 + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^16 + 3^17 + 2*3^18 + 3^19 + O(3^20)
sage: C = Cluster.from_polynomial(F)
sage: ascii_art(C)
(* * ((* *)_1/4 (* *)_1/4)_1/2)_0
sage: ascii_art(Cluster.from_picture(ascii_art(C)))
(* * ((* *)_1/4 (* *)_1/4)_1/2)_0

Unicode input and output:

sage: unicode_art(Cluster.from_picture('(● ● ((● ●)_1/4 (● ●)_1/4)_1/2)_0'))
(● ● ((● ●)_1/4 (● ●)_1/4)_1/2)_0

Negative valuations:

sage: ascii_art(Cluster.from_picture('(* (* *)_15/2)_-2'))
(* (* *)_15/2)_-2

Without depths:

sage: ascii_art(Cluster.from_picture('(* (* *))'))
(* (* *))
classmethod from_polynomial(f, factors=None)

Construct a Cluster from a polynomial.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: Cluster.from_polynomial((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
Cluster with 7 roots and 2 children
classmethod from_polynomial_without_roots(f, infinity=100000, factors=None)

Construct a Cluster from a polynomial without computing its root. This has the advantage that it also works for wild extensions, but you lose the root data.

NOTE:

The following input is currently broken

x = polygen(Zp(3)) F = (3 + 3^2 + 3^3 + 2*3^4 + 3^5 + 3^6 + 3^9 + 3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^14 + 3^16 + 3^17 + 2*3^18 + O(3^21))*x^3 + (2*3^2 + 3^3 + 3^4 + 2*3^6 + 2*3^8 + 2*3^9 + 3^10 + 3^11 + 3^13 + 3^14 + 2*3^16 + 3^17 + 2*3^18 + O(3^22))*x^2 + (3 + 3^2 + 3^3 + 2*3^4 + 3^5 + 3^6 + 3^7 + 3^10 + 3^12 + 2*3^15 + 2*3^16 + 2*3^18 + 3^19 + 3^20 + O(3^21))*x + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 3^8 + 2*3^11 + 3^12 + 3^13 + 3^14 + 3^15 + 3^17 + 2*3^18 + 3^19 + O(3^21) Cluster.from_polynomial_without_roots(F)

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 23
sage: x = polygen(Qp(p,200))
sage: f = x*(x-p^2)*(x-p)*(x-p-p^3)*(x-1)*(x-1-p^4)*(x-p-1)*(x-p-1-p^5)
sage: Cluster.from_polynomial_without_roots(f)._ascii_art_()
(((* *)_1 (* *)_2)_1 ((* *)_3 (* *)_4)_1)_0
sage: x = polygen(Qp(5,400))
sage: R = Cluster.from_polynomial_without_roots(x^5 + 256)
sage: R
Cluster with 5 roots and 5 children
classmethod from_roots(roots, leading_coefficient=None, phi=None, rho=None)

Construct a Cluster from a list of roots.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5)
sage: Cluster.from_roots([K(1), K(5), K(10)])
Cluster with 3 roots and 2 children
genus()

The genus of self, g such that number of odd children is 2g+1 or 2g+2.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.genus()
0
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10), K(25)])
sage: C.genus()
1
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10), K(25), K(50)])
sage: C.genus()
0
has_good_reduction(K)

Tests whether the curve associated to self has good reduction over K.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(3,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve(x^6 - 27)
sage: C = Cluster.from_curve(H)
sage: C.has_good_reduction(K)
False
sage: H = HyperellipticCurve(x^3 + 1)
sage: C = Cluster.from_curve(H)
sage: C.has_good_reduction(K)
False
sage: H = HyperellipticCurve(x^3 + x + 1)
sage: C = Cluster.from_curve(H)
sage: C.has_good_reduction(K)
True
has_potentially_good_reduction()

Tests whether the curve associated to self has potentially good reduction.

EXAMPLES:

Example 5.10

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve(x^6 - 27)
sage: C = Cluster.from_curve(H)
sage: C.has_potentially_good_reduction()
False

Example 5.8

sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: C = Cluster.from_curve(H)
sage: C.has_potentially_good_reduction()
False
has_potentially_totally_toric_reduction()

Checks whether the curve associated to self’s Jacobian has potentially totally toric reduction.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: C = Cluster.from_curve(H)
sage: C.has_potentially_totally_toric_reduction()
True
homology_of_special_fibre()

Computes H1 together with a Frobenius action if possible

EXAMPLES:

TODO what is this example 13.7 (ii) not sure on correctness:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 23
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(((x^2+1)^2 - 2*x^2*p^4 + 2*p^4 + p^8)*(x-2)*(x-3))
sage: C = Cluster.from_curve(H)
sage: H1, M, frob = C.homology_of_special_fibre() #TODO check M
sage: L = [b for b in H1.basis()]
sage: frob(L[0]) == -L[1]
True
sage: frob(L[1]) == -L[0]
True

Example 8.4:

sage: p = 5
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(x*(x-p)*(x-2*p)*(x-3*p)*(x-1)*(x-2)*(x-3)*(x-4))
sage: R = Cluster.from_curve(H)
sage: s = R.children()[-1]
sage: H1, M, frob = R.homology_of_special_fibre()
sage: H1
Free module generated by {Cluster with 4 roots and 4 children} over Integer Ring
sage: M
[2]
sage: L = next(b for b in H1.basis())
sage: frob(L) == L
True
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(x*(x-p)*(x-2*p)*(x-3*p)*(x-1)*(x-2)*(x-3)*(x-4))
sage: R = Cluster.from_curve(H)
sage: s = R.children()[-1]
sage: H1, M, frob = R.homology_of_special_fibre()
sage: H1
Free module generated by {Cluster with 4 roots and 4 children} over Integer Ring
sage: M
[2]
sage: L = next(b for b in H1.basis())
sage: frob(L) == -L
True

Example 8.5:

sage: p = 5
sage: x = polygen(Qp(p,150))
sage: n = 3
sage: H = HyperellipticCurve((x-1)*(x-2)*(x-3)*(x-p^2)*(x-p^(n+2))*(x+p^(n+2)))
sage: R = Cluster.from_curve(H)
sage: R.homology_of_special_fibre() # TODO double check lengths
(Free module generated by {Cluster with 2 roots and 2 children} over Integer Ring,
 [6],
 Generic endomorphism of Free module generated by {Cluster with 2 roots and 2 children} over Integer Ring)

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: n = 1
sage: H = HyperellipticCurve((x-1)*(x-2)*(x-3)*(x-p^2)*(x-p^(n+2))*(x+p^(n+2)))
sage: R = Cluster.from_curve(H)
sage: R.homology_of_special_fibre()
(Free module generated by {Cluster with 2 roots and 2 children} over Integer Ring,
 [2],
 Generic endomorphism of Free module generated by {Cluster with 2 roots and 2 children} over Integer Ring)

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: n = 5
sage: H = HyperellipticCurve((x-1)*(x-2)*(x-3)*(x-p^2)*(x-p^(n+2))*(x+p^(n+2)))
sage: R = Cluster.from_curve(H)
sage: R.homology_of_special_fibre()
(Free module generated by {Cluster with 2 roots and 2 children} over Integer Ring,
 [10],
 Generic endomorphism of Free module generated by {Cluster with 2 roots and 2 children} over Integer Ring)

Example 8.6:

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: a = 1
sage: b = 2
sage: c = 2
sage: H = HyperellipticCurve((x^2-p^a)*((x-1)^2-p^b)*(x^2*p^c - 1))
sage: R = Cluster.from_curve(H)
sage: H, M, frob = R.homology_of_special_fibre()
sage: H
Free module generated by {Cluster with 2 roots and 2 children, Cluster with 2 roots and 2 children} over Integer Ring
sage: M
[3 2]
[2 4]
sage: L = [b for b in H.basis()]
sage: frob(L[0]) == -L[0]
True
sage: frob(L[1]) == -L[1]
True

sage: p = 5
sage: x = polygen(Qp(p,150))
sage: a = 3
sage: b = 1
sage: c = 3
sage: H = HyperellipticCurve((x^2-p^a)*((x-1)^2-p^b)*(x^2*p^c - 1))
sage: R = Cluster.from_curve(H)
sage: H, M, frob = R.homology_of_special_fibre()
sage: H
Free module generated by {Cluster with 2 roots and 2 children, Cluster with 2 roots and 2 children} over Integer Ring
sage: M
[4 3]
[3 6]
sage: L = [b for b in H.basis()]
sage: frob(L[0]) == L[0]
True
sage: frob(L[1]) == L[1]
True

Check that Lmfdb curve 196.a.21952.1 completes:

sage: K = Qp(7,200)
sage: x = polygen(K)
sage: H = HyperellipticCurve(x.parent()([4, 12, 25, 30, 25, 12, 4]))
sage: R = Cluster.from_curve(H)
sage: R.homology_of_special_fibre()
(
                                                   [2 1]
Free module generated by {0, 1} over Integer Ring, [1 2], Generic endomorphism of Free module generated by {0, 1} over Integer Ring
)
inertia()

The action of a generator of the inertia group.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: C = Cluster.from_curve(H)
sage: C.children()[0].inertia() == C.children()[1]
False

If the cluster has root data this should be relatively fast:

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(x^(12) + 36*x^(11) + 534*x^(10) + 4094*x^9 + 17667*x^8 + 44018*x^7 + 61093*x^6 + 44018*x^5 + 17667*x^4 + 4094*x^3 + 534*x^2 + 36*x + 1)
sage: C = Cluster.from_curve(H)
sage: C.children()[-1].inertia() == C.children()[-1]
True
integral_determinant_valuation()

v\left(\frac{\omega^{\circ}}{\omega}\right)

EXAMPLES:

Example 14.8:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial(((x-7^2)^2+1)*((x-2 * 7^2)^2+1)*((x-3 * 7^2)^2+1)*(x^2-1))
sage: R.integral_determinant_valuation()
2

Example 14.9:

sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: f = 7^2*(x^6 - 1)
sage: n = 1
sage: R = Cluster.from_polynomial(7^(6*n)*f(x/7^n))
sage: R.integral_determinant_valuation()
5
sage: n = 2
sage: R = Cluster.from_polynomial(7^(6*n)*f(x/7^n))
sage: R.integral_determinant_valuation()
8

Kunzweiler: Differential forms example 1.5 (slightly corrected equation):

sage: p = 5
sage: x = polygen(Qp(p, 300))
sage: R = Cluster.from_polynomial(x*(x-p^6)*(x-2*p^6)*(x-p^4)*(x-2*p^4)*(x-3*p^4)*(x-1)*(x-1-p^8)*(x-1-2*p^8)*(x-1-3*p^8)*(x-2)*(x-3))
sage: R.integral_determinant_valuation()
21

Only works for semistable curves

sage: p = 13
sage: x = polygen(Qp(p, 300))
sage: R = Cluster.from_polynomial(x^6 + 4*x^5 + 6*x^4 + 2*x^3 + x^2 + 2*x + 1)
sage: R.integral_determinant_valuation()
Traceback (most recent call last):
...
NotImplementedError
integral_differential_lattice()

(\omega^{\circ}_i)_i as a lattice inside the standard basis differentials (x^i \mathrm d x/ y)_i.

EXAMPLES:

Example 14.8:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial(((x-7^2)^2+1)*((x-2 * 7^2)^2+1)*((x-3 * 7^2)^2+1)*(x^2-1))
sage: R.integral_differential_lattice()
[2*7 + O(7^201)              0              0]
[      O(7^197) 2*7 + O(7^201)              0]
[  2 + O(7^196)              0   2 + O(7^200)]

Example 14.9:

sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: f = 7^2*(x^6 - 1)
sage: n = 1
sage: R = Cluster.from_polynomial(7^(6*n)*f(x/7^n))
sage: R.integral_differential_lattice()
[7^3 + O(7^203)              0]
[             0 7^2 + O(7^202)]
sage: n = 2
sage: R = Cluster.from_polynomial(7^(6*n)*f(x/7^n))
sage: R.integral_differential_lattice()
[7^5 + O(7^205)              0]
[             0 7^3 + O(7^203)]

Kunzweiler: Differential forms example 1.5 (slightly corrected equation):

sage: p = 5
sage: x = polygen(Qp(p, 300))
sage: R = Cluster.from_polynomial(x*(x-p^6)*(x-2*p^6)*(x-p^4)*(x-2*p^4)*(x-3*p^4)*(x-1)*(x-1-p^8)*(x-1-2*p^8)*(x-1-3*p^8)*(x-2)*(x-3))
sage: R.integral_differential_lattice().determinant()
5^21 + O(5^321)

Only works for semistable curves

sage: p = 13
sage: x = polygen(Qp(p, 300))
sage: R = Cluster.from_polynomial(x^6 + 4*x^5 + 6*x^4 + 2*x^3 + x^2 + 2*x + 1)
sage: R.integral_differential_lattice()
Traceback (most recent call last):
...
NotImplementedError
is_center(z)

Checks if a point z is a center of the cluster, i.e. \min_{r\in self}v(z-r) = ` ``self.depth()`

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_center(C.center())
True

sage: C = Cluster.from_roots([K(1), K(2), K(10), K(35)])
sage: C.is_center(K(1/5))
False
sage: C = Cluster.from_roots([K(1)])
sage: C.is_center(K(1 + 5))
False

TESTS:

sage: p = 5
sage: K = Qp(p,150)
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: for s in C.all_descendants():
....:     assert s.is_center(s.center())
is_cotwin()

Check if self is a cotwin.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_cotwin()
True
sage: C.children()[0].is_cotwin()
False
sage: C.children()[1].is_cotwin()
False
sage: C = Cluster.from_roots([K(1), K(5), K(10), K(35)])
sage: C.is_cotwin()
False
sage: C.children()[0].is_cotwin()
False
sage: C.children()[1].is_cotwin()
True
sage: C = Cluster.from_roots([K(1), K(2), K(10), K(35)])
sage: C.is_cotwin()
True
sage: C.children()[0].is_cotwin()
False
sage: C.children()[1].is_cotwin()
False
is_even()

Check if self is even.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_even()
False
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10)])
sage: C.is_even()
True
sage: C = Cluster.from_roots([K(1), K(6), K(5), K(10)])
sage: C.is_even()
True
is_minimal()

Return whether or not the defining equation corresponding to self  is minimal. Theorem 16.2 and 16.3 in the users guide.

EXAMPLES:

Example 16.5:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial((x^2-1)*(x^3-p)*((x-2)^3 - p^7))
sage: R.is_minimal()
True

Example 16.6:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial(p^2*(x-1/p^2)*(x^5-1))
sage: R.is_minimal()
True

Example 16.7:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 11
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial((x^3-p^15)*(x^2-p^6)*(x^3 - p^3))
sage: R.is_minimal()
False
sage: R = Cluster.from_polynomial(((x^3-p^15)*(x^2-p^6)*(x^3 - p^3))(p^3*x)/p^18)
sage: R.is_minimal()
True

Random examples:

sage: p = 5
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial((x-1)*(x-2)*(x-3))
sage: R.is_minimal()
True
is_odd()

Check if self is odd.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_odd()
True
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10)])
sage: C.is_odd()
False
sage: C = Cluster.from_roots([K(1), K(6), K(5), K(10)])
sage: C.is_odd()
False
is_principal()

Check if self is principal, i.e. if |\mathfrak{s}|\ne 2 g+2 it is proper, not a twin or a cotwin and if |\mathfrak{s}|=2 g+2 then \mathfrak{s} has \geq 3 children.

EXAMPLES:

Not-proper:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(3,150)
sage: C = Cluster.from_roots([K(1), K(3), K(6)])
sage: C.children()[0].is_principal()
False

Cotwins:

sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10), K(35)])
sage: C.children()[1].is_principal()
False
sage: C = Cluster.from_roots([K(1), K(2), K(10), K(35)])
sage: C.is_principal()
False
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_principal()
False

A twin:

sage: C.children()[1].is_principal()
False

Not enough children:

sage: C = Cluster.from_roots([K(1), K(6), K(5), K(10)])
sage: C.is_principal()
False

Example 3.6 from the users guide:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: R.is_principal()
False
sage: a = R.children()[2]
sage: a.is_principal()
True
sage: all(not t.is_principal() for t in R.all_descendants() if t != a and t != R)
True
is_proper()

Returns whether or not self is proper, i.e. has size at least 2.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_proper()
True
sage: C.children()[1].is_proper()
True
sage: C.children()[0].is_proper()
False
is_semistable(K)

Tests whether the curve associated to self is semi-stable over K.

EXAMPLES:

Example 5.8

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: C = Cluster.from_curve(H)
sage: C.is_semistable(Qp(7))
True

Example 5.10:

sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve(x^6 - 27)
sage: C = Cluster.from_curve(H)
sage: C.is_semistable(Qp(3))
False

We don’t need roots necessarily and it doesn’t matter the field:

sage: C = Cluster.from_picture("((* * *)_1/2 *)_0")
sage: C.is_semistable(Qp(5))
False

We still don’t need roots, just a leading coefficient in some cases:

sage: C = Cluster.from_picture("(* * *)_0", leading_coefficient=Qp(5)(5))
sage: C.is_semistable(Qp(5))
False
is_top_cluster()

Check if self is the top cluster for the picture.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_top_cluster()
True
sage: C.children()[0].is_top_cluster()
False
is_translation_integral()

Return whether or not the curve corresponding to self  is integral (up to translation of x). Theorem 16.1 in the users guide.

EXAMPLES:

Example 16.4:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial(p*(x-1/p^2)*((x-1/p^2)^3 - p^9)*(x-1/p^2 - 1/p))
sage: R.is_translation_integral()
True

Random examples:

sage: p = 5
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial((x-1)*(x-2)*(x-3))
sage: R.is_translation_integral()
True

sage: p = 5
sage: x = polygen(Qp(p, 200))
sage: R = Cluster.from_polynomial((x-1)*(x^2-1/p))
sage: R.is_translation_integral()
False
is_twin()

Check if self is a twin.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_twin()
False
sage: C.children()[0].is_twin()
False
sage: C.children()[1].is_twin()
True
is_ubereven()

Check if self is übereven.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.is_ubereven()
False
sage: C.children()[0].is_ubereven()
False
sage: C.children()[1].is_ubereven()
False
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10)])
sage: C.is_ubereven()
False
sage: C = Cluster.from_roots([K(1), K(6), K(5), K(10)])
sage: C.is_ubereven()
True
jacobian_has_good_reduction(K)

Tests whether the curve associated to self’s Jacobian has good reduction over K.

EXAMPLES:

Example 5.10

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(3,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve(x^6 - 27)
sage: C = Cluster.from_curve(H)
sage: C.jacobian_has_good_reduction(K)
False
jacobian_has_potentially_good_reduction()

Test whether the curve associated to self’s Jacobian has potentially good reduction.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve(x^6 - 27)
sage: C = Cluster.from_curve(H)
sage: C.jacobian_has_potentially_good_reduction()
True
lambda_tilde()

Computes the \tilde\lambda of self (see section 3)

\tilde\lambda(\mathfrak s) = \frac{1}{2}\left(v(c)+|\tilde{\mathfrak{s}}| d_{\mathfrak{s}}+\sum_{r \notin \mathfrak{s}} d_{\mathfrak{s} \wedge r}\right)

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(x^3-p^5)
sage: C = Cluster.from_curve(H)
sage: C.lambda_tilde()
5/2
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve(x*(x^6-21*x^4-1911*x^2-21952))
sage: C = Cluster.from_curve(H)
sage: C.lambda_tilde()
3/4
sage: C.children()[1].lambda_tilde()
9/4
sage: C.children()[1].lambda_tilde()
9/4

Example 12.6

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p, 150))
sage: R = Cluster.from_polynomial_without_roots(x^5+256)
sage: R.lambda_tilde()
5/8

Example 12.7

sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^4 - 7)*(x-1))
sage: C = Cluster.from_curve(H)
sage: C.lambda_tilde()
0
sage: C.children()[1].lambda_tilde()
1/2

Example 12.8

sage: x = polygen(Qp(97,150))
sage: H = HyperellipticCurve((x^3 - 97)*(x-1)*(x-2)*(x-3))
sage: C = Cluster.from_curve(H)
sage: C.lambda_tilde()
0
sage: C.children()[3].lambda_tilde()
1/2

An example without roots (but with a leading coefficient still):

sage: C = Cluster.from_picture("(* (* *)_2)_1", leading_coefficient = Qp(5)(25))
sage: C.lambda_tilde()
3/2
leading_coefficient()

Return the leading coefficient of the polynomial defining this cluster.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: K = Qp(p,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve(2*(x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: C = Cluster.from_curve(H)
sage: C.leading_coefficient()
2 + O(5^150)

sage: C = Cluster.from_roots([K(1), K(6), K(26), K(126)])
sage: C.leading_coefficient()
Traceback (most recent call last):
...
AttributeError: This cluster does not have a leading coefficient stored.

sage: C = Cluster(Matrix(ZZ, 4, 4,[\
           [20, 1, 0, 0 ],\
           [1, 20, 0, 0 ],\
           [0, 0, 20, 1 ],\
           [0, 0, 1, 20 ],\
        ]))
sage: C.leading_coefficient()
Traceback (most recent call last):
...
AttributeError: This cluster does not have a leading coefficient stored.
sage: C = Cluster.from_roots([K(1), K(6), K(26), K(126)], leading_coefficient=1)
sage: C.leading_coefficient()
1
lmfdb_label()

Return the lmfdb label of self.

meet(other)

Construct self \wedge other.

EXAMPLES:

Example 3.6 from the users guide:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: a = R.children()[2]
sage: t1 = a.children()[0]
sage: t2 = a.children()[1]
sage: t1.meet(t2) == a
True
sage: t1.meet(a) == a
True
sage: t1.meet(R.children()[1]) == R
True
minimal_discriminant()

Computes the valuation of the minimal discriminant of the curve. This is only implemented for semi-stable curves.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: f = (x^3 - 7^15)*(x^2-7^6)*(x^3-7^3)
sage: Cluster.from_polynomial(f).minimal_discriminant()
24

Example 15.7:

sage: f = 7*(x^2+1)*(x^2+36)*(x^2+64)
sage: Cluster.from_polynomial(f).minimal_discriminant()
22
sage: #x = polygen(Qq(7^2,150,names="t"))
sage: #f = 7*(x^2+1)*(x^2+36)*(x^2+64)
sage: #Cluster.from_polynomial(f).minimal_discriminant()

Example 15.6:

sage: p = 11
sage: x = polygen(Qp(p, 200))
sage: C = Cluster.from_polynomial(p*(x^2-p^5)*(x^3-p^3)*((x-1)^3-p^9))
sage: C.minimal_discriminant()
27
n_tame()

EXAMPLES:

Example 12.5

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 3
sage: x = polygen(Qp(p))
sage: R = Cluster.from_polynomial((x^2-p^2)*((x-1)^2-p^2)*((x-2)^2-p^2))
sage: R.n_tame()
2

Example 12.6

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p, 150))
sage: R = Cluster.from_polynomial_without_roots(x^5+256)
sage: R.n_tame()
4

Example 12.7

sage: x = polygen(Qp(7))
sage: R = Cluster.from_polynomial(x^5+5*x^4+40*x^3+80*x^2+256*x)
sage: R.n_tame()
3

Example 12.8

sage: x = polygen(Qp(97,150))
sage: H = HyperellipticCurve((x^3 - 97)*(x-1)*(x-2)*(x-3))
sage: C = Cluster.from_curve(H)
sage: C.n_tame()
2

Example 1.2 from M2D2:

sage: p = 3
sage: x = polygen(Qp(p,200))
sage: R = Cluster.from_polynomial((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: R.n_tame()
1
n_wild()

The wild component of the conductor exponent.

EXAMPLES:

Lmfdb curve 249.a.249.1:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 3
sage: x = polygen(Qp(p))
sage: R = Cluster.from_polynomial(x^6 + 2*x^3 + 4*x^2 + 4*x + 1)
sage: R.n_tame()
1
sage: R.n_wild() #should be 0
0

Example 12.5

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 3
sage: x = polygen(Qp(p))
sage: R = Cluster.from_polynomial((x^2-p^2)*((x-1)^2-p^2)*((x-2)^2-p^2))
sage: R.n_wild()
0

Lmfdb curve 360.a.6480.1:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p))
sage: R = Cluster.from_polynomial(x^6 - 10*x^4 + 29*x^2 - 20)
sage: R.n_tame()
1
sage: R.n_wild()
0
nu()

Computes the \nu of self (see section 3)

EXAMPLES:

Example 5.8

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve((x^2 + 7^2)*(x^2 - 7^15)*(x - 7^6)*(x - 7^6 - 7^9))
sage: C = Cluster.from_curve(H)
sage: C.children()[2].nu()
26

Example 5.10

sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve(x^6 - 27)
sage: C = Cluster.from_curve(H)
sage: C.children()[0].nu()
9/2

Other

sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(x^3-p^5)
sage: C = Cluster.from_curve(H)
sage: C.nu()
5
sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve(((x-7^2)^2+1)*((x-2*7^2)^2+1)*((x-3*7^2)^2+1)*(x^2-1))
sage: C = Cluster.from_curve(H)
sage: C.nu()
0
sage: C.children()[2].nu()
6
sage: C.children()[3].nu()
6

An example without roots (but with a leading coefficient still):

sage: C = Cluster.from_picture("(* (* *)_2)_1", leading_coefficient = Qp(5)(25))
sage: C.nu()
5
parent_cluster()

Return the parent cluster of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(6), K(26), K(126)])
sage: C.children()[1].children()[1].children()[1].parent_cluster().parent_cluster()
Cluster with 3 roots and 2 children
potential_toric_rank()

Computes the potential toric rank of the Jacobian of the curve.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve(x^6 - 27)
sage: C = Cluster.from_curve(H)
sage: C.potential_toric_rank()
0

sage: C = Cluster.from_picture('(* (* *))')
sage: C.potential_toric_rank()
1

sage: C = Cluster.from_picture('(* * *)')
sage: C.potential_toric_rank()
0
red(x, check=True)

Compute the reduction of a point to the component corresponding to self.

EXAMPLES:

Example 6.9

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(5,150))
sage: H = HyperellipticCurve(x*((x+1)^2 - 5)*(x+4)*(x-6))
sage: R = Cluster.from_curve(H)
sage: R.red(1)
1
sage: R.red(5)
0

Old example 6.6

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve((x+5)*(x-4)*(x-13)*x*(x-3)*(x+4))
sage: R = Cluster.from_curve(H)
sage: R.red(1)
1
sage: R.red(5)
2

Example 6.10

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve((x^4-p^8)*(x^2+2*x+1-p^2)*(x^2-2*x+1-p))
sage: R = Cluster.from_curve(H)
sage: R.red(2)
2
sage: R.red(H.lift_x(2))
(2 : 1 : 1)
sage: R.red(H.lift_x(3))
(3 : 2 : 1)
relative_depth()

Return the depth of the cluster.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.relative_depth()
0
sage: C.children()[1].relative_depth()
1
sage: C = Cluster.from_roots([K(5), K(25), K(50)])
sage: C.relative_depth()
1
sage: C.children()[1].relative_depth()
1
sage: C = Cluster.from_roots([K(1), K(6), K(26), K(126)])
sage: C.children()[1].children()[1].relative_depth()
1
root_number()

Computes the root number of self.

EXAMPLES:

Example 13.7 (i)

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 23
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(((x-1)^2 - p^4)*(x^2 - p^4)*(x-2)*(x-3))
sage: C = Cluster.from_curve(H)
sage: C.root_number()
1

Example 13.7 (ii)

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 23
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(((x^2+1)^2 - 2*p^4*x^2 + 2*p^4+  p^8)*(x-2)*(x-3))
sage: C = Cluster.from_curve(H)
sage: C.root_number()
-1

Example 13.7 (iii)

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 23
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(-(x^2 - p^4)*((x-1)^2 - p^4)*(x-2)*(x-3))
sage: C = Cluster.from_curve(H)
sage: C.root_number()
1

Example 13.8

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve(p*(x^2-p^5)*((x-1)^2-p^5)*((x-2)^2-p^5))
sage: C = Cluster.from_curve(H)
sage: C.root_number()  # 1
Traceback (most recent call last):
...
NotImplementedError: Cluster is not semi-stable

Example 13.9

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 7
sage: x = polygen(Qp(p,150))
sage: H = HyperellipticCurve((x^3-p^8)*(x-1)*((x-1)^2-p^p))
sage: C = Cluster.from_curve(H)
sage: C.root_number()  # -1
Traceback (most recent call last):
...
NotImplementedError: Cluster is not semi-stable

Lmfdb curve 1503.a.4509.1

sage: K = Qp(3,200)
sage: x = polygen(K)
sage: H = HyperellipticCurve(x^6 + 4*x^5 - 2*x^4 - 10*x^3 + x^2 + 6*x + 1)
sage: R3 = Cluster.from_curve(H)
sage: K = Qp(167,200)
sage: x = polygen(K)
sage: H = HyperellipticCurve(x^6 + 4*x^5 - 2*x^4 - 10*x^3 + x^2 + 6*x + 1)
sage: R167 = Cluster.from_curve(H)
sage: R3.root_number()*R167.root_number()
-1

Lmfdb curve 363.a.43923.1

sage: K = Qp(3,200)
sage: x = polygen(K)
sage: H = HyperellipticCurve(44*x^5 - 51*x^4 - 28*x^3 + 40*x^2 + 4*x - 8)
sage: R3 = Cluster.from_curve(H)
sage: K = Qp(11,200)
sage: x = polygen(K)
sage: H = HyperellipticCurve(44*x^5 - 51*x^4 - 28*x^3 + 40*x^2 + 4*x - 8)
sage: R11 = Cluster.from_curve(H)
sage: R11.root_number()*R3.root_number()
1
roots()

Return the list of roots in this cluster.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(6), K(26), K(126)])
sage: C.roots()
[1 + O(5^150), 1 + 5 + O(5^150), 1 + 5^2 + O(5^150), 1 + 5^3 + O(5^150)]
sage: C = Cluster(Matrix(ZZ, 4, 4,[\
           [20, 1, 0, 0 ],\
           [1, 20, 0, 0 ],\
           [0, 0, 20, 1 ],\
           [0, 0, 1, 20 ],\
        ]))
sage: C.roots()
Traceback (most recent call last):
...
AttributeError: This cluster does not have root information stored.
set_center(c, check=True)

Set the center of self to c, useful to check against examples done by hand.

size()

The size of self, the number of roots contained in the cluster.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.size()
3
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10), K(25)])
sage: C.size()
5
sage: C = Cluster.from_roots([K(1), K(2), K(5), K(10), K(25), K(50)])
sage: C.size()
6
sage: C.children()[2].size()
4
star()

Construct self*, if self is not a cotwin this is the smallest cluster containing self whose parent is not übereven (and the top cluster if no such cluster exists). If self is a cotwin, its star is its child of size 2g.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: a = R.children()[2]
sage: t1 = a.children()[0]
sage: t2 = a.children()[1]
sage: t1.star() == a
True
sage: t2.star() == a
True
sage: a.star() == a
True
sage: R.star() == a
True

Some cotwins:

sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.star()
Cluster with 2 roots and 2 children

sage: C = Cluster.from_roots([K(1), K(2), K(10), K(35)])
sage: C.star()
Cluster with 2 roots and 2 children

sage: C = Cluster.from_roots([K(1), K(5), K(10), K(35)])
sage: C.children()[1].star()
Cluster with 2 roots and 2 children
tamagawa_number(check_semistable=True)

Compute the Tamagawa number of self.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: x = polygen(K)
sage: R = Cluster.from_polynomial((x^4-5^4)*(x+1)*(x+2))
sage: R.tamagawa_number()
2

Example 10.4:

sage: K = Qp(5,150)
sage: x = polygen(K)
sage: R = Cluster.from_polynomial((x^2-5^2)*(x+1)*(x-1)*(x-2))
sage: R.tamagawa_number()
2

Example 10.6:

sage: p = 7
sage: x = polygen(Qp(p, 200))
sage: w = 2
sage: a = 7
sage: u = 2
sage: z = 3
sage: f = ((x^(2)+1)^(2)-p^(u))*((x-1)^(2)-p^(z))*(x-p^(w / 2))*(x-p^(w / 2+2))*((x^(2)+p^(w+4))^(2)-p^(2*(w+4)+a))
sage: R = Cluster.from_polynomial(f)
sage: R.tamagawa_number() == a*(u*z + 2*z*w + u*w)
True

Elliptic curve 15.a1:

sage: E = EllipticCurve("15.a1")
sage: E.tamagawa_number(3)
2
sage: E = E.short_weierstrass_model(complete_cube=False).change_ring(Qp(3,150))
sage: R = Cluster.from_curve(E)
sage: R.tamagawa_number()
2

Elliptic curve 576.c4:

sage: E = EllipticCurve([9, 0])
sage: E.tamagawa_number(3)
2
sage: E = E.short_weierstrass_model(complete_cube=False).change_ring(Qp(3,150))
sage: R = Cluster.from_curve(E)
sage: R.is_semistable(Qp(3))
False
sage: R.tamagawa_number()
Traceback (most recent call last):
...
NotImplementedError

Hyperelliptic Curve 630.a.34020.1:

sage: R.<tx> = PolynomialRing(Qp(3,200))
sage: X = HyperellipticCurve(R([60, -24, -91, 2, 41, 12]))
sage: C = Cluster.from_curve(X)
sage: C.tamagawa_number()
2

Hyperelliptic Curve 4815.a.14445.1:

sage: R.<tx> = PolynomialRing(Qp(3,200))
sage: X = HyperellipticCurve(R([5, 40, 84, 0, -56, -28, -4]))
sage: C = Cluster.from_curve(X)
sage: C.tamagawa_number()
1

Time limit example:

sage: x = polygen(Qp(7,150))
sage: H = HyperellipticCurve(x^(12) + 36*x^(11) + 534*x^(10) + 4094*x^9 + 17667*x^8 + 44018*x^7 + 61093*x^6 + 44018*x^5 + 17667*x^4 + 4094*x^3 + 534*x^2 + 36*x + 1)
sage: C = Cluster.from_curve(H)
sage: C.tamagawa_number()
1
theta(frobenius_reduction=False)

A choice of \sqrt{c \prod_{r \notin \mathfrak{s}}\left(z_{\mathfrak{s}}-r\right)}.

If the optional parameter frobenius_reduction is set, then the residue of the unit part will be returned.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: K = Qp(p,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.theta()
Traceback (most recent call last):
...
AttributeError: This cluster does not have a leading coefficient stored.
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: C.theta()
1 + O(5^150)
sage: D = C.children()[1]
sage: D.theta()
2 + 5 + 2*5^2 + 5^3 + 2*5^4 + 5^5 + 4*5^6 + 2*5^7 + 2*5^8 + 2*5^9 + 5^10 + 4*5^11 + 2*5^13 + 3*5^14 + 4*5^15 + 4*5^16 + 4*5^17 + 5^19 + 4*5^20 + 4*5^22 + 4*5^25 + 5^26 + 3*5^27 + 3*5^30 + 4*5^32 + 3*5^34 + 5^35 + 5^36 + 4*5^37 + 5^38 + 2*5^39 + 3*5^40 + 5^41 + 3*5^42 + 5^43 + 5^44 + 3*5^45 + 2*5^46 + 2*5^48 + 3*5^50 + 2*5^51 + 5^52 + 2*5^53 + 3*5^54 + 4*5^55 + 4*5^56 + 4*5^57 + 5^59 + 2*5^60 + 3*5^61 + 4*5^63 + 2*5^65 + 4*5^66 + 2*5^68 + 3*5^69 + 4*5^70 + 2*5^71 + 4*5^72 + 5^73 + 2*5^74 + 2*5^75 + 3*5^76 + 4*5^77 + 5^78 + 5^79 + 3*5^80 + 4*5^81 + 4*5^82 + 5^83 + 3*5^84 + 4*5^86 + 2*5^87 + 5^88 + 2*5^90 + 5^91 + 3*5^93 + 5^94 + 5^95 + 5^96 + 5^97 + 4*5^99 + 3*5^100 + 5^101 + 3*5^102 + 2*5^103 + 2*5^105 + 5^107 + 5^108 + 4*5^109 + 2*5^110 + 3*5^111 + 4*5^112 + 5^113 + 4*5^114 + 2*5^115 + 4*5^116 + 4*5^117 + 5^118 + 4*5^119 + 2*5^120 + 5^121 + 4*5^122 + 4*5^123 + 5^125 + 3*5^126 + 5^128 + 3*5^131 + 4*5^134 + 3*5^135 + 5^136 + 4*5^137 + 2*5^138 + 5^139 + 3*5^143 + 5^144 + 4*5^145 + 3*5^147 + 5^148 + O(5^150)
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: a = R.children()[0]
sage: #a.theta() TODO renable
theta_squared()

c \prod_{r \notin \mathfrak{s}}\left(z_{\mathfrak{s}}-r\right).

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: K = Qp(p,150)
sage: C = Cluster.from_roots([K(1), K(5), K(10)])
sage: C.theta_squared()
Traceback (most recent call last):
...
AttributeError: This cluster does not have a leading coefficient stored.
sage: x = polygen(K)
sage: C = Cluster.from_polynomial((x-1)*(x-(1+p^2))*(x-(1-p^2))*(x-p)*x*(x-p^3)*(x+p^3))
sage: C.theta_squared()
1 + O(5^150)
sage: D = C.children()[1]
sage: D.theta_squared() == 624
True
sage: K = Qp(7,150)
sage: x = polygen(K)
sage: H = HyperellipticCurve((x^2+7^2)*(x^2-7^(15))*(x-7^6)*(x-7^6-7^9))
sage: R = Cluster.from_curve(H)
sage: a = R.children()[0]
sage: a.theta_squared()   # not tested - TODO renable
sage: x = polygen(Qp(3,150))
sage: H = HyperellipticCurve((x-1)*((x-3)^2+81)*((x+3)^2+81))
sage: C = Cluster.from_curve(H)
sage: #C.children()[1].children()[0].set_center(3)
sage: #C.children()[1].children()[0].theta_squared() == 234
sage: #C.children()[1].children()[1].set_center(-3)
sage: #C.children()[1].children()[1].theta_squared() == -468

Example 4.11:

sage: K = Qq(11^3, 200, names="a")
sage: a = K.gen()
sage: z = K.teichmuller(10*a^2 + 7*a + 8)
sage: x = polygen(K)
sage: f = prod(x-a for a in [0,1,2,z-11,z+11,z^2 - 11, z^2 +11, z^4 -11, z^4 + 11]).map_coefficients(lambda x: x.trace()/3, new_base_ring=Qp(11, 200))
sage: H = HyperellipticCurve(f)
sage: R = Cluster.from_curve(H)
sage: t1 = R.children()[3]
sage: t2 = R.children()[4]
sage: t4 = R.children()[5]
sage: z = t1.center()
sage: #(t1.theta_squared() - z^2 - 3*z - 7).residue() # also only true with correct order TODO 0
sage: # (t2.theta_squared() + 3*z^2 + 2*z +8).residue()
sage: # (t4.theta_squared() + 9*z^2 + z +9).residue()
top_cluster()

Return the top cluster for the picture.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: K = Qp(5,150)
sage: C = Cluster.from_roots([K(1), K(6), K(26), K(126)])
sage: C.children()[1].children()[1].children()[1].top_cluster().size()
4
xi(a)

Compute \xi_{self}(a) = \max \left\{-\operatorname{ord}_{2}\left(\left[I_{K}: I_{self}\right] a\right), 0\right\}.

EXAMPLES:

Example 12.6

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: p = 5
sage: x = polygen(Qp(p, 150))
sage: R = Cluster.from_polynomial_without_roots(x^5+256)
sage: R.xi(R.lambda_tilde())
3
sage: R.xi(R.depth())
2

Example 12.7

sage: from sage_cluster_pictures.cluster_pictures import Cluster
sage: x = polygen(Qp(7))
sage: R = Cluster.from_polynomial(x^5+5*x^4+40*x^3+80*x^2+256*x)
sage: R.xi(R.lambda_tilde())
0
sage: R.xi(R.depth())
0
sage: s = R.children()[1]
sage: R.xi(s.lambda_tilde())
1
sage: R.xi(s.depth())
2
sage_cluster_pictures.cluster_pictures.orbit_decomposition(F, S, cond=None)

Decompose a list S into orbits under the function F, returning only those satisfying cond.

EXAMPLES:

sage: from sage_cluster_pictures.cluster_pictures import orbit_decomposition
sage: orbit_decomposition(lambda x: x + 1, list(Integers(15)))
[[14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]]
sage: orbit_decomposition(lambda x: x + 1, list(Integers(15)), cond = lambda x: len(x) < 1)
[]