Path: blob/master/src/sage/dynamics/flat_surfaces/strata.py
8817 views
r"""1Strata of differentials on Riemann surfaces23The space of Abelian (or quadratic) differentials is stratified by the4degrees of the zeroes (and simple poles for quadratic5differentials). Each stratum has one, two or three connected6components and each is associated to an (extended) Rauzy class. The7:meth:`~sage.dynamics.flat_surfaces.strata.AbelianStratum.connected_components`8method (only available for Abelian stratum) give the decomposition of9a stratum (which corresponds to the SAGE object10:class:`~sage.dynamics.flat_surfaces.strata.AbelianStratum`).1112The work for Abelian differentials was done by Maxim Kontsevich and Anton13Zorich in [KonZor03]_ and for quadratic differentials by Erwan Lanneau in14[Lan08]_. Zorich gave an algorithm to pass from a connected component of a15stratum to the associated Rauzy class (for both interval exchange16transformations and linear involutions) in [Zor08]_ and is implemented for17Abelian stratum at different level (approximately one for each component):1819- for connected stratum :meth:`~ConnectedComponentOfAbelianStratum.representative`20- for hyperellitic component :meth:`~HypConnectedComponentOfAbelianStratum.representative`21- for non hyperelliptic component, the algorithm is the same as for connected22component23- for odd component :meth:`~OddConnectedComponentOfAbelianStratum.representative`24- for even component :meth:`~EvenConnectedComponentOfAbelianStratum.representative`2526The inverse operation (pass from an interval exchange transformation to27the connected component) is partially written in [KonZor03]_ and28simply named here29:meth:`~sage.dynamics.interval_exchanges.template.PermutationIET.connected_component`.3031All the code here was first available on Mathematica [ZS]_.3233REFERENCES:3435.. [KonZor03] M. Kontsevich, A. Zorich "Connected components of the moduli space36of Abelian differentials with prescripebd singularities" Invent. math. 153,37631-678 (2003)3839.. [Lan08] E. Lanneau "Connected components of the strata of the moduli spaces40of quadratic differentials", Annales sci. de l'ENS, serie 4, fascicule 1,4141, 1-56 (2008)4243.. [Zor08] A. Zorich "Explicit Jenkins-Strebel representatives of all strata of44Abelian and quadratic differentials", Journal of Modern Dynamics, vol. 2,45no 1, 139-185 (2008) (http://www.math.psu.edu/jmd)4647.. [ZS] Anton Zorich, "Generalized Permutation software"48(http://perso.univ-rennes1.fr/anton.zorich/Software/software_en.html)4950.. NOTE::5152The quadratic strata are not yet implemented.5354AUTHORS:5556- Vincent Delecroix (2009-09-29): initial version575859EXAMPLES:6061Construction of a stratum from a list of singularity degrees::6263sage: a = AbelianStratum(1,1)64sage: print a65H(1, 1)66sage: print a.genus()67268sage: print a.nintervals()6957071::7273sage: a = AbelianStratum(4,3,2,1)74sage: print a75H(4, 3, 2, 1)76sage: print a.genus()77678sage: print a.nintervals()79158081By convention, the degrees are always written in decreasing order::8283sage: a1 = AbelianStratum(4,3,2,1)84sage: a185H(4, 3, 2, 1)86sage: a2 = AbelianStratum(2,3,1,4)87sage: a288H(4, 3, 2, 1)89sage: a1 == a290True9192It is also possible to consider stratum with an incoming or an93outgoing separatrix marked (the aim of this consideration is to94attach a specified degree at the left or the right of the associated95interval exchange transformation)::9697sage: a_out = AbelianStratum(1, 1, marked_separatrix='out')98sage: a_out99H^out(1, 1)100sage: a_in = AbelianStratum(1, 1, marked_separatrix='in')101sage: a_in102H^in(1, 1)103sage: a_out == a_in104False105106Get a list of strata with constraints on genus or on the number of intervals107of a representative::108109sage: for a in AbelianStrata(genus=3):110....: print a111H(4)112H(3, 1)113H(2, 2)114H(2, 1, 1)115H(1, 1, 1, 1)116117::118119sage: for a in AbelianStrata(nintervals=5):120....: print a121H^out(0, 2)122H^out(2, 0)123H^out(1, 1)124H^out(0, 0, 0, 0)125126::127128sage: for a in AbelianStrata(genus=2, nintervals=5):129....: print a130H^out(0, 2)131H^out(2, 0)132H^out(1, 1)133134Obtains the connected components of a stratum::135136sage: a = AbelianStratum(0)137sage: print a.connected_components()138[H_hyp(0)]139140::141142sage: a = AbelianStratum(6)143sage: cc = a.connected_components()144sage: print cc145[H_hyp(6), H_odd(6), H_even(6)]146sage: for c in cc:147....: print c, "\n", c.representative(alphabet=range(1,9))148H_hyp(6)1491 2 3 4 5 6 7 81508 7 6 5 4 3 2 1151H_odd(6)1521 2 3 4 5 6 7 81534 3 6 5 8 7 2 1154H_even(6)1551 2 3 4 5 6 7 81566 5 4 3 8 7 2 1157158::159160sage: a = AbelianStratum(1, 1, 1, 1)161sage: print a.connected_components()162[H_c(1, 1, 1, 1)]163sage: c = a.connected_components()[0]164sage: print c.representative(alphabet="abcdefghi")165a b c d e f g h i166e d c f i h g b a167168The zero attached on the left of the associated Abelian permutation169corresponds to the first singularity degree::170171sage: a = AbelianStratum(4, 2, marked_separatrix='out')172sage: b = AbelianStratum(2, 4, marked_separatrix='out')173sage: print a == b174False175sage: print a, ":", a.connected_components()176H^out(4, 2) : [H_odd^out(4, 2), H_even^out(4, 2)]177sage: print b, ":", b.connected_components()178H^out(2, 4) : [H_odd^out(2, 4), H_even^out(2, 4)]179sage: a_odd, a_even = a.connected_components()180sage: b_odd, b_even = b.connected_components()181182The representatives are hence different::183184sage: print a_odd.representative(alphabet=range(1,10))1851 2 3 4 5 6 7 8 91864 3 6 5 7 9 8 2 1187sage: print b_odd.representative(alphabet=range(1,10))1881 2 3 4 5 6 7 8 91894 3 5 7 6 9 8 2 1190191::192193sage: print a_even.representative(alphabet=range(1,10))1941 2 3 4 5 6 7 8 91956 5 4 3 7 9 8 2 1196sage: print b_even.representative(alphabet=range(1,10))1971 2 3 4 5 6 7 8 91987 6 5 4 3 9 8 2 1199200You can retrieve the decomposition of the irreducible Abelian permutations into201Rauzy diagrams from the classification of strata::202203sage: a = AbelianStrata(nintervals=4)204sage: l = sum([stratum.connected_components() for stratum in a], [])205sage: n = map(lambda x: x.rauzy_diagram().cardinality(), l)206sage: for c,i in zip(l,n):207....: print c, ":", i208H_hyp^out(2) : 7209H_hyp^out(0, 0, 0) : 6210sage: print sum(n)21113212213::214215sage: a = AbelianStrata(nintervals=5)216sage: l = sum([stratum.connected_components() for stratum in a], [])217sage: n = map(lambda x: x.rauzy_diagram().cardinality(), l)218sage: for c,i in zip(l,n):219....: print c, ":", i220H_hyp^out(0, 2) : 11221H_hyp^out(2, 0) : 35222H_hyp^out(1, 1) : 15223H_hyp^out(0, 0, 0, 0) : 10224sage: print sum(n)22571226227::228229sage: a = AbelianStrata(nintervals=6)230sage: l = sum([stratum.connected_components() for stratum in a], [])231sage: n = map(lambda x: x.rauzy_diagram().cardinality(), l)232sage: for c,i in zip(l,n):233....: print c, ":", i234H_hyp^out(4) : 31235H_odd^out(4) : 134236H_hyp^out(0, 2, 0) : 66237H_hyp^out(2, 0, 0) : 105238H_hyp^out(0, 1, 1) : 20239H_hyp^out(1, 1, 0) : 90240H_hyp^out(0, 0, 0, 0, 0) : 15241sage: print sum(n)242461243"""244#*****************************************************************************245# Copyright (C) 2009 Vincent Delecroix <[email protected]>246#247# Distributed under the terms of the GNU General Public License (GPL)248# http://www.gnu.org/licenses/249#*****************************************************************************250251from sage.structure.sage_object import SageObject252253from sage.combinat.combinat import CombinatorialClass254from sage.combinat.combinat import InfiniteAbstractCombinatorialClass255from sage.combinat.partition import Partitions256257from sage.rings.integer import Integer258from sage.rings.rational import Rational259260261def AbelianStrata(genus=None, nintervals=None, marked_separatrix=None):262r"""263Abelian strata.264265INPUT:266267- ``genus`` - a non negative integer or ``None``268269- ``nintervals`` - a non negative integer or ``None``270271- ``marked_separatrix`` - 'no' (for no marking), 'in' (for marking an272incoming separatrix) or 'out' (for marking an outgoing separatrix)273274EXAMPLES:275276Abelian strata with a given genus::277278sage: for s in AbelianStrata(genus=1): print s279H(0)280281::282283sage: for s in AbelianStrata(genus=2): print s284H(2)285H(1, 1)286287::288289sage: for s in AbelianStrata(genus=3): print s290H(4)291H(3, 1)292H(2, 2)293H(2, 1, 1)294H(1, 1, 1, 1)295296::297298sage: for s in AbelianStrata(genus=4): print s299H(6)300H(5, 1)301H(4, 2)302H(4, 1, 1)303H(3, 3)304H(3, 2, 1)305H(3, 1, 1, 1)306H(2, 2, 2)307H(2, 2, 1, 1)308H(2, 1, 1, 1, 1)309H(1, 1, 1, 1, 1, 1)310311Abelian strata with a given number of intervals::312313sage: for s in AbelianStrata(nintervals=2): print s314H^out(0)315316::317318sage: for s in AbelianStrata(nintervals=3): print s319H^out(0, 0)320321::322323sage: for s in AbelianStrata(nintervals=4): print s324H^out(2)325H^out(0, 0, 0)326327::328329sage: for s in AbelianStrata(nintervals=5): print s330H^out(0, 2)331H^out(2, 0)332H^out(1, 1)333H^out(0, 0, 0, 0)334335Abelian strata with both constraints::336337sage: for s in AbelianStrata(genus=2, nintervals=4): print s338H^out(2)339340::341342sage: for s in AbelianStrata(genus=5, nintervals=12): print s343H^out(8, 0, 0)344H^out(0, 8, 0)345H^out(0, 7, 1)346H^out(1, 7, 0)347H^out(7, 1, 0)348H^out(0, 6, 2)349H^out(2, 6, 0)350H^out(6, 2, 0)351H^out(1, 6, 1)352H^out(6, 1, 1)353H^out(0, 5, 3)354H^out(3, 5, 0)355H^out(5, 3, 0)356H^out(1, 5, 2)357H^out(2, 5, 1)358H^out(5, 2, 1)359H^out(0, 4, 4)360H^out(4, 4, 0)361H^out(1, 4, 3)362H^out(3, 4, 1)363H^out(4, 3, 1)364H^out(2, 4, 2)365H^out(4, 2, 2)366H^out(2, 3, 3)367H^out(3, 3, 2)368"""369if genus is None:370if nintervals is None:371return AbelianStrata_all()372else:373return AbelianStrata_d(374nintervals=nintervals,375marked_separatrix=marked_separatrix)376else:377if nintervals is None:378return AbelianStrata_g(379genus=genus,380marked_separatrix=marked_separatrix)381else:382return AbelianStrata_gd(383genus=genus,384nintervals=nintervals,385marked_separatrix=marked_separatrix)386387388class AbelianStrata_g(CombinatorialClass):389r"""390Stratas of genus g surfaces.391392INPUT:393394- ``genus`` - a non negative integer395396- ``marked_separatrix`` - 'no', 'out' or 'in'397"""398def __init__(self, genus=None, marked_separatrix=None):399r"""400TESTS::401402sage: s = AbelianStrata(genus=3)403sage: s == loads(dumps(s))404True405406sage: AbelianStrata(genus=-3)407Traceback (most recent call last):408...409ValueError: genus must be positive410411sage: AbelianStrata(genus=3, marked_separatrix='yes')412Traceback (most recent call last):413...414ValueError: marked_separatrix must be no, out or in415"""416genus = Integer(genus)417418if not(genus >= 0):419raise ValueError('genus must be positive')420421if marked_separatrix is None:422marked_separatrix = 'no'423if not marked_separatrix in ['no', 'out', 'in']:424raise ValueError("marked_separatrix must be no, out or in")425self._marked_separatrix = marked_separatrix426427self._genus = genus428429def _repr_(self):430r"""431TESTS::432433sage: repr(AbelianStrata(genus=3)) #indirect doctest434'Abelian strata of genus 3 surfaces'435"""436if self._marked_separatrix == 'no':437return "Abelian strata of genus %d surfaces" % (self._genus)438elif self._marked_separatrix == 'in':439return "Abelian strata of genus %d surfaces and a marked incoming separatrix" % (self._genus)440else:441return "Abelian strata of genus %d surfaces and a marked outgoing separatrix" % (self._genus)442443def __iter__(self):444r"""445TESTS::446447sage: list(AbelianStrata(genus=1))448[H(0)]449"""450if self._genus == 0:451pass452elif self._genus == 1:453yield AbelianStratum(0, marked_separatrix=self._marked_separatrix)454else:455if self._marked_separatrix == 'no':456for p in Partitions(2*self._genus-2):457yield AbelianStratum(p)458else:459for p in Partitions(2*self._genus-2):460l = list(p)461for t in set(l):462i = l.index(t)463yield AbelianStratum([t] + l[:i] + l[i+1:],464marked_separatrix=self._marked_separatrix)465466467class AbelianStrata_d(CombinatorialClass):468r"""469Strata with constraint number of intervals.470471INPUT:472473- ``nintervals`` - an integer greater than 1474475- ``marked_separatrix`` - 'no', 'out' or 'in'476"""477def __init__(self, nintervals=None, marked_separatrix=None):478r"""479TESTS::480481sage: s = AbelianStrata(nintervals=10)482sage: s == loads(dumps(s))483True484485sage: AbelianStrata(nintervals=1)486Traceback (most recent call last):487...488ValueError: number of intervals must be at least 2489490sage: AbelianStrata(nintervals=4, marked_separatrix='maybe')491Traceback (most recent call last):492...493ValueError: marked_separatrix must be no, out or in494"""495nintervals = Integer(nintervals)496497if not(nintervals > 1):498raise ValueError("number of intervals must be at least 2")499500self._nintervals = nintervals501502if marked_separatrix is None:503marked_separatrix = 'out'504if not marked_separatrix in ['no', 'out', 'in']:505raise ValueError("marked_separatrix must be no, out or in")506self._marked_separatrix = marked_separatrix507508def _repr_(self):509r"""510TESTS::511512sage: repr(AbelianStrata(nintervals=2,marked_separatrix='no')) #indirect doctest513'Abelian strata with 2 intervals IET'514"""515if self._marked_separatrix == 'no':516return "Abelian strata with %d intervals IET" % (self._nintervals)517elif self._marked_separatrix == 'in':518return "Abelian strata with %d intervals IET and a marked incoming separatrix" % (self._nintervals)519else:520return "Abelian strata with %d intervals IET and a marked outgoing separatrix" % (self._nintervals)521522def __iter__(self):523r"""524TESTS::525526sage: for a in AbelianStrata(nintervals=4): print a527H^out(2)528H^out(0, 0, 0)529"""530n = self._nintervals531for s in range(1+n % 2, n, 2):532for p in Partitions(n-1, length=s):533l = [k-1 for k in p]534if self._marked_separatrix == 'no':535yield AbelianStratum(l, marked_separatrix='no')536else:537for t in set(l):538i = l.index(t)539yield AbelianStratum([t] + l[:i] + l[i+1:],540marked_separatrix=self._marked_separatrix)541542543class AbelianStrata_gd(CombinatorialClass):544r"""545Abelian strata of prescribed genus and number of intervals.546547INPUT:548549- ``genus`` - integer: the genus of the surfaces550551- ``nintervals`` - integer: the number of intervals552553- ``marked_separatrix`` - 'no', 'in' or 'out'554"""555def __init__(self, genus=None, nintervals=None, marked_separatrix=None):556r"""557TESTS::558559sage: s = AbelianStrata(genus=4,nintervals=10)560sage: s == loads(dumps(s))561True562563sage: AbelianStrata(genus=-1)564Traceback (most recent call last):565...566ValueError: genus must be positive567568sage: AbelianStrata(genus=1, nintervals=1)569Traceback (most recent call last):570...571ValueError: number of intervals must be at least 2572573sage: AbelianStrata(genus=1, marked_separatrix='so')574Traceback (most recent call last):575...576ValueError: marked_separatrix must be no, out or in577"""578genus = Integer(genus)579580if not(genus >= 0):581raise ValueError("genus must be positive")582self._genus = genus583584nintervals = Integer(nintervals)585if not(nintervals > 1):586raise ValueError("number of intervals must be at least 2")587self._nintervals = nintervals588589if marked_separatrix is None:590marked_separatrix = 'out'591if not marked_separatrix in ['no', 'out', 'in']:592raise ValueError("marked_separatrix must be no, out or in")593594self._marked_separatrix = marked_separatrix595596def __repr__(self):597r"""598TESTS::599600sage: a = AbelianStrata(genus=2,nintervals=4,marked_separatrix='no')601sage: repr(a) #indirect doctest602'Abelian strata of genus 2 surfaces and 4 intervals'603"""604if self._marked_separatrix == 'no':605return "Abelian strata of genus %d surfaces and %d intervals" % (self._genus, self._nintervals)606elif self._marked_separatrix == 'in':607return "Abelian strata of genus %d surfaces and %d intervals and a marked incoming ihorizontal separatrix" % (self._genus, self._nintervals)608else:609return "Abelian strata of genus %d surfaces and %d intervals and a marked outgoing horizontal separatrix" % (self._genus, self._nintervals)610611def __iter__(self):612r"""613TESTS::614615sage: list(AbelianStrata(genus=2,nintervals=4))616[H^out(2)]617"""618if self._genus == 0:619pass620elif self._genus == 1:621if self._nintervals >= 2:622yield AbelianStratum([0]*(self._nintervals-1),623marked_separatrix='out')624else:625s = self._nintervals - 2*self._genus + 1626for p in Partitions(2*self._genus - 2 + s, length=s):627l = [k-1 for k in p]628for t in set(l):629i = l.index(t)630yield AbelianStratum([t] + l[:i] +631l[i+1:], marked_separatrix='out')632633634class AbelianStrata_all(InfiniteAbstractCombinatorialClass):635r"""636Abelian strata.637"""638def __repr__(self):639r"""640TESTS::641642sage: repr(AbelianStrata()) #indirect doctest643'Abelian strata'644"""645return "Abelian strata"646647def _infinite_cclass_slice(self, g):648r"""649TESTS::650651sage: AbelianStrata()[0]652H(0)653sage: AbelianStrata()[1]654H(2)655sage: AbelianStrata()[2]656H(1, 1)657658::659660sage: a = AbelianStrata()661sage: a._infinite_cclass_slice(0) == AbelianStrata(genus=0)662True663sage: a._infinite_cclass_slice(10) == AbelianStrata(genus=10)664True665"""666return AbelianStrata_g(g)667668669class AbelianStratum(SageObject):670"""671Stratum of Abelian differentials.672673A stratum with a marked outgoing separatrix corresponds to Rauzy diagram674with left induction, a stratum with marked incoming separatrix correspond675to Rauzy diagram with right induction.676If there is no marked separatrix, the associated Rauzy diagram is the677extended Rauzy diagram (consideration of the678:meth:`sage.dynamics.interval_exchanges.template.Permutation.symmetric`679operation of Boissy-Lanneau).680681When you want to specify a marked separatrix, the degree on which it is is682the first term of your degrees list.683684INPUT:685686- ``marked_separatrix`` - ``None`` (default) or 'in' (for incoming687separatrix) or 'out' (for outgoing separatrix).688689EXAMPLES:690691Creation of an Abelian stratum and get its connected components::692693sage: a = AbelianStratum(2, 2)694sage: print a695H(2, 2)696sage: a.connected_components()697[H_hyp(2, 2), H_odd(2, 2)]698699Specification of marked separatrix:700701::702703sage: a = AbelianStratum(4,2,marked_separatrix='in')704sage: print a705H^in(4, 2)706sage: b = AbelianStratum(2,4,marked_separatrix='in')707sage: print b708H^in(2, 4)709sage: a == b710False711712::713714sage: a = AbelianStratum(4,2,marked_separatrix='out')715sage: print a716H^out(4, 2)717sage: b = AbelianStratum(2,4,marked_separatrix='out')718sage: print b719H^out(2, 4)720sage: a == b721False722723Get a representative of a connected component::724725sage: a = AbelianStratum(2,2)726sage: a_hyp, a_odd = a.connected_components()727sage: print a_hyp.representative()7281 2 3 4 5 6 77297 6 5 4 3 2 1730sage: print a_odd.representative()7310 1 2 3 4 5 67323 2 4 6 5 1 0733734You can choose the alphabet::735736sage: print a_odd.representative(alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ")737A B C D E F G738D C E G F B A739740By default, you get a reduced permutation, but you can specify741that you want a labelled one::742743sage: p_reduced = a_odd.representative()744sage: p_labelled = a_odd.representative(reduced=False)745"""746def __init__(self, *l, **d):747"""748TESTS::749750sage: s = AbelianStratum(0)751sage: s == loads(dumps(s))752True753sage: s = AbelianStratum(1,1,1,1)754sage: s == loads(dumps(s))755True756757sage: AbelianStratum('no','way')758Traceback (most recent call last):759...760ValueError: input must be a list of integers761762sage: AbelianStratum([1,1,1,1], marked_separatrix='full')763Traceback (most recent call last):764...765ValueError: marked_separatrix must be one of 'no', 'in', 'out'766"""767if l == ():768pass769770elif hasattr(l[0], "__iter__") and len(l) == 1:771l = l[0]772773if not all(isinstance(i, (Integer, int)) for i in l):774raise ValueError("input must be a list of integers")775776if 'marked_separatrix' in d:777m = d['marked_separatrix']778779if m is None:780m = 'no'781782if (m != 'no' and m != 'in' and m != 'out'):783raise ValueError("marked_separatrix must be one of 'no', "784"'in', 'out'")785self._marked_separatrix = m786787else: # default value788self._marked_separatrix = 'no'789790self._zeroes = list(l)791792if not self._marked_separatrix is 'no':793self._zeroes[1:] = sorted(self._zeroes[1:], reverse=True)794else:795self._zeroes.sort(reverse=True)796797self._genus = sum(l)/2 + 1798799self._genus = Integer(self._genus)800801zeroes = filter(lambda x: x > 0, self._zeroes)802zeroes.sort()803804if self._genus == 1:805self._cc = (HypCCA,)806807elif self._genus == 2:808self._cc = (HypCCA,)809810elif self._genus == 3:811if zeroes == [2, 2] or zeroes == [4]:812self._cc = (HypCCA, OddCCA)813else:814self._cc = (CCA,)815816elif len(zeroes) == 1:817# just one zeros [2g-2]818self._cc = (HypCCA, OddCCA, EvenCCA)819820elif zeroes == [self._genus-1, self._genus-1]:821# two similar zeros [g-1, g-1]822if self._genus % 2 == 0:823self._cc = (HypCCA, NonHypCCA)824825else:826self._cc = (HypCCA, OddCCA, EvenCCA)827828elif len(filter(lambda x: x % 2, zeroes)) == 0:829# even zeroes [2 l_1, 2 l_2, ..., 2 l_n]830self._cc = (OddCCA, EvenCCA)831832else:833self._cc = (CCA, )834835def _repr_(self):836"""837TESTS::838839sage: repr(AbelianStratum(1,1)) #indirect doctest840'H(1, 1)'841"""842if self._marked_separatrix == 'no':843return "H(" + str(self._zeroes)[1:-1] + ")"844else:845return ("H" +846'^' + self._marked_separatrix +847"(" + str(self._zeroes)[1:-1] + ")")848849def __str__(self):850r"""851TESTS::852853sage: str(AbelianStratum(1,1))854'H(1, 1)'855"""856if self._marked_separatrix == 'no':857return "H(" + str(self._zeroes)[1:-1] + ")"858else:859return ("H" +860'^' + self._marked_separatrix +861"(" + str(self._zeroes)[1:-1] + ")")862863def __eq__(self, other):864r"""865TESTS:866867sage: a = AbelianStratum(1,3)868sage: b = AbelianStratum(3,1)869sage: c = AbelianStratum(1,3,marked_separatrix='out')870sage: d = AbelianStratum(3,1,marked_separatrix='out')871sage: e = AbelianStratum(1,3,marked_separatrix='in')872sage: f = AbelianStratum(3,1,marked_separatrix='in')873sage: a == b # no difference for unmarked874True875sage: c == d # difference for out mark876False877sage: e == f # difference for in mark878False879sage: a == c # difference between no mark and out mark880False881sage: a == e # difference between no mark and in mark882False883sage: c == e # difference between out mark adn in mark884False885886sage: a == False887Traceback (most recent call last):888...889TypeError: the right member must be a stratum890"""891if type(self) != type(other):892raise TypeError("the right member must be a stratum")893894return (self._marked_separatrix == other._marked_separatrix and895self._zeroes == other._zeroes)896897def __ne__(self, other):898r"""899TESTS::900901sage: a = AbelianStratum(1,3)902sage: b = AbelianStratum(3,1)903sage: c = AbelianStratum(1,3,marked_separatrix='out')904sage: d = AbelianStratum(3,1,marked_separatrix='out')905sage: e = AbelianStratum(1,3,marked_separatrix='in')906sage: f = AbelianStratum(3,1,marked_separatrix='in')907sage: a != b # no difference for unmarked908False909sage: c != d # difference for out mark910True911sage: e != f # difference for in mark912True913sage: a != c # difference between no mark and out mark914True915sage: a != e # difference between no mark and in mark916True917sage: c != e # difference between out mark adn in mark918True919sage: a != False920Traceback (most recent call last):921...922TypeError: the right member must be a stratum923"""924if type(self) != type(other):925raise TypeError("the right member must be a stratum")926927return (self._marked_separatrix != other._marked_separatrix or928self._zeroes != other._zeroes)929930def __cmp__(self, other):931r"""932The order is given by the natural:933934self < other iff adherance(self) c adherance(other)935936TESTS::937938sage: a3 = AbelianStratum(3,2,1)939sage: a3_out = AbelianStratum(3,2,1,marked_separatrix='out')940sage: a3_in = AbelianStratum(3,2,1,marked_separatrix='in')941sage: a3 == a3_out942False943sage: a3 == a3_in944False945sage: a3_out == a3_in946False947"""948if (type(self) != type(other) or949self._marked_separatrix != other._marked_separatrix):950raise TypeError("the other must be a stratum with same marking")951952if self._zeroes < other._zeroes:953return 1954elif self._zeroes > other._zeroes:955return -1956return 0957958def connected_components(self):959"""960Lists the connected components of the Stratum.961962OUTPUT:963964list -- a list of connected components of stratum965966EXAMPLES:967968::969970sage: AbelianStratum(0).connected_components()971[H_hyp(0)]972973::974975sage: AbelianStratum(2).connected_components()976[H_hyp(2)]977sage: AbelianStratum(1,1).connected_components()978[H_hyp(1, 1)]979980::981982sage: AbelianStratum(4).connected_components()983[H_hyp(4), H_odd(4)]984sage: AbelianStratum(3,1).connected_components()985[H_c(3, 1)]986sage: AbelianStratum(2,2).connected_components()987[H_hyp(2, 2), H_odd(2, 2)]988sage: AbelianStratum(2,1,1).connected_components()989[H_c(2, 1, 1)]990sage: AbelianStratum(1,1,1,1).connected_components()991[H_c(1, 1, 1, 1)]992"""993return map(lambda x: x(self), self._cc)994995def is_connected(self):996r"""997Tests if the strata is connected.998999OUTPUT:10001001boolean -- ``True`` if it is connected else ``False``10021003EXAMPLES:10041005::10061007sage: AbelianStratum(2).is_connected()1008True1009sage: AbelianStratum(2).connected_components()1010[H_hyp(2)]10111012::10131014sage: AbelianStratum(2,2).is_connected()1015False1016sage: AbelianStratum(2,2).connected_components()1017[H_hyp(2, 2), H_odd(2, 2)]1018"""1019return len(self._cc) == 110201021def genus(self):1022r"""1023Returns the genus of the stratum.10241025OUTPUT:10261027integer -- the genus10281029EXAMPLES:10301031::10321033sage: AbelianStratum(0).genus()103411035sage: AbelianStratum(1,1).genus()103621037sage: AbelianStratum(3,2,1).genus()103841039"""1040return self._genus10411042def nintervals(self):1043r"""1044Returns the number of intervals of any iet of the strata.10451046OUTPUT:10471048integer -- the number of intervals for any associated iet10491050EXAMPLES:10511052::10531054sage: AbelianStratum(0).nintervals()105521056sage: AbelianStratum(0,0).nintervals()105731058sage: AbelianStratum(2).nintervals()105941060sage: AbelianStratum(1,1).nintervals()106151062"""1063return 2 * self.genus() + len(self._zeroes) - 1106410651066class ConnectedComponentOfAbelianStratum(SageObject):1067r"""1068Connected component of Abelian stratum.10691070.. warning::10711072Internal class! Do not use directly!10731074TESTS:10751076Tests for outgoing marked separatrices::10771078sage: a = AbelianStratum(4,2,0,marked_separatrix='out')1079sage: a_odd, a_even = a.connected_components()1080sage: a_odd.representative().attached_out_degree()108141082sage: a_even.representative().attached_out_degree()1083410841085::10861087sage: a = AbelianStratum(2,4,0,marked_separatrix='out')1088sage: a_odd, a_even = a.connected_components()1089sage: a_odd.representative().attached_out_degree()109021091sage: a_even.representative().attached_out_degree()1092210931094::10951096sage: a = AbelianStratum(0,4,2,marked_separatrix='out')1097sage: a_odd, a_even = a.connected_components()1098sage: a_odd.representative().attached_out_degree()109901100sage: a_even.representative().attached_out_degree()1101011021103::11041105sage: a = AbelianStratum(3,2,1,marked_separatrix='out')1106sage: a_c = a.connected_components()[0]1107sage: a_c.representative().attached_out_degree()1108311091110::11111112sage: a = AbelianStratum(2,3,1,marked_separatrix='out')1113sage: a_c = a.connected_components()[0]1114sage: a_c.representative().attached_out_degree()1115211161117::11181119sage: a = AbelianStratum(1,3,2,marked_separatrix='out')1120sage: a_c = a.connected_components()[0]1121sage: a_c.representative().attached_out_degree()1122111231124Tests for incoming separatrices::11251126sage: a = AbelianStratum(4,2,0,marked_separatrix='in')1127sage: a_odd, a_even = a.connected_components()1128sage: a_odd.representative().attached_in_degree()112941130sage: a_even.representative().attached_in_degree()1131411321133::11341135sage: a = AbelianStratum(2,4,0,marked_separatrix='in')1136sage: a_odd, a_even = a.connected_components()1137sage: a_odd.representative().attached_in_degree()113821139sage: a_even.representative().attached_in_degree()1140211411142::11431144sage: a = AbelianStratum(0,4,2,marked_separatrix='in')1145sage: a_odd, a_even = a.connected_components()1146sage: a_odd.representative().attached_in_degree()114701148sage: a_even.representative().attached_in_degree()1149011501151::11521153sage: a = AbelianStratum(3,2,1,marked_separatrix='in')1154sage: a_c = a.connected_components()[0]1155sage: a_c.representative().attached_in_degree()1156311571158::11591160sage: a = AbelianStratum(2,3,1,marked_separatrix='in')1161sage: a_c = a.connected_components()[0]1162sage: a_c.representative().attached_in_degree()1163211641165::11661167sage: a = AbelianStratum(1,3,2,marked_separatrix='in')1168sage: a_c = a.connected_components()[0]1169sage: a_c.representative().attached_in_degree()117011171"""1172_name = 'c'11731174def __init__(self, parent):1175r"""1176TESTS::11771178sage: a = AbelianStratum([1]*10).connected_components()[0]1179sage: a == loads(dumps(a))1180True1181"""1182self._parent = parent11831184def _repr_(self):1185r"""1186TESTS::11871188sage: a = AbelianStratum([1]*8).connected_components()[0]1189sage: repr(a) #indirect doctest1190'H_c(1, 1, 1, 1, 1, 1, 1, 1)'1191"""1192if self._parent._marked_separatrix == 'no':1193return ("H" +1194"_" + self._name +1195"(" + str(self._parent._zeroes)[1:-1] + ")")11961197else:1198return ("H" +1199"_" + self._name +1200"^" + self._parent._marked_separatrix +1201"(" + str(self._parent._zeroes)[1:-1] + ")")12021203def __str__(self):1204r"""1205TESTS::12061207sage: str(AbelianStratum([1]*8))1208'H(1, 1, 1, 1, 1, 1, 1, 1)'1209"""1210if self._parent._marked_separatrix == 'no':1211return ("H" +1212"_" + self._name +1213"(" + str(self._parent._zeroes)[1:-1] + ")")12141215else:1216return ("H" +1217"_" + self._name +1218"^" + self._parent._marked_separatrix +1219"(" + str(self._parent._zeroes)[1:-1] + ")")12201221def parent(self):1222r"""1223The stratum of this component12241225OUTPUT:12261227stratum - the stratum where this component leaves12281229EXAMPLES::12301231sage: p = iet.Permutation('a b','b a')1232sage: c = p.connected_component()1233sage: c.parent()1234H(0)1235"""1236return self._parent12371238def representative(self, reduced=True, alphabet=None):1239r"""1240Returns the Zorich representative of this connected component.12411242Zorich constructs explicitely interval exchange1243transformations for each stratum in [Zor08]_.12441245INPUT:12461247- ``reduced`` - boolean (default: ``True``): whether you1248obtain a reduced or labelled permutation12491250- ``alphabet`` - an alphabet or ``None``: whether you want to1251specify an alphabet for your permutation12521253OUTPUT:12541255permutation -- a permutation which lives in this component12561257EXAMPLES:12581259::12601261sage: c = AbelianStratum(1,1,1,1).connected_components()[0]1262sage: print c1263H_c(1, 1, 1, 1)1264sage: p = c.representative(alphabet=range(9))1265sage: print p12660 1 2 3 4 5 6 7 812674 3 2 5 8 7 6 1 01268sage: p.connected_component()1269H_c(1, 1, 1, 1)1270"""1271g = self._parent._genus1272zeroes = filter(lambda x: x > 0, self._parent._zeroes)1273n = self._parent._zeroes.count(0)12741275l0 = range(0, 4*g-3)1276l1 = [4, 3, 2]1277for k in range(5, 4*g-6, 4):1278l1 += [k, k+3, k+2, k+1]1279l1 += [1, 0]1280k = 31281for d in zeroes:1282for i in range(d-1):1283del l0[l0.index(k)]1284del l1[l1.index(k)]1285k += 21286k += 212871288if n != 0:1289interval = range(4*g-3, 4*g-3+n)12901291if self._parent._zeroes[0] == 0:1292k = l0.index(4)1293l0[k:k] = interval1294l1[-1:-1] = interval1295else:1296l0[1:1] = interval1297l1.extend(interval)12981299if self._parent._marked_separatrix == 'in':1300l0.reverse()1301l1.reverse()13021303if reduced:1304from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET1305return ReducedPermutationIET([l0, l1], alphabet=alphabet)13061307else:1308from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET1309return LabelledPermutationIET([l0, l1], alphabet=alphabet)131013111312def genus(self):1313r"""1314Returns the genus of the surfaces in this connected component.13151316OUTPUT:13171318integer -- the genus of the surface13191320EXAMPLES:13211322::13231324sage: a = AbelianStratum(6,4,2,0,0)1325sage: c_odd, c_even = a.connected_components()1326sage: c_odd.genus()132771328sage: c_even.genus()1329713301331::13321333sage: a = AbelianStratum([1]*8)1334sage: c = a.connected_components()[0]1335sage: c.genus()133651337"""1338return self._parent.genus()13391340def nintervals(self):1341r"""1342Returns the number of intervals of the representative.13431344OUTPUT:13451346integer -- the number of intervals in any representative13471348EXAMPLES:13491350::13511352sage: a = AbelianStratum(6,4,2,0,0)1353sage: c_odd, c_even = a.connected_components()1354sage: c_odd.nintervals()1355181356sage: c_even.nintervals()13571813581359::13601361sage: a = AbelianStratum([1]*8)1362sage: c = a.connected_components()[0]1363sage: c.nintervals()1364171365"""1366return self.parent().nintervals()13671368def rauzy_diagram(self, reduced=True):1369r"""1370Returns the Rauzy diagram associated to this connected component.13711372OUTPUT:13731374rauzy diagram -- the Rauzy diagram associated to this stratum13751376EXAMPLES:13771378::13791380sage: c = AbelianStratum(0).connected_components()[0]1381sage: r = c.rauzy_diagram()1382"""1383return self.representative(reduced=reduced).rauzy_diagram()13841385def __cmp__(self, other):1386r"""1387TESTS::13881389sage: a1 = AbelianStratum(1,1,1,1)1390sage: c1 = a1.connected_components()[0]1391sage: a2 = AbelianStratum(3,1)1392sage: c2 = a2.connected_components()[0]1393sage: c1 == c11394True1395sage: c1 == c21396False1397sage: a1 = AbelianStratum(1,1,1,1)1398sage: c1 = a1.connected_components()[0]1399sage: a2 = AbelianStratum(2, 2)1400sage: c2_hyp, c2_odd = a2.connected_components()1401sage: c1 != c11402False1403sage: c1 != c2_hyp1404True1405sage: c2_hyp != c2_odd1406True1407sage: c1 == True1408Traceback (most recent call last):1409...1410TypeError: other must be a connected component1411"""1412if not isinstance(other, CCA):1413raise TypeError("other must be a connected component")14141415if type(self) == type(other):1416if self._parent._zeroes > other._parent._zeroes:1417return 11418elif self._parent._zeroes < other._parent._zeroes:1419return -11420return 014211422return cmp(type(self), type(other))14231424CCA = ConnectedComponentOfAbelianStratum142514261427class HypConnectedComponentOfAbelianStratum(CCA):1428"""1429Hyperelliptic component of Abelian stratum.14301431.. warning::14321433Internal class! Do not use directly!1434"""1435_name = 'hyp'14361437def representative(self, reduced=True, alphabet=None):1438r"""1439Returns the Zorich representative of this connected component.14401441Zorich constructs explicitely interval exchange1442transformations for each stratum in [Zor08]_.14431444INPUT:14451446- ``reduced`` - boolean (defaut: ``True``): whether you obtain1447a reduced or labelled permutation14481449- ``alphabet`` - alphabet or ``None`` (defaut: ``None``):1450whether you want to specify an alphabet for your1451representative14521453EXAMPLES:14541455::14561457sage: c = AbelianStratum(0).connected_components()[0]1458sage: c1459H_hyp(0)1460sage: p = c.representative(alphabet="01")1461sage: p14620 114631 01464sage: p.connected_component()1465H_hyp(0)14661467::14681469sage: c = AbelianStratum(0,0).connected_components()[0]1470sage: c1471H_hyp(0, 0)1472sage: p = c.representative(alphabet="abc")1473sage: p1474a b c1475c b a1476sage: p.connected_component()1477H_hyp(0, 0)14781479::14801481sage: c = AbelianStratum(2).connected_components()[0]1482sage: c1483H_hyp(2)1484sage: p = c.representative(alphabet="ABCD")1485sage: p1486A B C D1487D C B A1488sage: p.connected_component()1489H_hyp(2)14901491::14921493sage: c = AbelianStratum(1,1).connected_components()[0]1494sage: c1495H_hyp(1, 1)1496sage: p = c.representative(alphabet="01234")1497sage: p14980 1 2 3 414994 3 2 1 01500sage: p.connected_component()1501H_hyp(1, 1)1502"""1503g = self._parent._genus1504n = self._parent._zeroes.count(0)1505m = len(self._parent._zeroes) - n15061507if m == 0: # on the torus1508if n == 1:1509l0 = [0, 1]1510l1 = [1, 0]1511elif n == 2:1512l0 = [0, 1, 2]1513l1 = [2, 1, 0]1514else:1515l0 = range(1, n+2)1516l1 = [n+1] + range(1, n+1)15171518elif m == 1: # H(2g-2,0^n) or H(0,2g-2,0^(n-1))1519l0 = range(1, 2*g+1)1520l1 = range(2*g, 0, -1)1521interval = range(2*g+1, 2*g+n+1)15221523if self._parent._zeroes[0] == 0:1524l0[-1:-1] = interval1525l1[-1:-1] = interval1526else:1527l0[1:1] = interval1528l1[1:1] = interval15291530else: # H(g-1,g-1,0^n) or H(0,g-1,g-1,0^(n-1))1531l0 = range(1, 2*g+2)1532l1 = range(2*g+1, 0, -1)1533interval = range(2*g+2, 2*g+n+2)15341535if self._parent._zeroes[0] == 0:1536l0[-1:-1] = interval1537l1[-1:-1] = interval1538else:1539l0[1:1] = interval1540l1[1:1] = interval15411542if self._parent._marked_separatrix == 'in':1543l0.reverse()1544l1.reverse()15451546if reduced:1547from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET1548return ReducedPermutationIET([l0, l1], alphabet=alphabet)15491550else:1551from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET1552return LabelledPermutationIET([l0, l1], alphabet=alphabet)15531554HypCCA = HypConnectedComponentOfAbelianStratum155515561557class NonHypConnectedComponentOfAbelianStratum(CCA):1558"""1559Non hyperelliptic component of Abelian stratum.15601561.. warning::15621563Internal class! Do not use directly!1564"""1565_name = 'nonhyp'15661567NonHypCCA = NonHypConnectedComponentOfAbelianStratum156815691570class EvenConnectedComponentOfAbelianStratum(CCA):1571"""1572Connected component of Abelian stratum with even spin structure.15731574.. warning::15751576Internal class! Do not use directly!1577"""1578_name = 'even'15791580def representative(self, reduced=True, alphabet=None):1581r"""1582Returns the Zorich representative of this connected component.15831584Zorich constructs explicitely interval exchange1585transformations for each stratum in [Zor08]_.15861587EXAMPLES:15881589::15901591sage: c = AbelianStratum(6).connected_components()[2]1592sage: c1593H_even(6)1594sage: p = c.representative(alphabet=range(8))1595sage: p15960 1 2 3 4 5 6 715975 4 3 2 7 6 1 01598sage: p.connected_component()1599H_even(6)16001601::16021603sage: c = AbelianStratum(4,4).connected_components()[2]1604sage: c1605H_even(4, 4)1606sage: p = c.representative(alphabet=range(11))1607sage: p16080 1 2 3 4 5 6 7 8 9 1016095 4 3 2 6 8 7 10 9 1 01610sage: p.connected_component()1611H_even(4, 4)1612"""1613zeroes = filter(lambda x: x > 0, self._parent._zeroes)1614n = self._parent._zeroes.count(0)1615g = self._parent._genus16161617l0 = range(3*g-2)1618l1 = [6, 5, 4, 3, 2, 7, 9, 8]1619for k in range(10, 3*g-4, 3):1620l1 += [k, k+2, k+1]1621l1 += [1, 0]16221623k = 41624for d in zeroes:1625for i in range(d/2-1):1626del l0[l0.index(k)]1627del l1[l1.index(k)]1628k += 31629k += 316301631# if there are marked points we transform 0 in [3g-2, 3g-3, ...]1632if n != 0:1633interval = range(3*g-2, 3*g - 2 + n)16341635if self._parent._zeroes[0] == 0:1636k = l0.index(6)1637l0[k:k] = interval1638l1[-1:-1] = interval1639else:1640l0[1:1] = interval1641l1.extend(interval)16421643if self._parent._marked_separatrix == 'in':1644l0.reverse()1645l1.reverse()16461647if reduced:1648from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET1649return ReducedPermutationIET([l0, l1], alphabet=alphabet)16501651else:1652from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET1653return LabelledPermutationIET([l0, l1], alphabet=alphabet)16541655EvenCCA = EvenConnectedComponentOfAbelianStratum165616571658class OddConnectedComponentOfAbelianStratum(CCA):1659r"""1660Connected component of an Abelian stratum with odd spin parity.16611662.. warning::16631664Internal class! Do not use directly!1665"""1666_name = 'odd'16671668def representative(self, reduced=True, alphabet=None):1669"""1670Returns the Zorich representative of this connected component.16711672Zorich constructs explicitely interval exchange1673transformations for each stratum in [Zor08]_.16741675EXAMPLES:16761677::16781679sage: a = AbelianStratum(6).connected_components()[1]1680sage: print a.representative(alphabet=range(8))16810 1 2 3 4 5 6 716823 2 5 4 7 6 1 016831684::16851686sage: a = AbelianStratum(4,4).connected_components()[1]1687sage: print a.representative(alphabet=range(11))16880 1 2 3 4 5 6 7 8 9 1016893 2 5 4 6 8 7 10 9 1 01690"""1691zeroes = filter(lambda x: x > 0, self._parent._zeroes)1692zeroes = map(lambda x: x/2, zeroes)16931694n = self._parent._zeroes.count(0)1695g = self._parent._genus16961697l0 = range(3*g-2)1698l1 = [3, 2]1699for k in range(4, 3*g-4, 3):1700l1 += [k, k+2, k+1]1701l1 += [1, 0]17021703k = 41704for d in zeroes:1705for i in range(d-1):1706del l0[l0.index(k)]1707del l1[l1.index(k)]1708k += 31709k += 317101711# marked points1712if n != 0:1713interval = range(3*g-2, 3*g-2+n)17141715if self._parent._zeroes[0] == 0:1716k = l0.index(3)1717l0[k:k] = interval1718l1[-1:-1] = interval1719else:1720l0[1:1] = interval1721l1.extend(interval)17221723if self._parent._marked_separatrix == 'in':1724l0.reverse()1725l1.reverse()17261727if reduced:1728from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET1729return ReducedPermutationIET([l0, l1], alphabet=alphabet)17301731else:1732from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET1733return LabelledPermutationIET([l0, l1], alphabet=alphabet)17341735OddCCA = OddConnectedComponentOfAbelianStratum173617371738