surface_dynamics package overview
surface_dynamics is a SageMath package for translation surfaces in Sage that is maintained by Vincent Delecroix (see the complete list of contributors on the PyPI page). You can install it using the following one-line command
$ sage -pip install surface_dynamics --user
Or alternatively, you can use it inside Sage Cell (thanks to Andrey Novoseltsev).
This page describes quickly some usage of the library. Other sources of information includes
Below, I briefly describe the usage of this package.
General usage
Once it is installed on your computer and Sage is launched, you need to enter the following command to be able to use the library
>>> from surface_dynamics import *
The above command makes accessible a lot of new objects like iet
, AbelianStratum
,
QuadraticStratum
, CylinderDiagram
, Origami
and OrigamiDatabase
. Recall that to access
the documentation within Sage you need to put a question mark after the command and press enter
>>> Origami?
Signature: Origami(r, u, sparse=False, check=True, as_tuple=False, positions=None, name=None)
Docstring:
Constructor for origami
INPUT:
* "r", "u" - two permutations
...
Most of the functions in the package are well documented together with examples.
Citation
To cite the software, use the following bibtex entry
@manual{ Sdyn,
Author = { Delecroix, V. et al. },
Month = { March },
Year = { 2019 },
Title = { Surface Dynamics - SageMath package, Version 0.4.1 },
Doi = { 10.5281/zenodo.3237923 },
Url = { https://doi.org/10.5281/zenodo.3237923 }
}
Strata and Interval exchange transformations
The package contains a lot of code to deal with interval exchange transformations and linear involutions. Here is how a permutation can be created
>>> p = iet.Permutation('a b c d', 'd c b a')
>>> p
a b c d
d c b a
>>> p.stratum()
H(2)
and a generalized permutation
>>> q = iet.GeneralizedPermutation('a a', 'b b c c d d e e')
>>> q.stratum()
Q_0(1, -1^5)
You can also get one permutation from a given stratum component (following the method of A. Zorich "Explicit Jenkins-Strebel representatives of all strata of Abelian and quadratic differentials", 2008)
>>> A = AbelianStratum(4,4)
>>> cc = A.odd_component()
>>> cc.permutation_representative()
0 1 2 3 4 5 6 7 8 9 10
3 2 5 4 6 8 7 10 9 1 0
>>> Q = QuadraticStratum(12)
>>> Q_reg = Q.regular_component()
>>> Q_irr = Q.irregular_component()
>>> Q_reg.permutation_representative()
0 1 2 1 2 3 4 3 4 5
5 6 7 6 7 0
>>> Q_irr.permutation_representative()
0 1 2 3 4 5 6 5
7 6 4 7 3 2 1 0
Once you have a permutation, you can construct the associated Rauzy diagram. They can in turn be used to create self-similar interval exchange transformations from a loop.
>>> p = iet.Permutation('a b c d', 'd c b a')
>>> R = p.rauzy_diagram()
>>> g = R.path(p, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1)
>>> T = g.self_similar_iet()
>>> T
Interval exchange transformation of [0, a[ with permutation
a b c d
d c b a
In the path 0
corresponds to top Rauzy induction and 1
to bottom. The number
a
that appears in the interval [0, a[
of the interval exchange string above
is a number field element (all computations at this stage are done exactly).
>>> la, lb, lc, ld = T.lengths()
>>> (4*lb^2 - 10*lb - 5).is_zero()
True
You can extract other information from the loop g
such as the substitution
whose fixed point gives the coding of the orbit of the point 0
under the
interval exchange transformation
>>> s = g.substitution()
>>> s
WordMorphism: a->adbbd, b->adbbdbbd, c->adbcbcbd, d->adbcbd
>>> s.fixed_point('a')
word: adbbdadbcbdadbbdbbdadbbdbbdadbcbdadbbdad...
The fact that the above infinite word is the coding of 0
can be checked via
>>> x = 0
>>> for _ in range(30):
... print T.in_which_interval(x),
... x = T(x)
a d b b d a d b c b d a d b b d b b d a d b b d b b d a d b
The example we choose is exceptional since there are two eigenvalues 1
(while
the generic spectrum is simple by A. Avila M. Viana "Simplicity of Lyapunov
spectra: proof of the Zorich-Kontsevich conjecture" 2007)
>>> g.matrix().eigenvalues()
[1, 1, 0.1458980337503155?, 6.854101966249684?]
Lyapunov exponents
Approxmiations of the Lyapunov exponents of the Kontsevich-Zorich cocycle can be computed in various situations. For example on connected component of Abelian strata
>>> H4_odd = AbelianStratum(4).odd_component()
>>> H4_odd.lyapunov_exponents()
[1.0021979229418148, 0.41891862918527395, 0.18809229410591524]
On components of strata of quadratic differentials the exponents on and can be computed separatly
>>> Q12_reg = QuadraticStratum(12).regular_component()
>>> Q12_reg.lyapunov_exponents_H_plus()
[0.6671, 0.4506, 0.2372, 0.08841]
>>> Q12_reg.lyapunov_exponents_H_minus()
[1.001, 0.6669, 0.45018, 0.3139, 0.23218, 0.12143, 0.08594]
More generally, one can compute the Lyapunov exponents of the restriction of the Kontsevich-Zorich cocycle in a covering locus to any isotypic invariant subbundle::
>>> p = iet.GeneralizedPermutation('a a', 'b b c c d d e e')
>>> c = p.cover(['(1,2,3,4)', '(1,4,3,2)', '(1,2,3,4)', '()', '()'])
>>> c.stratum()
Q_3(10, 2^3, -1^8)
>>> for (lexp,char) in c.lyapunov_exponents_H_plus(isotypic_decomposition=True, return_char=True):
... print "{:15}: {}".format(char, lexp)
(1, 1, 1, 1) : []
(1, -1, 1, -1) : [0.3360]
(2, 0, -2, 0) : [0.1665, 0.1661]
Origamis
To build an origami you just need to enter the two permutations defining it
to the constructor Origami
>>> from surface_dynamics.all import *
>>> o = Origami('(1,2)', '(1,3)')
>>> o
(1,2)(3)
(1,3)(2)
By convention the permutation are named r
(for right) and u
(for up)
>>> o.r()
(1,2)
>>> o.u()
(1,3)
There are also some predefined origamis that are accessible via origamis
>>> ew = origamis.EierlegendeWollmilchsau()
>>> ew
Eierlegende Wollmilchsau
>>> ew.u()
(1,5,3,7)(2,8,4,6)
>>> ew.r()
(1,2,3,4)(5,6,7,8)
And it is also possible to build them from strata
>>> A = AbelianStratum(2,2)
>>> cc = A.odd_component()
>>> cc.one_origami()
(1,2,3,4,5,6)
(1,6)(2)(3,4)(5)
You can then compute many invariants
>>> o.stratum()
H_2(2)
>>> ew.stratum()
H_3(1^4)
>>> G = o.veech_group()
>>> G
Arithmetic subgroup with permutations of right cosets
S2=(2,3)
S3=(1,2,3)
L=(1,2)
R=(1,3)
>>> G.is_congruence()
True
>>> o.lyapunov_exponents_approx()
[0.333686792523229]
>>> o.sum_of_lyapunov_exponents()
4/3
>>> ew.veech_group()
Arithmetic subgroup with permutations of right cosets
S2=()
S3=()
L=()
R=()
>>> ew.lyapunov_exponents_approx()
[0.0000483946861896958, 0.0000468061832920360]
>>> ew.sum_of_lyapunov_exponents()
1
If you are interested in some statistics of a Teichmüller curve you can iterate through the origamis it contains. For example we study the distribution of the number of cylinders in all Teichmüller curves of the component (genus 3) with 11 squares
>>> cc = AbelianStratum(4).odd_component()
>>> for T in cc.arithmetic_teichmueller_curves(11):
... cyls = [0]*3
... for o in T:
... n = len(o.cylinder_decomposition())
... cyls[n-1] += 1
... print cyls
[1474, 4310, 2016]
[110, 0, 90]
[1650, 636, 1114]
The origami database
The origami database is a database that contains the list of all arithmetic Teichmüller curves (up to some number of squares). It is a standard sqlite database and can also be read from other programs.
>>> from surface_dynamics import *
>>> D = OrigamiDatabase()
>>> q = D.query(stratum=AbelianStratum(2), nb_squares=9)
>>> q.number_of()
2
>>> o1,o2 = q.list()
>>> o1
(1)(2)(3)(4)(5)(6)(7,8,9)
(1,2,3,4,5,6,7)(8)(9)
>>> o2
(1)(2)(3)(4)(5)(6)(7)(8,9)
(1,2,3,4,5,6,7,8)(9)
To get the list of columns available in the database you can do
>>> D.cols()
['representative',
'stratum',
'component',
'primitive',
'quasi_primitive',
'orientation_cover',
'hyperelliptic',
...
'automorphism_group_name']
Each column is available for display
>>> q = D.query(stratum=AbelianStratum(2))
>>> q.cols
>>> D = OrigamiDatabase()
>>> q = D.query(('stratum', '=', AbelianStratum(2)), ('nb_squares', '<', 15))
>>> q.cols('nb_squares', 'veech_group_level', 'teich_curve_nu2',
... 'teich_curve_nu3', 'teich_curve_genus', 'monodromy_name')
>>> q.show()
Nb squares vg level Teich curve nu2 Teich curve genus Monodromy
---------------------------------------------------------------------------------------------
3 2 1 0 S3
4 12 1 0 S4
5 60 0 0 S5
5 15 1 0 A5
6 60 0 0 S6
7 420 2 0 S7
7 105 0 0 A7
8 840 2 1 S8
9 630 3 0 A9
9 2520 0 2 S9
10 2520 0 4 S10
11 6930 0 3 A11
11 27720 3 6 S11
12 27720 4 11 S12
13 90090 3 7 A13
13 360360 0 14 S13
14 360360 0 25 S14
You can get some information about the filling of the database with
>>> D.info(genus=3)
genus 3
=======
H_3(4)^hyp : 163 T. curves (up to 51 squares)
H_3(4)^odd : 118 T. curves (up to 41 squares)
H_3(3, 1)^c : 72 T. curves (up to 25 squares)
H_3(2^2)^hyp : 280 T. curves (up to 33 squares)
H_3(2^2)^odd : 390 T. curves (up to 30 squares)
H_3(2, 1^2)^c: 253 T. curves (up to 20 squares)
H_3(1^4)^c : 468 T. curves (up to 20 squares)
Total: 1744 Teichmueller curves
More
If you have any doubt, question or request, send me an e-mail and I will update the package or/and this document. Any contribution is welcome!
Cet article est publié sous la licence Creative Commons Attribution-NonCommercial 4.0 International License.
This article is published under the Creative Commons Attribution-NonCommercial 4.0 International License.