def __init__(self, permutation=None, lengths=None): r""" INPUT: - ``permutation`` - a permutation (LabelledPermutationIET) - ``lengths`` - the list of lengths TEST:: sage: p=iet.IntervalExchangeTransformation(('a','a'),[1]) sage: p == loads(dumps(p)) True """ from labelled import LabelledPermutationIET if permutation is None or lengths is None: self._permutation = LabelledPermutationIET() self._lengths = [] else: self._permutation = permutation self._lengths = lengths
def Permutation(*args,**kargs): r""" Returns a permutation of an interval exchange transformation. Those permutations are the combinatoric part of an interval exchange transformation (IET). The combinatorial study of those objects starts with Gerard Rauzy [R79]_ and William Veech [V78]_. The combinatoric part of interval exchange transformation can be taken independently from its dynamical origin. It has an important link with strata of Abelian differential (see :mod:`~sage.combinat.iet.strata`) INPUT: - ``intervals`` - string, two strings, list, tuples that can be converted to two lists - ``reduced`` - boolean (default: False) specifies reduction. False means labelled permutation and True means reduced permutation. - ``flips`` - iterable (default: None) the letters which correspond to flipped intervals. OUTPUT: permutation -- the output type depends of the data. EXAMPLES: Creation of labelled permutations :: sage: iet.Permutation('a b c d','d c b a') a b c d d c b a sage: iet.Permutation([[0,1,2,3],[2,1,3,0]]) 0 1 2 3 2 1 3 0 sage: iet.Permutation([0, 'A', 'B', 1], ['B', 0, 1, 'A']) 0 A B 1 B 0 1 A Creation of reduced permutations:: sage: iet.Permutation('a b c', 'c b a', reduced = True) a b c c b a sage: iet.Permutation([0, 1, 2, 3], [1, 3, 0, 2]) 0 1 2 3 1 3 0 2 Creation of flipped permutations:: sage: iet.Permutation('a b c', 'c b a', flips=['a','b']) -a -b c c -b -a sage: iet.Permutation('a b c', 'c b a', flips=['a'], reduced=True) -a b c c b -a TESTS: :: sage: p = iet.Permutation('a b c','c b a') sage: iet.Permutation(p) == p True sage: iet.Permutation(p, reduced=True) == p.reduced() True :: sage: p = iet.Permutation('a','a',flips='a',reduced=True) sage: iet.Permutation(p) == p True :: sage: p = iet.Permutation('a b c','c b a',flips='a') sage: iet.Permutation(p) == p True sage: iet.Permutation(p, reduced=True) == p.reduced() True :: sage: p = iet.Permutation('a b c','c b a',reduced=True) sage: iet.Permutation(p) == p True """ from labelled import LabelledPermutation from labelled import LabelledPermutationIET from labelled import FlippedLabelledPermutationIET from reduced import ReducedPermutation from reduced import ReducedPermutationIET from reduced import FlippedReducedPermutationIET if 'reduced' not in kargs : reduction = None elif not isinstance(kargs["reduced"], bool) : raise TypeError("reduced must be of type boolean") else : if kargs["reduced"] == True : reduction = True else : reduction = False if 'flips' not in kargs : flips = [] else : flips = list(kargs['flips']) if 'alphabet' not in kargs : alphabet = None else : alphabet = kargs['alphabet'] if len(args) == 1: args = args[0] if isinstance(args, LabelledPermutation): if flips == []: if reduction is None or reduction is False: from copy import copy return copy(args) else: return args.reduced() else: # conversion not yet implemented reduced = reduction in (None, False) return PermutationIET( args.list(), reduced=reduced, flips=flips, alphabet=alphabet) if isinstance(args, ReducedPermutation): if flips == []: if reduction is None or reduction is True: from copy import copy return copy(args) else: # conversion not yet implemented return PermutationIET( args.list(), reduced=True) else: # conversion not yet implemented reduced = reduction in (None, True) return PermutationIET( args.list(), reduced=reduced, flips=flips, alphabet=alphabet) a = _two_lists(args) l = a[0] + a[1] letters = set(l) for letter in flips : if letter not in letters : raise ValueError, "flips contains not valid letters" for letter in letters : if a[0].count(letter) != 1 or a[1].count(letter) != 1: raise ValueError, "letters must appear once in each interval" if reduction == True : if flips == [] : return ReducedPermutationIET(a, alphabet=alphabet) else : return FlippedReducedPermutationIET(a, alphabet=alphabet, flips=flips) else : if flips == [] : return LabelledPermutationIET(a, alphabet=alphabet) else : return FlippedLabelledPermutationIET(a, alphabet=alphabet, flips=flips)
def __mul__(self, other): r""" Composition of iet. The domain (i.e. the length) of the two iets must be the same). The alphabet choosen depends on the permutation. TESTS: :: sage: p = iet.Permutation("a b", "a b") sage: t = iet.IET(p, [1,1]) sage: r = t*t sage: r.permutation() aa bb aa bb sage: r.lengths() [1, 1] :: sage: p = iet.Permutation("a b","b a") sage: t = iet.IET(p, [1,1]) sage: r = t*t sage: r.permutation() ab ba ab ba sage: r.lengths() [1, 1] :: sage: p = iet.Permutation("1 2 3 4 5","5 4 3 2 1") sage: q = iet.Permutation("a b","b a") sage: s = iet.IET(p, [1]*5) sage: t = iet.IET(q, [1/2, 9/2]) sage: r = s*t sage: r.permutation() a5 b1 b2 b3 b4 b5 b5 a5 b4 b3 b2 b1 sage: r.lengths() [1/2, 1, 1, 1, 1, 1/2] sage: r = t*s sage: r.permutation() 1b 2b 3b 4b 5a 5b 5b 4b 3b 2b 1b 5a sage: r.lengths() [1, 1, 1, 1, 1/2, 1/2] sage: t = iet.IET(q, [3/2, 7/2]) sage: r = s*t sage: r.permutation() a4 a5 b1 b2 b3 b4 a5 b4 a4 b3 b2 b1 sage: r.lengths() [1/2, 1, 1, 1, 1, 1/2] sage: t = iet.IET(q, [5/2,5/2]) sage: r = s*t sage: r.permutation() a3 a4 a5 b1 b2 b3 a5 a4 b3 a3 b2 b1 sage: r = t*s sage: r.permutation() 1b 2b 3a 3b 4a 5a 3b 2b 1b 5a 4a 3a :: sage: p = iet.Permutation("a b","b a") sage: s = iet.IET(p, [4,2]) sage: q = iet.Permutation("c d","d c") sage: t = iet.IET(q, [3, 3]) sage: r1 = t * s sage: r1.permutation() ac ad bc ad bc ac sage: r1.lengths() [1, 3, 2] sage: r2 = s * t sage: r2.permutation() ca cb da cb da ca sage: r2.lengths() [1, 2, 3] """ assert (isinstance(other, IntervalExchangeTransformation) and self.length() == other.length()) from labelled import LabelledPermutationIET from sage.combinat.words.words import Words other_sg = other.range_singularities()[1:] self_sg = self.domain_singularities()[1:] n_other = len(other._permutation) n_self = len(self._permutation) interval_other = other._permutation._intervals[1] interval_self = self._permutation._intervals[0] d_other = dict([(i, []) for i in interval_other]) d_self = dict([(i, []) for i in interval_self]) i_other = 0 i_self = 0 x = 0 l_lengths = [] while i_other < n_other and i_self < n_self: j_other = interval_other[i_other] j_self = interval_self[i_self] d_other[j_other].append(j_self) d_self[j_self].append(j_other) if other_sg[i_other] < self_sg[i_self]: l = other_sg[i_other] - x x = other_sg[i_other] i_other += 1 elif other_sg[i_other] > self_sg[i_self]: l = self_sg[i_self] - x x = self_sg[i_self] i_self += 1 else: l = self_sg[i_self] - x x = self_sg[i_self] i_other += 1 i_self += 1 l_lengths.append(((j_other, j_self), l)) alphabet_other = other._permutation.alphabet() alphabet_self = self._permutation.alphabet() d_lengths = dict(l_lengths) l_lengths = [] top_interval = [] for i in other._permutation._intervals[0]: for j in d_other[i]: a = alphabet_other.unrank(i) b = alphabet_self.unrank(j) top_interval.append(str(a) + str(b)) l_lengths.append(d_lengths[(i, j)]) bottom_interval = [] for i in self._permutation._intervals[1]: for j in d_self[i]: a = alphabet_other.unrank(j) b = alphabet_self.unrank(i) bottom_interval.append(str(a) + str(b)) p = LabelledPermutationIET((top_interval, bottom_interval)) return IntervalExchangeTransformation(p, l_lengths)
def recoding(self, n): r""" Recode this interval exchange transformation on the words of length ``n``. EXAMPLES:: sage: from surface_dynamics.all import * sage: p = iet.Permutation('a d c b', 'b c a d', alphabet='abcd') sage: T = iet.IntervalExchangeTransformation(p, [119,213,82,33]) sage: T.recoding(2) Interval exchange transformation of [0, 447[ with permutation ab db cc cb ba bd bc ba bd bc cc cb ab db sage: T.recoding(3) Interval exchange transformation of [0, 447[ with permutation aba abd abc dbc ccb cba bab bdb bcc bcb cba aba abd abc dbc bcc bcb ccb bab bdb """ length = len(self._permutation) lengths = self._lengths A = self.permutation().alphabet() unrank = A.unrank top = self._permutation._labels[0] bot = self._permutation._labels[1] bot_twin = self._permutation._twin[1] sg_top = self.domain_singularities()[ 1:-1] # iterates of the top singularities cuts = [[[i], lengths[i]] for i in bot] # the refined bottom interval translations = self.translations() for step in range(n - 1): i = 0 y = self.base_ring().zero() new_sg_top = [] limits = [0] for j, x in enumerate(sg_top): while y < x: cuts[i][0].append(top[j]) y += cuts[i][1] i += 1 limits.append(i) if y != x: cuts.insert(i, [cuts[i - 1][0][:-1], cuts[i - 1][1]]) cuts[i - 1][1] -= y - x cuts[i][0].append(top[j + 1]) cuts[i][1] = y - x i += 1 while i < len(cuts): cuts[i][0].append(top[j + 1]) i += 1 limits.append(len(cuts)) # now we reorder cuts with respect to T according to the cut at # limits if step != n - 2: new_cuts = [] for j in bot_twin: new_cuts.extend(cuts[limits[j]:limits[j + 1]]) cuts = new_cuts # build the new interval exchange transformations itop = [None] * (max(top) + 1) for i, j in enumerate(top): itop[j] = i key = lambda x: [itop[i] for i in x[0]] top = sorted(cuts, key=key) lengths = [y for x, y in top] top = [''.join(str(unrank(i)) for i in x) for x, y in top] bot = cuts bot = [''.join(str(unrank(i)) for i in x) for x, y in bot] from labelled import LabelledPermutationIET p = LabelledPermutationIET((top, bot)) return IntervalExchangeTransformation(p, lengths)