Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/dynamics/interval_exchanges/constructors.py
8815 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 theoretic 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
from template import PermutationIET, PermutationLI
145
146
def _two_lists(a):
147
r"""
148
Try to return the input as a list of two lists
149
150
INPUT:
151
152
- ``a`` - either a string, one or two lists, one or two tuples
153
154
OUTPUT:
155
156
-- two lists
157
158
TESTS:
159
160
::
161
sage: from sage.dynamics.interval_exchanges.constructors import _two_lists
162
sage: _two_lists(('a1 a2','b1 b2'))
163
[['a1', 'a2'], ['b1', 'b2']]
164
sage: _two_lists('a1 a2\nb1 b2')
165
[['a1', 'a2'], ['b1', 'b2']]
166
sage: _two_lists(['a b','c'])
167
[['a', 'b'], ['c']]
168
169
..The ValueError and TypeError can be raised if it fails::
170
171
sage: _two_lists('a b')
172
Traceback (most recent call last):
173
...
174
ValueError: your chain must contain two lines
175
sage: _two_lists('a b\nc d\ne f')
176
Traceback (most recent call last):
177
...
178
ValueError: your chain must contain two lines
179
sage: _two_lists(1)
180
Traceback (most recent call last):
181
...
182
TypeError: argument not accepted
183
sage: _two_lists([1,2,3])
184
Traceback (most recent call last):
185
...
186
ValueError: your argument can not be split in two parts
187
"""
188
from sage.combinat.permutation import Permutation
189
190
res = [None, None]
191
192
if isinstance(a,str):
193
a = a.split('\n')
194
if len(a) != 2:
195
raise ValueError("your chain must contain two lines")
196
else :
197
res[0] = a[0].split()
198
res[1] = a[1].split()
199
200
elif isinstance(a, Permutation):
201
res[0] = range(1,len(a)+1)
202
res[1] = [a[i] for i in range(len(a))]
203
204
elif not hasattr(a,'__len__'):
205
raise TypeError("argument not accepted")
206
207
elif len(a) == 0 or len(a) > 2:
208
raise ValueError("your argument can not be split in two parts")
209
210
elif len(a) == 1:
211
a = a[0]
212
if isinstance(a, Permutation):
213
res[0] = range(1,len(a)+1)
214
res[1] = [a[i] for i in range(len(a))]
215
216
elif isinstance(a, (list,tuple)):
217
if (len(a) != 2):
218
raise ValueError("your list must contain two objects")
219
for i in range(2):
220
if isinstance(a[i], str):
221
res[i] = a[i].split()
222
else:
223
res[i] = list(a[i])
224
225
else :
226
raise TypeError("argument not accepted")
227
228
else :
229
for i in range(2):
230
if isinstance(a[i], str):
231
res[i] = a[i].split()
232
else:
233
res[i] = list(a[i])
234
235
return res
236
237
def Permutation(*args,**kargs):
238
r"""
239
Returns a permutation of an interval exchange transformation.
240
241
Those permutations are the combinatoric part of an interval exchange
242
transformation (IET). The combinatorial study of those objects starts with
243
Gerard Rauzy [R79]_ and William Veech [V78]_.
244
245
The combinatoric part of interval exchange transformation can be taken
246
independently from its dynamical origin. It has an important link with
247
strata of Abelian differential (see :mod:`~sage.dynamics.interval_exchanges.strata`)
248
249
INPUT:
250
251
- ``intervals`` - string, two strings, list, tuples that can be converted to
252
two lists
253
254
- ``reduced`` - boolean (default: False) specifies reduction. False means
255
labelled permutation and True means reduced permutation.
256
257
- ``flips`` - iterable (default: None) the letters which correspond to
258
flipped intervals.
259
260
OUTPUT:
261
262
permutation -- the output type depends of the data.
263
264
EXAMPLES:
265
266
Creation of labelled permutations ::
267
268
sage: iet.Permutation('a b c d','d c b a')
269
a b c d
270
d c b a
271
sage: iet.Permutation([[0,1,2,3],[2,1,3,0]])
272
0 1 2 3
273
2 1 3 0
274
sage: iet.Permutation([0, 'A', 'B', 1], ['B', 0, 1, 'A'])
275
0 A B 1
276
B 0 1 A
277
278
Creation of reduced permutations::
279
280
sage: iet.Permutation('a b c', 'c b a', reduced = True)
281
a b c
282
c b a
283
sage: iet.Permutation([0, 1, 2, 3], [1, 3, 0, 2])
284
0 1 2 3
285
1 3 0 2
286
287
Creation of flipped permutations::
288
289
sage: iet.Permutation('a b c', 'c b a', flips=['a','b'])
290
-a -b c
291
c -b -a
292
sage: iet.Permutation('a b c', 'c b a', flips=['a'], reduced=True)
293
-a b c
294
c b -a
295
296
TESTS:
297
298
::
299
300
sage: p = iet.Permutation('a b c','c b a')
301
sage: iet.Permutation(p) == p
302
True
303
sage: iet.Permutation(p, reduced=True) == p.reduced()
304
True
305
306
::
307
308
sage: p = iet.Permutation('a','a',flips='a',reduced=True)
309
sage: iet.Permutation(p) == p
310
True
311
312
::
313
314
sage: p = iet.Permutation('a b c','c b a',flips='a')
315
sage: iet.Permutation(p) == p
316
True
317
sage: iet.Permutation(p, reduced=True) == p.reduced()
318
True
319
320
::
321
322
sage: p = iet.Permutation('a b c','c b a',reduced=True)
323
sage: iet.Permutation(p) == p
324
True
325
326
TESTS::
327
328
sage: iet.Permutation('a b c','c b a',reduced='badly')
329
Traceback (most recent call last):
330
...
331
TypeError: reduced must be of type boolean
332
sage: iet.Permutation('a','a',flips='b',reduced=True)
333
Traceback (most recent call last):
334
...
335
ValueError: flips contains not valid letters
336
sage: iet.Permutation('a b c','c a a',reduced=True)
337
Traceback (most recent call last):
338
...
339
ValueError: letters must appear once in each interval
340
"""
341
from labelled import LabelledPermutation
342
from labelled import LabelledPermutationIET
343
from labelled import FlippedLabelledPermutationIET
344
345
from reduced import ReducedPermutation
346
from reduced import ReducedPermutationIET
347
from reduced import FlippedReducedPermutationIET
348
349
if 'reduced' not in kargs :
350
reduction = None
351
elif not isinstance(kargs["reduced"], bool) :
352
raise TypeError("reduced must be of type boolean")
353
else :
354
reduction = kargs["reduced"]
355
356
if 'flips' not in kargs :
357
flips = []
358
else :
359
flips = list(kargs['flips'])
360
361
362
if 'alphabet' not in kargs :
363
alphabet = None
364
else :
365
alphabet = kargs['alphabet']
366
367
if len(args) == 1:
368
args = args[0]
369
if isinstance(args, LabelledPermutation):
370
if flips == []:
371
if reduction is None or not reduction:
372
from copy import copy
373
return copy(args)
374
else:
375
return args.reduced()
376
else: # conversion not yet implemented
377
reduced = reduction in (None, False)
378
return PermutationIET(
379
args.list(),
380
reduced=reduced,
381
flips=flips,
382
alphabet=alphabet)
383
384
if isinstance(args, ReducedPermutation):
385
if flips == []:
386
if reduction is None or reduction:
387
from copy import copy
388
return copy(args)
389
else: # conversion not yet implemented
390
return PermutationIET(
391
args.list(),
392
reduced=True)
393
else: # conversion not yet implemented
394
reduced = reduction in (None, True)
395
return PermutationIET(
396
args.list(),
397
reduced=reduced,
398
flips=flips,
399
alphabet=alphabet)
400
401
a = _two_lists(args)
402
403
l = a[0] + a[1]
404
letters = set(l)
405
406
for letter in flips :
407
if letter not in letters :
408
raise ValueError("flips contains not valid letters")
409
410
for letter in letters :
411
if a[0].count(letter) != 1 or a[1].count(letter) != 1:
412
raise ValueError("letters must appear once in each interval")
413
414
if reduction :
415
if flips == [] :
416
return ReducedPermutationIET(a, alphabet=alphabet)
417
else :
418
return FlippedReducedPermutationIET(a, alphabet=alphabet, flips=flips)
419
else :
420
if flips == [] :
421
return LabelledPermutationIET(a, alphabet=alphabet)
422
else :
423
return FlippedLabelledPermutationIET(a, alphabet=alphabet, flips=flips)
424
425
def GeneralizedPermutation(*args,**kargs):
426
r"""
427
Returns a permutation of an interval exchange transformation.
428
429
Those permutations are the combinatoric part of linear involutions and were
430
introduced by Danthony-Nogueira [DN90]_. The full combinatoric study and
431
precise links with strata of quadratic differentials was achieved few years
432
later by Boissy-Lanneau [BL08]_.
433
434
INPUT:
435
436
- ``intervals`` - strings, list, tuples
437
438
- ``reduced`` - boolean (defaut: False) specifies reduction. False means
439
labelled permutation and True means reduced permutation.
440
441
- ``flips`` - iterable (default: None) the letters which correspond to
442
flipped intervals.
443
444
OUTPUT:
445
446
generalized permutation -- the output type depends on the data.
447
448
EXAMPLES:
449
450
Creation of labelled generalized permutations::
451
452
sage: iet.GeneralizedPermutation('a b b','c c a')
453
a b b
454
c c a
455
sage: iet.GeneralizedPermutation('a a','b b c c')
456
a a
457
b b c c
458
sage: iet.GeneralizedPermutation([[0,1,2,3,1],[4,2,5,3,5,4,0]])
459
0 1 2 3 1
460
4 2 5 3 5 4 0
461
462
Creation of reduced generalized permutations::
463
464
sage: iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
465
a b b
466
c c a
467
sage: iet.GeneralizedPermutation('a a b b', 'c c d d', reduced = True)
468
a a b b
469
c c d d
470
471
Creation of flipped generalized permutations::
472
473
sage: iet.GeneralizedPermutation('a b c a', 'd c d b', flips = ['a','b'])
474
-a -b c -a
475
d c d -b
476
477
TESTS::
478
479
sage: iet.GeneralizedPermutation('a a b b', 'c c d d', reduced = 'may')
480
Traceback (most recent call last):
481
...
482
TypeError: reduced must be of type boolean
483
sage: iet.GeneralizedPermutation('a b c a', 'd c d b', flips = ['e','b'])
484
Traceback (most recent call last):
485
...
486
TypeError: The flip list is not valid
487
sage: iet.GeneralizedPermutation('a b c a', 'd c c b', flips = ['a','b'])
488
Traceback (most recent call last):
489
...
490
ValueError: Letters must reappear twice
491
"""
492
from labelled import LabelledPermutation
493
from labelled import LabelledPermutationLI
494
from labelled import FlippedLabelledPermutationLI
495
496
from reduced import ReducedPermutation
497
from reduced import ReducedPermutationLI
498
from reduced import FlippedReducedPermutationLI
499
500
if 'reduced' not in kargs :
501
reduction = None
502
elif not isinstance(kargs["reduced"], bool) :
503
raise TypeError("reduced must be of type boolean")
504
else :
505
reduction = kargs["reduced"]
506
507
if 'flips' not in kargs :
508
flips = []
509
else :
510
flips = list(kargs['flips'])
511
512
513
if 'alphabet' not in kargs :
514
alphabet = None
515
else :
516
alphabet = kargs['alphabet']
517
518
if len(args) == 1:
519
args = args[0]
520
if isinstance(args, LabelledPermutation):
521
if flips == []:
522
if reduction is None or not reduction:
523
from copy import copy
524
return copy(args)
525
else:
526
return args.reduced()
527
else: # conversion not yet implemented
528
reduced = reduction in (None, False)
529
return PermutationLI(
530
args.list(),
531
reduced=reduced,
532
flips=flips,
533
alphabet=alphabet)
534
535
if isinstance(args, ReducedPermutation):
536
if flips == []:
537
if reduction is None or reduction:
538
from copy import copy
539
return copy(args)
540
else: # conversion not yet implemented
541
return PermutationLI(
542
args.list(),
543
reduced=True)
544
else: # conversion not yet implemented
545
reduced = reduction in (None, True)
546
return PermutationLI(
547
args.list(),
548
reduced=reduced,
549
flips=flips,
550
alphabet=alphabet)
551
552
a = _two_lists(args)
553
554
if 'reduced' not in kargs :
555
reduction = False
556
elif not isinstance(kargs["reduced"], bool) :
557
raise TypeError("reduced must be of type boolean")
558
else :
559
reduction = kargs["reduced"]
560
561
if 'flips' not in kargs :
562
flips = []
563
else :
564
flips = list(kargs['flips'])
565
566
if 'alphabet' not in kargs :
567
alphabet = None
568
else :
569
alphabet = kargs['alphabet']
570
571
l = a[0] + a[1]
572
letters = set(l)
573
574
for letter in flips :
575
if letter not in letters :
576
raise TypeError("The flip list is not valid")
577
578
for letter in letters :
579
if l.count(letter) != 2:
580
raise ValueError("Letters must reappear twice")
581
582
# check existence of admissible length
583
b0 = a[0][:]
584
b1 = a[1][:]
585
for letter in letters :
586
if b0.count(letter) == 1 :
587
del b0[b0.index(letter)]
588
del b1[b1.index(letter)]
589
590
if (b0 == []) and (b1 == []):
591
return Permutation(a,**kargs)
592
593
elif (b0 == []) or (b1 == []):
594
raise ValueError("There is no admissible length")
595
596
if reduction :
597
if flips == [] :
598
return ReducedPermutationLI(a, alphabet=alphabet)
599
else :
600
return FlippedReducedPermutationLI(a, alphabet=alphabet, flips=flips)
601
else :
602
if flips == [] :
603
return LabelledPermutationLI(a, alphabet=alphabet)
604
else :
605
return FlippedLabelledPermutationLI(a, alphabet=alphabet, flips=flips)
606
607
def Permutations_iterator(nintervals=None, irreducible=True,
608
reduced=False, alphabet=None):
609
r"""
610
Returns an iterator over permutations.
611
612
This iterator allows you to iterate over permutations with given
613
constraints. If you want to iterate over permutations coming from a given
614
stratum you have to use the module :mod:`~sage.dynamics.flat_surfaces.strata` and
615
generate Rauzy diagrams from connected components.
616
617
INPUT:
618
619
- ``nintervals`` - non negative integer
620
621
- ``irreducible`` - boolean (default: True)
622
623
- ``reduced`` - boolean (default: False)
624
625
- ``alphabet`` - alphabet (default: None)
626
627
OUTPUT:
628
629
iterator -- an iterator over permutations
630
631
EXAMPLES:
632
633
Generates all reduced permutations with given number of intervals::
634
635
sage: P = iet.Permutations_iterator(nintervals=2,alphabet="ab",reduced=True)
636
sage: for p in P: print p, "\n* *"
637
a b
638
b a
639
* *
640
sage: P = iet.Permutations_iterator(nintervals=3,alphabet="abc",reduced=True)
641
sage: for p in P: print p, "\n* * *"
642
a b c
643
b c a
644
* * *
645
a b c
646
c a b
647
* * *
648
a b c
649
c b a
650
* * *
651
652
TESTS::
653
654
sage: P = iet.Permutations_iterator(nintervals=None, alphabet=None)
655
Traceback (most recent call last):
656
...
657
ValueError: You must specify an alphabet or a length
658
sage: P = iet.Permutations_iterator(nintervals=None, alphabet=ZZ)
659
Traceback (most recent call last):
660
...
661
ValueError: You must specify a length with infinite alphabet
662
"""
663
from labelled import LabelledPermutationsIET_iterator
664
from reduced import ReducedPermutationsIET_iterator
665
from sage.combinat.words.alphabet import Alphabet
666
from sage.rings.infinity import Infinity
667
668
if nintervals is None:
669
if alphabet is None:
670
raise ValueError("You must specify an alphabet or a length")
671
else:
672
alphabet = Alphabet(alphabet)
673
if alphabet.cardinality() is Infinity:
674
raise ValueError("You must specify a length with infinite alphabet")
675
nintervals = alphabet.cardinality()
676
677
elif alphabet is None:
678
alphabet = range(1, nintervals+1)
679
680
if reduced:
681
return ReducedPermutationsIET_iterator(nintervals,
682
irreducible=irreducible,
683
alphabet=alphabet)
684
else:
685
return LabelledPermutationsIET_iterator(nintervals,
686
irreducible=irreducible,
687
alphabet=alphabet)
688
689
def RauzyDiagram(*args, **kargs):
690
r"""
691
Return an object coding a Rauzy diagram.
692
693
The Rauzy diagram is an oriented graph with labelled edges. The set of
694
vertices corresponds to the permutations obtained by different operations
695
(mainly the .rauzy_move() operations that corresponds to an induction of
696
interval exchange transformation). The edges correspond to the action of the
697
different operations considered.
698
699
It first appeard in the original article of Rauzy [R79]_.
700
701
INPUT:
702
703
- ``intervals`` - lists, or strings, or tuples
704
705
- ``reduced`` - boolean (default: False) to precise reduction
706
707
- ``flips`` - list (default: []) for flipped permutations
708
709
- ``right_induction`` - boolean (default: True) consideration of left
710
induction in the diagram
711
712
- ``left_induction`` - boolean (default: False) consideration of right
713
induction in the diagram
714
715
- ``left_right_inversion`` - boolean (default: False) consideration of
716
inversion
717
718
- ``top_bottom_inversion`` - boolean (default: False) consideration of
719
reversion
720
721
- ``symmetric`` - boolean (default: False) consideration of the symmetric
722
operation
723
724
OUTPUT:
725
726
Rauzy diagram -- the Rauzy diagram that corresponds to your request
727
728
EXAMPLES:
729
730
Standard Rauzy diagrams::
731
732
sage: iet.RauzyDiagram('a b c d', 'd b c a')
733
Rauzy diagram with 12 permutations
734
sage: iet.RauzyDiagram('a b c d', 'd b c a', reduced = True)
735
Rauzy diagram with 6 permutations
736
737
Extended Rauzy diagrams::
738
739
sage: iet.RauzyDiagram('a b c d', 'd b c a', symmetric=True)
740
Rauzy diagram with 144 permutations
741
742
Using Rauzy diagrams and path in Rauzy diagrams::
743
744
sage: r = iet.RauzyDiagram('a b c', 'c b a')
745
sage: print r
746
Rauzy diagram with 3 permutations
747
sage: p = iet.Permutation('a b c','c b a')
748
sage: p in r
749
True
750
sage: g0 = r.path(p, 'top', 'bottom','top')
751
sage: g1 = r.path(p, 'bottom', 'top', 'bottom')
752
sage: print g0.is_loop(), g1.is_loop()
753
True True
754
sage: print g0.is_full(), g1.is_full()
755
False False
756
sage: g = g0 + g1
757
sage: g
758
Path of length 6 in a Rauzy diagram
759
sage: print g.is_loop(), g.is_full()
760
True True
761
sage: m = g.matrix()
762
sage: print m
763
[1 1 1]
764
[2 4 1]
765
[2 3 2]
766
sage: s = g.orbit_substitution()
767
sage: s
768
WordMorphism: a->acbbc, b->acbbcbbc, c->acbc
769
sage: s.incidence_matrix() == m
770
True
771
772
We can then create the corresponding interval exchange transformation and
773
comparing the orbit of `0` to the fixed point of the orbit substitution::
774
775
sage: v = m.eigenvectors_right()[-1][1][0]
776
sage: T = iet.IntervalExchangeTransformation(p, v).normalize()
777
sage: print T
778
Interval exchange transformation of [0, 1[ with permutation
779
a b c
780
c b a
781
sage: w1 = []
782
sage: x = 0
783
sage: for i in range(20):
784
....: w1.append(T.in_which_interval(x))
785
....: x = T(x)
786
sage: w1 = Word(w1)
787
sage: w1
788
word: acbbcacbcacbbcbbcacb
789
sage: w2 = s.fixed_point('a')
790
sage: w2[:20]
791
word: acbbcacbcacbbcbbcacb
792
sage: w2[:20] == w1
793
True
794
"""
795
if not kargs.has_key('reduced'):
796
kargs['reduced'] = False
797
if not kargs.has_key('flips'):
798
kargs['flips'] = []
799
if not kargs.has_key('alphabet'):
800
kargs['alphabet'] = None
801
802
p = GeneralizedPermutation(
803
args,
804
reduced= kargs['reduced'],
805
flips = kargs['flips'],
806
alphabet = kargs['alphabet'])
807
808
if not kargs.has_key('right_induction'):
809
kargs['right_induction'] = True
810
if not kargs.has_key('left_induction'):
811
kargs['left_induction'] = False
812
if not kargs.has_key('left_right_inversion'):
813
kargs['left_right_inversion'] = False
814
if not kargs.has_key('top_bottom_inversion'):
815
kargs['top_bottom_inversion'] = False
816
if not kargs.has_key('symmetric'):
817
kargs['symmetric'] = False
818
819
return p.rauzy_diagram(
820
right_induction = kargs['right_induction'],
821
left_induction = kargs['left_induction'],
822
left_right_inversion = kargs['left_right_inversion'],
823
top_bottom_inversion = kargs['top_bottom_inversion'],
824
symmetric = kargs['symmetric'])
825
826
#TODO
827
# def GeneralizedPermutation_iterator():
828
# print "gpi"
829
830
def IntervalExchangeTransformation(permutation=None, lengths=None):
831
"""
832
Constructs an Interval exchange transformation.
833
834
An interval exchange transformation (or iet) is a map from an
835
interval to itself. It is defined on the interval except at a finite
836
number of points (the singularities) and is a translation on each
837
connected component of the complement of the singularities. Moreover it is a
838
bijection on its image (or it is injective).
839
840
An interval exchange transformation is encoded by two datas. A permutation
841
(that corresponds to the way we echange the intervals) and a vector of
842
positive reals (that corresponds to the lengths of the complement of the
843
singularities).
844
845
INPUT:
846
847
- ``permutation`` - a permutation
848
849
- ``lengths`` - a list or a dictionnary of lengths
850
851
OUTPUT:
852
853
interval exchange transformation -- an map of an interval
854
855
EXAMPLES:
856
857
Two initialization methods, the first using a iet.Permutation::
858
859
sage: p = iet.Permutation('a b c','c b a')
860
sage: t = iet.IntervalExchangeTransformation(p, {'a':1,'b':0.4523,'c':2.8})
861
862
The second is more direct::
863
864
sage: t = iet.IntervalExchangeTransformation(('a b','b a'),{'a':1,'b':4})
865
866
It's also possible to initialize the lengths only with a list::
867
868
sage: t = iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,0.4,2])
869
870
The two fundamental operations are Rauzy move and normalization::
871
872
sage: t = iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,0.4,2])
873
sage: s = t.rauzy_move()
874
sage: s_n = s.normalize(t.length())
875
sage: s_n.length() == t.length()
876
True
877
878
A not too simple example of a self similar interval exchange transformation::
879
880
sage: p = iet.Permutation('a b c d','d c b a')
881
sage: d = p.rauzy_diagram()
882
sage: g = d.path(p, 't', 't', 'b', 't', 'b', 'b', 't', 'b')
883
sage: m = g.matrix()
884
sage: v = m.eigenvectors_right()[-1][1][0]
885
sage: t = iet.IntervalExchangeTransformation(p,v)
886
sage: s = t.rauzy_move(iterations=8)
887
sage: s.normalize() == t.normalize()
888
True
889
890
TESTS::
891
892
sage: iet.IntervalExchangeTransformation(('a b c','c b a'),[0.123,2])
893
Traceback (most recent call last):
894
...
895
ValueError: bad number of lengths
896
sage: iet.IntervalExchangeTransformation(('a b c','c b a'),[0.1,'rho',2])
897
Traceback (most recent call last):
898
...
899
TypeError: unable to convert x (='rho') into a real number
900
sage: iet.IntervalExchangeTransformation(('a b c','c b a'),[0.1,-2,2])
901
Traceback (most recent call last):
902
...
903
ValueError: lengths must be positive
904
"""
905
from iet import IntervalExchangeTransformation as _IET
906
from labelled import LabelledPermutationIET
907
from template import FlippedPermutation
908
909
if isinstance(permutation, FlippedPermutation):
910
raise TypeError("flips are not yet implemented")
911
if isinstance(permutation, LabelledPermutationIET):
912
p = permutation
913
else:
914
p = Permutation(permutation,reduced=False)
915
916
917
if isinstance(lengths, dict):
918
l = [0] * len(p)
919
alphabet = p._alphabet
920
for letter in lengths:
921
l[alphabet.rank(letter)] = lengths[letter]
922
else:
923
l = list(lengths)
924
925
if len(l) != len(p):
926
raise ValueError("bad number of lengths")
927
928
for x in l:
929
try:
930
y = float(x)
931
except ValueError:
932
raise TypeError("unable to convert x (='%s') into a real number" % (str(x)))
933
934
if y <= 0:
935
raise ValueError("lengths must be positive")
936
937
return _IET(p, l)
938
939
IET = IntervalExchangeTransformation
940
941
#TODO
942
# def LinearInvolution(*args,**kargs):
943
# r"""
944
# Constructs a Linear Involution from the given data
945
# """
946
# from iet import LinearInvolution as _LI
947
# pass
948
949
# LI = LinearInvolution
950
951