Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/dynamics/interval_exchanges/reduced.py
8815 views
1
r"""
2
Reduced permutations
3
4
A reduced (generalized) permutation is better suited to study strata of Abelian
5
(or quadratic) holomorphic forms on Riemann surfaces. The Rauzy diagram is an
6
invariant of such a component. Corentin Boissy proved the identification of
7
Rauzy diagrams with connected components of stratas. But the geometry of the
8
diagram and the relation with the strata is not yet totally understood.
9
10
AUTHORS:
11
12
- Vincent Delecroix (2000-09-29): initial version
13
14
TESTS::
15
16
sage: from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET
17
sage: ReducedPermutationIET([['a','b'],['b','a']])
18
a b
19
b a
20
sage: ReducedPermutationIET([[1,2,3],[3,1,2]])
21
1 2 3
22
3 1 2
23
sage: from sage.dynamics.interval_exchanges.reduced import ReducedPermutationLI
24
sage: ReducedPermutationLI([[1,1],[2,2,3,3,4,4]])
25
1 1
26
2 2 3 3 4 4
27
sage: ReducedPermutationLI([['a','a','b','b','c','c'],['d','d']])
28
a a b b c c
29
d d
30
sage: from sage.dynamics.interval_exchanges.reduced import FlippedReducedPermutationIET
31
sage: FlippedReducedPermutationIET([[1,2,3],[3,2,1]],flips=[1,2])
32
-1 -2 3
33
3 -2 -1
34
sage: FlippedReducedPermutationIET([['a','b','c'],['b','c','a']],flips='b')
35
a -b c
36
-b c a
37
sage: from sage.dynamics.interval_exchanges.reduced import FlippedReducedPermutationLI
38
sage: FlippedReducedPermutationLI([[1,1],[2,2,3,3,4,4]], flips=[1,4])
39
-1 -1
40
2 2 3 3 -4 -4
41
sage: FlippedReducedPermutationLI([['a','a','b','b'],['c','c']],flips='ac')
42
-a -a b b
43
-c -c
44
sage: from sage.dynamics.interval_exchanges.reduced import ReducedRauzyDiagram
45
sage: p = ReducedPermutationIET([[1,2,3],[3,2,1]])
46
sage: d = ReducedRauzyDiagram(p)
47
"""
48
#*****************************************************************************
49
# Copyright (C) 2008 Vincent Delecroix <[email protected]>
50
#
51
# Distributed under the terms of the GNU General Public License (GPL)
52
# http://www.gnu.org/licenses/
53
#*****************************************************************************
54
55
from sage.structure.sage_object import SageObject
56
57
from copy import copy
58
59
from sage.combinat.words.alphabet import Alphabet
60
from sage.rings.integer import Integer
61
62
from template import PermutationIET, PermutationLI # permutations
63
from template import FlippedPermutationIET, FlippedPermutationLI # flipped permutations
64
from template import twin_list_iet, twin_list_li
65
from template import RauzyDiagram, FlippedRauzyDiagram
66
67
from template import interval_conversion, side_conversion
68
69
class ReducedPermutation(SageObject) :
70
r"""
71
Template for reduced objects.
72
73
.. warning::
74
75
Internal class! Do not use directly!
76
77
INPUT:
78
79
- ``intervals`` - a list of two list of labels
80
81
- ``alphabet`` - (default: None) any object that can be used to initialize an Alphabet or None. In this latter case, the letter of the intervals are used to generate one.
82
"""
83
def __init__(self,intervals=None,alphabet=None):
84
r"""
85
TESTS::
86
87
sage: from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET
88
sage: p = ReducedPermutationIET()
89
sage: loads(dumps(p)) == p
90
True
91
sage: p = ReducedPermutationIET([['a','b'],['b','a']])
92
sage: loads(dumps(p)) == p
93
True
94
sage: from sage.dynamics.interval_exchanges.reduced import ReducedPermutationLI
95
sage: p = ReducedPermutationLI()
96
sage: loads(dumps(p)) == p
97
True
98
sage: p = ReducedPermutationLI([['a','a'],['b','b']])
99
sage: loads(dumps(p)) == p
100
True
101
"""
102
self._hash = None
103
104
if intervals is None:
105
self._twin = [[],[]]
106
self._alphabet = alphabet
107
108
else:
109
self._init_twin(intervals)
110
111
if alphabet is None:
112
self._init_alphabet(intervals)
113
else:
114
alphabet = Alphabet(alphabet)
115
if alphabet.cardinality() < len(self):
116
raise TypeError("The alphabet is too short")
117
self._alphabet = alphabet
118
119
def __len__(self):
120
r"""
121
TESTS::
122
123
sage: p = iet.Permutation('a b','b a',reduced=True)
124
sage: len(p)
125
2
126
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True)
127
sage: len(p)
128
3
129
sage: p = iet.GeneralizedPermutation('a a','b b c c',reduced=True)
130
sage: len(p)
131
3
132
"""
133
return (len(self._twin[0]) + len(self._twin[1])) / 2
134
135
def length_top(self):
136
r"""
137
Returns the number of intervals in the top segment.
138
139
OUTPUT:
140
141
integer -- the length of the top segment
142
143
EXAMPLES::
144
145
sage: p = iet.Permutation('a b c','c b a')
146
sage: p.length_top()
147
3
148
sage: p = iet.GeneralizedPermutation('a a b','c d c b d')
149
sage: p.length_top()
150
3
151
sage: p = iet.GeneralizedPermutation('a b c b d c d', 'e a e')
152
sage: p.length_top()
153
7
154
"""
155
return len(self._twin[0])
156
157
def length_bottom(self):
158
r"""
159
Returns the number of intervals in the bottom segment.
160
161
OUTPUT:
162
163
integer -- the length of the bottom segment
164
165
EXAMPLES::
166
167
sage: p = iet.Permutation('a b c','c b a')
168
sage: p.length_bottom()
169
3
170
sage: p = iet.GeneralizedPermutation('a a b','c d c b d')
171
sage: p.length_bottom()
172
5
173
"""
174
return len(self._twin[1])
175
176
def length(self, interval=None):
177
r"""
178
Returns the 2-uple of lengths.
179
180
p.length() is identical to (p.length_top(), p.length_bottom())
181
If an interval is specified, it returns the length of the specified
182
interval.
183
184
INPUT:
185
186
- ``interval`` - None, 'top' (or 't' or 0) or 'bottom' (or 'b' or 1)
187
188
OUTPUT:
189
190
integer or 2-uple of integers -- the corresponding lengths
191
192
EXAMPLES::
193
194
sage: p = iet.Permutation('a b c','c b a')
195
sage: p.length()
196
(3, 3)
197
sage: p = iet.GeneralizedPermutation('a a b','c d c b d')
198
sage: p.length()
199
(3, 5)
200
"""
201
if interval is None :
202
return len(self._twin[0]),len(self._twin[1])
203
else :
204
interval = interval_conversion(interval)
205
return len(self._twin[interval])
206
207
def __getitem__(self,i):
208
r"""
209
TESTS::
210
211
sage: p = iet.Permutation('a b', 'b a', reduced=True)
212
sage: print p[0]
213
['a', 'b']
214
sage: print p[1]
215
['b', 'a']
216
sage: p.alphabet([0,1])
217
sage: print p[0]
218
[0, 1]
219
sage: print p[1]
220
[1, 0]
221
"""
222
return self.list().__getitem__(i)
223
224
def __copy__(self) :
225
r"""
226
Returns a copy of self.
227
228
EXAMPLES::
229
230
sage: p = iet.Permutation('a b c', 'c b a', reduced=True)
231
sage: q = copy(p)
232
sage: p == q
233
True
234
sage: p is q
235
False
236
sage: p = iet.GeneralizedPermutation('a b b','c c a', reduced=True)
237
sage: q = copy(p)
238
sage: p == q
239
True
240
sage: p is q
241
False
242
"""
243
q = self.__class__()
244
245
q._twin = [self._twin[0][:], self._twin[1][:]]
246
q._alphabet = self._alphabet
247
q._repr_type = self._repr_type
248
q._repr_options = self._repr_options
249
250
return q
251
252
def erase_letter(self, letter):
253
r"""
254
Erases a letter.
255
256
INPUT:
257
258
- ``letter`` - a letter which is a label of an interval of self
259
260
EXAMPLES:
261
262
::
263
264
sage: p = iet.Permutation('a b c','c b a')
265
sage: p.erase_letter('a')
266
b c
267
c b
268
269
::
270
271
sage: p = iet.GeneralizedPermutation('a b b','c c a')
272
sage: p.erase_letter('a')
273
b b
274
c c
275
"""
276
l = self.list()
277
278
del l[0][l[0].index(letter)]
279
del l[1][l[1].index(letter)]
280
281
return self.__class__(l)
282
283
def right_rauzy_move(self, winner):
284
r"""
285
Performs a Rauzy move on the right.
286
287
EXAMPLES:
288
289
::
290
291
sage: p = iet.Permutation('a b c','c b a',reduced=True)
292
sage: p.right_rauzy_move(0)
293
a b c
294
c a b
295
sage: p.right_rauzy_move(1)
296
a b c
297
b c a
298
299
::
300
301
sage: p = iet.GeneralizedPermutation('a a','b b c c',reduced=True)
302
sage: p.right_rauzy_move(0)
303
a b b
304
c c a
305
"""
306
winner = interval_conversion(winner)
307
308
result = copy(self)
309
310
loser_to = result._get_loser_to(winner)
311
# beware here, loser_to can contain 2 or 3 items
312
# (depending on the presence of flip)
313
314
result._twin_rauzy_move(winner, loser_to)
315
316
return result
317
318
def left_rauzy_move(self, winner):
319
r"""
320
Performs a Rauzy move on the left.
321
322
EXAMPLES:
323
324
::
325
326
sage: p = iet.Permutation('a b c','c b a',reduced=True)
327
sage: p.left_rauzy_move(0)
328
a b c
329
b c a
330
sage: p.right_rauzy_move(1)
331
a b c
332
b c a
333
334
::
335
336
sage: p = iet.GeneralizedPermutation('a a','b b c c',reduced=True)
337
sage: p.left_rauzy_move(0)
338
a a b
339
b c c
340
"""
341
winner = interval_conversion(winner)
342
343
result = copy(self)
344
result._reversed()
345
result = result.right_rauzy_move(winner)
346
result._reversed()
347
return result
348
349
_RP = ReducedPermutation
350
351
def alphabetized_atwin(twin, alphabet):
352
"""
353
Alphabetization of a twin of iet.
354
355
TESTS::
356
357
sage: from sage.dynamics.interval_exchanges.reduced import alphabetized_atwin
358
359
::
360
361
sage: twin = [[0,1],[0,1]]
362
sage: alphabet = Alphabet("ab")
363
sage: alphabetized_atwin(twin, alphabet)
364
[['a', 'b'], ['a', 'b']]
365
366
::
367
368
sage: twin = [[1,0],[1,0]]
369
sage: alphabet = Alphabet([0,1])
370
sage: alphabetized_atwin(twin, alphabet)
371
[[0, 1], [1, 0]]
372
373
::
374
375
sage: twin = [[1,2,3,0],[3,0,1,2]]
376
sage: alphabet = Alphabet("abcd")
377
sage: alphabetized_atwin(twin,alphabet)
378
[['a', 'b', 'c', 'd'], ['d', 'a', 'b', 'c']]
379
"""
380
l = [[],[]]
381
382
l[0] = map(lambda x: alphabet.unrank(x), range(len(twin[0])))
383
l[1] = map(lambda x: alphabet.unrank(x), twin[1])
384
385
return l
386
387
def ReducedPermutationsIET_iterator(
388
nintervals=None,
389
irreducible=True,
390
alphabet=None):
391
r"""
392
Returns an iterator over reduced permutations
393
394
INPUT:
395
396
- ``nintervals`` - integer or None
397
398
- ``irreducible`` - boolean
399
400
- ``alphabet`` - something that should be converted to an alphabet
401
of at least nintervals letters
402
403
TESTS::
404
405
sage: for p in iet.Permutations_iterator(3,reduced=True,alphabet="abc"):
406
....: print p #indirect doctest
407
a b c
408
b c a
409
a b c
410
c a b
411
a b c
412
c b a
413
"""
414
from itertools import imap,ifilter
415
from sage.combinat.permutation import Permutations
416
417
if irreducible is False:
418
if nintervals is None:
419
raise ValueError("please choose a number of intervals")
420
421
nintervals = Integer(nintervals)
422
423
if not(nintervals > 0):
424
raise ValueError('number of intervals must be positive')
425
426
a0 = range(1,nintervals+1)
427
f = lambda x: ReducedPermutationIET([a0,list(x)],
428
alphabet=alphabet)
429
return imap(f, Permutations(nintervals))
430
else:
431
return ifilter(lambda x: x.is_irreducible(),
432
ReducedPermutationsIET_iterator(nintervals,False,alphabet))
433
434
class ReducedPermutationIET(ReducedPermutation, PermutationIET):
435
"""
436
Reduced permutation from iet
437
438
Permutation from iet without numerotation of intervals. For initialization,
439
you should use GeneralizedPermutation which is the class factory for all
440
permutation types.
441
442
EXAMPLES:
443
444
Equality testing (no equality of letters but just of ordering)::
445
446
sage: p = iet.Permutation('a b c', 'c b a', reduced = True)
447
sage: q = iet.Permutation('p q r', 'r q p', reduced = True)
448
sage: p == q
449
True
450
451
Reducibility testing::
452
453
sage: p = iet.Permutation('a b c', 'c b a', reduced = True)
454
sage: p.is_irreducible()
455
True
456
457
::
458
459
sage: q = iet.Permutation('a b c d', 'b a d c', reduced = True)
460
sage: q.is_irreducible()
461
False
462
463
464
Rauzy movability and Rauzy move::
465
466
sage: p = iet.Permutation('a b c', 'c b a', reduced = True)
467
sage: p.has_rauzy_move(1)
468
True
469
sage: print p.rauzy_move(1)
470
a b c
471
b c a
472
473
Rauzy diagrams::
474
475
sage: p = iet.Permutation('a b c d', 'd a b c')
476
sage: p_red = iet.Permutation('a b c d', 'd a b c', reduced = True)
477
sage: d = p.rauzy_diagram()
478
sage: d_red = p_red.rauzy_diagram()
479
sage: p.rauzy_move(0) in d
480
True
481
sage: print d.cardinality(), d_red.cardinality()
482
12 6
483
"""
484
def _init_twin(self, a):
485
r"""
486
Initializes the _twin attribute
487
488
TESTS::
489
490
sage: p = iet.Permutation('a b','b a',reduced=True) #indirect doctest
491
sage: p._twin
492
[[1, 0], [1, 0]]
493
"""
494
self._twin = twin_list_iet(a)
495
496
def list(self):
497
r"""
498
Returns a list of two list that represents the permutation.
499
500
EXAMPLES::
501
502
sage: p = iet.GeneralizedPermutation('a b','b a',reduced=True)
503
sage: p.list() == [p[0], p[1]]
504
True
505
sage: p.list() == [['a', 'b'], ['b', 'a']]
506
True
507
508
::
509
510
sage: p = iet.GeneralizedPermutation('a b c', 'b c a',reduced=True)
511
sage: iet.GeneralizedPermutation(p.list(),reduced=True) == p
512
True
513
"""
514
a0 = map(self._alphabet.unrank, range(0,len(self)))
515
a1 = map(self._alphabet.unrank, self._twin[1])
516
return [a0,a1]
517
518
def is_identity(self):
519
r"""
520
Returns True if self is the identity.
521
522
EXAMPLES::
523
524
sage: iet.Permutation("a b","a b",reduced=True).is_identity()
525
True
526
sage: iet.Permutation("a b","b a",reduced=True).is_identity()
527
False
528
"""
529
for i in range(len(self)):
530
if self._twin[0][i] != i:
531
return False
532
return True
533
534
def __hash__(self):
535
r"""
536
Returns a hash value (does not depends of the alphabet).
537
538
TESTS::
539
sage: p = iet.Permutation([1,2],[1,2], reduced=True)
540
sage: q = iet.Permutation([1,2],[2,1], reduced=True)
541
sage: r = iet.Permutation([2,1],[1,2], reduced=True)
542
sage: hash(p) == hash(q)
543
False
544
sage: hash(q) == hash(r)
545
True
546
"""
547
if self._hash is None:
548
self._hash = hash(tuple(self._twin[0]))
549
return self._hash
550
551
def __cmp__(self, other):
552
r"""
553
Defines a natural lexicographic order.
554
555
TESTS::
556
557
sage: p = iet.GeneralizedPermutation('a b','a b',reduced=True)
558
sage: q = copy(p)
559
sage: q.alphabet([0,1])
560
sage: p == q
561
True
562
sage: p0 = iet.GeneralizedPermutation('a b', 'a b', reduced=True)
563
sage: p1 = iet.GeneralizedPermutation('a b', 'b a', reduced=True)
564
sage: p0 < p1 and p1 > p0
565
True
566
sage: q0 = iet.GeneralizedPermutation('a b c','a b c',reduced=True)
567
sage: q1 = iet.GeneralizedPermutation('a b c','a c b',reduced=True)
568
sage: q2 = iet.GeneralizedPermutation('a b c','b a c',reduced=True)
569
sage: q3 = iet.GeneralizedPermutation('a b c','b c a',reduced=True)
570
sage: q4 = iet.GeneralizedPermutation('a b c','c a b',reduced=True)
571
sage: q5 = iet.GeneralizedPermutation('a b c','c b a',reduced=True)
572
sage: p0 < q0 and q0 > p0 and p1 < q0 and q0 > p1
573
True
574
sage: q0 < q1 and q1 > q0
575
True
576
sage: q1 < q2 and q2 > q1
577
True
578
sage: q2 < q3 and q3 > q2
579
True
580
sage: q3 < q4 and q4 > q3
581
True
582
sage: q4 < q5 and q5 > q4
583
True
584
"""
585
if type(self) != type(other):
586
raise ValueError("Permutations must be of the same type")
587
588
if len(self) > len(other):
589
return 1
590
elif len(self) < len(other):
591
return -1
592
593
n = len(self)
594
j = 0
595
while (j < n and self._twin[1][j] == other._twin[1][j]):
596
j += 1
597
598
if j != n:
599
if self._twin[1][j] > other._twin[1][j]: return 1
600
else: return -1
601
602
return 0
603
604
def _reversed(self):
605
r"""
606
Reverses the permutation.
607
608
EXAMPLES:
609
610
::
611
612
sage: p = iet.Permutation('a b c','c a b',reduced=True)
613
sage: p
614
a b c
615
c a b
616
sage: p._reversed()
617
sage: p
618
a b c
619
b c a
620
621
::
622
623
sage: p = iet.Permutation('a b c d','d a b c',reduced=True)
624
sage: p
625
a b c d
626
d a b c
627
sage: p._reversed()
628
sage: p
629
a b c d
630
b c d a
631
"""
632
tmp = [self._twin[0][:], self._twin[1][:]]
633
634
n = self.length_top()
635
for i in (0, 1):
636
for j in range(n):
637
tmp[i][n - 1 - j] = n - 1 - self._twin[i][j]
638
639
self._twin = tmp
640
641
def _inversed(self):
642
r"""
643
Inverses the permutation.
644
645
EXAMPLES:
646
647
::
648
649
sage: p = iet.Permutation('a b c','c a b',reduced=True)
650
sage: p
651
a b c
652
c a b
653
sage: p._inversed()
654
sage: p
655
a b c
656
b c a
657
658
::
659
660
sage: p = iet.Permutation('a b c d','d a b c',reduced=True)
661
sage: p
662
a b c d
663
d a b c
664
sage: p._inversed()
665
sage: p
666
a b c d
667
b c d a
668
"""
669
self._twin = [self._twin[1], self._twin[0]]
670
671
def has_rauzy_move(self, winner, side='right'):
672
r"""
673
Tests if the permutation is rauzy_movable on the left.
674
675
EXAMPLES:
676
677
::
678
679
sage: p = iet.Permutation('a b c','a c b',reduced=True)
680
sage: p.has_rauzy_move(0,'right')
681
True
682
sage: p.has_rauzy_move(0,'left')
683
False
684
sage: p.has_rauzy_move(1,'right')
685
True
686
sage: p.has_rauzy_move(1,'left')
687
False
688
689
::
690
691
sage: p = iet.Permutation('a b c d','c a b d',reduced=True)
692
sage: p.has_rauzy_move(0,'right')
693
False
694
sage: p.has_rauzy_move(0,'left')
695
True
696
sage: p.has_rauzy_move(1,'right')
697
False
698
sage: p.has_rauzy_move(1,'left')
699
True
700
"""
701
side = side_conversion(side)
702
winner = interval_conversion(winner)
703
704
return self._twin[winner][side] % len(self) != side % len(self)
705
706
def rauzy_move_relabel(self, winner, side='right'):
707
r"""
708
Returns the relabelization obtained from this move.
709
710
EXAMPLE::
711
712
sage: p = iet.Permutation('a b c d','d c b a')
713
sage: q = p.reduced()
714
sage: p_t = p.rauzy_move('t')
715
sage: q_t = q.rauzy_move('t')
716
sage: s_t = q.rauzy_move_relabel('t')
717
sage: s_t
718
WordMorphism: a->a, b->b, c->c, d->d
719
sage: map(s_t, p_t[0]) == map(Word, q_t[0])
720
True
721
sage: map(s_t, p_t[1]) == map(Word, q_t[1])
722
True
723
sage: p_b = p.rauzy_move('b')
724
sage: q_b = q.rauzy_move('b')
725
sage: s_b = q.rauzy_move_relabel('b')
726
sage: s_b
727
WordMorphism: a->a, b->d, c->b, d->c
728
sage: map(s_b, q_b[0]) == map(Word, p_b[0])
729
True
730
sage: map(s_b, q_b[1]) == map(Word, p_b[1])
731
True
732
"""
733
from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET
734
from sage.combinat.words.morphism import WordMorphism
735
736
winner = interval_conversion(winner)
737
side = side_conversion(side)
738
739
p = LabelledPermutationIET(self.list())
740
741
l0_q = p.rauzy_move(winner, side).list()[0]
742
743
d = dict([(self._alphabet[i],l0_q[i]) for i in range(len(self))])
744
745
return WordMorphism(d)
746
747
def _get_loser_to(self, winner) :
748
r"""
749
This function return the position of the future loser position.
750
751
TESTS:
752
753
::
754
755
sage: p = iet.Permutation('a b c','c b a',reduced=True)
756
sage: p._get_loser_to(0)
757
(1, 1)
758
sage: p._get_loser_to(1)
759
(0, 1)
760
761
::
762
763
sage: p = iet.Permutation('a b c','c a b',reduced=True)
764
sage: p._get_loser_to(0)
765
(1, 1)
766
sage: p._get_loser_to(1)
767
(0, 2)
768
769
::
770
771
sage: p = iet.Permutation('a b c','b c a',reduced=True)
772
sage: p._get_loser_to(0)
773
(1, 2)
774
sage: p._get_loser_to(1)
775
(0, 1)
776
"""
777
return (1-winner, self._twin[winner][-1]+1)
778
779
def _twin_rauzy_move(self, winner_interval, loser_to) :
780
r"""
781
Do a Rauzy move for this choice of winner.
782
783
TESTS::
784
785
sage: p = iet.Permutation('a b','b a',reduced=True)
786
sage: p.rauzy_move(0) == p #indirect doctest
787
True
788
sage: p.rauzy_move(1) == p #indirect doctest
789
True
790
"""
791
loser_interval = 1 - winner_interval
792
793
loser_twin_interval = winner_interval
794
loser_twin_position = self._twin[loser_interval][-1]
795
796
loser_interval_to, loser_position_to = loser_to
797
798
# move the loser
799
del self._twin[loser_interval][-1]
800
self._twin[loser_interval_to].insert(loser_position_to, loser_twin_position)
801
self._twin[loser_twin_interval][loser_twin_position] = loser_position_to
802
803
# increment the twins in the winner interval
804
for j in range(loser_position_to + 1, self.length(loser_interval_to)) :
805
self._twin[winner_interval][self._twin[loser_interval_to][j]] += 1
806
807
def rauzy_diagram(self, **kargs):
808
r"""
809
Returns the associated Rauzy diagram.
810
811
OUTPUT:
812
813
A Rauzy diagram
814
815
EXAMPLES:
816
817
::
818
819
sage: p = iet.Permutation('a b c d', 'd a b c',reduced=True)
820
sage: d = p.rauzy_diagram()
821
sage: p.rauzy_move(0) in d
822
True
823
sage: p.rauzy_move(1) in d
824
True
825
826
For more information, try help RauzyDiagram
827
"""
828
return ReducedRauzyDiagram(self, **kargs)
829
830
def alphabetized_qtwin(twin, alphabet):
831
"""
832
Alphabetization of a qtwin.
833
834
TESTS::
835
836
sage: from sage.dynamics.interval_exchanges.reduced import alphabetized_qtwin
837
838
::
839
840
sage: twin = [[(1,0),(1,1)],[(0,0),(0,1)]]
841
sage: alphabet = Alphabet("ab")
842
sage: print alphabetized_qtwin(twin,alphabet)
843
[['a', 'b'], ['a', 'b']]
844
845
::
846
847
sage: twin = [[(1,1), (1,0)],[(0,1), (0,0)]]
848
sage: alphabet=Alphabet("AB")
849
sage: alphabetized_qtwin(twin,alphabet)
850
[['A', 'B'], ['B', 'A']]
851
sage: alphabet=Alphabet("BA")
852
sage: alphabetized_qtwin(twin,alphabet)
853
[['B', 'A'], ['A', 'B']]
854
855
::
856
857
sage: twin = [[(0,1),(0,0)],[(1,1),(1,0)]]
858
sage: alphabet=Alphabet("ab")
859
sage: print alphabetized_qtwin(twin,alphabet)
860
[['a', 'a'], ['b', 'b']]
861
862
::
863
864
sage: twin = [[(0,2),(1,1),(0,0)],[(1,2),(0,1),(1,0)]]
865
sage: alphabet=Alphabet("abc")
866
sage: print alphabetized_qtwin(twin,alphabet)
867
[['a', 'b', 'a'], ['c', 'b', 'c']]
868
"""
869
i_a = 0
870
l = [[False]*len(twin[0]), [False]*len(twin[1])]
871
# False means empty here
872
for i in range(2) :
873
for j in range(len(l[i])) :
874
if l[i][j] is False :
875
l[i][j] = alphabet[i_a]
876
l[twin[i][j][0]][twin[i][j][1]] = alphabet[i_a]
877
i_a += 1
878
return l
879
880
class ReducedPermutationLI(ReducedPermutation, PermutationLI):
881
r"""
882
Reduced quadratic (or generalized) permutation.
883
884
EXAMPLES:
885
886
Reducibility testing::
887
888
sage: p = iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
889
sage: p.is_irreducible()
890
True
891
892
::
893
894
sage: p = iet.GeneralizedPermutation('a b c a', 'b d d c', reduced = True)
895
sage: p.is_irreducible()
896
False
897
sage: test, decomposition = p.is_irreducible(return_decomposition = True)
898
sage: test
899
False
900
sage: decomposition
901
(['a'], ['c', 'a'], [], ['c'])
902
903
Rauzy movavability and Rauzy move::
904
905
sage: p = iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
906
sage: p.has_rauzy_move(0)
907
True
908
sage: p.rauzy_move(0)
909
a a b b
910
c c
911
sage: p.rauzy_move(0).has_rauzy_move(0)
912
False
913
sage: p.rauzy_move(1)
914
a b b
915
c c a
916
917
Rauzy diagrams::
918
919
sage: p_red = iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
920
sage: d_red = p_red.rauzy_diagram()
921
sage: d_red.cardinality()
922
4
923
"""
924
def _init_twin(self, a):
925
r"""
926
Initializes the _twin attribute
927
928
TESTS::
929
930
sage: p = iet.GeneralizedPermutation('a a','b b',reduced=True) #indirect doctest
931
sage: p._twin
932
[[(0, 1), (0, 0)], [(1, 1), (1, 0)]]
933
"""
934
self._twin = twin_list_li(a)
935
936
def list(self) :
937
r"""
938
The permutations as a list of two lists.
939
940
EXAMPLES::
941
942
sage: p = iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
943
sage: list(p)
944
[['a', 'b', 'b'], ['c', 'c', 'a']]
945
"""
946
return alphabetized_qtwin(self._twin, self.alphabet())
947
948
def __eq__(self, other) :
949
r"""
950
Tests equality.
951
952
Two reduced permutations are equal if they have the same order of
953
apparition of intervals. Non necessarily the same alphabet.
954
955
TESTS::
956
957
sage: p = iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
958
sage: q = iet.GeneralizedPermutation('b a a', 'c c b', reduced = True)
959
sage: r = iet.GeneralizedPermutation('t s s', 'w w t', reduced = True)
960
sage: p == q
961
True
962
sage: p == r
963
True
964
"""
965
return type(self) == type(other) and self._twin == other._twin
966
967
def __ne__(self, other) :
968
"""
969
Tests difference.
970
971
TESTS::
972
sage: p = iet.GeneralizedPermutation('a b b', 'c c a', reduced = True)
973
sage: q = iet.GeneralizedPermutation('b b a', 'c c a', reduced = True)
974
sage: r = iet.GeneralizedPermutation('i j j', 'k k i', reduced = True)
975
sage: p != q
976
True
977
sage: p != r
978
False
979
"""
980
return type(self) != type(other) or (self._twin != other._twin)
981
982
def _get_loser_to(self, winner) :
983
r"""
984
This function return the position of the future loser position.
985
986
TESTS::
987
988
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True)
989
sage: p._get_loser_to(0)
990
(1, 1)
991
sage: p._get_loser_to(1)
992
(1, 1)
993
"""
994
loser = 1 - winner
995
996
if self._twin[winner][-1][0] == loser:
997
return (loser, self._twin[winner][-1][1] + 1)
998
else:
999
return (winner, self._twin[winner][-1][1])
1000
1001
def _twin_rauzy_move(self, winner_interval, loser_to) :
1002
r"""
1003
Rauzy move on the twin data
1004
1005
TESTS:
1006
1007
::
1008
1009
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True)
1010
sage: p.rauzy_move(0) #indirect doctest
1011
a a b
1012
b c c
1013
sage: p.rauzy_move(1) #indirect doctest
1014
a a
1015
b b c c
1016
1017
::
1018
1019
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True)
1020
sage: p.rauzy_move(0) #indirect doctest
1021
a a b
1022
b c c
1023
sage: p.rauzy_move(1) #indirect doctest
1024
a a
1025
b b c c
1026
"""
1027
loser_interval = 1 - winner_interval
1028
1029
loser_interval_to, loser_position_to = loser_to
1030
loser_twin_interval, loser_twin_position = self._twin[loser_interval][-1]
1031
1032
# increment the twins in the winner interval
1033
interval = [(self._twin[loser_interval_to][j], j) for j in range(loser_position_to, len(self._twin[loser_interval_to]))]
1034
for (i,j),k in interval : self._twin[i][j] = (loser_interval_to, k+1)
1035
1036
# prepare the loser new position in its twin
1037
self._twin[loser_twin_interval][loser_twin_position] = loser_to
1038
1039
# move the loser
1040
loser_twin = self._twin[loser_interval][-1]
1041
self._twin[loser_interval_to].insert(loser_position_to, loser_twin)
1042
del self._twin[loser_interval][-1]
1043
1044
def _reversed(self):
1045
r"""
1046
Reverses the permutation.
1047
1048
EXAMPLES:
1049
1050
::
1051
1052
sage: p = iet.GeneralizedPermutation('a b b','c c a',reduced=True)
1053
sage: p._reversed()
1054
sage: p
1055
a a b
1056
b c c
1057
1058
::
1059
1060
sage: p = iet.GeneralizedPermutation('a a','b b c c',reduced=True)
1061
sage: p._reversed()
1062
sage: p
1063
a a
1064
b b c c
1065
"""
1066
tmp = [self._twin[0][:], self._twin[1][:]]
1067
1068
n = self.length()
1069
1070
for i in (0,1):
1071
for j in range(n[i]):
1072
interval, position = self._twin[i][j]
1073
tmp[i][n[i] - 1 - j] = (
1074
interval,
1075
n[interval] - 1 - position)
1076
1077
self._twin = tmp
1078
1079
def _inversed(self):
1080
r"""
1081
Inverses the permutation.
1082
1083
EXAMPLES:
1084
1085
::
1086
1087
sage: p = iet.GeneralizedPermutation('a a','b b',reduced=True)
1088
sage: p._inversed()
1089
sage: p
1090
a a
1091
b b
1092
1093
::
1094
1095
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True)
1096
sage: p._inversed()
1097
sage: p
1098
a b b
1099
c c a
1100
1101
::
1102
1103
sage: p = iet.GeneralizedPermutation('a a','b b c c',reduced=True)
1104
sage: p._inversed()
1105
sage: p
1106
a a b b
1107
c c
1108
"""
1109
self._twin = [self._twin[1], self._twin[0]]
1110
1111
for interval in (0,1):
1112
for j in xrange(self.length(interval)):
1113
self._twin[interval][j] = (1-self._twin[interval][j][0],
1114
self._twin[interval][j][1])
1115
1116
def rauzy_diagram(self, **kargs):
1117
r"""
1118
Returns the associated Rauzy diagram.
1119
1120
The Rauzy diagram of a permutation corresponds to all permutations
1121
that we could obtain from this one by Rauzy move. The set obtained
1122
is a labelled Graph. The label of vertices being 0 or 1 depending
1123
on the type.
1124
1125
OUTPUT:
1126
1127
Rauzy diagram -- the graph of permutations obtained by rauzy induction
1128
1129
EXAMPLES::
1130
1131
sage: p = iet.Permutation('a b c d', 'd a b c')
1132
sage: d = p.rauzy_diagram()
1133
"""
1134
return ReducedRauzyDiagram(self, **kargs)
1135
1136
def labelize_flip(couple):
1137
r"""
1138
Returns a string from a 2-uple couple of the form (name, flip).
1139
1140
TESTS::
1141
1142
sage: from sage.dynamics.interval_exchanges.reduced import labelize_flip
1143
sage: labelize_flip((4,1))
1144
' 4'
1145
sage: labelize_flip(('a',-1))
1146
'-a'
1147
"""
1148
if couple[1] == -1: return '-' + str(couple[0])
1149
return ' ' + str(couple[0])
1150
1151
class FlippedReducedPermutation(ReducedPermutation):
1152
r"""
1153
Flipped Reduced Permutation.
1154
1155
.. warning::
1156
1157
Internal class! Do not use directly!
1158
1159
INPUT:
1160
1161
- ``intervals`` - a list of two lists
1162
1163
- ``flips`` - the flipped letters
1164
1165
- ``alphabet`` - an alphabet
1166
"""
1167
def __init__(self, intervals=None, flips=None, alphabet=None):
1168
r"""
1169
TESTS::
1170
1171
sage: p = iet.Permutation('a b','b a',reduced=True,flips='a')
1172
sage: p == loads(dumps(p))
1173
True
1174
sage: p = iet.Permutation('a b','b a',reduced=True,flips='b')
1175
sage: p == loads(dumps(p))
1176
True
1177
sage: p = iet.Permutation('a b','b a',reduced=True,flips='ab')
1178
sage: p == loads(dumps(p))
1179
True
1180
sage: p = iet.GeneralizedPermutation('a a','b b',reduced=True,flips='a')
1181
sage: p == loads(dumps(p))
1182
True
1183
sage: p = iet.GeneralizedPermutation('a a','b b',reduced=True,flips='b')
1184
sage: p == loads(dumps(p))
1185
True
1186
sage: p = iet.GeneralizedPermutation('a a','b b',reduced=True,flips='ab')
1187
sage: p == loads(dumps(p))
1188
True
1189
"""
1190
self._hash = None
1191
1192
if intervals is None:
1193
self._twin = [[],[]]
1194
self._flips = [[],[]]
1195
self._alphabet = None
1196
1197
else:
1198
if flips is None: flips = []
1199
1200
if alphabet is None : self._init_alphabet(intervals)
1201
else : self._alphabet = Alphabet(alphabet)
1202
1203
self._init_twin(intervals)
1204
self._init_flips(intervals, flips)
1205
1206
self._hash = None
1207
1208
def __copy__(self):
1209
r"""
1210
Returns a copy of self.
1211
1212
TESTS::
1213
1214
sage: p = iet.GeneralizedPermutation('a a b', 'c c b',reduced=True, flips='a')
1215
sage: q = copy(p)
1216
sage: p == q
1217
True
1218
sage: p is q
1219
False
1220
"""
1221
p = self.__class__()
1222
1223
p._twin = [self._twin[0][:], self._twin[1][:]]
1224
p._flips = [self._flips[0][:], self._flips[1][:]]
1225
p._alphabet = self._alphabet
1226
p._repr_type = self._repr_type
1227
p._repr_options = self._repr_options
1228
1229
return p
1230
1231
def right_rauzy_move(self, winner):
1232
r"""
1233
Performs a Rauzy move on the right.
1234
1235
EXAMPLE::
1236
1237
sage: p = iet.Permutation('a b c','c b a',reduced=True,flips='c')
1238
sage: p.right_rauzy_move('top')
1239
-a b -c
1240
-a -c b
1241
"""
1242
winner = interval_conversion(winner)
1243
1244
result = copy(self)
1245
1246
loser_to = result._get_loser_to(winner)
1247
1248
result._flip_rauzy_move(winner, loser_to)
1249
result._twin_rauzy_move(winner, loser_to)
1250
1251
return result
1252
1253
def _reversed(self):
1254
r"""
1255
Reverses the permutation
1256
1257
TESTS:
1258
1259
::
1260
1261
sage: p = iet.Permutation('a b c d','c d b a',reduced=True,flips='a')
1262
sage: p
1263
-a b c d
1264
c d b -a
1265
sage: p._reversed()
1266
sage: p
1267
a b c -d
1268
-d c a b
1269
sage: p._reversed()
1270
sage: p
1271
-a b c d
1272
c d b -a
1273
1274
::
1275
1276
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True,flips='a')
1277
sage: p
1278
-a -a b
1279
b c c
1280
sage: p._reversed()
1281
sage: p
1282
a -b -b
1283
c c a
1284
sage: p._reversed()
1285
sage: p
1286
-a -a b
1287
b c c
1288
"""
1289
super(FlippedReducedPermutation, self)._reversed()
1290
self._flips[0].reverse()
1291
self._flips[1].reverse()
1292
1293
def _inversed(self):
1294
r"""
1295
Inverses the permutation.
1296
1297
TESTS:
1298
1299
::
1300
1301
sage: p = iet.Permutation('a b c d','c d b a',flips='a')
1302
sage: p
1303
-a b c d
1304
c d b -a
1305
sage: p._inversed()
1306
sage: p
1307
c d b -a
1308
-a b c d
1309
sage: p._inversed()
1310
sage: p
1311
-a b c d
1312
c d b -a
1313
1314
::
1315
1316
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True,flips='a')
1317
sage: p
1318
-a -a b
1319
b c c
1320
sage: p._inversed()
1321
sage: p
1322
a b b
1323
-c -c a
1324
sage: p._inversed()
1325
sage: p
1326
-a -a b
1327
b c c
1328
"""
1329
super(FlippedReducedPermutation, self)._inversed()
1330
self._flips.reverse()
1331
1332
class FlippedReducedPermutationIET(
1333
FlippedReducedPermutation,
1334
FlippedPermutationIET,
1335
ReducedPermutationIET):
1336
r"""
1337
Flipped Reduced Permutation from iet
1338
1339
EXAMPLES
1340
1341
::
1342
1343
sage: p = iet.Permutation('a b c', 'c b a', flips=['a'], reduced=True)
1344
sage: p.rauzy_move(1)
1345
-a -b c
1346
-a c -b
1347
1348
TESTS::
1349
1350
sage: p = iet.Permutation('a b','b a',flips=['a'])
1351
sage: p == loads(dumps(p))
1352
True
1353
"""
1354
def __cmp__(self, other):
1355
r"""
1356
Defines a natural lexicographic order.
1357
1358
TESTS::
1359
1360
sage: p = iet.Permutation('a b','a b',reduced=True,flips='a')
1361
sage: q = copy(p)
1362
sage: q.alphabet([0,1])
1363
sage: p == q
1364
True
1365
sage: l0 = ['a b','a b']
1366
sage: l1 = ['a b','b a']
1367
sage: l2 = ['b a', 'a b']
1368
sage: p0 = iet.Permutation(l0, reduced=True, flips='ab')
1369
sage: p1 = iet.Permutation(l1, reduced=True, flips='a')
1370
sage: p2 = iet.Permutation(l2, reduced=True, flips='b')
1371
sage: p3 = iet.Permutation(l1, reduced=True, flips='ab')
1372
sage: p4 = iet.Permutation(l2 ,reduced=True,flips='ab')
1373
sage: p0 == p1 or p0 == p2 or p0 == p3 or p0 == p4
1374
False
1375
sage: p0 != p1 and p0 != p2 and p0 != p3 and p0 != p4
1376
True
1377
sage: p1 == p2 and p3 == p4
1378
True
1379
sage: p1 != p2 or p3 != p4
1380
False
1381
sage: p1 == p3 or p1 == p4 or p2 == p3 or p2 == p4
1382
False
1383
sage: p1 != p3 and p1 != p4 and p2 != p3 and p2 != p4
1384
True
1385
sage: p1 = iet.Permutation(l1,reduced=True, flips='a')
1386
sage: p2 = iet.Permutation(l1,reduced=True, flips='b')
1387
sage: p3 = iet.Permutation(l1,reduced=True, flips='ab')
1388
sage: p2 > p3 and p3 < p2
1389
True
1390
sage: p1 > p2 and p2 < p1
1391
True
1392
sage: p1 > p3 and p3 < p1
1393
True
1394
sage: q1 = iet.Permutation(l0, reduced=True, flips='a')
1395
sage: q2 = iet.Permutation(l0, reduced=True, flips='b')
1396
sage: q3 = iet.Permutation(l0, reduced=True, flips='ab')
1397
sage: q2 > q1 and q2 > q3 and q1 < q2 and q3 < q2
1398
True
1399
sage: q1 > q3
1400
True
1401
sage: q3 < q1
1402
True
1403
sage: r = iet.Permutation('a b c','a b c', reduced=True, flips='a')
1404
sage: r > p1 and r > p2 and r > p3
1405
True
1406
sage: p1 < r and p2 < r and p3 < r
1407
True
1408
"""
1409
if type(self) != type(other):
1410
return -1
1411
1412
if len(self) > len(other):
1413
return 1
1414
elif len(self) < len(other):
1415
return -1
1416
1417
n = len(self)
1418
j = 0
1419
while (j < n and
1420
self._twin[1][j] == other._twin[1][j] and
1421
self._flips[1][j] == other._flips[1][j]):
1422
j += 1
1423
1424
if j != n:
1425
if self._twin[1][j] > other._twin[1][j]: return 1
1426
elif self._twin[1][j] < other._twin[1][j]: return -1
1427
else: return self._flips[1][j]
1428
1429
return 0
1430
1431
def list(self, flips=False):
1432
r"""
1433
Returns a list representation of self.
1434
1435
INPUT:
1436
1437
- ``flips`` - boolean (default: False) if True the output contains
1438
2-uple of (label, flip)
1439
1440
EXAMPLES:
1441
1442
::
1443
sage: p = iet.Permutation('a b','b a',reduced=True,flips='b')
1444
sage: p.list(flips=True)
1445
[[('a', 1), ('b', -1)], [('b', -1), ('a', 1)]]
1446
sage: p.list(flips=False)
1447
[['a', 'b'], ['b', 'a']]
1448
sage: p.alphabet([0,1])
1449
sage: p.list(flips=True)
1450
[[(0, 1), (1, -1)], [(1, -1), (0, 1)]]
1451
sage: p.list(flips=False)
1452
[[0, 1], [1, 0]]
1453
1454
One can recover the initial permutation from this list::
1455
1456
sage: p = iet.Permutation('a b','b a',reduced=True,flips='a')
1457
sage: iet.Permutation(p.list(), flips=p.flips(), reduced=True) == p
1458
True
1459
"""
1460
if flips:
1461
a0 = zip(map(self.alphabet().unrank, range(0,len(self))), self._flips[0])
1462
a1 = zip(map(self.alphabet().unrank, self._twin[1]), self._flips[1])
1463
1464
else:
1465
a0 = map(self.alphabet().unrank, range(0,len(self)))
1466
a1 = map(self.alphabet().unrank, self._twin[1])
1467
1468
return [a0,a1]
1469
1470
def _get_loser_to(self, winner) :
1471
r"""
1472
This function return the position of the future loser position.
1473
1474
TESTS:
1475
1476
::
1477
1478
sage: p = iet.GeneralizedPermutation('a b b','c c a', reduced=True, flips='ab')
1479
sage: p._get_loser_to(0)
1480
(0, 2)
1481
sage: p._get_loser_to(1)
1482
(0, 0)
1483
1484
::
1485
1486
sage: p = iet.GeneralizedPermutation('a a','b b c c',reduced=True,flips='a')
1487
sage: p._get_loser_to(0)
1488
(0, 1)
1489
"""
1490
if self._flips[winner][-1] == 1 :
1491
return (1-winner, self._twin[winner][-1]+1)
1492
else :
1493
return (1-winner, self._twin[winner][-1])
1494
1495
def _flip_rauzy_move(self, winner, loser_to):
1496
r"""
1497
Performs a Rauzy move on flips.
1498
1499
TESTS::
1500
1501
sage: p = iet.GeneralizedPermutation('a b b','c c a', reduced=True, flips='ab')
1502
sage: p
1503
-a -b -b
1504
c c -a
1505
sage: p.rauzy_move(1) #indirect doctest
1506
a -b a
1507
c c -b
1508
sage: p.rauzy_move(0) #indirect doctest
1509
a -b a -b
1510
c c
1511
"""
1512
loser = 1 - winner
1513
1514
loser_twin_interval, loser_twin_position = winner, self._twin[loser][-1]
1515
loser_interval_to, loser_position_to = loser_to
1516
1517
flip = self._flips[winner][-1] * self._flips[loser][-1]
1518
1519
self._flips[loser_twin_interval][loser_twin_position] = flip
1520
1521
del self._flips[loser][-1]
1522
self._flips[loser_interval_to].insert(loser_position_to, flip)
1523
1524
def rauzy_diagram(self, **kargs):
1525
r"""
1526
Returns the associated Rauzy diagram.
1527
1528
EXAMPLES::
1529
1530
sage: p = iet.Permutation('a b','b a',reduced=True,flips='a')
1531
sage: r = p.rauzy_diagram()
1532
sage: p in r
1533
True
1534
"""
1535
return FlippedReducedRauzyDiagram(self, **kargs)
1536
1537
class FlippedReducedPermutationLI(
1538
FlippedReducedPermutation,
1539
FlippedPermutationLI,
1540
ReducedPermutationLI):
1541
r"""
1542
Flipped Reduced Permutation from li
1543
1544
EXAMPLES:
1545
1546
Creation using the GeneralizedPermutation function::
1547
1548
sage: p = iet.GeneralizedPermutation('a a b', 'b c c', reduced=True, flips='a')
1549
"""
1550
def _get_loser_to(self, winner) :
1551
r"""
1552
This function return the position of the future loser position.
1553
1554
TESTS:
1555
1556
::
1557
1558
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True,flips='b')
1559
sage: p._get_loser_to(0)
1560
(1, 0)
1561
sage: p._get_loser_to(1)
1562
(1, 1)
1563
1564
::
1565
1566
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True,flips='c')
1567
sage: p._get_loser_to(0)
1568
(1, 1)
1569
sage: p._get_loser_to(1)
1570
(1, 2)
1571
"""
1572
loser = 1 - winner
1573
1574
if self._twin[winner][-1][0] == loser :
1575
if self._flips[winner][-1] == 1 :
1576
return (loser, self._twin[winner][-1][1] + 1)
1577
else :
1578
return (loser, self._twin[winner][-1][1])
1579
else :
1580
if self._flips[winner][-1] == 1 :
1581
return (winner, self._twin[winner][-1][1])
1582
else :
1583
return (winner, self._twin[winner][-1][1] + 1)
1584
1585
def _flip_rauzy_move(self, winner, loser_to):
1586
r"""
1587
Performs a Rauzy move on flips
1588
1589
TESTS::
1590
1591
sage: p = iet.GeneralizedPermutation('a a b','b c c',flips='b',reduced=True)
1592
sage: p
1593
a a -b
1594
-b c c
1595
sage: p.rauzy_move('top') #indirect doctest
1596
a a -b
1597
-c -b -c
1598
"""
1599
loser = 1 - winner
1600
1601
loser_twin_interval, loser_twin_position = self._twin[loser][-1]
1602
loser_interval_to, loser_position_to = loser_to
1603
1604
flip = self._flips[winner][-1] * self._flips[loser][-1]
1605
1606
self._flips[loser_twin_interval][loser_twin_position] = flip
1607
1608
del self._flips[loser][-1]
1609
self._flips[loser_interval_to].insert(loser_position_to, flip)
1610
1611
def list(self, flips=False):
1612
r"""
1613
Returns a list representation of self.
1614
1615
INPUT:
1616
1617
- ``flips`` - boolean (default: False) return the list with flips
1618
1619
EXAMPLES:
1620
1621
::
1622
1623
sage: p = iet.GeneralizedPermutation('a a','b b',reduced=True,flips='a')
1624
sage: p.list(flips=True)
1625
[[('a', -1), ('a', -1)], [('b', 1), ('b', 1)]]
1626
sage: p.list(flips=False)
1627
[['a', 'a'], ['b', 'b']]
1628
1629
sage: p = iet.GeneralizedPermutation('a a b','b c c',reduced=True,flips='abc')
1630
sage: p.list(flips=True)
1631
[[('a', -1), ('a', -1), ('b', -1)], [('b', -1), ('c', -1), ('c', -1)]]
1632
sage: p.list(flips=False)
1633
[['a', 'a', 'b'], ['b', 'c', 'c']]
1634
1635
one can rebuild the permutation from the list::
1636
1637
sage: p = iet.GeneralizedPermutation('a a b','b c c',flips='a',reduced=True)
1638
sage: iet.GeneralizedPermutation(p.list(),flips=p.flips(),reduced=True) == p
1639
True
1640
"""
1641
i_a = 0
1642
l = [[False]*len(self._twin[0]), [False]*len(self._twin[1])]
1643
1644
if flips:
1645
for i in range(2): # False means empty here
1646
for j in range(len(l[i])):
1647
if l[i][j] is False:
1648
l[i][j] = (self._alphabet.unrank(i_a), self._flips[i][j])
1649
l[self._twin[i][j][0]][self._twin[i][j][1]] = l[i][j]
1650
i_a += 1
1651
1652
else:
1653
for i in range(2): # False means empty here
1654
for j in range(len(l[i])):
1655
if l[i][j] is False:
1656
l[i][j] = self._alphabet.unrank(i_a)
1657
l[self._twin[i][j][0]][self._twin[i][j][1]] = l[i][j]
1658
i_a += 1
1659
return l
1660
1661
def __eq__(self, other) :
1662
r"""
1663
TESTS::
1664
1665
sage: a0 = [0,0,1]
1666
sage: a1 = [1,2,2]
1667
sage: p = iet.GeneralizedPermutation(a0,a1,reduced=True,flips=[0])
1668
sage: q = copy(p)
1669
sage: q.alphabet("abc")
1670
sage: p == q
1671
True
1672
sage: b0 = [1,0,0]
1673
sage: b1 = [2,2,1]
1674
sage: r = iet.GeneralizedPermutation(b0,b1,reduced=True,flips=[0])
1675
sage: p == r or q == r
1676
False
1677
"""
1678
return (type(self) == type(other) and
1679
self._twin == other._twin and
1680
self._flips == other._flips)
1681
1682
def __ne__(self, other) :
1683
r"""
1684
TESTS::
1685
1686
sage: a0 = [0,0,1]
1687
sage: a1 = [1,2,2]
1688
sage: p = iet.GeneralizedPermutation(a0,a1,reduced=True,flips=[0])
1689
sage: q = copy(p)
1690
sage: q.alphabet("abc")
1691
sage: p != q
1692
False
1693
sage: b0 = [1,0,0]
1694
sage: b1 = [2,2,1]
1695
sage: r = iet.GeneralizedPermutation(b0,b1,reduced=True,flips=[0])
1696
sage: p != r and q != r
1697
True
1698
"""
1699
return (type(self) != type(other) or
1700
self._twin != other._twin or
1701
self._flips != other._flips)
1702
1703
def rauzy_diagram(self, **kargs):
1704
r"""
1705
Returns the associated Rauzy diagram.
1706
1707
For more explanation and a list of arguments try help(iet.RauzyDiagram)
1708
1709
EXAMPLES::
1710
1711
sage: p = iet.GeneralizedPermutation('a a b','c c b',reduced=True)
1712
sage: r = p.rauzy_diagram()
1713
sage: p in r
1714
True
1715
"""
1716
return FlippedReducedRauzyDiagram(self, **kargs)
1717
1718
class ReducedRauzyDiagram(RauzyDiagram):
1719
r"""
1720
Rauzy diagram of reduced permutations
1721
"""
1722
def _permutation_to_vertex(self, p):
1723
r"""
1724
The necessary data to store the permutation.
1725
1726
TESTS::
1727
1728
1729
sage: p = iet.Permutation('a b c','c b a',reduced=True) #indirect doctest
1730
sage: r = p.rauzy_diagram()
1731
sage: p in r
1732
True
1733
"""
1734
return (tuple(p._twin[0]), tuple(p._twin[1]))
1735
1736
def _set_element(self, data=None):
1737
r"""
1738
Sets self._element with data.
1739
1740
TESTS::
1741
1742
sage: p = iet.Permutation('a b c','c b a',reduced=True)
1743
sage: r = p.rauzy_diagram()
1744
sage: p in r #indirect doctest
1745
True
1746
"""
1747
self._element._twin = [list(data[0]), list(data[1])]
1748
1749
class FlippedReducedRauzyDiagram(FlippedRauzyDiagram, ReducedRauzyDiagram):
1750
r"""
1751
Rauzy diagram of flipped reduced permutations.
1752
"""
1753
def _permutation_to_vertex(self, p):
1754
r"""
1755
TESTS::
1756
1757
sage: p = iet.GeneralizedPermutation('a b b','c c a',flips='a',reduced=True)
1758
sage: r = p.rauzy_diagram()
1759
sage: p in r #indirect doctest
1760
True
1761
"""
1762
return ((tuple(p._twin[0]), tuple(p._twin[1])),
1763
(tuple(p._flips[0]), tuple(p._flips[1])))
1764
1765
def _set_element(self, data=None):
1766
r"""
1767
Sets self._element with data.
1768
TESTS::
1769
1770
sage: r = iet.RauzyDiagram('a b c','c b a',flips='b',reduced=True) #indirect doctest
1771
"""
1772
self._element._twin = [list(data[0][0]), list(data[0][1])]
1773
self._element._flips = [list(data[1][0]), list(data[1][1])]
1774
1775