Covering construction¶
Permutation cover
This module deals with combinatorial data for covering of connected components of strata of Abelian and quadratic differentials. The main feature is to be able to compute Lyapunov exponents.
- class surface_dynamics.interval_exchanges.cover.PermutationCover(base, degree, perms)[source]¶
Bases:
object
An interval exchange permutation together with covering data.
Let pi be the combinatorial data of an interval exchange transformation (or linear involution) on the alphabet {1, 2, ldots, m}. A cover of degree d is given by a list of permutations sigma_i in S_d for each i in {1, 2, ldots, m}.
In order to do so, each interval on the base surface should come with an orientation. This orientation is automatically chosen by convention according to a clockwise orientation of the surface. The two copies of any interval have to be oriented alternatively in this chosen orientation and in the opposite to it.
This convention is made such that the permutation associated to each interval is the action of the path going into the interval oriented according to the clockwise orientation and going out of the other one.
This class store three attributes
_base
– combinatorial data of an i.e.t. or a l.i._degree_cover
– (integer) degree of the cover_permut_cover
– list of permutations describing the cover_inv_permut_cover
– list of inverses of_permut_cover
- automorphism_group[source]¶
File: /home/runner/work/surface-dynamics/surface-dynamics/surface_dynamics/interval_exchanges/cover.py (starting at line 621)
Return the Deck group of the cover.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2,3)', '(1,3,2)', '']).automorphism_group() Permutation Group with generators [(1,2,3), (1,3,2)] sage: p.cover(['(1,2)', '(1,3)', '']).automorphism_group() Permutation Group with generators [()]
- base()[source]¶
Return the combinatorial data corresponding to the base of this cover
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a b b','c c a') sage: c = p.cover(['(1,2,3)','(1,3)','(1,2)']) sage: q = c.base() sage: q a b b c c a sage: q == p True
- covering_data(label)[source]¶
Returns the permutation associated to the given
label
.EXAMPLES:
sage: from surface_dynamics import * sage: p = Stratum([1,1,-1,-1], k=2).components()[0].permutation_representative() sage: pc = p.orientation_cover() sage: pc Covering of degree 2 of the permutation: 0 1 2 3 3 2 1 4 4 0 sage: pc.covering_data(1) () sage: pc.covering_data(3) (1,2)
- covering_data_tuple(label)[source]¶
Returns the permutation associated to the given
label
as a tuple on {0, 1, ldots, d-1} where d is the degree of the cover.EXAMPLES:
sage: from surface_dynamics import * sage: p = Stratum([1,1,-1,-1], k=2).components()[0].permutation_representative() sage: pc = p.orientation_cover() sage: pc Covering of degree 2 of the permutation: 0 1 2 3 3 2 1 4 4 0 sage: pc.covering_data_tuple(1) [0, 1] sage: pc.covering_data_tuple(3) [1, 0]
- genus()[source]¶
Genus of the covering translation surface
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2)', '()', '(1,2)']).genus() 1 sage: p.cover(['(1,2)', '(1,2)', '(1,2)']).genus() 0
- group¶
File: /home/runner/work/surface-dynamics/surface-dynamics/surface_dynamics/interval_exchanges/cover.py (starting at line 621)
Return the Deck group of the cover.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2,3)', '(1,3,2)', '']).automorphism_group() Permutation Group with generators [(1,2,3), (1,3,2)] sage: p.cover(['(1,2)', '(1,3)', '']).automorphism_group() Permutation Group with generators [()]
- interval_diagram(sign=False)[source]¶
Return the interval diagram.
This is the permutation induced on the subintervals of this cover while we turn around the singularities. This is mainly used to compute the stratum of this permutation.
OUTPUT:
A list of lists of pairs
(label, index of interval)
ifsign=False
or a list of triples(label, index of interval, sign)
.EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: c = p.cover(['(1,2)','(1,3)','(1,4)']) sage: c.interval_diagram() [[('a', 1), ('a', 0)], [('a', 2)], [('a', 3)], [('a', 0), ('b', 1), ('a', 1), ('b', 0), ('a', 2), ('b', 2)], [('a', 3), ('b', 3)], [('b', 2), ('c', 2), ('b', 0), ('c', 0), ('b', 3), ('c', 3)], [('b', 1), ('c', 1)], [('c', 3), ('c', 0)], [('c', 1)], [('c', 2)]] sage: c.interval_diagram(sign=True) [[('a', 1, -1), ('a', 0, -1)], [('a', 2, -1)], [('a', 3, -1)], [('a', 0, 1), ('b', 1, 1), ..., ('b', 2, 1)], [('a', 3, 1), ('b', 3, 1)], [('b', 2, -1), ('c', 2, 1), ..., ('c', 3, 1)], [('b', 1, -1), ('c', 1, 1)], [('c', 3, -1), ('c', 0, -1)], [('c', 1, -1)], [('c', 2, -1)]]
- is_orientable()[source]¶
Test whether this permutation cover has an orientable foliation.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: from itertools import product sage: it = iter(product(('()', '(1,2)'), repeat=3)) sage: next(it) ('()', '()', '()') sage: for cov in it: ....: c = p.cover(cov) ....: print("%28s %s" % (cov, c.is_orientable())) ('()', '()', '(1,2)') False ('()', '(1,2)', '()') False ('()', '(1,2)', '(1,2)') False ('(1,2)', '()', '()') False ('(1,2)', '()', '(1,2)') True ('(1,2)', '(1,2)', '()') False ('(1,2)', '(1,2)', '(1,2)') False
- isotypic_projectors(characters=None, floating_point=True)[source]¶
Return the list of projectors on isotypical components in the canonical basis as well as the half ranks of the projection in absolute homology.
INPUT:
characters
- (defaultNone
), if set toNone
compute projectors for all characters, otherwise if set to a list of characters return only the projectors for these characters.floating_point
- (defaultTrue
) if set toTrue
then all computations are performed over floating point numbers. Otherwise, exact cyclotomic elements are kept until the very last steps of the computation.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.Permutation('a b', 'b a') sage: Q = QuaternionGroup() sage: a,b = Q.gens() sage: pp = p.regular_cover(Q, [a, b]) sage: X = pp.isotypic_projectors() sage: X[0][0] array([[0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. ], [0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125], ... [0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125, 0. , 0.125]]) sage: import numpy as np sage: Y = pp.isotypic_projectors(floating_point=False) sage: np.allclose(X[0], Y[0]) True sage: X[1] [1, 0, 0, 0, 2] sage: sum(X[1]) == pp.genus() True
- lyapunov_exponents_H_plus(nb_vectors=None, nb_experiments=10, nb_iterations=65536, output_file=None, return_speed=False, isotypic_decomposition=False, return_char=False, verbose=False, floating_point=True)[source]¶
Compute the H^+ Lyapunov exponents in the covering locus.
This method calls a C-library that performs renormalization (i.e. Rauzy induction and orthogonalization of vectors under the Kontsevich-Zorich cocycle). The computation might be significantly faster if
nb_vectors=1
(or if it is not provided but genus is 1) as in this case no orthogonalization is needed.INPUT:
nb_vectors
– the number of exponents to compute. The number of vectors must not exceed the dimension of the space!nb_experiments
– the number of experiments to perform. It might be around 100 (default value) in order that the estimation of confidence interval is accurate enough.nb_iterations
– the number of iteration of the Rauzy-Zorich algorithm to perform for each experiments. The default is 2^15=32768 which is rather small but provide a good compromise between speed and quality of approximation.output_file
– if provided (as a file object or a string) output the additional information in the given file rather than on the standard output.return_speed
– whether or not return the lyapunov exponents list in a pair with the speed of the geodesic.isotypic_decomposition
– either a boolean or a character or a list of characters.return_char
– whether or not return the character corresponding to the isotypic component.verbose
– ifTrue
provide additional information rather than returning only the Lyapunov exponents (i.e. elapsed time, confidence intervals, …)float
– whether the isotypical decomposition and projectors are computed over exact or floating point numbers
EXAMPLES:
sage: from surface_dynamics import * sage: q = Stratum([1,1,-1,-1], k=2).one_component() sage: q.lyapunov_exponents_H_plus(nb_iterations=2**19) # abs tol 0.1 [0.666666] sage: p = q.permutation_representative(reduced=False).orientation_cover() sage: c = p.lyapunov_exponents_H_plus(isotypic_decomposition=True, nb_iterations=2**19)[0] sage: c[0] # abs tol 0.1 1.000000 sage: p = iet.GeneralizedPermutation('e a a', 'b b c c d d e') sage: p.stratum() Q_0(1, -1^5) sage: p.alphabet() {'e', 'a', 'b', 'c', 'd'} sage: c = p.cover(['()', '(1,2)', '()', '(1,2)', '(1,2)']) sage: c.stratum(fake_zeros=True) Q_1(1^2, 0^4, -1^2) sage: c.lyapunov_exponents_H_plus(nb_iterations=2**19) # abs tol 0.1 [0.666666]
Some cyclic covers (see [EskKonZor11] for the formulas):
sage: p = iet.GeneralizedPermutation('c a a', 'b b c', alphabet='abc') sage: def cyclic(n,a): ....: return [(i+a)%n + 1 for i in range(n)] sage: def cyclic_cover(n, a, b, c): ....: return p.cover([cyclic(n,c), cyclic(n,a), cyclic(n, b)]) sage: def cyclic_cover_regular(n, a, b, c): ....: G = groups.misc.MultiplicativeAbelian([n]) ....: x, = G.gens() ....: return p.regular_cover(G, [x**c, x**a, x**b]) sage: c = cyclic_cover(7,1,1,2) sage: lexp = c.lyapunov_exponents_H_plus(isotypic_decomposition=True, nb_iterations=2**19) sage: lexp # abs tol 0.1 [[], [0.2857, 0.2857], [0.5714, 0.5714], [0.2857, 0.2857]] sage: c = cyclic_cover(7, 1, 2, 3) sage: lexp = c.lyapunov_exponents_H_plus(isotypic_decomposition=True, return_char=True, nb_iterations=2**19) sage: lexp[0] ([], (1, 1, 1, 1, 1, 1, 1)) sage: lexp[1][0] # abs tol 0.1 [0.2857, 0.2857] sage: lexp[1][1] (2, E(7) + E(7)^6, ..., E(7) + E(7)^6) sage: lexp[2][0] # abs tol 0.1 [0.2857, 0.2857] sage: lexp[2][1] (2, E(7)^2 + E(7)^5, ..., E(7)^2 + E(7)^5) sage: lexp[3][0] # abs tol 0.1 [0.5714, 0.5714] sage: lexp[3][1] (2, E(7)^3 + E(7)^4, ..., E(7)^3 + E(7)^4)
The Eierlegendewollmilchsau as a quaternionic cover of the once punctured torus:
sage: p = iet.Permutation('a b', 'b a') sage: Q = QuaternionGroup() sage: a,b = Q.gens() sage: c = p.cover([a, b]) sage: c.lyapunov_exponents_H_plus(nb_iterations=2**19) # abs tol 0.05 [1.0, 0.0, 0.0]
- masur_polygon(lengths, heights)[source]¶
Return the Masur polygon for the given
lengths
andheights
.EXAMPLES:
sage: from surface_dynamics import iet sage: p = iet.Permutation('a b c', 'c b a').cover(['(1,2)','(1,3)','(1,4)']) sage: S = p.masur_polygon([1,4,2], [2,0,-1]) # optional: sage_flatsurf sage: stratum = S.stratum() # optional: sage_flatsurf # random sage: stratum # optional: sage_flatsurf H_4(3^2) sage: stratum = p.stratum() # optional: sage_flatsurf # random sage: stratum # optional: sage_flatsurf H_4(3^2)
- monodromy[source]¶
File: /home/runner/work/surface-dynamics/surface-dynamics/surface_dynamics/interval_exchanges/cover.py (starting at line 602)
Return the monodromy of this covering.
That it to say the permutation group generated by the action of the fundamental group.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2,3)', '(1,3,2)', '']).monodromy() Permutation Group with generators [(1,2,3), (1,3,2), ()] sage: p.cover(['(1,2)', '(1,3)', '']).monodromy() Permutation Group with generators [(1,2), (1,3), ()]
- profile()[source]¶
Return the profile of the surface.
The profile of a translation surface is the list of angles of singularities in the surface divided by pi.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.Permutation('a b', 'b a') sage: p.cover(['(1,2)', '(1,3)']).profile() [6] sage: p.cover(['(1,2,3)','(1,4)']).profile() [6, 2] sage: p.cover(['(1,2,3)(4,5,6)','(1,4,7)(2,5)(3,6)']).profile() [6, 2, 2, 2, 2] sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2)', '()', '(1,2)']).profile() [2, 2, 2, 2]
- stratum(fake_zeros=True)[source]¶
Return the stratum of the covering translation surface.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2)', '()', '(1,2)']).stratum() H_1(0^4) sage: p.cover(['(1,2)', '()', '(1,2)']).stratum(fake_zeros=False) H_1(0) sage: p.cover(['(1,2)', '(1,2)', '(1,2)']).stratum() Q_0(0^2, -1^4) sage: p.cover(['(1,2)', '(1,2)', '(1,2)']).stratum(fake_zeros=False) Q_0(-1^4)
- class surface_dynamics.interval_exchanges.cover.RegularCover(base, grp, elts, check=True)[source]¶
Bases:
PermutationCover
An interval exchange permutation together with a regular covering data.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.Permutation('a b c', 'c b a') sage: G = Zmod(3) sage: p.regular_cover(G, [1, 0, 2]) Regular cover of degree 3 with group Multiplicative Abelian group isomorphic to C3 of the permutation: a b c c b a sage: G = AbelianGroup([2,4]) sage: p.regular_cover(G, [(1,0), (0,0), (0,1)]) Regular cover of degree 8 with group Multiplicative Abelian group isomorphic to C2 x C4 of the permutation: a b c c b a sage: G = GL(2, 3) sage: g1, g2 = G.gens() sage: p.regular_cover(G, [g1, g2, g1 * g2]) Regular cover of degree 48 with group General Linear Group of degree 2 over Finite Field of size 3 of the permutation: a b c c b a
An example using a semi-direct product built with GAP:
sage: C1 = libgap.CyclicGroup(2^5) sage: C2 = libgap.CyclicGroup(2) sage: gens1 = libgap.GeneratorsOfGroup(C1) sage: gens2 = libgap.GeneratorsOfGroup(C2) sage: alpha = libgap.GroupHomomorphismByImages(C1, C1, [gens1[0]], [gens1[0]^(-1)]) sage: phi = libgap.GroupHomomorphismByImages(C2, libgap.AutomorphismGroup(C1), [gens2[0]], [alpha]) sage: G = libgap.SemidirectProduct(C2, phi, C1) sage: x = libgap.Image(libgap.eval("Embedding")(G, 2), gens1[0]) sage: y = libgap.Image(libgap.eval("Embedding")(G, 1), gens2[0]) sage: p = iet.Permutation('a b', 'b a') sage: pp = p.regular_cover(G, [x, y]) sage: pp Regular cover of degree 64 with group <pc group of size 64 with 6 generators> of the permutation: a b b a sage: pp.isotypic_projectors()[1] [1, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] sage: pp.lyapunov_exponents_H_plus(isotypic_decomposition=True) # not tested (too long) [[1.000], [], [], [], [0.5065137173173205, 0.5064242515256905], [0.25364063157823696, 0.25344903617958725], [0.7562155727190676, 0.7562259157608896], [0.1267784864027805, 0.12676433404844129], [0.3806034038221321, 0.38056305175722355], [0.6287868199859215, 0.6287551837770511], [0.8797056039630107, 0.8797049392731162], [0.06522712186764967, 0.06491210232533576], [0.1903390673409358, 0.19013594965668126], [0.3173095347090416, 0.3171889234380455], [0.44497853721724967, 0.444804933849061], [0.5662613367551405, 0.5662491535341443], [0.6906239438432811, 0.6905716259455005], [0.8165503109407333, 0.8164624067719244], [0.9385523471932377, 0.9383981565833286]]
- group()[source]¶
File: /home/runner/work/surface-dynamics/surface-dynamics/surface_dynamics/interval_exchanges/cover.py (starting at line 621)
Return the Deck group of the cover.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2,3)', '(1,3,2)', '']).automorphism_group() Permutation Group with generators [(1,2,3), (1,3,2)] sage: p.cover(['(1,2)', '(1,3)', '']).automorphism_group() Permutation Group with generators [()]
- is_orientable()[source]¶
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b c d', 'b e d c f f e') sage: G = Zmod(2) sage: p.regular_cover(G, [1, 1, 1, 1, 1, 1]).is_orientable() False sage: p.regular_cover(G, [0, 1, 1, 1, 0, 0]).is_orientable() False sage: p.regular_cover(G, [1, 0, 0, 0, 1, 1]).is_orientable() True sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: G = GL(2, GF(3)) sage: g1 = G([[2,0],[0,1]]) sage: g2 = G([[2,1],[2,0]]) sage: p.regular_cover(G, [g1, g2, g1]).is_orientable() True
- monodromy()[source]¶
File: /home/runner/work/surface-dynamics/surface-dynamics/surface_dynamics/interval_exchanges/cover.py (starting at line 602)
Return the monodromy of this covering.
That it to say the permutation group generated by the action of the fundamental group.
EXAMPLES:
sage: from surface_dynamics import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2,3)', '(1,3,2)', '']).monodromy() Permutation Group with generators [(1,2,3), (1,3,2), ()] sage: p.cover(['(1,2)', '(1,3)', '']).monodromy() Permutation Group with generators [(1,2), (1,3), ()]