Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/combinat/iet/constructors.py
4057 views
1
r"""
2
Class factories for Interval exchange transformations.
3
4
This library is designed for the usage and manipulation of interval
5
exchange transformations and linear involutions. It defines specialized
6
types of permutation (constructed using :meth:`iet.Permutation`) some
7
associated graph (constructed using :meth:`iet.RauzyGraph`) and some maps
8
of intervals (constructed using :meth:`iet.IntervalExchangeTransformation`).
9
10
11
EXAMPLES:
12
13
Creation of an interval exchange transformation::
14
15
sage: T = iet.IntervalExchangeTransformation(('a b','b a'),(sqrt(2),1))
16
sage: print T
17
Interval exchange transformation of [0, sqrt(2) + 1[ with permutation
18
a b
19
b a
20
21
It can also be initialized using permutation (group theoritic ones)::
22
23
sage: p = Permutation([3,2,1])
24
sage: T = iet.IntervalExchangeTransformation(p, [1/3,2/3,1])
25
sage: print T
26
Interval exchange transformation of [0, 2[ with permutation
27
1 2 3
28
3 2 1
29
30
For the manipulation of permutations of iet, there are special types provided
31
by this module. All of them can be constructed using the constructor
32
iet.Permutation. For the creation of labelled permutations of interval exchange
33
transformation::
34
35
sage: p1 = iet.Permutation('a b c', 'c b a')
36
sage: print p1
37
a b c
38
c b a
39
40
They can be used for initialization of an iet::
41
42
sage: p = iet.Permutation('a b','b a')
43
sage: T = iet.IntervalExchangeTransformation(p, [1,sqrt(2)])
44
sage: print T
45
Interval exchange transformation of [0, sqrt(2) + 1[ with permutation
46
a b
47
b a
48
49
You can also, create labelled permutations of linear involutions::
50
51
sage: p = iet.GeneralizedPermutation('a a b', 'b c c')
52
sage: print p
53
a a b
54
b c c
55
56
Sometimes it's more easy to deal with reduced permutations::
57
58
sage: p = iet.Permutation('a b c', 'c b a', reduced = True)
59
sage: print p
60
a b c
61
c b a
62
63
Permutations with flips::
64
65
sage: p1 = iet.Permutation('a b c', 'c b a', flips = ['a','c'])
66
sage: print p1
67
-a b -c
68
-c b -a
69
70
Creation of Rauzy diagrams::
71
72
sage: r = iet.RauzyDiagram('a b c', 'c b a')
73
74
Reduced Rauzy diagrams are constructed using the same arguments than for
75
permutations::
76
77
sage: r = iet.RauzyDiagram('a b b','c c a')
78
sage: r_red = iet.RauzyDiagram('a b b','c c a',reduced=True)
79
sage: r.cardinality()
80
12
81
sage: r_red.cardinality()
82
4
83
84
By defaut, Rauzy diagram are generated by induction on the right. You can use
85
several options to enlarge (or restrict) the diagram (try help(iet.RauzyDiagram) for
86
more precisions)::
87
88
sage: r1 = iet.RauzyDiagram('a b c','c b a',right_induction=True)
89
sage: r2 = iet.RauzyDiagram('a b c','c b a',left_right_inversion=True)
90
91
You can consider self similar iet using path in Rauzy diagrams and eigenvectors
92
of the corresponding matrix::
93
94
sage: p = iet.Permutation("a b c d", "d c b a")
95
sage: d = p.rauzy_diagram()
96
sage: g = d.path(p, 't', 't', 'b', 't', 'b', 'b', 't', 'b')
97
sage: g
98
Path of length 8 in a Rauzy diagram
99
sage: g.is_loop()
100
True
101
sage: g.is_full()
102
True
103
sage: m = g.matrix()
104
sage: v = m.eigenvectors_right()[-1][1][0]
105
sage: T1 = iet.IntervalExchangeTransformation(p, v)
106
sage: T2 = T1.rauzy_move(iterations=8)
107
sage: T1.normalize(1) == T2.normalize(1)
108
True
109
110
REFERENCES:
111
112
.. [BL08] Corentin Boissy and Erwan Lanneau, "Dynamics and geometry of the
113
Rauzy-Veech induction for quadratic differentials" (arxiv:0710.5614) to appear
114
in Ergodic Theory and Dynamical Systems
115
116
.. [DN90] Claude Danthony and Arnaldo Nogueira "Measured foliations on
117
nonorientable surfaces", Annales scientifiques de l'Ecole Normale
118
Superieure, Ser. 4, 23, no. 3 (1990) p 469-494
119
120
.. [N85] Arnaldo Nogueira, "Almost all Interval Exchange Transformations with
121
Flips are Nonergodic" (Ergod. Th. & Dyn. Systems, Vol 5., (1985), 257-271
122
123
.. [R79] Gerard Rauzy, "Echanges d'intervalles et transformations induites",
124
Acta Arith. 34, no. 3, 203-212, 1980
125
126
.. [V78] William Veech, "Interval exchange transformations", J. Analyse Math.
127
33, 222-272
128
129
.. [Z] Anton Zorich, "Generalized Permutation software"
130
(http://perso.univ-rennes1.fr/anton.zorich)
131
132
133
AUTHORS:
134
135
- Vincent Delecroix (2009-09-29): initial version
136
137
"""
138
#*****************************************************************************
139
# Copyright (C) 2008 Vincent Delecroix <[email protected]>
140
#
141
# Distributed under the terms of the GNU General Public License (GPL)
142
# http://www.gnu.org/licenses/
143
#*****************************************************************************
144
145
def _two_lists(a):
146
r"""
147
Try to return the input as a list of two lists
148
149
INPUT:
150
151
- ``a`` - either a string, one or two lists, one or two tuples
152
153
OUTPUT:
154
155
-- two lists
156
157
TESTS:
158
159
::
160
sage: from sage.combinat.iet.constructors import _two_lists
161
sage: _two_lists(('a1 a2','b1 b2'))
162
[['a1', 'a2'], ['b1', 'b2']]
163
sage: _two_lists('a1 a2\nb1 b2')
164
[['a1', 'a2'], ['b1', 'b2']]
165
sage: _two_lists(['a b','c'])
166
[['a', 'b'], ['c']]
167
168
..The ValueError and TypeError can be raised if it fails::
169
170
sage: _two_lists('a b')
171
Traceback (most recent call last):
172
...
173
ValueError: your chain must contain two lines
174
sage: _two_lists('a b\nc d\ne f')
175
Traceback (most recent call last):
176
...
177
ValueError: your chain must contain two lines
178
sage: _two_lists(1)
179
Traceback (most recent call last):
180
...
181
TypeError: argument not accepted
182
"""
183
from sage.combinat.permutation import Permutation_class
184
185
res = [None,None]
186
187
if isinstance(a,str):
188
a = a.split('\n')
189
if len(a) != 2:
190
raise ValueError, "your chain must contain two lines"
191
else :
192
res[0] = a[0].split()
193
res[1] = a[1].split()
194
195
elif isinstance(a, Permutation_class):
196
res[0] = range(1,len(a)+1)
197
res[1] = [a[i] for i in range(len(a))]
198
199
elif not hasattr(a,'__len__'):
200
raise TypeError, "argument not accepted"
201
202
elif len(a) == 0 or len(a) > 2:
203
raise ValueError, "your argument can not be split in two parts"
204
205
elif len(a) == 1:
206
a = a[0]
207
if isinstance(a, Permutation_class):
208
res[0] = range(1,len(a)+1)
209
res[1] = [a[i] for i in range(len(a))]
210
211
elif isinstance(a, (list,tuple)):
212
if (len(a) != 2):
213
raise ValueError, "your list must contain two objects"
214
for i in range(2):
215
if isinstance(a[i], str):
216
res[i] = a[i].split()
217
else:
218
res[i] = list(a[i])
219
220
else :
221
raise TypeError, "argument not accepted"
222
223
else :
224
for i in range(2):
225
if isinstance(a[i], str):
226
res[i] = a[i].split()
227
else:
228
res[i] = list(a[i])
229
230
return res
231
232
def Permutation(*args,**kargs):
233
r"""
234
Returns a permutation of an interval exchange transformation.
235
236
Those permutations are the combinatoric part of an interval exchange
237
transformation (IET). The combinatorial study of those objects starts with
238
Gerard Rauzy [R79]_ and William Veech [V78]_.
239
240
The combinatoric part of interval exchange transformation can be taken
241
independently from its dynamical origin. It has an important link with
242
strata of Abelian differential (see :mod:`~sage.combinat.iet.strata`)
243
244
INPUT:
245
246
- ``intervals`` - string, two strings, list, tuples that can be converted to
247
two lists
248
249
- ``reduced`` - boolean (default: False) specifies reduction. False means
250
labelled permutation and True means reduced permutation.
251
252
- ``flips`` - iterable (default: None) the letters which correspond to
253
flipped intervals.
254
255
OUTPUT:
256
257
permutation -- the output type depends of the data.
258
259
EXAMPLES:
260
261
Creation of labelled permutations ::
262
263
sage: iet.Permutation('a b c d','d c b a')
264
a b c d
265
d c b a
266
sage: iet.Permutation([[0,1,2,3],[2,1,3,0]])
267
0 1 2 3
268
2 1 3 0
269
sage: iet.Permutation([0, 'A', 'B', 1], ['B', 0, 1, 'A'])
270
0 A B 1
271
B 0 1 A
272
273
Creation of reduced permutations::
274
275
sage: iet.Permutation('a b c', 'c b a', reduced = True)
276
a b c
277
c b a
278
sage: iet.Permutation([0, 1, 2, 3], [1, 3, 0, 2])
279
0 1 2 3
280
1 3 0 2
281
282
Creation of flipped permutations::
283
284
sage: iet.Permutation('a b c', 'c b a', flips=['a','b'])
285
-a -b c
286
c -b -a
287
sage: iet.Permutation('a b c', 'c b a', flips=['a'], reduced=True)
288
-a b c
289
c b -a
290
291
TESTS:
292
293
::
294
295
sage: p = iet.Permutation('a b c','c b a')
296
sage: iet.Permutation(p) == p
297
True
298
sage: iet.Permutation(p, reduced=True) == p.reduced()
299
True
300
301
::
302
303
sage: p = iet.Permutation('a','a',flips='a',reduced=True)
304
sage: iet.Permutation(p) == p
305
True
306
307
::
308
309
sage: p = iet.Permutation('a b c','c b a',flips='a')
310
sage: iet.Permutation(p) == p
311
True
312
sage: iet.Permutation(p, reduced=True) == p.reduced()
313
True
314
315
::
316
317
sage: p = iet.Permutation('a b c','c b a',reduced=True)
318
sage: iet.Permutation(p) == p
319
True
320
"""
321
from labelled import LabelledPermutation
322
from labelled import LabelledPermutationIET
323
from labelled import FlippedLabelledPermutationIET
324
325
from reduced import ReducedPermutation
326
from reduced import ReducedPermutationIET
327
from reduced import FlippedReducedPermutationIET
328
329
if 'reduced' not in kargs :
330
reduction = None
331
elif not isinstance(kargs["reduced"], bool) :
332
raise TypeError("reduced must be of type boolean")
333
else :
334
if kargs["reduced"] == True : reduction = True
335
else : reduction = False
336
337
if 'flips' not in kargs :
338
flips = []
339
else :
340
flips = list(kargs['flips'])
341
342
343
if 'alphabet' not in kargs :
344
alphabet = None
345
else :
346
alphabet = kargs['alphabet']
347
348
if len(args) == 1:
349
args = args[0]
350
if isinstance(args, LabelledPermutation):
351
if flips == []:
352
if reduction is None or reduction is False:
353
from copy import copy
354
return copy(args)
355
else:
356
return args.reduced()
357
else: # conversion not yet implemented
358
reduced = reduction in (None, False)
359
return PermutationIET(
360
args.list(),
361
reduced=reduced,
362
flips=flips,
363
alphabet=alphabet)
364
365
if isinstance(args, ReducedPermutation):
366
if flips == []:
367
if reduction is None or reduction is True:
368
from copy import copy
369
return copy(args)
370
else: # conversion not yet implemented
371
return PermutationIET(
372
args.list(),
373
reduced=True)
374
else: # conversion not yet implemented
375
reduced = reduction in (None, True)
376
return PermutationIET(
377
args.list(),
378
reduced=reduced,
379
flips=flips,
380
alphabet=alphabet)
381
382
a = _two_lists(args)
383
384
l = a[0] + a[1]
385
letters = set(l)
386
387
for letter in flips :
388
if letter not in letters :
389
raise ValueError, "flips contains not valid letters"
390
391
for letter in letters :
392
if a[0].count(letter) != 1 or a[1].count(letter) != 1:
393
raise ValueError, "letters must appear once in each interval"
394
395
if reduction == True :
396
if flips == [] :
397
return ReducedPermutationIET(a, alphabet=alphabet)
398
else :
399
return FlippedReducedPermutationIET(a, alphabet=alphabet, flips=flips)
400
else :
401
if flips == [] :
402
return LabelledPermutationIET(a, alphabet=alphabet)
403
else :
404
return FlippedLabelledPermutationIET(a, alphabet=alphabet, flips=flips)
405
406
def GeneralizedPermutation(*args,**kargs):
407
r"""
408
Returns a permutation of an interval exchange transformation.
409
410
Those permutations are the combinatoric part of linear involutions and were
411
introduced by Danthony-Nogueira [DN90]_. The full combinatoric study and
412
precise links with strata of quadratic differentials was achieved few years
413
later by Boissy-Lanneau [BL08]_.
414
415
INPUT:
416
417
- ``intervals`` - strings, list, tuples
418
419
- ``reduced`` - boolean (defaut: False) specifies reduction. False means
420
labelled permutation and True means reduced permutation.
421
422
- ``flips`` - iterable (default: None) the letters which correspond to
423
flipped intervals.
424
425
OUTPUT:
426
427
generalized permutation -- the output type depends on the data.
428
429
EXAMPLES:
430
431
Creation of labelled generalized permutations::
432
433
sage: iet.GeneralizedPermutation('a b b','c c a')
434
a b b
435
c c a
436
sage: iet.GeneralizedPermutation('a a','b b c c')
437
a a
438
b b c c
439
sage: iet.GeneralizedPermutation([[0,1,2,3,1],[4,2,5,3,5,4,0]])
440
0 1 2 3 1
441
4 2 5 3 5 4 0
442
443
Creation of reduced generalized permutations::
444
445
sage: iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
446
a b b
447
c c a
448
sage: iet.GeneralizedPermutation('a a b b', 'c c d d', reduced = True)
449
a a b b
450
c c d d
451
452
Creation of flipped generalized permutations::
453
454
sage: iet.GeneralizedPermutation('a b c a', 'd c d b', flips = ['a','b'])
455
-a -b c -a
456
d c d -b
457
"""
458
from template import FlippedPermutation
459
460
from labelled import LabelledPermutation
461
from labelled import LabelledPermutationLI
462
from labelled import FlippedLabelledPermutationLI
463
464
from reduced import ReducedPermutation
465
from reduced import ReducedPermutationLI
466
from reduced import FlippedReducedPermutationLI
467
468
if 'reduced' not in kargs :
469
reduction = None
470
elif not isinstance(kargs["reduced"], bool) :
471
raise TypeError("reduced must be of type boolean")
472
else :
473
if kargs["reduced"] == True : reduction = True
474
else : reduction = False
475
476
if 'flips' not in kargs :
477
flips = []
478
else :
479
flips = list(kargs['flips'])
480
481
482
if 'alphabet' not in kargs :
483
alphabet = None
484
else :
485
alphabet = kargs['alphabet']
486
487
if len(args) == 1:
488
args = args[0]
489
if isinstance(args, LabelledPermutation):
490
if flips == []:
491
if reduction is None or reduction is False:
492
from copy import copy
493
return copy(args)
494
else:
495
return args.reduced()
496
else: # conversion not yet implemented
497
reduced = reduction in (None, False)
498
return PermutationLI(
499
args.list(),
500
reduced=reduced,
501
flips=flips,
502
alphabet=alphabet)
503
504
if isinstance(args, ReducedPermutation):
505
if flips == []:
506
if reduction is None or reduction is True:
507
from copy import copy
508
return copy(args)
509
else: # conversion not yet implemented
510
return PermutationLI(
511
args.list(),
512
reduced=True)
513
else: # conversion not yet implemented
514
reduced = reduction in (None, True)
515
return PermutationLI(
516
args.list(),
517
reduced=reduced,
518
flips=flips,
519
alphabet=alphabet)
520
521
a = _two_lists(args)
522
523
if 'reduced' not in kargs :
524
reduction = False
525
elif not isinstance(kargs["reduced"], bool) :
526
raise TypeError("reduced must be of type boolean")
527
else :
528
if kargs["reduced"] == True : reduction = True
529
else : reduction = False
530
531
if 'flips' not in kargs :
532
flips = []
533
else :
534
flips = list(kargs['flips'])
535
536
if 'alphabet' not in kargs :
537
alphabet = None
538
else :
539
alphabet = kargs['alphabet']
540
541
l = a[0] + a[1]
542
letters = set(l)
543
544
for letter in flips :
545
if letter not in letters :
546
raise TypeError("The flip list is not valid")
547
548
for letter in letters :
549
if l.count(letter) != 2:
550
raise ValueError, "Letters must reappear twice"
551
552
# check exitence of admissible length
553
b0 = a[0][:]
554
b1 = a[1][:]
555
for letter in letters :
556
if b0.count(letter) == 1 :
557
del b0[b0.index(letter)]
558
del b1[b1.index(letter)]
559
560
if (b0 == []) and (b1 == []):
561
return Permutation(a,**kargs)
562
563
elif (b0 == []) or (b1 == []):
564
raise ValueError, "There is no admissible length"
565
566
if reduction == True :
567
if flips == [] :
568
return ReducedPermutationLI(a, alphabet=alphabet)
569
else :
570
return FlippedReducedPermutationLI(a, alphabet=alphabet, flips=flips)
571
else :
572
if flips == [] :
573
return LabelledPermutationLI(a, alphabet=alphabet)
574
else :
575
return FlippedLabelledPermutationLI(a, alphabet=alphabet, flips=flips)
576
577
def Permutations_iterator(
578
nintervals=None,
579
irreducible=True,
580
reduced=False,
581
alphabet=None):
582
r"""
583
Returns an iterator over permutations.
584
585
This iterator allows you to iterate over permutations with given
586
constraints. If you want to iterate over permutations coming from a given
587
stratum you have to use the module :mod:`~sage.combinat.iet.strata` and
588
generate Rauzy diagrams from connected components.
589
590
INPUT:
591
592
- ``nintervals`` - non negative integer
593
594
- ``irreducible`` - boolean (default: True)
595
596
- ``reduced`` - boolean (default: False)
597
598
- ``alphabet`` - alphabet (default: None)
599
600
OUTPUT:
601
602
iterator -- an iterator over permutations
603
604
EXAMPLES:
605
606
Generates all reduced permutations with given number of intervals::
607
608
sage: P = iet.Permutations_iterator(nintervals=2,alphabet="ab",reduced=True)
609
sage: for p in P: print p, "\n* *"
610
a b
611
b a
612
* *
613
sage: P = iet.Permutations_iterator(nintervals=3,alphabet="abc",reduced=True)
614
sage: for p in P: print p, "\n* * *"
615
a b c
616
b c a
617
* * *
618
a b c
619
c a b
620
* * *
621
a b c
622
c b a
623
* * *
624
"""
625
from labelled import LabelledPermutationsIET_iterator
626
from reduced import ReducedPermutationsIET_iterator
627
628
if nintervals is None:
629
if alphabet is None:
630
raise ValueError, "You must specify an alphabet or a length"
631
else:
632
alphabet = Alphabet(alphabet)
633
if alphabet.cardinality() is Infinity:
634
raise ValueError, "You must sepcify a length with infinite alphabet"
635
nintervals = alphabet.cardinality()
636
637
elif alphabet is None:
638
alphabet = range(1,nintervals+1)
639
640
if reduced:
641
return ReducedPermutationsIET_iterator(
642
nintervals,
643
irreducible=irreducible,
644
alphabet=alphabet)
645
else:
646
return LabelledPermutationsIET_iterator(
647
nintervals,
648
irreducible=irreducible,
649
alphabet=alphabet)
650
651
def RauzyDiagram(*args, **kargs):
652
r"""
653
Return an object coding a Rauzy diagram.
654
655
The Rauzy diagram is an oriented graph with labelled edges. The set of
656
vertices corresponds to the permutations obtained by different operations
657
(mainly the .rauzy_move() operations that corresponds to an induction of
658
interval exchange transformation). The edges correspond to the action of the
659
different operations considered.
660
661
It first appeard in the original article of Rauzy [R79]_.
662
663
INPUT:
664
665
- ``intervals`` - lists, or strings, or tuples
666
667
- ``reduced`` - boolean (default: False) to precise reduction
668
669
- ``flips`` - list (default: []) for flipped permutations
670
671
- ``right_induction`` - boolean (default: True) consideration of left
672
induction in the diagram
673
674
- ``left_induction`` - boolean (default: False) consideration of right
675
induction in the diagram
676
677
- ``left_right_inversion`` - boolean (default: False) consideration of
678
inversion
679
680
- ``top_bottom_inversion`` - boolean (default: False) consideration of
681
reversion
682
683
- ``symmetric`` - boolean (default: False) consideration of the symmetric
684
operation
685
686
OUTPUT:
687
688
Rauzy diagram -- the Rauzy diagram that corresponds to your request
689
690
EXAMPLES:
691
692
Standard Rauzy diagrams::
693
694
sage: iet.RauzyDiagram('a b c d', 'd b c a')
695
Rauzy diagram with 12 permutations
696
sage: iet.RauzyDiagram('a b c d', 'd b c a', reduced = True)
697
Rauzy diagram with 6 permutations
698
699
Extended Rauzy diagrams::
700
701
sage: iet.RauzyDiagram('a b c d', 'd b c a', symmetric=True)
702
Rauzy diagram with 144 permutations
703
704
Using Rauzy diagrams and path in Rauzy diagrams::
705
706
sage: r = iet.RauzyDiagram('a b c', 'c b a')
707
sage: print r
708
Rauzy diagram with 3 permutations
709
sage: p = iet.Permutation('a b c','c b a')
710
sage: p in r
711
True
712
sage: g0 = r.path(p, 'top', 'bottom','top')
713
sage: g1 = r.path(p, 'bottom', 'top', 'bottom')
714
sage: print g0.is_loop(), g1.is_loop()
715
True True
716
sage: print g0.is_full(), g1.is_full()
717
False False
718
sage: g = g0 + g1
719
sage: g
720
Path of length 6 in a Rauzy diagram
721
sage: print g.is_loop(), g.is_full()
722
True True
723
sage: m = g.matrix()
724
sage: print m
725
[1 1 1]
726
[2 4 1]
727
[2 3 2]
728
sage: s = g.orbit_substitution()
729
sage: print s
730
WordMorphism: a->acbbc, b->acbbcbbc, c->acbc
731
sage: s.incidence_matrix() == m
732
True
733
734
We can then create the corresponding interval exchange transformation and
735
comparing the orbit of `0` to the fixed point of the orbit substitution::
736
737
sage: v = m.eigenvectors_right()[-1][1][0]
738
sage: T = iet.IntervalExchangeTransformation(p, v).normalize()
739
sage: print T
740
Interval exchange transformation of [0, 1[ with permutation
741
a b c
742
c b a
743
sage: w1 = []
744
sage: x = 0
745
sage: for i in range(20):
746
... w1.append(T.in_which_interval(x))
747
... x = T(x)
748
sage: w1 = Word(w1)
749
sage: w1
750
word: acbbcacbcacbbcbbcacb
751
sage: w2 = s.fixed_point('a')
752
sage: w2[:20]
753
word: acbbcacbcacbbcbbcacb
754
sage: w2[:20] == w1
755
True
756
"""
757
if not kargs.has_key('reduced'):
758
kargs['reduced'] = False
759
if not kargs.has_key('flips'):
760
kargs['flips'] =[]
761
if not kargs.has_key('alphabet'):
762
kargs['alphabet'] = None
763
764
p = GeneralizedPermutation(
765
args,
766
reduced= kargs['reduced'],
767
flips = kargs['flips'],
768
alphabet = kargs['alphabet'])
769
770
if not kargs.has_key('right_induction'):
771
kargs['right_induction'] = True
772
if not kargs.has_key('left_induction'):
773
kargs['left_induction'] = False
774
if not kargs.has_key('left_right_inversion'):
775
kargs['left_right_inversion'] = False
776
if not kargs.has_key('top_bottom_inversion'):
777
kargs['top_bottom_inversion'] = False
778
if not kargs.has_key('symmetric'):
779
kargs['symmetric'] = False
780
781
return p.rauzy_diagram(
782
right_induction = kargs['right_induction'],
783
left_induction = kargs['left_induction'],
784
left_right_inversion = kargs['left_right_inversion'],
785
top_bottom_inversion = kargs['top_bottom_inversion'],
786
symmetric = kargs['symmetric'])
787
788
#TODO
789
# def GeneralizedPermutation_iterator():
790
# print "gpi"
791
792
def IntervalExchangeTransformation(permutation=None,lengths=None):
793
"""
794
Constructs an Interval exchange transformation.
795
796
An interval exchange transformation (or iet) is a map from an
797
interval to itself. It is defined on the interval except at a finite
798
number of points (the singularities) and is a translation on each
799
connected component of the complement of the singularities. Moreover it is a
800
bijection on its image (or it is injective).
801
802
An interval exchange transformation is encoded by two datas. A permutation
803
(that corresponds to the way we echange the intervals) and a vector of
804
positive reals (that corresponds to the lengths of the complement of the
805
singularities).
806
807
INPUT:
808
809
- ``permutation`` - a permutation
810
811
- ``lengths`` - a list or a dictionnary of lengths
812
813
OUTPUT:
814
815
interval exchange transformation -- an map of an interval
816
817
EXAMPLES:
818
819
Two initialization methods, the first using a iet.Permutation::
820
821
sage: p = iet.Permutation('a b c','c b a')
822
sage: t = iet.IntervalExchangeTransformation(p, {'a':1,'b':0.4523,'c':2.8})
823
824
The second is more direct::
825
826
sage: t = iet.IntervalExchangeTransformation(('a b','b a'),{'a':1,'b':4})
827
828
It's also possible to initialize the lengths only with a list::
829
830
sage: t = iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,0.4,2])
831
832
The two fundamental operations are Rauzy move and normalization::
833
834
sage: t = iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,0.4,2])
835
sage: s = t.rauzy_move()
836
sage: s_n = s.normalize(t.length())
837
sage: s_n.length() == t.length()
838
True
839
840
A not too simple example of a self similar interval exchange transformation::
841
842
sage: p = iet.Permutation('a b c d','d c b a')
843
sage: d = p.rauzy_diagram()
844
sage: g = d.path(p, 't', 't', 'b', 't', 'b', 'b', 't', 'b')
845
sage: m = g.matrix()
846
sage: v = m.eigenvectors_right()[-1][1][0]
847
sage: t = iet.IntervalExchangeTransformation(p,v)
848
sage: s = t.rauzy_move(iterations=8)
849
sage: s.normalize() == t.normalize()
850
True
851
"""
852
from iet import IntervalExchangeTransformation as _IET
853
from labelled import LabelledPermutationIET
854
from template import FlippedPermutation
855
856
if isinstance(permutation, FlippedPermutation):
857
raise TypeError, "flips are not yet implemented"
858
if isinstance(permutation, LabelledPermutationIET):
859
p = permutation
860
else:
861
p = Permutation(permutation,reduced=False)
862
863
864
if isinstance(lengths, dict):
865
l = [0] * len(p)
866
alphabet = p._alphabet
867
for letter in lengths:
868
l[alphabet.rank(letter)] = lengths[letter]
869
else:
870
l = list(lengths)
871
872
if len(l) != len(p):
873
raise ValueError, "bad number of lengths"
874
875
for x in l:
876
try:
877
y = float(x)
878
except ValueError:
879
raise TypeError, "unable to convert x (='%s') into a real number" %(str(x))
880
881
if y <= 0:
882
raise ValueError, "lengths must be positive"
883
884
return _IET(p,l)
885
886
IET = IntervalExchangeTransformation
887
888
#TODO
889
# def LinearInvolution(*args,**kargs):
890
# r"""
891
# Constructs a Linear Involution from the given data
892
# """
893
# from iet import LinearInvolution as _LI
894
# pass
895
896
# LI = LinearInvolution
897
898
899
900