Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/combinat/iet/labelled.py
4072 views
1
r"""
2
Labelled permutations
3
4
A labelled (generalized) permutation is better suited to study the dynamic of
5
a translation surface than a reduced one (see the module
6
:mod:`sage.combinat.iet.reduced`). The latter is more adapted to the
7
study of strata. This kind of permutation was introduced by Yoccoz [Yoc05]_
8
(see also [MMY03]_).
9
10
In fact, there is a geometric counterpart of labelled permutations. They
11
correspond to translation surface with marked outgoing separatrices (i.e. we fi
12
a label for each of them).
13
14
Remarks that Rauzy diagram of reduced objects are significantly smaller than
15
the one for labelled object (for the permutation a b d b e / e d c a c the
16
labelled Rauzy diagram contains 8760 permutations, and the reduced only 73).
17
But, as it is in geometrical way, the labelled Rauzy diagram is a covering of
18
the reduced Rauzy diagram.
19
20
AUTHORS:
21
22
- Vincent Delecroix (2009-09-29) : initial version
23
24
TESTS::
25
26
sage: from sage.combinat.iet.labelled import LabelledPermutationIET
27
sage: LabelledPermutationIET([['a', 'b', 'c'], ['c', 'b', 'a']])
28
a b c
29
c b a
30
sage: LabelledPermutationIET([[1,2,3,4],[4,1,2,3]])
31
1 2 3 4
32
4 1 2 3
33
sage: from sage.combinat.iet.labelled import LabelledPermutationLI
34
sage: LabelledPermutationLI([[1,1],[2,2,3,3,4,4]])
35
1 1
36
2 2 3 3 4 4
37
sage: LabelledPermutationLI([['a','a','b','b','c','c'],['d','d']])
38
a a b b c c
39
d d
40
sage: from sage.combinat.iet.labelled import FlippedLabelledPermutationIET
41
sage: FlippedLabelledPermutationIET([[1,2,3],[3,2,1]],flips=[1,2])
42
-1 -2 3
43
3 -2 -1
44
sage: FlippedLabelledPermutationIET([['a','b','c'],['b','c','a']],flips='b')
45
a -b c
46
-b c a
47
sage: from sage.combinat.iet.labelled import FlippedLabelledPermutationLI
48
sage: FlippedLabelledPermutationLI([[1,1],[2,2,3,3,4,4]], flips=[1,4])
49
-1 -1
50
2 2 3 3 -4 -4
51
sage: FlippedLabelledPermutationLI([['a','a','b','b'],['c','c']],flips='ac')
52
-a -a b b
53
-c -c
54
sage: from sage.combinat.iet.labelled import LabelledRauzyDiagram
55
sage: p = LabelledPermutationIET([[1,2,3],[3,2,1]])
56
sage: d1 = LabelledRauzyDiagram(p)
57
sage: p = LabelledPermutationIET([['a','b'],['b','a']])
58
sage: d = p.rauzy_diagram()
59
sage: g1 = d.path(p, 'top', 'bottom')
60
sage: g1.matrix()
61
[1 1]
62
[1 2]
63
sage: g2 = d.path(p, 'bottom', 'top')
64
sage: g2.matrix()
65
[2 1]
66
[1 1]
67
sage: p = LabelledPermutationIET([['a','b','c','d'],['d','c','b','a']])
68
sage: d = p.rauzy_diagram()
69
sage: g = d.path(p, 't', 't', 'b', 't', 'b', 'b', 't', 'b')
70
sage: g
71
Path of length 8 in a Rauzy diagram
72
sage: g.is_loop()
73
True
74
sage: g.is_full()
75
True
76
sage: s1 = g.orbit_substitution()
77
sage: print s1
78
WordMorphism: a->adbd, b->adbdbd, c->adccd, d->adcd
79
sage: s2 = g.interval_substitution()
80
sage: print s2
81
WordMorphism: a->abcd, b->bab, c->cdc, d->dcbababcd
82
sage: s1.incidence_matrix() == s2.incidence_matrix().transpose()
83
True
84
85
REFERENCES:
86
87
.. [Yoc05] Jean-Cristophe Yoccoz "Echange d'Intervalles", Cours au college de
88
France
89
90
.. [MMY03] Jean-Cristophe Yoccoz, Stefano Marmi and Pierre Moussa "On the
91
cohomological equation for interval exchange maps", arXiv:math/0304469v1
92
"""
93
#*****************************************************************************
94
# Copyright (C) 2008 Vincent Delecroix <[email protected]>
95
#
96
# Distributed under the terms of the GNU General Public License (GPL)
97
# http://www.gnu.org/licenses/
98
#*****************************************************************************
99
100
from sage.structure.sage_object import SageObject
101
from sage.misc.lazy_attribute import lazy_attribute
102
103
from copy import copy
104
105
from sage.combinat.words.alphabet import Alphabet
106
from sage.combinat.words.morphism import WordMorphism
107
108
from sage.matrix.constructor import identity_matrix
109
from sage.rings.integer import Integer
110
from sage.combinat.words.alphabet import Alphabet
111
112
from template import PermutationIET, PermutationLI
113
from template import FlippedPermutationIET, FlippedPermutationLI
114
from template import twin_list_iet, twin_list_li
115
from template import RauzyDiagram, FlippedRauzyDiagram
116
from template import interval_conversion, side_conversion
117
118
class LabelledPermutation(SageObject):
119
r"""
120
General template for labelled objects.
121
122
.. warning::
123
Internal class! Do not use directly!
124
"""
125
def __init__(self, intervals=None, alphabet=None):
126
r"""
127
TESTS::
128
129
sage: from sage.combinat.iet.labelled import LabelledPermutationIET
130
sage: p1 = LabelledPermutationIET([[1,2,3],[3,2,1]])
131
sage: p1 == loads(dumps(p1))
132
True
133
sage: p2 = LabelledPermutationIET([['a', 'b', 'c'], ['c', 'b', 'a']])
134
sage: p2 == loads(dumps(p2))
135
True
136
sage: p3 = LabelledPermutationIET([['1','2','3'],['3','2','1']])
137
sage: p3 == loads(dumps(p3))
138
True
139
sage: from sage.combinat.iet.labelled import LabelledPermutationLI
140
sage: p1 = LabelledPermutationLI([[1,2,2],[3,3,1]])
141
sage: p1 == loads(dumps(p1))
142
True
143
sage: p2 = LabelledPermutationLI([['a','b','b'],['c','c','a']])
144
sage: p2 == loads(dumps(p2))
145
True
146
sage: p3 = LabelledPermutationLI([['1','2','2'],['3','3','1']])
147
sage: p3 == loads(dumps(p3))
148
True
149
"""
150
self._hash = None
151
152
if intervals is None:
153
self._intervals = [[],[]]
154
self._alphabet = None
155
156
else:
157
if alphabet is not None:
158
alphabet = Alphabet(alphabet)
159
if alphabet.cardinality() < len(intervals[0]) :
160
raise ValueError, "the alphabet is too short"
161
self._alphabet = alphabet
162
163
else:
164
self._init_alphabet(intervals)
165
166
self._intervals = [
167
map(self._alphabet.rank, intervals[0]),
168
map(self._alphabet.rank, intervals[1])]
169
170
def __copy__(self):
171
r"""
172
Returns a copy of self.
173
174
TESTS::
175
176
sage: p = iet.Permutation('a b c','c b a')
177
sage: q = copy(p)
178
sage: p == q
179
True
180
sage: p is q
181
False
182
sage: p._inversed()
183
sage: p == q
184
False
185
sage: p._inversed()
186
sage: p == q
187
True
188
sage: p._reversed()
189
sage: p == q
190
False
191
sage: q._reversed()
192
sage: p == q
193
True
194
"""
195
result = self.__class__()
196
197
result._intervals = [
198
copy(self._intervals[0]),
199
copy(self._intervals[1])]
200
201
result._alphabet = self._alphabet
202
result._repr_type = self._repr_type
203
result._repr_options = self._repr_options
204
205
return result
206
207
def __len__(self):
208
r"""
209
TESTS::
210
211
sage: len(iet.Permutation('',''))
212
0
213
sage: len(iet.Permutation('a','a'))
214
1
215
sage: len(iet.Permutation('1 2 3 4 5 6','1 2 3 4 5 6'))
216
6
217
"""
218
return (len(self._intervals[0]) + len(self._intervals[1])) / 2
219
220
def length_top(self):
221
r"""
222
Returns the number of intervals in the top segment.
223
224
OUTPUT:
225
226
integer -- number of intervals
227
228
EXAMPLES::
229
230
sage: iet.Permutation('a b c','c b a').length_top()
231
3
232
sage: iet.GeneralizedPermutation('a a','b b c c').length_top()
233
2
234
sage: iet.GeneralizedPermutation('a a b b','c c').length_top()
235
4
236
"""
237
return len(self._intervals[0])
238
239
def length_bottom(self):
240
r"""
241
Returns the number of intervals in the bottom segment.
242
243
OUTPUT:
244
245
integer -- number of intervals
246
247
EXAMPLES::
248
249
sage: iet.Permutation('a b','b a').length_bottom()
250
2
251
sage: iet.GeneralizedPermutation('a a','b b c c').length_bottom()
252
4
253
sage: iet.GeneralizedPermutation('a a b b','c c').length_bottom()
254
2
255
"""
256
return len(self._intervals[1])
257
258
def length(self, interval=None):
259
r"""
260
Returns a 2-uple of lengths.
261
262
p.length() is identical to (p.length_top(), p.length_bottom())
263
If an interval is specified, it returns the length of the specified
264
interval.
265
266
INPUT:
267
268
- ``interval`` - None, 'top' or 'bottom'
269
270
OUTPUT:
271
272
tuple -- a 2-uple of integers
273
274
EXAMPLES::
275
276
sage: iet.Permutation('a b c','c b a').length()
277
(3, 3)
278
sage: iet.GeneralizedPermutation('a a','b b c c').length()
279
(2, 4)
280
sage: iet.GeneralizedPermutation('a a b b','c c').length()
281
(4, 2)
282
"""
283
if interval is None:
284
return len(self._intervals[0]),len(self._intervals[1])
285
else:
286
interval = interval_conversion(interval)
287
return len(self._intervals[interval])
288
289
def __getitem__(self,i):
290
r"""
291
TESTS::
292
293
sage: p = iet.Permutation([0,1,2,3],[3,2,1,0])
294
sage: p[0][0]
295
0
296
sage: p[1][2]
297
1
298
sage: p = iet.Permutation('a b c','c b a')
299
sage: p[0][1]
300
'b'
301
sage: p[1][2]
302
'a'
303
"""
304
return map(self._alphabet.unrank, self._intervals[i])
305
306
def __hash__(self):
307
r"""
308
ALGORITHM:
309
310
Uses the hash of string
311
312
TESTS::
313
314
sage: from sage.combinat.iet.labelled import *
315
sage: p1 = LabelledPermutationIET([[1,2],[1,2]])
316
sage: p2 = LabelledPermutationIET([[1,2],[2,1]])
317
sage: p3 = LabelledPermutationLI([[1,1],[2,2]])
318
sage: hash(p1) == hash(p2)
319
False
320
sage: hash(p1) == hash(p3)
321
False
322
sage: hash(p2) == hash(p3)
323
False
324
sage: p1 = LabelledPermutationLI([[1,1], [2,2,3,3]])
325
sage: p2 = LabelledPermutationLI([[1,1,2], [2,3,3]])
326
sage: p3 = LabelledPermutationLI([[1,1,2,2], [3,3]])
327
sage: hash(p1) == hash(p2)
328
False
329
sage: hash(p1) == hash(p3)
330
False
331
sage: hash(p2) == hash(p3)
332
False
333
"""
334
if self._hash is None:
335
t = []
336
t.extend([str(i) for i in self._intervals[0]])
337
t.extend([str(-(i+1)) for i in self._intervals[1]])
338
self._hash = hash(''.join(t))
339
return self._hash
340
341
def _reversed(self):
342
r"""
343
TODO:
344
345
resolve properly the mutablility problem with the _twin attribute.
346
347
TESTS::
348
349
sage: p = iet.Permutation([1,2,3],[3,1,2])
350
sage: p
351
1 2 3
352
3 1 2
353
sage: p._reversed()
354
sage: p
355
3 2 1
356
2 1 3
357
"""
358
if self.__dict__.has_key('_twin'):
359
del self.__dict__['_twin']
360
if self._hash is not None:
361
self._hash = None
362
363
self._intervals[0].reverse()
364
self._intervals[1].reverse()
365
366
def _inversed(self):
367
r"""
368
TODO:
369
370
properly resolve the mutability problem of the twin
371
372
TESTS::
373
374
sage: p = iet.Permutation([1,2,3],[3,1,2])
375
sage: p
376
1 2 3
377
3 1 2
378
sage: p._inversed()
379
sage: p
380
3 1 2
381
1 2 3
382
"""
383
if self.__dict__.has_key('_twin'):
384
del self.__dict__['_twin']
385
if self._hash is not None:
386
self._hash = None
387
388
self._intervals = (self._intervals[1],self._intervals[0])
389
390
def list(self):
391
r"""
392
Returns a list of two lists corresponding to the intervals.
393
394
OUTPUT:
395
396
list -- two lists of labels
397
398
EXAMPLES:
399
400
The list of an permutation from iet::
401
402
sage: p1 = iet.Permutation('1 2 3', '3 1 2')
403
sage: p1.list()
404
[['1', '2', '3'], ['3', '1', '2']]
405
sage: p1.alphabet("abc")
406
sage: p1.list()
407
[['a', 'b', 'c'], ['c', 'a', 'b']]
408
409
Recovering the permutation from this list (and the alphabet)::
410
411
sage: q1 = iet.Permutation(p1.list(),alphabet=p1.alphabet())
412
sage: p1 == q1
413
True
414
415
The list of a quadratic permutation::
416
417
sage: p2 = iet.GeneralizedPermutation('g o o', 'd d g')
418
sage: p2.list()
419
[['g', 'o', 'o'], ['d', 'd', 'g']]
420
421
Recovering the permutation::
422
423
sage: q2 = iet.GeneralizedPermutation(p2.list(),alphabet=p2.alphabet())
424
sage: p2 == q2
425
True
426
"""
427
a0 = map(self._alphabet.unrank, self._intervals[0])
428
a1 = map(self._alphabet.unrank, self._intervals[1])
429
return [a0, a1]
430
431
def erase_letter(self, letter):
432
r"""
433
Return the permutation with the specified letter removed.
434
435
OUTPUT:
436
437
permutation -- the resulting permutation
438
439
EXAMPLES:
440
441
::
442
443
sage: p = iet.Permutation('a b c d','c d b a')
444
sage: p.erase_letter('a')
445
b c d
446
c d b
447
sage: p.erase_letter('b')
448
a c d
449
c d a
450
sage: p.erase_letter('c')
451
a b d
452
d b a
453
sage: p.erase_letter('d')
454
a b c
455
c b a
456
457
::
458
459
sage: p = iet.GeneralizedPermutation('a b b','c c a')
460
sage: p.erase_letter('a')
461
b b
462
c c
463
464
Beware, there is no validity check for permutation from linear
465
involutions::
466
467
sage: p = iet.GeneralizedPermutation('a b b','c c a')
468
sage: p.erase_letter('b')
469
a
470
c c a
471
"""
472
l = [[],[]]
473
letters = self.letters()
474
a = letters.index(letter)
475
476
for i in (0,1):
477
for b in self._intervals[i]:
478
if b < a:
479
l[i].append(b)
480
elif b > a:
481
l[i].append(b-1)
482
483
res = copy(self)
484
res._intervals = l
485
res.alphabet(letters[0:a] + letters[a+1:])
486
487
return res
488
489
def rauzy_move_matrix(self, winner=None, side='right'):
490
r"""
491
Returns the Rauzy move matrix.
492
493
This matrix corresponds to the action of a Rauzy move on the vector of
494
lengths. By convention (to get a positive matrix), the matrix is define
495
as the inverse transformation on the length vector.
496
497
OUTPUT:
498
499
matrix -- a square matrix of positive integers
500
501
EXAMPLES:
502
503
::
504
505
sage: p = iet.Permutation('a b','b a')
506
sage: p.rauzy_move_matrix('t')
507
[1 0]
508
[1 1]
509
sage: p.rauzy_move_matrix('b')
510
[1 1]
511
[0 1]
512
513
::
514
515
sage: p = iet.Permutation('a b c d','b d a c')
516
sage: q = p.left_right_inverse()
517
sage: m0 = p.rauzy_move_matrix(winner='top',side='right')
518
sage: n0 = q.rauzy_move_matrix(winner='top',side='left')
519
sage: m0 == n0
520
True
521
sage: m1 = p.rauzy_move_matrix(winner='bottom',side='right')
522
sage: n1 = q.rauzy_move_matrix(winner='bottom',side='left')
523
sage: m1 == n1
524
True
525
"""
526
if winner is None and side is None:
527
return identity_matrix(len(self))
528
529
winner = interval_conversion(winner)
530
side = side_conversion(side)
531
532
winner_letter = self._intervals[winner][side]
533
loser_letter = self._intervals[1-winner][side]
534
535
m = copy(identity_matrix(len(self)))
536
m[winner_letter, loser_letter] = 1
537
538
return m
539
540
def rauzy_move_winner(self,winner=None,side=None):
541
r"""
542
Returns the winner of a Rauzy move.
543
544
INPUT:
545
546
- ``winner`` - either 'top' or 'bottom' ('t' or 'b' for short)
547
548
- ``side`` - either 'left' or 'right' ('l' or 'r' for short)
549
550
OUTPUT:
551
552
-- a label
553
554
EXAMPLES:
555
556
::
557
558
sage: p = iet.Permutation('a b c d','b d a c')
559
sage: p.rauzy_move_winner('top','right')
560
'd'
561
sage: p.rauzy_move_winner('bottom','right')
562
'c'
563
sage: p.rauzy_move_winner('top','left')
564
'a'
565
sage: p.rauzy_move_winner('bottom','left')
566
'b'
567
568
::
569
570
sage: p = iet.GeneralizedPermutation('a b b c','d c a e d e')
571
sage: p.rauzy_move_winner('top','right')
572
'c'
573
sage: p.rauzy_move_winner('bottom','right')
574
'e'
575
sage: p.rauzy_move_winner('top','left')
576
'a'
577
sage: p.rauzy_move_winner('bottom','left')
578
'd'
579
"""
580
if winner is None and side is None:
581
return None
582
583
winner = interval_conversion(winner)
584
side = side_conversion(side)
585
586
return self[winner][side]
587
588
def rauzy_move_loser(self,winner=None,side=None):
589
r"""
590
Returns the loser of a Rauzy move
591
592
INPUT:
593
594
- ``winner`` - either 'top' or 'bottom' ('t' or 'b' for short)
595
596
- ``side`` - either 'left' or 'right' ('l' or 'r' for short)
597
598
OUTPUT:
599
600
-- a label
601
602
EXAMPLES::
603
604
sage: p = iet.Permutation('a b c d','b d a c')
605
sage: p.rauzy_move_loser('top','right')
606
'c'
607
sage: p.rauzy_move_loser('bottom','right')
608
'd'
609
sage: p.rauzy_move_loser('top','left')
610
'b'
611
sage: p.rauzy_move_loser('bottom','left')
612
'a'
613
"""
614
if winner is None and side is None:
615
return None
616
617
winner = interval_conversion(winner)
618
side = side_conversion(side)
619
620
return self[1-winner][side]
621
622
def LabelledPermutationsIET_iterator(
623
nintervals=None,
624
irreducible=True,
625
alphabet=None):
626
r"""
627
Returns an iterator over labelled permutations.
628
629
INPUT:
630
631
- ``nintervals`` - integer or None
632
633
- ``irreducible`` - boolean (default: True)
634
635
- ``alphabet`` - something that should be converted to an alphabet of at least nintervals letters
636
637
OUTPUT:
638
639
iterator -- an iterator over permutations
640
641
TESTS::
642
643
sage: for p in iet.Permutations_iterator(2, alphabet="ab"):
644
... print p, "\n****" #indirect doctest
645
a b
646
b a
647
****
648
b a
649
a b
650
****
651
sage: for p in iet.Permutations_iterator(3, alphabet="abc"):
652
... print p, "\n*****" #indirect doctest
653
a b c
654
b c a
655
*****
656
a b c
657
c a b
658
*****
659
a b c
660
c b a
661
*****
662
a c b
663
b a c
664
*****
665
a c b
666
b c a
667
*****
668
a c b
669
c b a
670
*****
671
b a c
672
a c b
673
*****
674
b a c
675
c a b
676
*****
677
b a c
678
c b a
679
*****
680
b c a
681
a b c
682
*****
683
b c a
684
a c b
685
*****
686
b c a
687
c a b
688
*****
689
c a b
690
a b c
691
*****
692
c a b
693
b a c
694
*****
695
c a b
696
b c a
697
*****
698
c b a
699
a b c
700
*****
701
c b a
702
a c b
703
*****
704
c b a
705
b a c
706
*****
707
"""
708
from itertools import imap, ifilter, product
709
from sage.combinat.permutation import Permutations
710
711
if irreducible is False:
712
if nintervals is None:
713
raise ValueError, "choose a number of intervals"
714
else:
715
assert(isinstance(nintervals,(int,Integer)))
716
assert(nintervals > 0)
717
718
f = lambda x: LabelledPermutationIET([list(x[0]),list(x[1])],alphabet=alphabet)
719
720
alphabet = Alphabet(alphabet)
721
g = lambda x: [alphabet.unrank(k-1) for k in x]
722
P = map(g, Permutations(nintervals))
723
return imap(f,product(P,P))
724
else:
725
return ifilter(
726
lambda x: x.is_irreducible(),
727
LabelledPermutationsIET_iterator(nintervals,False,alphabet))
728
729
class LabelledPermutationIET(LabelledPermutation, PermutationIET):
730
"""
731
Labelled permutation for iet
732
733
EXAMPLES:
734
735
Reducibility testing::
736
737
sage: p = iet.Permutation('a b c', 'c b a')
738
sage: p.is_irreducible()
739
True
740
741
sage: q = iet.Permutation('a b c d', 'b a d c')
742
sage: q.is_irreducible()
743
False
744
745
Rauzy movability and Rauzy move::
746
747
sage: p = iet.Permutation('a b c', 'c b a')
748
sage: p.has_rauzy_move('top')
749
True
750
sage: print p.rauzy_move('bottom')
751
a c b
752
c b a
753
sage: p.has_rauzy_move('top')
754
True
755
sage: print p.rauzy_move('top')
756
a b c
757
c a b
758
759
Rauzy diagram::
760
761
sage: p = iet.Permutation('a b c', 'c b a')
762
sage: d = p.rauzy_diagram()
763
sage: p in d
764
True
765
"""
766
def __cmp__(self, other):
767
r"""
768
ALGORITHM:
769
770
The order is lexicographic on intervals[0] + intervals[1]
771
772
TESTS::
773
sage: list_of_p2 = []
774
sage: p0 = iet.Permutation('1 2', '1 2')
775
sage: p1 = iet.Permutation('1 2', '2 1')
776
sage: p0 != p0
777
False
778
sage: (p0 == p0) and (p0 < p1)
779
True
780
sage: (p1 > p0) and (p1 == p1)
781
True
782
"""
783
if type(self) != type(other):
784
return -1
785
786
n = len(self)
787
if n != len(other):
788
return n - len(other)
789
790
i, j = 0,0
791
while (self._intervals[i][j] == other._intervals[i][j]):
792
j += 1
793
if j == n:
794
if i == 1: return 0
795
i = 1
796
j = 0
797
return self._intervals[i][j] - other._intervals[i][j]
798
799
@lazy_attribute
800
def _twin(self):
801
r"""
802
The twin relations of the permutation.
803
804
TESTS::
805
sage: p = iet.Permutation('a b','a b')
806
sage: p._twin
807
[[0, 1], [0, 1]]
808
sage: p = iet.Permutation('a b','b a')
809
sage: p._twin
810
[[1, 0], [1, 0]]
811
"""
812
return twin_list_iet(self._intervals)
813
814
def reduced(self):
815
r"""
816
Returns the associated reduced abelian permutation.
817
818
OUTPUT:
819
820
a reduced permutation -- the underlying reduced permutation
821
822
823
EXAMPLES:
824
825
sage: p = iet.Permutation("a b c d","d c a b")
826
sage: q = iet.Permutation("a b c d","d c a b",reduced=True)
827
sage: p.reduced() == q
828
True
829
"""
830
from reduced import ReducedPermutationIET
831
832
return ReducedPermutationIET(self.list(),alphabet=self._alphabet)
833
834
def is_identity(self):
835
r"""
836
Returns True if self is the identity.
837
838
OUTPUT:
839
840
bool -- True if self corresponds to the identity
841
842
EXAMPLES::
843
844
sage: iet.Permutation("a b","a b").is_identity()
845
True
846
sage: iet.Permutation("a b","b a").is_identity()
847
False
848
"""
849
for i in range(len(self)):
850
if self._intervals[0][i] != self._intervals[1][i]:
851
return False
852
return True
853
854
def has_rauzy_move(self, winner=None, side=None):
855
r"""
856
Returns True if you can perform a Rauzy move.
857
858
INPUT:
859
860
- ``winner`` - the winner interval ('top' or 'bottom')
861
862
- ``side`` - (default: 'right') the side ('left' or 'right')
863
864
OUTPUT:
865
866
bool -- True if self has a Rauzy move
867
868
EXAMPLES:
869
870
::
871
872
sage: p = iet.Permutation('a b','b a')
873
sage: p.has_rauzy_move()
874
True
875
876
::
877
878
sage: p = iet.Permutation('a b c','b a c')
879
sage: p.has_rauzy_move()
880
False
881
"""
882
if side is None: side = -1
883
else: side = side_conversion(side)
884
885
if not winner is None: winner = interval_conversion(winner)
886
887
return self._intervals[0][side] != self._intervals[1][side]
888
889
def rauzy_move(self, winner=None, side=None, iteration=1):
890
r"""
891
Returns the Rauzy move.
892
893
INPUT:
894
895
- ``winner`` - the winner interval ('top' or 'bottom')
896
897
- ``side`` - (default: 'right') the side ('left' or 'right')
898
899
OUTPUT:
900
901
permutation -- the Rauzy move of the permutation
902
903
EXAMPLES:
904
905
::
906
907
sage: p = iet.Permutation('a b','b a')
908
sage: p.rauzy_move('t','right')
909
a b
910
b a
911
sage: p.rauzy_move('b','right')
912
a b
913
b a
914
915
::
916
917
sage: p = iet.Permutation('a b c','c b a')
918
sage: p.rauzy_move('t','right')
919
a b c
920
c a b
921
sage: p.rauzy_move('b','right')
922
a c b
923
c b a
924
925
::
926
927
sage: p = iet.Permutation('a b','b a')
928
sage: p.rauzy_move('t','left')
929
a b
930
b a
931
sage: p.rauzy_move('b','left')
932
a b
933
b a
934
935
::
936
937
sage: p = iet.Permutation('a b c','c b a')
938
sage: p.rauzy_move('t','left')
939
a b c
940
b c a
941
sage: p.rauzy_move('b','left')
942
b a c
943
c b a
944
"""
945
side = side_conversion(side)
946
winner = interval_conversion(winner)
947
948
result = copy(self)
949
950
for i in range(iteration):
951
winner_letter = result._intervals[winner][side]
952
loser_letter = result._intervals[1-winner].pop(side)
953
954
loser_to = result._intervals[1-winner].index(winner_letter) - side
955
result._intervals[1-winner].insert(loser_to, loser_letter)
956
957
return result
958
959
def rauzy_move_interval_substitution(self,winner=None,side=None):
960
r"""
961
Returns the interval substitution associated.
962
963
INPUT:
964
965
- ``winner`` - the winner interval ('top' or 'bottom')
966
967
- ``side`` - (default: 'right') the side ('left' or 'right')
968
969
OUTPUT:
970
971
WordMorphism -- a substitution on the alphabet of the permutation
972
973
EXAMPLES::
974
975
sage: p = iet.Permutation('a b','b a')
976
sage: print p.rauzy_move_interval_substitution('top','right')
977
WordMorphism: a->a, b->ba
978
sage: print p.rauzy_move_interval_substitution('bottom','right')
979
WordMorphism: a->ab, b->b
980
sage: print p.rauzy_move_interval_substitution('top','left')
981
WordMorphism: a->ba, b->b
982
sage: print p.rauzy_move_interval_substitution('bottom','left')
983
WordMorphism: a->a, b->ab
984
"""
985
d = dict([(letter,letter) for letter in self.letters()])
986
987
if winner is None and side is None:
988
return WordMorphism(d)
989
990
winner = interval_conversion(winner)
991
side = side_conversion(side)
992
993
winner_letter = self.rauzy_move_winner(winner,side)
994
loser_letter = self.rauzy_move_loser(winner,side)
995
996
if side == 0:
997
d[winner_letter] = [loser_letter,winner_letter]
998
else:
999
d[winner_letter] = [winner_letter,loser_letter]
1000
1001
return WordMorphism(d)
1002
1003
def rauzy_move_orbit_substitution(self,winner=None,side=None):
1004
r"""
1005
Return the action fo the rauzy_move on the orbit.
1006
1007
INPUT:
1008
1009
- ``i`` - integer
1010
1011
- ``winner`` - the winner interval ('top' or 'bottom')
1012
1013
- ``side`` - (default: 'right') the side ('right' or 'left')
1014
1015
OUTPUT:
1016
1017
WordMorphism -- a substitution on the alphabet of self
1018
1019
EXAMPLES::
1020
1021
sage: p = iet.Permutation('a b','b a')
1022
sage: print p.rauzy_move_orbit_substitution('top','right')
1023
WordMorphism: a->ab, b->b
1024
sage: print p.rauzy_move_orbit_substitution('bottom','right')
1025
WordMorphism: a->a, b->ab
1026
sage: print p.rauzy_move_orbit_substitution('top','left')
1027
WordMorphism: a->a, b->ba
1028
sage: print p.rauzy_move_orbit_substitution('bottom','left')
1029
WordMorphism: a->ba, b->b
1030
"""
1031
d = dict([(letter,letter) for letter in self.letters()])
1032
1033
if winner is None and side is None:
1034
return WordMorphism(d)
1035
1036
winner = interval_conversion(winner)
1037
side = side_conversion(side)
1038
1039
1040
loser_letter = self.rauzy_move_loser(winner,side)
1041
1042
top_letter = self.alphabet().unrank(self._intervals[0][side])
1043
bottom_letter = self.alphabet().unrank(self._intervals[1][side])
1044
1045
d[loser_letter] = [bottom_letter,top_letter]
1046
1047
return WordMorphism(d)
1048
1049
def rauzy_diagram(self, **args):
1050
"""
1051
Returns the associated Rauzy diagram.
1052
1053
For more information try help(iet.RauzyDiagram).
1054
1055
OUTPUT:
1056
1057
Rauzy diagram -- the Rauzy diagram of the permutation
1058
1059
EXAMPLES::
1060
1061
sage: p = iet.Permutation('a b c', 'c b a')
1062
sage: d = p.rauzy_diagram()
1063
"""
1064
return LabelledRauzyDiagram(self, **args)
1065
1066
class LabelledPermutationLI(LabelledPermutation, PermutationLI):
1067
r"""
1068
Labelled quadratic (or generalized) permutation
1069
1070
EXAMPLES:
1071
1072
Reducibility testing::
1073
1074
sage: p = iet.GeneralizedPermutation('a b b', 'c c a')
1075
sage: p.is_irreducible()
1076
True
1077
1078
Reducibility testing with associated decomposition::
1079
1080
sage: p = iet.GeneralizedPermutation('a b c a', 'b d d c')
1081
sage: p.is_irreducible()
1082
False
1083
sage: test, decomposition = p.is_irreducible(return_decomposition = True)
1084
sage: print test
1085
False
1086
sage: print decomposition
1087
(['a'], ['c', 'a'], [], ['c'])
1088
1089
Rauzy movability and Rauzy move::
1090
1091
sage: p = iet.GeneralizedPermutation('a a b b c c', 'd d')
1092
sage: p.has_rauzy_move(0)
1093
False
1094
sage: p.has_rauzy_move(1)
1095
True
1096
sage: q = p.rauzy_move(1)
1097
sage: print q
1098
a a b b c
1099
c d d
1100
sage: q.has_rauzy_move(0)
1101
True
1102
sage: q.has_rauzy_move(1)
1103
True
1104
1105
Rauzy diagrams::
1106
1107
sage: p = iet.GeneralizedPermutation('0 0 1 1','2 2')
1108
sage: r = p.rauzy_diagram()
1109
sage: p in r
1110
True
1111
"""
1112
def __cmp__(self, other):
1113
r"""
1114
ALGORITHM:
1115
1116
Order is lexicographic on length of intervals and on intervals.
1117
1118
TESTS::
1119
sage: p0 = iet.GeneralizedPermutation('0 0','1 1 2 2')
1120
sage: p1 = iet.GeneralizedPermutation('0 0','1 2 1 2')
1121
sage: p2 = iet.GeneralizedPermutation('0 0','1 2 2 1')
1122
sage: p3 = iet.GeneralizedPermutation('0 0 1','1 2 2')
1123
sage: p4 = iet.GeneralizedPermutation('0 0 1 1','2 2')
1124
sage: p5 = iet.GeneralizedPermutation('0 1 0 1','2 2')
1125
sage: p6 = iet.GeneralizedPermutation('0 1 1 0','2 2')
1126
sage: p0 == p0 and p0 < p1 and p0 < p2 and p0 < p3 and p0 < p4
1127
True
1128
sage: p0 < p5 and p0 < p6 and p1 < p2 and p1 < p3 and p1 < p4
1129
True
1130
sage: p1 < p5 and p1 < p6 and p2 < p3 and p2 < p4 and p2 < p5
1131
True
1132
sage: p2 < p6 and p3 < p4 and p3 < p5 and p3 < p6 and p4 < p5
1133
True
1134
sage: p4 < p6 and p5 < p6 and p0 == p0 and p1 == p1 and p2 == p2
1135
True
1136
sage: p3 == p3 and p4 == p4 and p5 == p5 and p6 == p6
1137
True
1138
"""
1139
if type(self) != type(other):
1140
return -1
1141
1142
n = len(self)
1143
1144
if n != len(other): return n - len(other)
1145
1146
l0 = self._intervals[0]
1147
l1 = other._intervals[0]
1148
1149
n = len(self._intervals[0])
1150
1151
if n != len(other._intervals[0]): return n - len(other._intervals[0])
1152
1153
i = 0
1154
while (i < n) and (l0[i] == l1[i]):
1155
i += 1
1156
1157
if i != n:
1158
return l0[i] - l1[i]
1159
1160
l0 = self._intervals[1]
1161
l1 = other._intervals[1]
1162
n = len(self._intervals[1])
1163
1164
i = 0
1165
while (i < n) and (l0[i] == l1[i]):
1166
i += 1
1167
1168
if i != n:
1169
return l0[i] - l1[i]
1170
1171
return 0
1172
1173
def has_right_rauzy_move(self, winner):
1174
r"""
1175
Test of Rauzy movability with a specified winner)
1176
1177
A quadratic (or generalized) permutation is rauzy_movable type
1178
depending on the possible length of the last interval. It's
1179
dependent of the length equation.
1180
1181
INPUT:
1182
1183
- ``winner`` - 'top' (or 't' or 0) or 'bottom' (or 'b' or 1)
1184
1185
OUTPUT:
1186
1187
bool -- True if self has a Rauzy move
1188
1189
EXAMPLES:
1190
1191
::
1192
1193
sage: p = iet.GeneralizedPermutation('a a','b b')
1194
sage: p.has_right_rauzy_move('top')
1195
False
1196
sage: p.has_right_rauzy_move('bottom')
1197
False
1198
1199
::
1200
1201
sage: p = iet.GeneralizedPermutation('a a b','b c c')
1202
sage: p.has_right_rauzy_move('top')
1203
True
1204
sage: p.has_right_rauzy_move('bottom')
1205
True
1206
1207
::
1208
1209
sage: p = iet.GeneralizedPermutation('a a','b b c c')
1210
sage: p.has_right_rauzy_move('top')
1211
True
1212
sage: p.has_right_rauzy_move('bottom')
1213
False
1214
1215
::
1216
1217
sage: p = iet.GeneralizedPermutation('a a b b','c c')
1218
sage: p.has_right_rauzy_move('top')
1219
False
1220
sage: p.has_right_rauzy_move('bottom')
1221
True
1222
"""
1223
winner = interval_conversion(winner)
1224
loser = self._intervals[1-winner][-1]
1225
1226
# the same letter at the right-end (False)
1227
if self._intervals[0][-1] == self._intervals[1][-1] :
1228
return False
1229
1230
# the winner (or loser) letter is repeated on the other interval (True)
1231
if self._intervals[0][-1] in self._intervals[1]: return True
1232
if self._intervals[1][-1] in self._intervals[0]: return True
1233
1234
# the loser letters is the only letter repeated in the loser
1235
# interval (False)
1236
for i,c in enumerate((self._intervals[1-winner])):
1237
if c != loser and c in self._intervals[1-winner][i+1:]:
1238
return True
1239
1240
return False
1241
1242
def right_rauzy_move(self, winner):
1243
r"""
1244
Perform a Rauzy move on the right (the standard one).
1245
1246
INPUT:
1247
1248
- ``winner`` - 'top' (or 't' or 0) or 'bottom' (or 'b' or 1)
1249
1250
OUTPUT:
1251
1252
boolean -- True if self has a Rauzy move
1253
1254
EXAMPLES:
1255
1256
::
1257
1258
sage: p = iet.GeneralizedPermutation('a a b','b c c')
1259
sage: p.right_rauzy_move(0)
1260
a a b
1261
b c c
1262
sage: p.right_rauzy_move(1)
1263
a a
1264
b b c c
1265
1266
::
1267
1268
sage: p = iet.GeneralizedPermutation('a b b','c c a')
1269
sage: p.right_rauzy_move(0)
1270
a a b b
1271
c c
1272
sage: p.right_rauzy_move(1)
1273
a b b
1274
c c a
1275
1276
TESTS::
1277
1278
sage: p = iet.GeneralizedPermutation('a a b','b c c')
1279
sage: q = p.top_bottom_inverse()
1280
sage: q = q.right_rauzy_move(0)
1281
sage: q = q.top_bottom_inverse()
1282
sage: q == p.right_rauzy_move(1)
1283
True
1284
sage: q = p.top_bottom_inverse()
1285
sage: q = q.right_rauzy_move(1)
1286
sage: q = q.top_bottom_inverse()
1287
sage: q == p.right_rauzy_move(0)
1288
True
1289
sage: p = p.left_right_inverse()
1290
sage: q = q.left_rauzy_move(0)
1291
sage: q = q.left_right_inverse()
1292
sage: q == p.right_rauzy_move(0)
1293
True
1294
sage: q = p.left_right_inverse()
1295
sage: q = q.left_rauzy_move(1)
1296
sage: q = q.left_right_inverse()
1297
sage: q == p.right_rauzy_move(1)
1298
True
1299
"""
1300
result = copy(self)
1301
1302
winner_letter = result._intervals[winner][-1]
1303
loser_letter = result._intervals[1-winner].pop(-1)
1304
1305
if winner_letter in result._intervals[winner][:-1]:
1306
loser_to = result._intervals[winner].index(winner_letter)
1307
result._intervals[winner].insert(loser_to, loser_letter)
1308
else:
1309
loser_to = result._intervals[1-winner].index(winner_letter) + 1
1310
result._intervals[1-winner].insert(loser_to, loser_letter)
1311
1312
return result
1313
1314
def left_rauzy_move(self, winner):
1315
r"""
1316
Perform a Rauzy move on the left.
1317
1318
INPUT:
1319
1320
- ``winner`` - 'top' or 'bottom'
1321
1322
OUTPUT:
1323
1324
permutation -- the Rauzy move of self
1325
1326
EXAMPLES:
1327
1328
::
1329
1330
sage: p = iet.GeneralizedPermutation('a a b','b c c')
1331
sage: p.left_rauzy_move(0)
1332
a a b b
1333
c c
1334
sage: p.left_rauzy_move(1)
1335
a a b
1336
b c c
1337
1338
::
1339
1340
sage: p = iet.GeneralizedPermutation('a b b','c c a')
1341
sage: p.left_rauzy_move(0)
1342
a b b
1343
c c a
1344
sage: p.left_rauzy_move(1)
1345
b b
1346
c c a a
1347
1348
1349
TESTS::
1350
1351
sage: p = iet.GeneralizedPermutation('a a b','b c c')
1352
sage: q = p.top_bottom_inverse()
1353
sage: q = q.left_rauzy_move(0)
1354
sage: q = q.top_bottom_inverse()
1355
sage: q == p.left_rauzy_move(1)
1356
True
1357
sage: q = p.top_bottom_inverse()
1358
sage: q = q.left_rauzy_move(1)
1359
sage: q = q.top_bottom_inverse()
1360
sage: q == p.left_rauzy_move(0)
1361
True
1362
sage: q = p.left_right_inverse()
1363
sage: q = q.right_rauzy_move(0)
1364
sage: q = q.left_right_inverse()
1365
sage: q == p.left_rauzy_move(0)
1366
True
1367
sage: q = p.left_right_inverse()
1368
sage: q = q.right_rauzy_move(1)
1369
sage: q = q.left_right_inverse()
1370
sage: q == p.left_rauzy_move(1)
1371
True
1372
"""
1373
result = copy(self)
1374
1375
winner_letter = result._intervals[winner][0]
1376
loser_letter = result._intervals[1-winner].pop(0)
1377
1378
if winner_letter in result._intervals[winner][1:]:
1379
loser_to = result._intervals[winner][1:].index(winner_letter)+2
1380
result._intervals[winner].insert(loser_to, loser_letter)
1381
1382
else:
1383
loser_to = result._intervals[1-winner].index(winner_letter)
1384
result._intervals[1-winner].insert(loser_to, loser_letter)
1385
1386
return result
1387
1388
def reduced(self):
1389
r"""
1390
Returns the associated reduced quadratic permutations.
1391
1392
OUTPUT:
1393
1394
permutation -- the underlying reduced permutation
1395
1396
EXAMPLES::
1397
1398
sage: p = iet.GeneralizedPermutation('a a','b b c c')
1399
sage: q = p.reduced()
1400
sage: q
1401
a a
1402
b b c c
1403
sage: p.rauzy_move(0).reduced() == q.rauzy_move(0)
1404
True
1405
"""
1406
from reduced import ReducedPermutationLI
1407
1408
return ReducedPermutationLI(self.list(),alphabet=self._alphabet)
1409
1410
def rauzy_diagram(self, **kargs):
1411
r"""
1412
Returns the associated RauzyDiagram.
1413
1414
OUTPUT:
1415
1416
Rauzy diagram -- the Rauzy diagram of the permutation
1417
1418
EXAMPLES::
1419
1420
sage: p = iet.GeneralizedPermutation('a b c b', 'c d d a')
1421
sage: d = p.rauzy_diagram()
1422
sage: p in d
1423
True
1424
1425
For more information, try help(iet.RauzyDiagram)
1426
"""
1427
return LabelledRauzyDiagram(self, **kargs)
1428
1429
@lazy_attribute
1430
def _twin(self):
1431
r"""
1432
The twin list of the permutation
1433
1434
TEST::
1435
1436
sage: p = iet.GeneralizedPermutation('a a','b b')
1437
sage: p._twin
1438
[[(0, 1), (0, 0)], [(1, 1), (1, 0)]]
1439
"""
1440
return twin_list_li(self._intervals)
1441
1442
class FlippedLabelledPermutation(LabelledPermutation):
1443
r"""
1444
General template for labelled objects
1445
1446
.. warning::
1447
Internal class! Do not use directly!
1448
"""
1449
def __init__(self, intervals=None, alphabet=None, flips=None):
1450
r"""
1451
INPUT:
1452
1453
- `intervals` - the intervals as a list of two lists
1454
1455
- `alphabet` - something that should be converted to an alphabe
1456
1457
- `flips` - a list of letters of the alphabet
1458
1459
TESTS:
1460
1461
::
1462
1463
sage: from sage.combinat.iet.labelled import FlippedLabelledPermutationIET
1464
sage: p = FlippedLabelledPermutationIET([['a','b'],['a','b']],flips='a')
1465
sage: p == loads(dumps(p))
1466
True
1467
sage: p = FlippedLabelledPermutationIET([['a','b'],['b','a']],flips='ab')
1468
sage: p == loads(dumps(p))
1469
True
1470
1471
::
1472
1473
sage: from sage.combinat.iet.labelled import FlippedLabelledPermutationLI
1474
sage: p = FlippedLabelledPermutationLI([['a','a','b'],['b','c','c']],flips='a')
1475
sage: p == loads(dumps(p))
1476
True
1477
sage: p = FlippedLabelledPermutationLI([['a','a'],['b','b','c','c']],flips='ac')
1478
sage: p == loads(dumps(p))
1479
True
1480
"""
1481
if intervals is None: intervals=[[],[]]
1482
if flips is None: flips = []
1483
1484
super(FlippedLabelledPermutation, self).__init__(intervals, alphabet)
1485
self._init_flips(intervals, flips)
1486
1487
def __copy__(self):
1488
r"""
1489
Returns a copy of self
1490
1491
TESTS::
1492
1493
sage: p = iet.Permutation('a b c','c b a',flips='a')
1494
sage: h = hash(p)
1495
sage: t = p._twin
1496
sage: q = copy(p)
1497
sage: q == p
1498
True
1499
sage: q is p
1500
False
1501
sage: q._twin is p._twin
1502
False
1503
"""
1504
result = self.__class__()
1505
1506
result._intervals = [
1507
self._intervals[0][:],
1508
self._intervals[1][:]]
1509
result._flips = [
1510
self._flips[0][:],
1511
self._flips[1][:]
1512
]
1513
1514
result._alphabet = self._alphabet
1515
result._repr_type = self._repr_type
1516
result._repr_options = self._repr_options
1517
1518
return result
1519
1520
def list(self, flips=False):
1521
r"""
1522
Returns a list associated to the permutation.
1523
1524
INPUT:
1525
1526
- ``flips`` - boolean (default: False)
1527
1528
OUTPUT:
1529
1530
list -- two lists of labels
1531
1532
EXAMPLES::
1533
1534
sage: p = iet.GeneralizedPermutation('0 0 1 2 2 1', '3 3', flips='1')
1535
sage: p.list(flips=True)
1536
[[('0', 1), ('0', 1), ('1', -1), ('2', 1), ('2', 1), ('1', -1)], [('3', 1), ('3', 1)]]
1537
sage: p.list(flips=False)
1538
[['0', '0', '1', '2', '2', '1'], ['3', '3']]
1539
1540
The list can be used to reconstruct the permutation
1541
1542
::
1543
1544
sage: p = iet.Permutation('a b c','c b a',flips='ab')
1545
sage: p == iet.Permutation(p.list(), flips=p.flips())
1546
True
1547
1548
::
1549
1550
sage: p = iet.GeneralizedPermutation('a b b c','c d d a',flips='ad')
1551
sage: p == iet.GeneralizedPermutation(p.list(),flips=p.flips())
1552
True
1553
"""
1554
if flips:
1555
a0 = zip(map(self._alphabet.unrank, self._intervals[0]), self._flips[0])
1556
a1 = zip(map(self._alphabet.unrank, self._intervals[1]), self._flips[1])
1557
else:
1558
a0 = map(self._alphabet.unrank, self._intervals[0])
1559
a1 = map(self._alphabet.unrank, self._intervals[1])
1560
1561
return [a0,a1]
1562
1563
def __getitem__(self,i):
1564
r"""
1565
Get labels and flips of specified interval.
1566
1567
The result is a 2-uple (letter, flip) where letter is the name of the
1568
sub-interval and flip is a number corresponding to the presence of flip
1569
as following: 1 (no flip) and -1 (a flip).
1570
1571
EXAMPLES::
1572
1573
sage: p = iet.Permutation('a b', 'b a', flips='a')
1574
sage: print p[0]
1575
[('a', -1), ('b', 1)]
1576
sage: p = iet.GeneralizedPermutation('c p p', 't t c', flips='ct')
1577
sage: print p[1]
1578
[('t', -1), ('t', -1), ('c', -1)]
1579
"""
1580
if not isinstance(i, (Integer, int)):
1581
raise TypeError("Must be an integer")
1582
if i != 0 and i != 1:
1583
raise IndexError("The integer must be 0 or 1")
1584
1585
letters = map(self._alphabet.unrank, self._intervals[i])
1586
flips = self._flips[i]
1587
1588
return zip(letters,flips)
1589
1590
def __eq__(self,other):
1591
r"""
1592
Test of equality
1593
1594
ALGORITHM:
1595
1596
not considering the alphabet used for the representation but just the
1597
order
1598
1599
TESTS::
1600
1601
sage: p1 = iet.Permutation('a b c','c b a',flips='a')
1602
sage: p2 = iet.Permutation('a b c','c b a',flips='b')
1603
sage: p3 = iet.Permutation('d e f','f e d',flips='d')
1604
sage: p1 == p1 and p2 == p2 and p3 == p3
1605
True
1606
sage: p1 == p2
1607
False
1608
sage: p1 == p3
1609
True
1610
"""
1611
return (
1612
type(self) == type(other) and
1613
self._intervals == other._intervals and
1614
self._flips == other._flips)
1615
1616
def __ne__(self,other):
1617
r"""
1618
Test of difference
1619
1620
ALGORITHM:
1621
1622
not considering the alphabet used for the representation
1623
1624
TESTS::
1625
1626
sage: p1 = iet.Permutation('a b c','c b a',flips='a')
1627
sage: p2 = iet.Permutation('a b c','c b a',flips='b')
1628
sage: p3 = iet.Permutation('d e f','f e d',flips='d')
1629
sage: p1 != p1 or p2 != p2 or p3 != p3
1630
False
1631
sage: p1 != p2
1632
True
1633
sage: p1 != p3
1634
False
1635
"""
1636
return (
1637
type(self) != type(other) or
1638
self._intervals != other._intervals or
1639
self._flips != other._flips)
1640
1641
def _inversed(self):
1642
r"""
1643
Inversion of the permutation (called by tb_inverse).
1644
1645
TODO:
1646
1647
Resolve properly the mutability problem associated to hash value and
1648
twin list.
1649
1650
TESTS::
1651
1652
sage: p = iet.Permutation('a','a',flips='a')
1653
sage: p.tb_inverse() #indirect doctest
1654
-a
1655
-a
1656
sage: p = iet.Permutation('a b','a b',flips='a')
1657
sage: p.tb_inverse() #indirect doctest
1658
-a b
1659
-a b
1660
sage: p = iet.Permutation('a b','a b',flips='b')
1661
sage: p.tb_inverse() #indirect doctest
1662
a -b
1663
a -b
1664
sage: p = iet.Permutation('a b','b a',flips='a')
1665
sage: p.tb_inverse() #indirect doctest
1666
b -a
1667
-a b
1668
sage: p = iet.Permutation('a b','b a',flips='b')
1669
sage: p.tb_inverse() #indirect doctest
1670
-b a
1671
a -b
1672
"""
1673
if hasattr(self, '_twin'):
1674
delattr(self, '_twin')
1675
1676
if self._hash is not None:
1677
self._hash = None
1678
1679
self._intervals.reverse()
1680
self._flips.reverse()
1681
1682
def _reversed(self):
1683
r"""
1684
Reverses the permutation (called by lr_inverse)
1685
1686
TODO:
1687
1688
Resolve properly the mutability problem with _twin list and the hash
1689
value.
1690
1691
TESTS::
1692
1693
sage: p = iet.Permutation('a','a',flips='a')
1694
sage: p.lr_inverse() #indirect doctest
1695
-a
1696
-a
1697
sage: p = iet.Permutation('a b','a b',flips='a')
1698
sage: p.lr_inverse() #indirect doctest
1699
b -a
1700
b -a
1701
sage: p = iet.Permutation('a b','a b',flips='b')
1702
sage: p.lr_inverse() #indirect doctest
1703
-b a
1704
-b a
1705
sage: p = iet.Permutation('a b','b a',flips='a')
1706
sage: p.lr_inverse() #indirect doctest
1707
b -a
1708
-a b
1709
sage: p = iet.Permutation('a b','b a',flips='b')
1710
sage: p.lr_inverse() #indirect doctest
1711
-b a
1712
a -b
1713
"""
1714
if hasattr(self, '_twin'):
1715
delattr(self, '_twin')
1716
1717
if self._hash is not None:
1718
self._hash is None
1719
1720
self._intervals[0].reverse()
1721
self._intervals[1].reverse()
1722
self._flips[0].reverse()
1723
self._flips[1].reverse()
1724
1725
class FlippedLabelledPermutationIET(
1726
FlippedLabelledPermutation,
1727
FlippedPermutationIET,
1728
LabelledPermutationIET):
1729
r"""
1730
Flipped labelled permutation from iet.
1731
1732
EXAMPLES:
1733
1734
Reducibility testing (does not depends of flips)::
1735
1736
sage: p = iet.Permutation('a b c', 'c b a',flips='a')
1737
sage: p.is_irreducible()
1738
True
1739
sage: q = iet.Permutation('a b c d', 'b a d c', flips='bc')
1740
sage: q.is_irreducible()
1741
False
1742
1743
Rauzy movability and Rauzy move::
1744
1745
sage: p = iet.Permutation('a b c', 'c b a',flips='a')
1746
sage: print p
1747
-a b c
1748
c b -a
1749
sage: print p.rauzy_move(1)
1750
-c -a b
1751
-c b -a
1752
sage: print p.rauzy_move(0)
1753
-a b c
1754
c -a b
1755
1756
Rauzy diagrams::
1757
1758
sage: d = iet.RauzyDiagram('a b c d','d a b c',flips='a')
1759
1760
AUTHORS:
1761
1762
- Vincent Delecroix (2009-09-29): initial version
1763
"""
1764
def reduced(self):
1765
r"""
1766
The associated reduced permutation.
1767
1768
OUTPUT:
1769
1770
permutation -- the associated reduced permutation
1771
1772
EXAMPLE::
1773
1774
sage: p = iet.Permutation('a b c','c b a',flips='a')
1775
sage: q = iet.Permutation('a b c','c b a',flips='a',reduced=True)
1776
sage: p.reduced() == q
1777
True
1778
"""
1779
from sage.combinat.iet.reduced import FlippedReducedPermutationIET
1780
1781
return FlippedReducedPermutationIET(
1782
intervals=self.list(flips=False),
1783
flips=self.flips(),
1784
alphabet=self.alphabet())
1785
1786
def __hash__(self):
1787
r"""
1788
ALGORITHM:
1789
1790
Uses hash of string
1791
1792
TESTS::
1793
1794
sage: p =[]
1795
sage: p.append(iet.Permutation('a b','a b',flips='a'))
1796
sage: p.append(iet.Permutation('a b','a b',flips='b'))
1797
sage: p.append(iet.Permutation('a b','a b',flips='ab'))
1798
sage: p.append(iet.Permutation('a b','b a',flips='a'))
1799
sage: p.append(iet.Permutation('a b','b a',flips='b'))
1800
sage: p.append(iet.Permutation('a b','b a',flips='ab'))
1801
sage: h = map(hash, p)
1802
sage: for i in range(len(h)-1):
1803
... if h[i] == h[i+1]:
1804
... print "You choose a bad hash!"
1805
"""
1806
if self._hash is None:
1807
f = self._flips
1808
i = self._intervals
1809
l = []
1810
l.extend([str(j*(1+k)) for j,k in zip(f[0],i[0])])
1811
l.extend([str(-j*(1+k)) for j,k in zip(f[1],i[1])])
1812
self._hash = hash(''.join(l))
1813
1814
return self._hash
1815
1816
def rauzy_move(self,winner=None,side=None):
1817
r"""
1818
Returns the Rauzy move.
1819
1820
INPUT:
1821
1822
- ``winner`` - 'top' (or 't' or 0) or 'bottom' (or 'b' or 1)
1823
1824
- ``side`` - (default: 'right') 'right' (or 'r') or 'left' (or 'l')
1825
1826
OUTPUT:
1827
1828
permutation -- the Rauzy move of self
1829
1830
EXAMPLES:
1831
1832
::
1833
1834
sage: p = iet.Permutation('a b','b a',flips='a')
1835
sage: p.rauzy_move('top')
1836
-a b
1837
b -a
1838
sage: p.rauzy_move('bottom')
1839
-b -a
1840
-b -a
1841
1842
::
1843
1844
sage: p = iet.Permutation('a b c','c b a',flips='b')
1845
sage: p.rauzy_move('top')
1846
a -b c
1847
c a -b
1848
sage: p.rauzy_move('bottom')
1849
a c -b
1850
c -b a
1851
"""
1852
winner = interval_conversion(winner)
1853
side = side_conversion(side)
1854
1855
result = copy(self)
1856
1857
winner_letter = result._intervals[winner][side]
1858
loser_letter = result._intervals[1-winner].pop(side)
1859
1860
winner_flip = result._flips[winner][side]
1861
loser_flip = result._flips[1-winner].pop(side)
1862
1863
loser_twin = result._intervals[winner].index(loser_letter)
1864
result._flips[winner][loser_twin] = winner_flip * loser_flip
1865
1866
loser_to = result._intervals[1-winner].index(winner_letter) - side
1867
if winner_flip == -1: loser_to += 1 + 2*side
1868
1869
result._intervals[1-winner].insert(loser_to, loser_letter)
1870
result._flips[1-winner].insert(loser_to, winner_flip * loser_flip)
1871
1872
return result
1873
1874
def rauzy_diagram(self, **kargs):
1875
r"""
1876
Returns the Rauzy diagram associated to this permutation.
1877
1878
For more information, try help(iet.RauzyDiagram)
1879
1880
OUTPUT:
1881
1882
RauzyDiagram -- the Rauzy diagram of self
1883
1884
EXAMPLES::
1885
1886
sage: p = iet.Permutation('a b c', 'c b a',flips='a')
1887
sage: p.rauzy_diagram()
1888
Rauzy diagram with 3 permutations
1889
"""
1890
return FlippedLabelledRauzyDiagram(self, **kargs)
1891
1892
class FlippedLabelledPermutationLI(
1893
FlippedLabelledPermutation,
1894
FlippedPermutationLI,
1895
LabelledPermutationLI):
1896
r"""
1897
Flipped labelled quadratic (or generalized) permutation.
1898
1899
EXAMPLES:
1900
1901
Reducibility testing::
1902
1903
sage: p = iet.GeneralizedPermutation('a b b', 'c c a', flips='a')
1904
sage: p.is_irreducible()
1905
True
1906
1907
Reducibility testing with associated decomposition::
1908
1909
sage: p = iet.GeneralizedPermutation('a b c a', 'b d d c', flips='ab')
1910
sage: p.is_irreducible()
1911
False
1912
sage: test, decomp = p.is_irreducible(return_decomposition = True)
1913
sage: print test
1914
False
1915
sage: print decomp
1916
(['a'], ['c', 'a'], [], ['c'])
1917
1918
Rauzy movability and Rauzy move::
1919
1920
sage: p = iet.GeneralizedPermutation('a a b b c c', 'd d', flips='d')
1921
sage: p.has_rauzy_move(0)
1922
False
1923
sage: p.has_rauzy_move(1)
1924
True
1925
sage: p = iet.GeneralizedPermutation('a a b','b c c',flips='c')
1926
sage: p.has_rauzy_move(0)
1927
True
1928
sage: p.has_rauzy_move(1)
1929
True
1930
"""
1931
def reduced(self):
1932
r"""
1933
The associated reduced permutation.
1934
1935
OUTPUT:
1936
1937
permutation -- the associated reduced permutation
1938
1939
EXAMPLE::
1940
1941
sage: p = iet.GeneralizedPermutation('a a','b b c c',flips='a')
1942
sage: q = iet.GeneralizedPermutation('a a','b b c c',flips='a',reduced=True)
1943
sage: p.reduced() == q
1944
True
1945
"""
1946
from sage.combinat.iet.reduced import FlippedReducedPermutationLI
1947
1948
return FlippedReducedPermutationLI(
1949
intervals=self.list(flips=False),
1950
flips=self.flips(),
1951
alphabet=self.alphabet())
1952
1953
def right_rauzy_move(self, winner):
1954
r"""
1955
Perform a Rauzy move on the right (the standard one).
1956
1957
INPUT:
1958
1959
- ``winner`` - either 'top' or 'bottom' ('t' or 'b' for short)
1960
1961
OUTPUT:
1962
1963
permutation -- the Rauzy move of self
1964
1965
EXAMPLES:
1966
1967
::
1968
1969
sage: p = iet.GeneralizedPermutation('a a b','b c c',flips='c')
1970
sage: p.right_rauzy_move(0)
1971
a a b
1972
-c b -c
1973
sage: p.right_rauzy_move(1)
1974
a a
1975
-b -c -b -c
1976
1977
::
1978
1979
sage: p = iet.GeneralizedPermutation('a b b','c c a',flips='ab')
1980
sage: p.right_rauzy_move(0)
1981
a -b a -b
1982
c c
1983
sage: p.right_rauzy_move(1)
1984
b -a b
1985
c c -a
1986
"""
1987
result = copy(self)
1988
1989
winner_letter = result._intervals[winner][-1]
1990
winner_flip = result._flips[winner][-1]
1991
1992
loser_letter = result._intervals[1-winner].pop(-1)
1993
loser_flip = result._flips[1-winner].pop(-1)
1994
1995
if loser_letter in result._intervals[winner]:
1996
loser_twin = result._intervals[winner].index(loser_letter)
1997
result._flips[winner][loser_twin] = loser_flip*winner_flip
1998
else:
1999
loser_twin = result._intervals[1-winner].index(loser_letter)
2000
result._flips[1-winner][loser_twin] = loser_flip*winner_flip
2001
2002
if winner_letter in result._intervals[winner][:-1]:
2003
loser_to = result._intervals[winner].index(winner_letter)
2004
if winner_flip == -1: loser_to += 1
2005
result._intervals[winner].insert(loser_to, loser_letter)
2006
result._flips[winner].insert(loser_to, loser_flip*winner_flip)
2007
else:
2008
loser_to = result._intervals[1-winner].index(winner_letter)
2009
if loser_flip == 1: loser_to += 1
2010
result._intervals[1-winner].insert(loser_to, loser_letter)
2011
result._flips[1-winner].insert(loser_to, loser_flip*winner_flip)
2012
2013
return result
2014
2015
def left_rauzy_move(self, winner):
2016
r"""
2017
Perform a Rauzy move on the left.
2018
2019
INPUT:
2020
2021
- ``winner`` - either 'top' or 'bottom' ('t' or 'b' for short)
2022
2023
OUTPUT:
2024
2025
-- a permutation
2026
2027
EXAMPLES:
2028
2029
::
2030
2031
sage: p = iet.GeneralizedPermutation('a a b','b c c')
2032
sage: p.left_rauzy_move(0)
2033
a a b b
2034
c c
2035
sage: p.left_rauzy_move(1)
2036
a a b
2037
b c c
2038
2039
::
2040
2041
sage: p = iet.GeneralizedPermutation('a b b','c c a')
2042
sage: p.left_rauzy_move(0)
2043
a b b
2044
c c a
2045
sage: p.left_rauzy_move(1)
2046
b b
2047
c c a a
2048
"""
2049
result = copy(self)
2050
2051
winner_letter = result._intervals[winner][0]
2052
loser_letter = result._intervals[1-winner].pop(0)
2053
2054
if winner_letter in result._intervals[winner][1:]:
2055
loser_to = result._intervals[winner][1:].index(winner_letter)+2
2056
result._intervals[winner].insert(loser_to, loser_letter)
2057
2058
else:
2059
loser_to = result._intervals[1-winner].index(winner_letter)
2060
result._intervals[1-winner].insert(loser_to, loser_letter)
2061
2062
return result
2063
2064
def rauzy_diagram(self, **kargs):
2065
r"""
2066
Returns the associated Rauzy diagram.
2067
2068
For more information, try help(RauzyDiagram)
2069
2070
OUTPUT :
2071
2072
-- a RauzyDiagram
2073
2074
EXAMPLES::
2075
2076
sage: p = iet.GeneralizedPermutation('a b b a', 'c d c d')
2077
sage: d = p.rauzy_diagram()
2078
"""
2079
return FlippedLabelledRauzyDiagram(self, **kargs)
2080
2081
class LabelledRauzyDiagram(RauzyDiagram):
2082
r"""
2083
Template for Rauzy diagrams of labelled permutations.
2084
2085
...DO NOT USE...
2086
"""
2087
class Path(RauzyDiagram.Path):
2088
r"""
2089
Path in Labelled Rauzy diagram.
2090
"""
2091
def matrix(self):
2092
r"""
2093
Returns the matrix associated to a path.
2094
2095
The matrix associated to a Rauzy induction, is the linear
2096
application that allows to recover the lengths of self from the
2097
lengths of the induced.
2098
2099
OUTPUT:
2100
2101
matrix -- a square matrix of integers
2102
2103
EXAMPLES:
2104
2105
::
2106
2107
sage: p = iet.Permutation('a1 a2','a2 a1')
2108
sage: d = p.rauzy_diagram()
2109
sage: g = d.path(p,'top')
2110
sage: g.matrix()
2111
[1 0]
2112
[1 1]
2113
sage: g = d.path(p,'bottom')
2114
sage: g.matrix()
2115
[1 1]
2116
[0 1]
2117
2118
::
2119
2120
sage: p = iet.Permutation('a b c','c b a')
2121
sage: d = p.rauzy_diagram()
2122
sage: g = d.path(p)
2123
sage: g.matrix() == identity_matrix(3)
2124
True
2125
sage: g = d.path(p,'top')
2126
sage: g.matrix()
2127
[1 0 0]
2128
[0 1 0]
2129
[1 0 1]
2130
sage: g = d.path(p,'bottom')
2131
sage: g.matrix()
2132
[1 0 1]
2133
[0 1 0]
2134
[0 0 1]
2135
"""
2136
return self.composition(self._parent.edge_to_matrix)
2137
2138
def interval_substitution(self):
2139
r"""
2140
Returns the substitution of intervals obtained.
2141
2142
OUTPUT:
2143
2144
WordMorphism -- the word morphism corresponding to the interval
2145
2146
EXAMPLES::
2147
2148
sage: p = iet.Permutation('a b','b a')
2149
sage: r = p.rauzy_diagram()
2150
sage: p0 = r.path(p,0)
2151
sage: s0 = p0.interval_substitution()
2152
sage: print s0
2153
WordMorphism: a->a, b->ba
2154
sage: p1 = r.path(p,1)
2155
sage: s1 = p1.interval_substitution()
2156
sage: print s1
2157
WordMorphism: a->ab, b->b
2158
sage: (p0 + p1).interval_substitution() == s1 * s0
2159
True
2160
sage: (p1 + p0).interval_substitution() == s0 * s1
2161
True
2162
"""
2163
return self.right_composition(self._parent.edge_to_interval_substitution)
2164
2165
def orbit_substitution(self):
2166
r"""
2167
Returns the substitution on the orbit of the left extremity.
2168
2169
OUTPUT:
2170
2171
WordMorhpism -- the word morphism corresponding to the orbit
2172
2173
EXAMPLES::
2174
2175
sage: p = iet.Permutation('a b','b a')
2176
sage: d = p.rauzy_diagram()
2177
sage: g0 = d.path(p,'top')
2178
sage: s0 = g0.orbit_substitution()
2179
sage: print s0
2180
WordMorphism: a->ab, b->b
2181
sage: g1 = d.path(p,'bottom')
2182
sage: s1 = g1.orbit_substitution()
2183
sage: print s1
2184
WordMorphism: a->a, b->ab
2185
sage: (g0 + g1).orbit_substitution() == s0 * s1
2186
True
2187
sage: (g1 + g0).orbit_substitution() == s1 * s0
2188
True
2189
"""
2190
return self.composition(self._parent.edge_to_orbit_substitution)
2191
2192
substitution = orbit_substitution # standard name
2193
dual_substitution = interval_substitution # standard name
2194
2195
def is_full(self):
2196
r"""
2197
Tests the fullness.
2198
2199
A path is full if all intervals win at least one time.
2200
2201
OUTPUT:
2202
2203
boolean -- True if the path is full and False else
2204
2205
EXAMPLE::
2206
2207
sage: p = iet.Permutation('a b c','c b a')
2208
sage: r = p.rauzy_diagram()
2209
sage: g0 = r.path(p,'t','b','t')
2210
sage: g1 = r.path(p,'b','t','b')
2211
sage: g0.is_full()
2212
False
2213
sage: g1.is_full()
2214
False
2215
sage: (g0 + g1).is_full()
2216
True
2217
sage: (g1 + g0).is_full()
2218
True
2219
"""
2220
return set(self._parent.letters()) == set(self.winners())
2221
2222
def edge_to_interval_substitution(self, p=None, edge_type=None):
2223
r"""
2224
Returns the interval substitution associated to an edge
2225
2226
OUTPUT:
2227
2228
WordMorphism -- the WordMorphism corresponding to the edge
2229
2230
EXAMPLE::
2231
2232
sage: p = iet.Permutation('a b c','c b a')
2233
sage: r = p.rauzy_diagram()
2234
sage: print r.edge_to_interval_substitution(None,None)
2235
WordMorphism: a->a, b->b, c->c
2236
sage: print r.edge_to_interval_substitution(p,0)
2237
WordMorphism: a->a, b->b, c->ca
2238
sage: print r.edge_to_interval_substitution(p,1)
2239
WordMorphism: a->ac, b->b, c->c
2240
"""
2241
if p is None and edge_type is None:
2242
return WordMorphism(dict((a,a) for a in self.letters()))
2243
2244
function_name = self._edge_types[edge_type][0] + '_interval_substitution'
2245
if not hasattr(self._element_class,function_name):
2246
return WordMorphism(dict((a,a) for a in self.letters()))
2247
2248
arguments = self._edge_types[edge_type][1]
2249
2250
return getattr(p,function_name)(*arguments)
2251
2252
def edge_to_orbit_substitution(self, p=None, edge_type=None):
2253
r"""
2254
Returns the interval substitution associated to an edge
2255
2256
OUTPUT:
2257
2258
WordMorphism -- the word morphism corresponding to the edge
2259
2260
EXAMPLE::
2261
2262
sage: p = iet.Permutation('a b c','c b a')
2263
sage: r = p.rauzy_diagram()
2264
sage: print r.edge_to_orbit_substitution(None,None)
2265
WordMorphism: a->a, b->b, c->c
2266
sage: print r.edge_to_orbit_substitution(p,0)
2267
WordMorphism: a->ac, b->b, c->c
2268
sage: print r.edge_to_orbit_substitution(p,1)
2269
WordMorphism: a->a, b->b, c->ac
2270
"""
2271
if p is None and edge_type is None:
2272
return WordMorphism(dict((a,a) for a in self.letters()))
2273
2274
function_name = self._edge_types[edge_type][0] + '_orbit_substitution'
2275
2276
if not hasattr(self._element_class,function_name):
2277
return WordMorphism(dict((a,a) for a in self.letters()))
2278
2279
arguments = self._edge_types[edge_type][1]
2280
return getattr(p,function_name)(*arguments)
2281
2282
def full_loop_iterator(self, start=None, max_length=1):
2283
r"""
2284
Returns an iterator over all full path starting at start.
2285
2286
INPUT:
2287
2288
- ``start`` - the start point
2289
2290
- ``max_length`` - a limit on the length of the paths
2291
2292
OUTPUT:
2293
2294
iterator -- iterator over full loops
2295
2296
EXAMPLE::
2297
2298
sage: p = iet.Permutation('a b','b a')
2299
sage: r = p.rauzy_diagram()
2300
sage: for g in r.full_loop_iterator(p,2):
2301
... print g.matrix(), "\n*****"
2302
[1 1]
2303
[1 2]
2304
*****
2305
[2 1]
2306
[1 1]
2307
*****
2308
"""
2309
from itertools import ifilter, imap
2310
2311
g = self.path(start)
2312
2313
ifull = ifilter(
2314
lambda x: x.is_loop() and x.is_full(),
2315
self._all_path_extension(g,max_length))
2316
2317
return imap(copy,ifull)
2318
2319
def full_nloop_iterator(self, start=None, length=1):
2320
r"""
2321
Returns an iterator over all full loops of given length.
2322
2323
INPUT:
2324
2325
- ``start`` - the initial permutation
2326
2327
- ``length`` - the length to consider
2328
2329
OUTPUT:
2330
2331
iterator -- an iterator over the full loops of given length
2332
2333
EXAMPLE::
2334
2335
sage: p = iet.Permutation('a b','b a')
2336
sage: d = p.rauzy_diagram()
2337
sage: for g in d.full_nloop_iterator(p,2):
2338
... print g.matrix(), "\n*****"
2339
[1 1]
2340
[1 2]
2341
*****
2342
[2 1]
2343
[1 1]
2344
*****
2345
"""
2346
from itertools import ifilter, imap
2347
2348
g = self.path(start)
2349
2350
ifull = ifilter(
2351
lambda x: x.is_loop() and x.is_full(),
2352
self._all_npath_extension(g,length))
2353
2354
return imap(copy, ifull)
2355
2356
def _permutation_to_vertex(self, p):
2357
r"""
2358
Translation of a labelled permutation to a vertex
2359
2360
INPUT:
2361
2362
- ``p`` - a labelled Permutation
2363
2364
TESTS::
2365
2366
sage: p = iet.Permutation('a b c','c b a')
2367
sage: r = p.rauzy_diagram()
2368
sage: p in r #indirect doctest
2369
True
2370
"""
2371
return (tuple(p._intervals[0]),tuple(p._intervals[1]))
2372
2373
def _set_element(self,data):
2374
r"""
2375
Sets self._element with data
2376
2377
TESTS::
2378
2379
sage: p = iet.Permutation('a b c','c b a')
2380
sage: r = p.rauzy_diagram()
2381
sage: r[p][0] == p.rauzy_move(0) #indirect doctest
2382
True
2383
sage: r[p][1] == p.rauzy_move(1) #indirect doctest
2384
True
2385
"""
2386
self._element._intervals = [list(data[0]), list(data[1])]
2387
2388
class FlippedLabelledRauzyDiagram(FlippedRauzyDiagram, LabelledRauzyDiagram):
2389
r"""
2390
Rauzy diagram of flipped labelled permutations
2391
"""
2392
def _permutation_to_vertex(self, p):
2393
r"""
2394
Returns what must be stored from p.
2395
2396
INPUT:
2397
2398
- ``p`` - a Flipped labelled permutation
2399
2400
TESTS::
2401
2402
sage: p = iet.Permutation('a b c','c b a',flips='a')
2403
sage: r = p.rauzy_diagram()
2404
sage: p in r #indirect doctest
2405
True
2406
"""
2407
return ((tuple(p._intervals[0]),tuple(p._intervals[1])),
2408
(tuple(p._flips[0]), tuple(p._flips[1])))
2409
2410
def _set_element(self, data):
2411
r"""
2412
Returns what the vertex i as a permutation.
2413
2414
TESTS::
2415
2416
sage: p = iet.Permutation('a b','b a',flips='a')
2417
sage: r = p.rauzy_diagram()
2418
sage: p in r #indirect doctest
2419
True
2420
"""
2421
self._element._intervals = [list(data[0][0]), list(data[0][1])]
2422
self._element._flips = [list(data[1][0]), list(data[1][1])]
2423
2424