Path: blob/master/src/sage/dynamics/interval_exchanges/constructors.py
8815 views
r"""1Class factories for Interval exchange transformations.23This library is designed for the usage and manipulation of interval4exchange transformations and linear involutions. It defines specialized5types of permutation (constructed using :meth:`iet.Permutation`) some6associated graph (constructed using :meth:`iet.RauzyGraph`) and some maps7of intervals (constructed using :meth:`iet.IntervalExchangeTransformation`).8910EXAMPLES:1112Creation of an interval exchange transformation::1314sage: T = iet.IntervalExchangeTransformation(('a b','b a'),(sqrt(2),1))15sage: print T16Interval exchange transformation of [0, sqrt(2) + 1[ with permutation17a b18b a1920It can also be initialized using permutation (group theoretic ones)::2122sage: p = Permutation([3,2,1])23sage: T = iet.IntervalExchangeTransformation(p, [1/3,2/3,1])24sage: print T25Interval exchange transformation of [0, 2[ with permutation261 2 3273 2 12829For the manipulation of permutations of iet, there are special types provided30by this module. All of them can be constructed using the constructor31iet.Permutation. For the creation of labelled permutations of interval exchange32transformation::3334sage: p1 = iet.Permutation('a b c', 'c b a')35sage: print p136a b c37c b a3839They can be used for initialization of an iet::4041sage: p = iet.Permutation('a b','b a')42sage: T = iet.IntervalExchangeTransformation(p, [1,sqrt(2)])43sage: print T44Interval exchange transformation of [0, sqrt(2) + 1[ with permutation45a b46b a4748You can also, create labelled permutations of linear involutions::4950sage: p = iet.GeneralizedPermutation('a a b', 'b c c')51sage: print p52a a b53b c c5455Sometimes it's more easy to deal with reduced permutations::5657sage: p = iet.Permutation('a b c', 'c b a', reduced = True)58sage: print p59a b c60c b a6162Permutations with flips::6364sage: p1 = iet.Permutation('a b c', 'c b a', flips = ['a','c'])65sage: print p166-a b -c67-c b -a6869Creation of Rauzy diagrams::7071sage: r = iet.RauzyDiagram('a b c', 'c b a')7273Reduced Rauzy diagrams are constructed using the same arguments than for74permutations::7576sage: r = iet.RauzyDiagram('a b b','c c a')77sage: r_red = iet.RauzyDiagram('a b b','c c a',reduced=True)78sage: r.cardinality()791280sage: r_red.cardinality()8148283By defaut, Rauzy diagram are generated by induction on the right. You can use84several options to enlarge (or restrict) the diagram (try help(iet.RauzyDiagram) for85more precisions)::8687sage: r1 = iet.RauzyDiagram('a b c','c b a',right_induction=True)88sage: r2 = iet.RauzyDiagram('a b c','c b a',left_right_inversion=True)8990You can consider self similar iet using path in Rauzy diagrams and eigenvectors91of the corresponding matrix::9293sage: p = iet.Permutation("a b c d", "d c b a")94sage: d = p.rauzy_diagram()95sage: g = d.path(p, 't', 't', 'b', 't', 'b', 'b', 't', 'b')96sage: g97Path of length 8 in a Rauzy diagram98sage: g.is_loop()99True100sage: g.is_full()101True102sage: m = g.matrix()103sage: v = m.eigenvectors_right()[-1][1][0]104sage: T1 = iet.IntervalExchangeTransformation(p, v)105sage: T2 = T1.rauzy_move(iterations=8)106sage: T1.normalize(1) == T2.normalize(1)107True108109REFERENCES:110111.. [BL08] Corentin Boissy and Erwan Lanneau, "Dynamics and geometry of the112Rauzy-Veech induction for quadratic differentials" (arxiv:0710.5614) to appear113in Ergodic Theory and Dynamical Systems114115.. [DN90] Claude Danthony and Arnaldo Nogueira "Measured foliations on116nonorientable surfaces", Annales scientifiques de l'Ecole Normale117Superieure, Ser. 4, 23, no. 3 (1990) p 469-494118119.. [N85] Arnaldo Nogueira, "Almost all Interval Exchange Transformations with120Flips are Nonergodic" (Ergod. Th. & Dyn. Systems, Vol 5., (1985), 257-271121122.. [R79] Gerard Rauzy, "Echanges d'intervalles et transformations induites",123Acta Arith. 34, no. 3, 203-212, 1980124125.. [V78] William Veech, "Interval exchange transformations", J. Analyse Math.12633, 222-272127128.. [Z] Anton Zorich, "Generalized Permutation software"129(http://perso.univ-rennes1.fr/anton.zorich)130131132AUTHORS:133134- Vincent Delecroix (2009-09-29): initial version135136"""137#*****************************************************************************138# Copyright (C) 2008 Vincent Delecroix <[email protected]>139#140# Distributed under the terms of the GNU General Public License (GPL)141# http://www.gnu.org/licenses/142#*****************************************************************************143from template import PermutationIET, PermutationLI144145def _two_lists(a):146r"""147Try to return the input as a list of two lists148149INPUT:150151- ``a`` - either a string, one or two lists, one or two tuples152153OUTPUT:154155-- two lists156157TESTS:158159::160sage: from sage.dynamics.interval_exchanges.constructors import _two_lists161sage: _two_lists(('a1 a2','b1 b2'))162[['a1', 'a2'], ['b1', 'b2']]163sage: _two_lists('a1 a2\nb1 b2')164[['a1', 'a2'], ['b1', 'b2']]165sage: _two_lists(['a b','c'])166[['a', 'b'], ['c']]167168..The ValueError and TypeError can be raised if it fails::169170sage: _two_lists('a b')171Traceback (most recent call last):172...173ValueError: your chain must contain two lines174sage: _two_lists('a b\nc d\ne f')175Traceback (most recent call last):176...177ValueError: your chain must contain two lines178sage: _two_lists(1)179Traceback (most recent call last):180...181TypeError: argument not accepted182sage: _two_lists([1,2,3])183Traceback (most recent call last):184...185ValueError: your argument can not be split in two parts186"""187from sage.combinat.permutation import Permutation188189res = [None, None]190191if isinstance(a,str):192a = a.split('\n')193if len(a) != 2:194raise ValueError("your chain must contain two lines")195else :196res[0] = a[0].split()197res[1] = a[1].split()198199elif isinstance(a, Permutation):200res[0] = range(1,len(a)+1)201res[1] = [a[i] for i in range(len(a))]202203elif not hasattr(a,'__len__'):204raise TypeError("argument not accepted")205206elif len(a) == 0 or len(a) > 2:207raise ValueError("your argument can not be split in two parts")208209elif len(a) == 1:210a = a[0]211if isinstance(a, Permutation):212res[0] = range(1,len(a)+1)213res[1] = [a[i] for i in range(len(a))]214215elif isinstance(a, (list,tuple)):216if (len(a) != 2):217raise ValueError("your list must contain two objects")218for i in range(2):219if isinstance(a[i], str):220res[i] = a[i].split()221else:222res[i] = list(a[i])223224else :225raise TypeError("argument not accepted")226227else :228for i in range(2):229if isinstance(a[i], str):230res[i] = a[i].split()231else:232res[i] = list(a[i])233234return res235236def Permutation(*args,**kargs):237r"""238Returns a permutation of an interval exchange transformation.239240Those permutations are the combinatoric part of an interval exchange241transformation (IET). The combinatorial study of those objects starts with242Gerard Rauzy [R79]_ and William Veech [V78]_.243244The combinatoric part of interval exchange transformation can be taken245independently from its dynamical origin. It has an important link with246strata of Abelian differential (see :mod:`~sage.dynamics.interval_exchanges.strata`)247248INPUT:249250- ``intervals`` - string, two strings, list, tuples that can be converted to251two lists252253- ``reduced`` - boolean (default: False) specifies reduction. False means254labelled permutation and True means reduced permutation.255256- ``flips`` - iterable (default: None) the letters which correspond to257flipped intervals.258259OUTPUT:260261permutation -- the output type depends of the data.262263EXAMPLES:264265Creation of labelled permutations ::266267sage: iet.Permutation('a b c d','d c b a')268a b c d269d c b a270sage: iet.Permutation([[0,1,2,3],[2,1,3,0]])2710 1 2 32722 1 3 0273sage: iet.Permutation([0, 'A', 'B', 1], ['B', 0, 1, 'A'])2740 A B 1275B 0 1 A276277Creation of reduced permutations::278279sage: iet.Permutation('a b c', 'c b a', reduced = True)280a b c281c b a282sage: iet.Permutation([0, 1, 2, 3], [1, 3, 0, 2])2830 1 2 32841 3 0 2285286Creation of flipped permutations::287288sage: iet.Permutation('a b c', 'c b a', flips=['a','b'])289-a -b c290c -b -a291sage: iet.Permutation('a b c', 'c b a', flips=['a'], reduced=True)292-a b c293c b -a294295TESTS:296297::298299sage: p = iet.Permutation('a b c','c b a')300sage: iet.Permutation(p) == p301True302sage: iet.Permutation(p, reduced=True) == p.reduced()303True304305::306307sage: p = iet.Permutation('a','a',flips='a',reduced=True)308sage: iet.Permutation(p) == p309True310311::312313sage: p = iet.Permutation('a b c','c b a',flips='a')314sage: iet.Permutation(p) == p315True316sage: iet.Permutation(p, reduced=True) == p.reduced()317True318319::320321sage: p = iet.Permutation('a b c','c b a',reduced=True)322sage: iet.Permutation(p) == p323True324325TESTS::326327sage: iet.Permutation('a b c','c b a',reduced='badly')328Traceback (most recent call last):329...330TypeError: reduced must be of type boolean331sage: iet.Permutation('a','a',flips='b',reduced=True)332Traceback (most recent call last):333...334ValueError: flips contains not valid letters335sage: iet.Permutation('a b c','c a a',reduced=True)336Traceback (most recent call last):337...338ValueError: letters must appear once in each interval339"""340from labelled import LabelledPermutation341from labelled import LabelledPermutationIET342from labelled import FlippedLabelledPermutationIET343344from reduced import ReducedPermutation345from reduced import ReducedPermutationIET346from reduced import FlippedReducedPermutationIET347348if 'reduced' not in kargs :349reduction = None350elif not isinstance(kargs["reduced"], bool) :351raise TypeError("reduced must be of type boolean")352else :353reduction = kargs["reduced"]354355if 'flips' not in kargs :356flips = []357else :358flips = list(kargs['flips'])359360361if 'alphabet' not in kargs :362alphabet = None363else :364alphabet = kargs['alphabet']365366if len(args) == 1:367args = args[0]368if isinstance(args, LabelledPermutation):369if flips == []:370if reduction is None or not reduction:371from copy import copy372return copy(args)373else:374return args.reduced()375else: # conversion not yet implemented376reduced = reduction in (None, False)377return PermutationIET(378args.list(),379reduced=reduced,380flips=flips,381alphabet=alphabet)382383if isinstance(args, ReducedPermutation):384if flips == []:385if reduction is None or reduction:386from copy import copy387return copy(args)388else: # conversion not yet implemented389return PermutationIET(390args.list(),391reduced=True)392else: # conversion not yet implemented393reduced = reduction in (None, True)394return PermutationIET(395args.list(),396reduced=reduced,397flips=flips,398alphabet=alphabet)399400a = _two_lists(args)401402l = a[0] + a[1]403letters = set(l)404405for letter in flips :406if letter not in letters :407raise ValueError("flips contains not valid letters")408409for letter in letters :410if a[0].count(letter) != 1 or a[1].count(letter) != 1:411raise ValueError("letters must appear once in each interval")412413if reduction :414if flips == [] :415return ReducedPermutationIET(a, alphabet=alphabet)416else :417return FlippedReducedPermutationIET(a, alphabet=alphabet, flips=flips)418else :419if flips == [] :420return LabelledPermutationIET(a, alphabet=alphabet)421else :422return FlippedLabelledPermutationIET(a, alphabet=alphabet, flips=flips)423424def GeneralizedPermutation(*args,**kargs):425r"""426Returns a permutation of an interval exchange transformation.427428Those permutations are the combinatoric part of linear involutions and were429introduced by Danthony-Nogueira [DN90]_. The full combinatoric study and430precise links with strata of quadratic differentials was achieved few years431later by Boissy-Lanneau [BL08]_.432433INPUT:434435- ``intervals`` - strings, list, tuples436437- ``reduced`` - boolean (defaut: False) specifies reduction. False means438labelled permutation and True means reduced permutation.439440- ``flips`` - iterable (default: None) the letters which correspond to441flipped intervals.442443OUTPUT:444445generalized permutation -- the output type depends on the data.446447EXAMPLES:448449Creation of labelled generalized permutations::450451sage: iet.GeneralizedPermutation('a b b','c c a')452a b b453c c a454sage: iet.GeneralizedPermutation('a a','b b c c')455a a456b b c c457sage: iet.GeneralizedPermutation([[0,1,2,3,1],[4,2,5,3,5,4,0]])4580 1 2 3 14594 2 5 3 5 4 0460461Creation of reduced generalized permutations::462463sage: iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)464a b b465c c a466sage: iet.GeneralizedPermutation('a a b b', 'c c d d', reduced = True)467a a b b468c c d d469470Creation of flipped generalized permutations::471472sage: iet.GeneralizedPermutation('a b c a', 'd c d b', flips = ['a','b'])473-a -b c -a474d c d -b475476TESTS::477478sage: iet.GeneralizedPermutation('a a b b', 'c c d d', reduced = 'may')479Traceback (most recent call last):480...481TypeError: reduced must be of type boolean482sage: iet.GeneralizedPermutation('a b c a', 'd c d b', flips = ['e','b'])483Traceback (most recent call last):484...485TypeError: The flip list is not valid486sage: iet.GeneralizedPermutation('a b c a', 'd c c b', flips = ['a','b'])487Traceback (most recent call last):488...489ValueError: Letters must reappear twice490"""491from labelled import LabelledPermutation492from labelled import LabelledPermutationLI493from labelled import FlippedLabelledPermutationLI494495from reduced import ReducedPermutation496from reduced import ReducedPermutationLI497from reduced import FlippedReducedPermutationLI498499if 'reduced' not in kargs :500reduction = None501elif not isinstance(kargs["reduced"], bool) :502raise TypeError("reduced must be of type boolean")503else :504reduction = kargs["reduced"]505506if 'flips' not in kargs :507flips = []508else :509flips = list(kargs['flips'])510511512if 'alphabet' not in kargs :513alphabet = None514else :515alphabet = kargs['alphabet']516517if len(args) == 1:518args = args[0]519if isinstance(args, LabelledPermutation):520if flips == []:521if reduction is None or not reduction:522from copy import copy523return copy(args)524else:525return args.reduced()526else: # conversion not yet implemented527reduced = reduction in (None, False)528return PermutationLI(529args.list(),530reduced=reduced,531flips=flips,532alphabet=alphabet)533534if isinstance(args, ReducedPermutation):535if flips == []:536if reduction is None or reduction:537from copy import copy538return copy(args)539else: # conversion not yet implemented540return PermutationLI(541args.list(),542reduced=True)543else: # conversion not yet implemented544reduced = reduction in (None, True)545return PermutationLI(546args.list(),547reduced=reduced,548flips=flips,549alphabet=alphabet)550551a = _two_lists(args)552553if 'reduced' not in kargs :554reduction = False555elif not isinstance(kargs["reduced"], bool) :556raise TypeError("reduced must be of type boolean")557else :558reduction = kargs["reduced"]559560if 'flips' not in kargs :561flips = []562else :563flips = list(kargs['flips'])564565if 'alphabet' not in kargs :566alphabet = None567else :568alphabet = kargs['alphabet']569570l = a[0] + a[1]571letters = set(l)572573for letter in flips :574if letter not in letters :575raise TypeError("The flip list is not valid")576577for letter in letters :578if l.count(letter) != 2:579raise ValueError("Letters must reappear twice")580581# check existence of admissible length582b0 = a[0][:]583b1 = a[1][:]584for letter in letters :585if b0.count(letter) == 1 :586del b0[b0.index(letter)]587del b1[b1.index(letter)]588589if (b0 == []) and (b1 == []):590return Permutation(a,**kargs)591592elif (b0 == []) or (b1 == []):593raise ValueError("There is no admissible length")594595if reduction :596if flips == [] :597return ReducedPermutationLI(a, alphabet=alphabet)598else :599return FlippedReducedPermutationLI(a, alphabet=alphabet, flips=flips)600else :601if flips == [] :602return LabelledPermutationLI(a, alphabet=alphabet)603else :604return FlippedLabelledPermutationLI(a, alphabet=alphabet, flips=flips)605606def Permutations_iterator(nintervals=None, irreducible=True,607reduced=False, alphabet=None):608r"""609Returns an iterator over permutations.610611This iterator allows you to iterate over permutations with given612constraints. If you want to iterate over permutations coming from a given613stratum you have to use the module :mod:`~sage.dynamics.flat_surfaces.strata` and614generate Rauzy diagrams from connected components.615616INPUT:617618- ``nintervals`` - non negative integer619620- ``irreducible`` - boolean (default: True)621622- ``reduced`` - boolean (default: False)623624- ``alphabet`` - alphabet (default: None)625626OUTPUT:627628iterator -- an iterator over permutations629630EXAMPLES:631632Generates all reduced permutations with given number of intervals::633634sage: P = iet.Permutations_iterator(nintervals=2,alphabet="ab",reduced=True)635sage: for p in P: print p, "\n* *"636a b637b a638* *639sage: P = iet.Permutations_iterator(nintervals=3,alphabet="abc",reduced=True)640sage: for p in P: print p, "\n* * *"641a b c642b c a643* * *644a b c645c a b646* * *647a b c648c b a649* * *650651TESTS::652653sage: P = iet.Permutations_iterator(nintervals=None, alphabet=None)654Traceback (most recent call last):655...656ValueError: You must specify an alphabet or a length657sage: P = iet.Permutations_iterator(nintervals=None, alphabet=ZZ)658Traceback (most recent call last):659...660ValueError: You must specify a length with infinite alphabet661"""662from labelled import LabelledPermutationsIET_iterator663from reduced import ReducedPermutationsIET_iterator664from sage.combinat.words.alphabet import Alphabet665from sage.rings.infinity import Infinity666667if nintervals is None:668if alphabet is None:669raise ValueError("You must specify an alphabet or a length")670else:671alphabet = Alphabet(alphabet)672if alphabet.cardinality() is Infinity:673raise ValueError("You must specify a length with infinite alphabet")674nintervals = alphabet.cardinality()675676elif alphabet is None:677alphabet = range(1, nintervals+1)678679if reduced:680return ReducedPermutationsIET_iterator(nintervals,681irreducible=irreducible,682alphabet=alphabet)683else:684return LabelledPermutationsIET_iterator(nintervals,685irreducible=irreducible,686alphabet=alphabet)687688def RauzyDiagram(*args, **kargs):689r"""690Return an object coding a Rauzy diagram.691692The Rauzy diagram is an oriented graph with labelled edges. The set of693vertices corresponds to the permutations obtained by different operations694(mainly the .rauzy_move() operations that corresponds to an induction of695interval exchange transformation). The edges correspond to the action of the696different operations considered.697698It first appeard in the original article of Rauzy [R79]_.699700INPUT:701702- ``intervals`` - lists, or strings, or tuples703704- ``reduced`` - boolean (default: False) to precise reduction705706- ``flips`` - list (default: []) for flipped permutations707708- ``right_induction`` - boolean (default: True) consideration of left709induction in the diagram710711- ``left_induction`` - boolean (default: False) consideration of right712induction in the diagram713714- ``left_right_inversion`` - boolean (default: False) consideration of715inversion716717- ``top_bottom_inversion`` - boolean (default: False) consideration of718reversion719720- ``symmetric`` - boolean (default: False) consideration of the symmetric721operation722723OUTPUT:724725Rauzy diagram -- the Rauzy diagram that corresponds to your request726727EXAMPLES:728729Standard Rauzy diagrams::730731sage: iet.RauzyDiagram('a b c d', 'd b c a')732Rauzy diagram with 12 permutations733sage: iet.RauzyDiagram('a b c d', 'd b c a', reduced = True)734Rauzy diagram with 6 permutations735736Extended Rauzy diagrams::737738sage: iet.RauzyDiagram('a b c d', 'd b c a', symmetric=True)739Rauzy diagram with 144 permutations740741Using Rauzy diagrams and path in Rauzy diagrams::742743sage: r = iet.RauzyDiagram('a b c', 'c b a')744sage: print r745Rauzy diagram with 3 permutations746sage: p = iet.Permutation('a b c','c b a')747sage: p in r748True749sage: g0 = r.path(p, 'top', 'bottom','top')750sage: g1 = r.path(p, 'bottom', 'top', 'bottom')751sage: print g0.is_loop(), g1.is_loop()752True True753sage: print g0.is_full(), g1.is_full()754False False755sage: g = g0 + g1756sage: g757Path of length 6 in a Rauzy diagram758sage: print g.is_loop(), g.is_full()759True True760sage: m = g.matrix()761sage: print m762[1 1 1]763[2 4 1]764[2 3 2]765sage: s = g.orbit_substitution()766sage: s767WordMorphism: a->acbbc, b->acbbcbbc, c->acbc768sage: s.incidence_matrix() == m769True770771We can then create the corresponding interval exchange transformation and772comparing the orbit of `0` to the fixed point of the orbit substitution::773774sage: v = m.eigenvectors_right()[-1][1][0]775sage: T = iet.IntervalExchangeTransformation(p, v).normalize()776sage: print T777Interval exchange transformation of [0, 1[ with permutation778a b c779c b a780sage: w1 = []781sage: x = 0782sage: for i in range(20):783....: w1.append(T.in_which_interval(x))784....: x = T(x)785sage: w1 = Word(w1)786sage: w1787word: acbbcacbcacbbcbbcacb788sage: w2 = s.fixed_point('a')789sage: w2[:20]790word: acbbcacbcacbbcbbcacb791sage: w2[:20] == w1792True793"""794if not kargs.has_key('reduced'):795kargs['reduced'] = False796if not kargs.has_key('flips'):797kargs['flips'] = []798if not kargs.has_key('alphabet'):799kargs['alphabet'] = None800801p = GeneralizedPermutation(802args,803reduced= kargs['reduced'],804flips = kargs['flips'],805alphabet = kargs['alphabet'])806807if not kargs.has_key('right_induction'):808kargs['right_induction'] = True809if not kargs.has_key('left_induction'):810kargs['left_induction'] = False811if not kargs.has_key('left_right_inversion'):812kargs['left_right_inversion'] = False813if not kargs.has_key('top_bottom_inversion'):814kargs['top_bottom_inversion'] = False815if not kargs.has_key('symmetric'):816kargs['symmetric'] = False817818return p.rauzy_diagram(819right_induction = kargs['right_induction'],820left_induction = kargs['left_induction'],821left_right_inversion = kargs['left_right_inversion'],822top_bottom_inversion = kargs['top_bottom_inversion'],823symmetric = kargs['symmetric'])824825#TODO826# def GeneralizedPermutation_iterator():827# print "gpi"828829def IntervalExchangeTransformation(permutation=None, lengths=None):830"""831Constructs an Interval exchange transformation.832833An interval exchange transformation (or iet) is a map from an834interval to itself. It is defined on the interval except at a finite835number of points (the singularities) and is a translation on each836connected component of the complement of the singularities. Moreover it is a837bijection on its image (or it is injective).838839An interval exchange transformation is encoded by two datas. A permutation840(that corresponds to the way we echange the intervals) and a vector of841positive reals (that corresponds to the lengths of the complement of the842singularities).843844INPUT:845846- ``permutation`` - a permutation847848- ``lengths`` - a list or a dictionnary of lengths849850OUTPUT:851852interval exchange transformation -- an map of an interval853854EXAMPLES:855856Two initialization methods, the first using a iet.Permutation::857858sage: p = iet.Permutation('a b c','c b a')859sage: t = iet.IntervalExchangeTransformation(p, {'a':1,'b':0.4523,'c':2.8})860861The second is more direct::862863sage: t = iet.IntervalExchangeTransformation(('a b','b a'),{'a':1,'b':4})864865It's also possible to initialize the lengths only with a list::866867sage: t = iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,0.4,2])868869The two fundamental operations are Rauzy move and normalization::870871sage: t = iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,0.4,2])872sage: s = t.rauzy_move()873sage: s_n = s.normalize(t.length())874sage: s_n.length() == t.length()875True876877A not too simple example of a self similar interval exchange transformation::878879sage: p = iet.Permutation('a b c d','d c b a')880sage: d = p.rauzy_diagram()881sage: g = d.path(p, 't', 't', 'b', 't', 'b', 'b', 't', 'b')882sage: m = g.matrix()883sage: v = m.eigenvectors_right()[-1][1][0]884sage: t = iet.IntervalExchangeTransformation(p,v)885sage: s = t.rauzy_move(iterations=8)886sage: s.normalize() == t.normalize()887True888889TESTS::890891sage: iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,2])892Traceback (most recent call last):893...894ValueError: bad number of lengths895sage: iet.IntervalExchangeTransformation(('a b c','c b a'),[0.1,'rho',2])896Traceback (most recent call last):897...898TypeError: unable to convert x (='rho') into a real number899sage: iet.IntervalExchangeTransformation(('a b c','c b a'),[0.1,-2,2])900Traceback (most recent call last):901...902ValueError: lengths must be positive903"""904from iet import IntervalExchangeTransformation as _IET905from labelled import LabelledPermutationIET906from template import FlippedPermutation907908if isinstance(permutation, FlippedPermutation):909raise TypeError("flips are not yet implemented")910if isinstance(permutation, LabelledPermutationIET):911p = permutation912else:913p = Permutation(permutation,reduced=False)914915916if isinstance(lengths, dict):917l = [0] * len(p)918alphabet = p._alphabet919for letter in lengths:920l[alphabet.rank(letter)] = lengths[letter]921else:922l = list(lengths)923924if len(l) != len(p):925raise ValueError("bad number of lengths")926927for x in l:928try:929y = float(x)930except ValueError:931raise TypeError("unable to convert x (='%s') into a real number" % (str(x)))932933if y <= 0:934raise ValueError("lengths must be positive")935936return _IET(p, l)937938IET = IntervalExchangeTransformation939940#TODO941# def LinearInvolution(*args,**kargs):942# r"""943# Constructs a Linear Involution from the given data944# """945# from iet import LinearInvolution as _LI946# pass947948# LI = LinearInvolution949950951