Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/dynamics/flat_surfaces/strata.py
8817 views
1
r"""
2
Strata of differentials on Riemann surfaces
3
4
The space of Abelian (or quadratic) differentials is stratified by the
5
degrees of the zeroes (and simple poles for quadratic
6
differentials). Each stratum has one, two or three connected
7
components and each is associated to an (extended) Rauzy class. The
8
:meth:`~sage.dynamics.flat_surfaces.strata.AbelianStratum.connected_components`
9
method (only available for Abelian stratum) give the decomposition of
10
a stratum (which corresponds to the SAGE object
11
:class:`~sage.dynamics.flat_surfaces.strata.AbelianStratum`).
12
13
The work for Abelian differentials was done by Maxim Kontsevich and Anton
14
Zorich in [KonZor03]_ and for quadratic differentials by Erwan Lanneau in
15
[Lan08]_. Zorich gave an algorithm to pass from a connected component of a
16
stratum to the associated Rauzy class (for both interval exchange
17
transformations and linear involutions) in [Zor08]_ and is implemented for
18
Abelian stratum at different level (approximately one for each component):
19
20
- for connected stratum :meth:`~ConnectedComponentOfAbelianStratum.representative`
21
- for hyperellitic component :meth:`~HypConnectedComponentOfAbelianStratum.representative`
22
- for non hyperelliptic component, the algorithm is the same as for connected
23
component
24
- for odd component :meth:`~OddConnectedComponentOfAbelianStratum.representative`
25
- for even component :meth:`~EvenConnectedComponentOfAbelianStratum.representative`
26
27
The inverse operation (pass from an interval exchange transformation to
28
the connected component) is partially written in [KonZor03]_ and
29
simply named here
30
:meth:`~sage.dynamics.interval_exchanges.template.PermutationIET.connected_component`.
31
32
All the code here was first available on Mathematica [ZS]_.
33
34
REFERENCES:
35
36
.. [KonZor03] M. Kontsevich, A. Zorich "Connected components of the moduli space
37
of Abelian differentials with prescripebd singularities" Invent. math. 153,
38
631-678 (2003)
39
40
.. [Lan08] E. Lanneau "Connected components of the strata of the moduli spaces
41
of quadratic differentials", Annales sci. de l'ENS, serie 4, fascicule 1,
42
41, 1-56 (2008)
43
44
.. [Zor08] A. Zorich "Explicit Jenkins-Strebel representatives of all strata of
45
Abelian and quadratic differentials", Journal of Modern Dynamics, vol. 2,
46
no 1, 139-185 (2008) (http://www.math.psu.edu/jmd)
47
48
.. [ZS] Anton Zorich, "Generalized Permutation software"
49
(http://perso.univ-rennes1.fr/anton.zorich/Software/software_en.html)
50
51
.. NOTE::
52
53
The quadratic strata are not yet implemented.
54
55
AUTHORS:
56
57
- Vincent Delecroix (2009-09-29): initial version
58
59
60
EXAMPLES:
61
62
Construction of a stratum from a list of singularity degrees::
63
64
sage: a = AbelianStratum(1,1)
65
sage: print a
66
H(1, 1)
67
sage: print a.genus()
68
2
69
sage: print a.nintervals()
70
5
71
72
::
73
74
sage: a = AbelianStratum(4,3,2,1)
75
sage: print a
76
H(4, 3, 2, 1)
77
sage: print a.genus()
78
6
79
sage: print a.nintervals()
80
15
81
82
By convention, the degrees are always written in decreasing order::
83
84
sage: a1 = AbelianStratum(4,3,2,1)
85
sage: a1
86
H(4, 3, 2, 1)
87
sage: a2 = AbelianStratum(2,3,1,4)
88
sage: a2
89
H(4, 3, 2, 1)
90
sage: a1 == a2
91
True
92
93
It is also possible to consider stratum with an incoming or an
94
outgoing separatrix marked (the aim of this consideration is to
95
attach a specified degree at the left or the right of the associated
96
interval exchange transformation)::
97
98
sage: a_out = AbelianStratum(1, 1, marked_separatrix='out')
99
sage: a_out
100
H^out(1, 1)
101
sage: a_in = AbelianStratum(1, 1, marked_separatrix='in')
102
sage: a_in
103
H^in(1, 1)
104
sage: a_out == a_in
105
False
106
107
Get a list of strata with constraints on genus or on the number of intervals
108
of a representative::
109
110
sage: for a in AbelianStrata(genus=3):
111
....: print a
112
H(4)
113
H(3, 1)
114
H(2, 2)
115
H(2, 1, 1)
116
H(1, 1, 1, 1)
117
118
::
119
120
sage: for a in AbelianStrata(nintervals=5):
121
....: print a
122
H^out(0, 2)
123
H^out(2, 0)
124
H^out(1, 1)
125
H^out(0, 0, 0, 0)
126
127
::
128
129
sage: for a in AbelianStrata(genus=2, nintervals=5):
130
....: print a
131
H^out(0, 2)
132
H^out(2, 0)
133
H^out(1, 1)
134
135
Obtains the connected components of a stratum::
136
137
sage: a = AbelianStratum(0)
138
sage: print a.connected_components()
139
[H_hyp(0)]
140
141
::
142
143
sage: a = AbelianStratum(6)
144
sage: cc = a.connected_components()
145
sage: print cc
146
[H_hyp(6), H_odd(6), H_even(6)]
147
sage: for c in cc:
148
....: print c, "\n", c.representative(alphabet=range(1,9))
149
H_hyp(6)
150
1 2 3 4 5 6 7 8
151
8 7 6 5 4 3 2 1
152
H_odd(6)
153
1 2 3 4 5 6 7 8
154
4 3 6 5 8 7 2 1
155
H_even(6)
156
1 2 3 4 5 6 7 8
157
6 5 4 3 8 7 2 1
158
159
::
160
161
sage: a = AbelianStratum(1, 1, 1, 1)
162
sage: print a.connected_components()
163
[H_c(1, 1, 1, 1)]
164
sage: c = a.connected_components()[0]
165
sage: print c.representative(alphabet="abcdefghi")
166
a b c d e f g h i
167
e d c f i h g b a
168
169
The zero attached on the left of the associated Abelian permutation
170
corresponds to the first singularity degree::
171
172
sage: a = AbelianStratum(4, 2, marked_separatrix='out')
173
sage: b = AbelianStratum(2, 4, marked_separatrix='out')
174
sage: print a == b
175
False
176
sage: print a, ":", a.connected_components()
177
H^out(4, 2) : [H_odd^out(4, 2), H_even^out(4, 2)]
178
sage: print b, ":", b.connected_components()
179
H^out(2, 4) : [H_odd^out(2, 4), H_even^out(2, 4)]
180
sage: a_odd, a_even = a.connected_components()
181
sage: b_odd, b_even = b.connected_components()
182
183
The representatives are hence different::
184
185
sage: print a_odd.representative(alphabet=range(1,10))
186
1 2 3 4 5 6 7 8 9
187
4 3 6 5 7 9 8 2 1
188
sage: print b_odd.representative(alphabet=range(1,10))
189
1 2 3 4 5 6 7 8 9
190
4 3 5 7 6 9 8 2 1
191
192
::
193
194
sage: print a_even.representative(alphabet=range(1,10))
195
1 2 3 4 5 6 7 8 9
196
6 5 4 3 7 9 8 2 1
197
sage: print b_even.representative(alphabet=range(1,10))
198
1 2 3 4 5 6 7 8 9
199
7 6 5 4 3 9 8 2 1
200
201
You can retrieve the decomposition of the irreducible Abelian permutations into
202
Rauzy diagrams from the classification of strata::
203
204
sage: a = AbelianStrata(nintervals=4)
205
sage: l = sum([stratum.connected_components() for stratum in a], [])
206
sage: n = map(lambda x: x.rauzy_diagram().cardinality(), l)
207
sage: for c,i in zip(l,n):
208
....: print c, ":", i
209
H_hyp^out(2) : 7
210
H_hyp^out(0, 0, 0) : 6
211
sage: print sum(n)
212
13
213
214
::
215
216
sage: a = AbelianStrata(nintervals=5)
217
sage: l = sum([stratum.connected_components() for stratum in a], [])
218
sage: n = map(lambda x: x.rauzy_diagram().cardinality(), l)
219
sage: for c,i in zip(l,n):
220
....: print c, ":", i
221
H_hyp^out(0, 2) : 11
222
H_hyp^out(2, 0) : 35
223
H_hyp^out(1, 1) : 15
224
H_hyp^out(0, 0, 0, 0) : 10
225
sage: print sum(n)
226
71
227
228
::
229
230
sage: a = AbelianStrata(nintervals=6)
231
sage: l = sum([stratum.connected_components() for stratum in a], [])
232
sage: n = map(lambda x: x.rauzy_diagram().cardinality(), l)
233
sage: for c,i in zip(l,n):
234
....: print c, ":", i
235
H_hyp^out(4) : 31
236
H_odd^out(4) : 134
237
H_hyp^out(0, 2, 0) : 66
238
H_hyp^out(2, 0, 0) : 105
239
H_hyp^out(0, 1, 1) : 20
240
H_hyp^out(1, 1, 0) : 90
241
H_hyp^out(0, 0, 0, 0, 0) : 15
242
sage: print sum(n)
243
461
244
"""
245
#*****************************************************************************
246
# Copyright (C) 2009 Vincent Delecroix <[email protected]>
247
#
248
# Distributed under the terms of the GNU General Public License (GPL)
249
# http://www.gnu.org/licenses/
250
#*****************************************************************************
251
252
from sage.structure.sage_object import SageObject
253
254
from sage.combinat.combinat import CombinatorialClass
255
from sage.combinat.combinat import InfiniteAbstractCombinatorialClass
256
from sage.combinat.partition import Partitions
257
258
from sage.rings.integer import Integer
259
from sage.rings.rational import Rational
260
261
262
def AbelianStrata(genus=None, nintervals=None, marked_separatrix=None):
263
r"""
264
Abelian strata.
265
266
INPUT:
267
268
- ``genus`` - a non negative integer or ``None``
269
270
- ``nintervals`` - a non negative integer or ``None``
271
272
- ``marked_separatrix`` - 'no' (for no marking), 'in' (for marking an
273
incoming separatrix) or 'out' (for marking an outgoing separatrix)
274
275
EXAMPLES:
276
277
Abelian strata with a given genus::
278
279
sage: for s in AbelianStrata(genus=1): print s
280
H(0)
281
282
::
283
284
sage: for s in AbelianStrata(genus=2): print s
285
H(2)
286
H(1, 1)
287
288
::
289
290
sage: for s in AbelianStrata(genus=3): print s
291
H(4)
292
H(3, 1)
293
H(2, 2)
294
H(2, 1, 1)
295
H(1, 1, 1, 1)
296
297
::
298
299
sage: for s in AbelianStrata(genus=4): print s
300
H(6)
301
H(5, 1)
302
H(4, 2)
303
H(4, 1, 1)
304
H(3, 3)
305
H(3, 2, 1)
306
H(3, 1, 1, 1)
307
H(2, 2, 2)
308
H(2, 2, 1, 1)
309
H(2, 1, 1, 1, 1)
310
H(1, 1, 1, 1, 1, 1)
311
312
Abelian strata with a given number of intervals::
313
314
sage: for s in AbelianStrata(nintervals=2): print s
315
H^out(0)
316
317
::
318
319
sage: for s in AbelianStrata(nintervals=3): print s
320
H^out(0, 0)
321
322
::
323
324
sage: for s in AbelianStrata(nintervals=4): print s
325
H^out(2)
326
H^out(0, 0, 0)
327
328
::
329
330
sage: for s in AbelianStrata(nintervals=5): print s
331
H^out(0, 2)
332
H^out(2, 0)
333
H^out(1, 1)
334
H^out(0, 0, 0, 0)
335
336
Abelian strata with both constraints::
337
338
sage: for s in AbelianStrata(genus=2, nintervals=4): print s
339
H^out(2)
340
341
::
342
343
sage: for s in AbelianStrata(genus=5, nintervals=12): print s
344
H^out(8, 0, 0)
345
H^out(0, 8, 0)
346
H^out(0, 7, 1)
347
H^out(1, 7, 0)
348
H^out(7, 1, 0)
349
H^out(0, 6, 2)
350
H^out(2, 6, 0)
351
H^out(6, 2, 0)
352
H^out(1, 6, 1)
353
H^out(6, 1, 1)
354
H^out(0, 5, 3)
355
H^out(3, 5, 0)
356
H^out(5, 3, 0)
357
H^out(1, 5, 2)
358
H^out(2, 5, 1)
359
H^out(5, 2, 1)
360
H^out(0, 4, 4)
361
H^out(4, 4, 0)
362
H^out(1, 4, 3)
363
H^out(3, 4, 1)
364
H^out(4, 3, 1)
365
H^out(2, 4, 2)
366
H^out(4, 2, 2)
367
H^out(2, 3, 3)
368
H^out(3, 3, 2)
369
"""
370
if genus is None:
371
if nintervals is None:
372
return AbelianStrata_all()
373
else:
374
return AbelianStrata_d(
375
nintervals=nintervals,
376
marked_separatrix=marked_separatrix)
377
else:
378
if nintervals is None:
379
return AbelianStrata_g(
380
genus=genus,
381
marked_separatrix=marked_separatrix)
382
else:
383
return AbelianStrata_gd(
384
genus=genus,
385
nintervals=nintervals,
386
marked_separatrix=marked_separatrix)
387
388
389
class AbelianStrata_g(CombinatorialClass):
390
r"""
391
Stratas of genus g surfaces.
392
393
INPUT:
394
395
- ``genus`` - a non negative integer
396
397
- ``marked_separatrix`` - 'no', 'out' or 'in'
398
"""
399
def __init__(self, genus=None, marked_separatrix=None):
400
r"""
401
TESTS::
402
403
sage: s = AbelianStrata(genus=3)
404
sage: s == loads(dumps(s))
405
True
406
407
sage: AbelianStrata(genus=-3)
408
Traceback (most recent call last):
409
...
410
ValueError: genus must be positive
411
412
sage: AbelianStrata(genus=3, marked_separatrix='yes')
413
Traceback (most recent call last):
414
...
415
ValueError: marked_separatrix must be no, out or in
416
"""
417
genus = Integer(genus)
418
419
if not(genus >= 0):
420
raise ValueError('genus must be positive')
421
422
if marked_separatrix is None:
423
marked_separatrix = 'no'
424
if not marked_separatrix in ['no', 'out', 'in']:
425
raise ValueError("marked_separatrix must be no, out or in")
426
self._marked_separatrix = marked_separatrix
427
428
self._genus = genus
429
430
def _repr_(self):
431
r"""
432
TESTS::
433
434
sage: repr(AbelianStrata(genus=3)) #indirect doctest
435
'Abelian strata of genus 3 surfaces'
436
"""
437
if self._marked_separatrix == 'no':
438
return "Abelian strata of genus %d surfaces" % (self._genus)
439
elif self._marked_separatrix == 'in':
440
return "Abelian strata of genus %d surfaces and a marked incoming separatrix" % (self._genus)
441
else:
442
return "Abelian strata of genus %d surfaces and a marked outgoing separatrix" % (self._genus)
443
444
def __iter__(self):
445
r"""
446
TESTS::
447
448
sage: list(AbelianStrata(genus=1))
449
[H(0)]
450
"""
451
if self._genus == 0:
452
pass
453
elif self._genus == 1:
454
yield AbelianStratum(0, marked_separatrix=self._marked_separatrix)
455
else:
456
if self._marked_separatrix == 'no':
457
for p in Partitions(2*self._genus-2):
458
yield AbelianStratum(p)
459
else:
460
for p in Partitions(2*self._genus-2):
461
l = list(p)
462
for t in set(l):
463
i = l.index(t)
464
yield AbelianStratum([t] + l[:i] + l[i+1:],
465
marked_separatrix=self._marked_separatrix)
466
467
468
class AbelianStrata_d(CombinatorialClass):
469
r"""
470
Strata with constraint number of intervals.
471
472
INPUT:
473
474
- ``nintervals`` - an integer greater than 1
475
476
- ``marked_separatrix`` - 'no', 'out' or 'in'
477
"""
478
def __init__(self, nintervals=None, marked_separatrix=None):
479
r"""
480
TESTS::
481
482
sage: s = AbelianStrata(nintervals=10)
483
sage: s == loads(dumps(s))
484
True
485
486
sage: AbelianStrata(nintervals=1)
487
Traceback (most recent call last):
488
...
489
ValueError: number of intervals must be at least 2
490
491
sage: AbelianStrata(nintervals=4, marked_separatrix='maybe')
492
Traceback (most recent call last):
493
...
494
ValueError: marked_separatrix must be no, out or in
495
"""
496
nintervals = Integer(nintervals)
497
498
if not(nintervals > 1):
499
raise ValueError("number of intervals must be at least 2")
500
501
self._nintervals = nintervals
502
503
if marked_separatrix is None:
504
marked_separatrix = 'out'
505
if not marked_separatrix in ['no', 'out', 'in']:
506
raise ValueError("marked_separatrix must be no, out or in")
507
self._marked_separatrix = marked_separatrix
508
509
def _repr_(self):
510
r"""
511
TESTS::
512
513
sage: repr(AbelianStrata(nintervals=2,marked_separatrix='no')) #indirect doctest
514
'Abelian strata with 2 intervals IET'
515
"""
516
if self._marked_separatrix == 'no':
517
return "Abelian strata with %d intervals IET" % (self._nintervals)
518
elif self._marked_separatrix == 'in':
519
return "Abelian strata with %d intervals IET and a marked incoming separatrix" % (self._nintervals)
520
else:
521
return "Abelian strata with %d intervals IET and a marked outgoing separatrix" % (self._nintervals)
522
523
def __iter__(self):
524
r"""
525
TESTS::
526
527
sage: for a in AbelianStrata(nintervals=4): print a
528
H^out(2)
529
H^out(0, 0, 0)
530
"""
531
n = self._nintervals
532
for s in range(1+n % 2, n, 2):
533
for p in Partitions(n-1, length=s):
534
l = [k-1 for k in p]
535
if self._marked_separatrix == 'no':
536
yield AbelianStratum(l, marked_separatrix='no')
537
else:
538
for t in set(l):
539
i = l.index(t)
540
yield AbelianStratum([t] + l[:i] + l[i+1:],
541
marked_separatrix=self._marked_separatrix)
542
543
544
class AbelianStrata_gd(CombinatorialClass):
545
r"""
546
Abelian strata of prescribed genus and number of intervals.
547
548
INPUT:
549
550
- ``genus`` - integer: the genus of the surfaces
551
552
- ``nintervals`` - integer: the number of intervals
553
554
- ``marked_separatrix`` - 'no', 'in' or 'out'
555
"""
556
def __init__(self, genus=None, nintervals=None, marked_separatrix=None):
557
r"""
558
TESTS::
559
560
sage: s = AbelianStrata(genus=4,nintervals=10)
561
sage: s == loads(dumps(s))
562
True
563
564
sage: AbelianStrata(genus=-1)
565
Traceback (most recent call last):
566
...
567
ValueError: genus must be positive
568
569
sage: AbelianStrata(genus=1, nintervals=1)
570
Traceback (most recent call last):
571
...
572
ValueError: number of intervals must be at least 2
573
574
sage: AbelianStrata(genus=1, marked_separatrix='so')
575
Traceback (most recent call last):
576
...
577
ValueError: marked_separatrix must be no, out or in
578
"""
579
genus = Integer(genus)
580
581
if not(genus >= 0):
582
raise ValueError("genus must be positive")
583
self._genus = genus
584
585
nintervals = Integer(nintervals)
586
if not(nintervals > 1):
587
raise ValueError("number of intervals must be at least 2")
588
self._nintervals = nintervals
589
590
if marked_separatrix is None:
591
marked_separatrix = 'out'
592
if not marked_separatrix in ['no', 'out', 'in']:
593
raise ValueError("marked_separatrix must be no, out or in")
594
595
self._marked_separatrix = marked_separatrix
596
597
def __repr__(self):
598
r"""
599
TESTS::
600
601
sage: a = AbelianStrata(genus=2,nintervals=4,marked_separatrix='no')
602
sage: repr(a) #indirect doctest
603
'Abelian strata of genus 2 surfaces and 4 intervals'
604
"""
605
if self._marked_separatrix == 'no':
606
return "Abelian strata of genus %d surfaces and %d intervals" % (self._genus, self._nintervals)
607
elif self._marked_separatrix == 'in':
608
return "Abelian strata of genus %d surfaces and %d intervals and a marked incoming ihorizontal separatrix" % (self._genus, self._nintervals)
609
else:
610
return "Abelian strata of genus %d surfaces and %d intervals and a marked outgoing horizontal separatrix" % (self._genus, self._nintervals)
611
612
def __iter__(self):
613
r"""
614
TESTS::
615
616
sage: list(AbelianStrata(genus=2,nintervals=4))
617
[H^out(2)]
618
"""
619
if self._genus == 0:
620
pass
621
elif self._genus == 1:
622
if self._nintervals >= 2:
623
yield AbelianStratum([0]*(self._nintervals-1),
624
marked_separatrix='out')
625
else:
626
s = self._nintervals - 2*self._genus + 1
627
for p in Partitions(2*self._genus - 2 + s, length=s):
628
l = [k-1 for k in p]
629
for t in set(l):
630
i = l.index(t)
631
yield AbelianStratum([t] + l[:i] +
632
l[i+1:], marked_separatrix='out')
633
634
635
class AbelianStrata_all(InfiniteAbstractCombinatorialClass):
636
r"""
637
Abelian strata.
638
"""
639
def __repr__(self):
640
r"""
641
TESTS::
642
643
sage: repr(AbelianStrata()) #indirect doctest
644
'Abelian strata'
645
"""
646
return "Abelian strata"
647
648
def _infinite_cclass_slice(self, g):
649
r"""
650
TESTS::
651
652
sage: AbelianStrata()[0]
653
H(0)
654
sage: AbelianStrata()[1]
655
H(2)
656
sage: AbelianStrata()[2]
657
H(1, 1)
658
659
::
660
661
sage: a = AbelianStrata()
662
sage: a._infinite_cclass_slice(0) == AbelianStrata(genus=0)
663
True
664
sage: a._infinite_cclass_slice(10) == AbelianStrata(genus=10)
665
True
666
"""
667
return AbelianStrata_g(g)
668
669
670
class AbelianStratum(SageObject):
671
"""
672
Stratum of Abelian differentials.
673
674
A stratum with a marked outgoing separatrix corresponds to Rauzy diagram
675
with left induction, a stratum with marked incoming separatrix correspond
676
to Rauzy diagram with right induction.
677
If there is no marked separatrix, the associated Rauzy diagram is the
678
extended Rauzy diagram (consideration of the
679
:meth:`sage.dynamics.interval_exchanges.template.Permutation.symmetric`
680
operation of Boissy-Lanneau).
681
682
When you want to specify a marked separatrix, the degree on which it is is
683
the first term of your degrees list.
684
685
INPUT:
686
687
- ``marked_separatrix`` - ``None`` (default) or 'in' (for incoming
688
separatrix) or 'out' (for outgoing separatrix).
689
690
EXAMPLES:
691
692
Creation of an Abelian stratum and get its connected components::
693
694
sage: a = AbelianStratum(2, 2)
695
sage: print a
696
H(2, 2)
697
sage: a.connected_components()
698
[H_hyp(2, 2), H_odd(2, 2)]
699
700
Specification of marked separatrix:
701
702
::
703
704
sage: a = AbelianStratum(4,2,marked_separatrix='in')
705
sage: print a
706
H^in(4, 2)
707
sage: b = AbelianStratum(2,4,marked_separatrix='in')
708
sage: print b
709
H^in(2, 4)
710
sage: a == b
711
False
712
713
::
714
715
sage: a = AbelianStratum(4,2,marked_separatrix='out')
716
sage: print a
717
H^out(4, 2)
718
sage: b = AbelianStratum(2,4,marked_separatrix='out')
719
sage: print b
720
H^out(2, 4)
721
sage: a == b
722
False
723
724
Get a representative of a connected component::
725
726
sage: a = AbelianStratum(2,2)
727
sage: a_hyp, a_odd = a.connected_components()
728
sage: print a_hyp.representative()
729
1 2 3 4 5 6 7
730
7 6 5 4 3 2 1
731
sage: print a_odd.representative()
732
0 1 2 3 4 5 6
733
3 2 4 6 5 1 0
734
735
You can choose the alphabet::
736
737
sage: print a_odd.representative(alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ")
738
A B C D E F G
739
D C E G F B A
740
741
By default, you get a reduced permutation, but you can specify
742
that you want a labelled one::
743
744
sage: p_reduced = a_odd.representative()
745
sage: p_labelled = a_odd.representative(reduced=False)
746
"""
747
def __init__(self, *l, **d):
748
"""
749
TESTS::
750
751
sage: s = AbelianStratum(0)
752
sage: s == loads(dumps(s))
753
True
754
sage: s = AbelianStratum(1,1,1,1)
755
sage: s == loads(dumps(s))
756
True
757
758
sage: AbelianStratum('no','way')
759
Traceback (most recent call last):
760
...
761
ValueError: input must be a list of integers
762
763
sage: AbelianStratum([1,1,1,1], marked_separatrix='full')
764
Traceback (most recent call last):
765
...
766
ValueError: marked_separatrix must be one of 'no', 'in', 'out'
767
"""
768
if l == ():
769
pass
770
771
elif hasattr(l[0], "__iter__") and len(l) == 1:
772
l = l[0]
773
774
if not all(isinstance(i, (Integer, int)) for i in l):
775
raise ValueError("input must be a list of integers")
776
777
if 'marked_separatrix' in d:
778
m = d['marked_separatrix']
779
780
if m is None:
781
m = 'no'
782
783
if (m != 'no' and m != 'in' and m != 'out'):
784
raise ValueError("marked_separatrix must be one of 'no', "
785
"'in', 'out'")
786
self._marked_separatrix = m
787
788
else: # default value
789
self._marked_separatrix = 'no'
790
791
self._zeroes = list(l)
792
793
if not self._marked_separatrix is 'no':
794
self._zeroes[1:] = sorted(self._zeroes[1:], reverse=True)
795
else:
796
self._zeroes.sort(reverse=True)
797
798
self._genus = sum(l)/2 + 1
799
800
self._genus = Integer(self._genus)
801
802
zeroes = filter(lambda x: x > 0, self._zeroes)
803
zeroes.sort()
804
805
if self._genus == 1:
806
self._cc = (HypCCA,)
807
808
elif self._genus == 2:
809
self._cc = (HypCCA,)
810
811
elif self._genus == 3:
812
if zeroes == [2, 2] or zeroes == [4]:
813
self._cc = (HypCCA, OddCCA)
814
else:
815
self._cc = (CCA,)
816
817
elif len(zeroes) == 1:
818
# just one zeros [2g-2]
819
self._cc = (HypCCA, OddCCA, EvenCCA)
820
821
elif zeroes == [self._genus-1, self._genus-1]:
822
# two similar zeros [g-1, g-1]
823
if self._genus % 2 == 0:
824
self._cc = (HypCCA, NonHypCCA)
825
826
else:
827
self._cc = (HypCCA, OddCCA, EvenCCA)
828
829
elif len(filter(lambda x: x % 2, zeroes)) == 0:
830
# even zeroes [2 l_1, 2 l_2, ..., 2 l_n]
831
self._cc = (OddCCA, EvenCCA)
832
833
else:
834
self._cc = (CCA, )
835
836
def _repr_(self):
837
"""
838
TESTS::
839
840
sage: repr(AbelianStratum(1,1)) #indirect doctest
841
'H(1, 1)'
842
"""
843
if self._marked_separatrix == 'no':
844
return "H(" + str(self._zeroes)[1:-1] + ")"
845
else:
846
return ("H" +
847
'^' + self._marked_separatrix +
848
"(" + str(self._zeroes)[1:-1] + ")")
849
850
def __str__(self):
851
r"""
852
TESTS::
853
854
sage: str(AbelianStratum(1,1))
855
'H(1, 1)'
856
"""
857
if self._marked_separatrix == 'no':
858
return "H(" + str(self._zeroes)[1:-1] + ")"
859
else:
860
return ("H" +
861
'^' + self._marked_separatrix +
862
"(" + str(self._zeroes)[1:-1] + ")")
863
864
def __eq__(self, other):
865
r"""
866
TESTS:
867
868
sage: a = AbelianStratum(1,3)
869
sage: b = AbelianStratum(3,1)
870
sage: c = AbelianStratum(1,3,marked_separatrix='out')
871
sage: d = AbelianStratum(3,1,marked_separatrix='out')
872
sage: e = AbelianStratum(1,3,marked_separatrix='in')
873
sage: f = AbelianStratum(3,1,marked_separatrix='in')
874
sage: a == b # no difference for unmarked
875
True
876
sage: c == d # difference for out mark
877
False
878
sage: e == f # difference for in mark
879
False
880
sage: a == c # difference between no mark and out mark
881
False
882
sage: a == e # difference between no mark and in mark
883
False
884
sage: c == e # difference between out mark adn in mark
885
False
886
887
sage: a == False
888
Traceback (most recent call last):
889
...
890
TypeError: the right member must be a stratum
891
"""
892
if type(self) != type(other):
893
raise TypeError("the right member must be a stratum")
894
895
return (self._marked_separatrix == other._marked_separatrix and
896
self._zeroes == other._zeroes)
897
898
def __ne__(self, other):
899
r"""
900
TESTS::
901
902
sage: a = AbelianStratum(1,3)
903
sage: b = AbelianStratum(3,1)
904
sage: c = AbelianStratum(1,3,marked_separatrix='out')
905
sage: d = AbelianStratum(3,1,marked_separatrix='out')
906
sage: e = AbelianStratum(1,3,marked_separatrix='in')
907
sage: f = AbelianStratum(3,1,marked_separatrix='in')
908
sage: a != b # no difference for unmarked
909
False
910
sage: c != d # difference for out mark
911
True
912
sage: e != f # difference for in mark
913
True
914
sage: a != c # difference between no mark and out mark
915
True
916
sage: a != e # difference between no mark and in mark
917
True
918
sage: c != e # difference between out mark adn in mark
919
True
920
sage: a != False
921
Traceback (most recent call last):
922
...
923
TypeError: the right member must be a stratum
924
"""
925
if type(self) != type(other):
926
raise TypeError("the right member must be a stratum")
927
928
return (self._marked_separatrix != other._marked_separatrix or
929
self._zeroes != other._zeroes)
930
931
def __cmp__(self, other):
932
r"""
933
The order is given by the natural:
934
935
self < other iff adherance(self) c adherance(other)
936
937
TESTS::
938
939
sage: a3 = AbelianStratum(3,2,1)
940
sage: a3_out = AbelianStratum(3,2,1,marked_separatrix='out')
941
sage: a3_in = AbelianStratum(3,2,1,marked_separatrix='in')
942
sage: a3 == a3_out
943
False
944
sage: a3 == a3_in
945
False
946
sage: a3_out == a3_in
947
False
948
"""
949
if (type(self) != type(other) or
950
self._marked_separatrix != other._marked_separatrix):
951
raise TypeError("the other must be a stratum with same marking")
952
953
if self._zeroes < other._zeroes:
954
return 1
955
elif self._zeroes > other._zeroes:
956
return -1
957
return 0
958
959
def connected_components(self):
960
"""
961
Lists the connected components of the Stratum.
962
963
OUTPUT:
964
965
list -- a list of connected components of stratum
966
967
EXAMPLES:
968
969
::
970
971
sage: AbelianStratum(0).connected_components()
972
[H_hyp(0)]
973
974
::
975
976
sage: AbelianStratum(2).connected_components()
977
[H_hyp(2)]
978
sage: AbelianStratum(1,1).connected_components()
979
[H_hyp(1, 1)]
980
981
::
982
983
sage: AbelianStratum(4).connected_components()
984
[H_hyp(4), H_odd(4)]
985
sage: AbelianStratum(3,1).connected_components()
986
[H_c(3, 1)]
987
sage: AbelianStratum(2,2).connected_components()
988
[H_hyp(2, 2), H_odd(2, 2)]
989
sage: AbelianStratum(2,1,1).connected_components()
990
[H_c(2, 1, 1)]
991
sage: AbelianStratum(1,1,1,1).connected_components()
992
[H_c(1, 1, 1, 1)]
993
"""
994
return map(lambda x: x(self), self._cc)
995
996
def is_connected(self):
997
r"""
998
Tests if the strata is connected.
999
1000
OUTPUT:
1001
1002
boolean -- ``True`` if it is connected else ``False``
1003
1004
EXAMPLES:
1005
1006
::
1007
1008
sage: AbelianStratum(2).is_connected()
1009
True
1010
sage: AbelianStratum(2).connected_components()
1011
[H_hyp(2)]
1012
1013
::
1014
1015
sage: AbelianStratum(2,2).is_connected()
1016
False
1017
sage: AbelianStratum(2,2).connected_components()
1018
[H_hyp(2, 2), H_odd(2, 2)]
1019
"""
1020
return len(self._cc) == 1
1021
1022
def genus(self):
1023
r"""
1024
Returns the genus of the stratum.
1025
1026
OUTPUT:
1027
1028
integer -- the genus
1029
1030
EXAMPLES:
1031
1032
::
1033
1034
sage: AbelianStratum(0).genus()
1035
1
1036
sage: AbelianStratum(1,1).genus()
1037
2
1038
sage: AbelianStratum(3,2,1).genus()
1039
4
1040
"""
1041
return self._genus
1042
1043
def nintervals(self):
1044
r"""
1045
Returns the number of intervals of any iet of the strata.
1046
1047
OUTPUT:
1048
1049
integer -- the number of intervals for any associated iet
1050
1051
EXAMPLES:
1052
1053
::
1054
1055
sage: AbelianStratum(0).nintervals()
1056
2
1057
sage: AbelianStratum(0,0).nintervals()
1058
3
1059
sage: AbelianStratum(2).nintervals()
1060
4
1061
sage: AbelianStratum(1,1).nintervals()
1062
5
1063
"""
1064
return 2 * self.genus() + len(self._zeroes) - 1
1065
1066
1067
class ConnectedComponentOfAbelianStratum(SageObject):
1068
r"""
1069
Connected component of Abelian stratum.
1070
1071
.. warning::
1072
1073
Internal class! Do not use directly!
1074
1075
TESTS:
1076
1077
Tests for outgoing marked separatrices::
1078
1079
sage: a = AbelianStratum(4,2,0,marked_separatrix='out')
1080
sage: a_odd, a_even = a.connected_components()
1081
sage: a_odd.representative().attached_out_degree()
1082
4
1083
sage: a_even.representative().attached_out_degree()
1084
4
1085
1086
::
1087
1088
sage: a = AbelianStratum(2,4,0,marked_separatrix='out')
1089
sage: a_odd, a_even = a.connected_components()
1090
sage: a_odd.representative().attached_out_degree()
1091
2
1092
sage: a_even.representative().attached_out_degree()
1093
2
1094
1095
::
1096
1097
sage: a = AbelianStratum(0,4,2,marked_separatrix='out')
1098
sage: a_odd, a_even = a.connected_components()
1099
sage: a_odd.representative().attached_out_degree()
1100
0
1101
sage: a_even.representative().attached_out_degree()
1102
0
1103
1104
::
1105
1106
sage: a = AbelianStratum(3,2,1,marked_separatrix='out')
1107
sage: a_c = a.connected_components()[0]
1108
sage: a_c.representative().attached_out_degree()
1109
3
1110
1111
::
1112
1113
sage: a = AbelianStratum(2,3,1,marked_separatrix='out')
1114
sage: a_c = a.connected_components()[0]
1115
sage: a_c.representative().attached_out_degree()
1116
2
1117
1118
::
1119
1120
sage: a = AbelianStratum(1,3,2,marked_separatrix='out')
1121
sage: a_c = a.connected_components()[0]
1122
sage: a_c.representative().attached_out_degree()
1123
1
1124
1125
Tests for incoming separatrices::
1126
1127
sage: a = AbelianStratum(4,2,0,marked_separatrix='in')
1128
sage: a_odd, a_even = a.connected_components()
1129
sage: a_odd.representative().attached_in_degree()
1130
4
1131
sage: a_even.representative().attached_in_degree()
1132
4
1133
1134
::
1135
1136
sage: a = AbelianStratum(2,4,0,marked_separatrix='in')
1137
sage: a_odd, a_even = a.connected_components()
1138
sage: a_odd.representative().attached_in_degree()
1139
2
1140
sage: a_even.representative().attached_in_degree()
1141
2
1142
1143
::
1144
1145
sage: a = AbelianStratum(0,4,2,marked_separatrix='in')
1146
sage: a_odd, a_even = a.connected_components()
1147
sage: a_odd.representative().attached_in_degree()
1148
0
1149
sage: a_even.representative().attached_in_degree()
1150
0
1151
1152
::
1153
1154
sage: a = AbelianStratum(3,2,1,marked_separatrix='in')
1155
sage: a_c = a.connected_components()[0]
1156
sage: a_c.representative().attached_in_degree()
1157
3
1158
1159
::
1160
1161
sage: a = AbelianStratum(2,3,1,marked_separatrix='in')
1162
sage: a_c = a.connected_components()[0]
1163
sage: a_c.representative().attached_in_degree()
1164
2
1165
1166
::
1167
1168
sage: a = AbelianStratum(1,3,2,marked_separatrix='in')
1169
sage: a_c = a.connected_components()[0]
1170
sage: a_c.representative().attached_in_degree()
1171
1
1172
"""
1173
_name = 'c'
1174
1175
def __init__(self, parent):
1176
r"""
1177
TESTS::
1178
1179
sage: a = AbelianStratum([1]*10).connected_components()[0]
1180
sage: a == loads(dumps(a))
1181
True
1182
"""
1183
self._parent = parent
1184
1185
def _repr_(self):
1186
r"""
1187
TESTS::
1188
1189
sage: a = AbelianStratum([1]*8).connected_components()[0]
1190
sage: repr(a) #indirect doctest
1191
'H_c(1, 1, 1, 1, 1, 1, 1, 1)'
1192
"""
1193
if self._parent._marked_separatrix == 'no':
1194
return ("H" +
1195
"_" + self._name +
1196
"(" + str(self._parent._zeroes)[1:-1] + ")")
1197
1198
else:
1199
return ("H" +
1200
"_" + self._name +
1201
"^" + self._parent._marked_separatrix +
1202
"(" + str(self._parent._zeroes)[1:-1] + ")")
1203
1204
def __str__(self):
1205
r"""
1206
TESTS::
1207
1208
sage: str(AbelianStratum([1]*8))
1209
'H(1, 1, 1, 1, 1, 1, 1, 1)'
1210
"""
1211
if self._parent._marked_separatrix == 'no':
1212
return ("H" +
1213
"_" + self._name +
1214
"(" + str(self._parent._zeroes)[1:-1] + ")")
1215
1216
else:
1217
return ("H" +
1218
"_" + self._name +
1219
"^" + self._parent._marked_separatrix +
1220
"(" + str(self._parent._zeroes)[1:-1] + ")")
1221
1222
def parent(self):
1223
r"""
1224
The stratum of this component
1225
1226
OUTPUT:
1227
1228
stratum - the stratum where this component leaves
1229
1230
EXAMPLES::
1231
1232
sage: p = iet.Permutation('a b','b a')
1233
sage: c = p.connected_component()
1234
sage: c.parent()
1235
H(0)
1236
"""
1237
return self._parent
1238
1239
def representative(self, reduced=True, alphabet=None):
1240
r"""
1241
Returns the Zorich representative of this connected component.
1242
1243
Zorich constructs explicitely interval exchange
1244
transformations for each stratum in [Zor08]_.
1245
1246
INPUT:
1247
1248
- ``reduced`` - boolean (default: ``True``): whether you
1249
obtain a reduced or labelled permutation
1250
1251
- ``alphabet`` - an alphabet or ``None``: whether you want to
1252
specify an alphabet for your permutation
1253
1254
OUTPUT:
1255
1256
permutation -- a permutation which lives in this component
1257
1258
EXAMPLES:
1259
1260
::
1261
1262
sage: c = AbelianStratum(1,1,1,1).connected_components()[0]
1263
sage: print c
1264
H_c(1, 1, 1, 1)
1265
sage: p = c.representative(alphabet=range(9))
1266
sage: print p
1267
0 1 2 3 4 5 6 7 8
1268
4 3 2 5 8 7 6 1 0
1269
sage: p.connected_component()
1270
H_c(1, 1, 1, 1)
1271
"""
1272
g = self._parent._genus
1273
zeroes = filter(lambda x: x > 0, self._parent._zeroes)
1274
n = self._parent._zeroes.count(0)
1275
1276
l0 = range(0, 4*g-3)
1277
l1 = [4, 3, 2]
1278
for k in range(5, 4*g-6, 4):
1279
l1 += [k, k+3, k+2, k+1]
1280
l1 += [1, 0]
1281
k = 3
1282
for d in zeroes:
1283
for i in range(d-1):
1284
del l0[l0.index(k)]
1285
del l1[l1.index(k)]
1286
k += 2
1287
k += 2
1288
1289
if n != 0:
1290
interval = range(4*g-3, 4*g-3+n)
1291
1292
if self._parent._zeroes[0] == 0:
1293
k = l0.index(4)
1294
l0[k:k] = interval
1295
l1[-1:-1] = interval
1296
else:
1297
l0[1:1] = interval
1298
l1.extend(interval)
1299
1300
if self._parent._marked_separatrix == 'in':
1301
l0.reverse()
1302
l1.reverse()
1303
1304
if reduced:
1305
from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET
1306
return ReducedPermutationIET([l0, l1], alphabet=alphabet)
1307
1308
else:
1309
from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET
1310
return LabelledPermutationIET([l0, l1], alphabet=alphabet)
1311
1312
1313
def genus(self):
1314
r"""
1315
Returns the genus of the surfaces in this connected component.
1316
1317
OUTPUT:
1318
1319
integer -- the genus of the surface
1320
1321
EXAMPLES:
1322
1323
::
1324
1325
sage: a = AbelianStratum(6,4,2,0,0)
1326
sage: c_odd, c_even = a.connected_components()
1327
sage: c_odd.genus()
1328
7
1329
sage: c_even.genus()
1330
7
1331
1332
::
1333
1334
sage: a = AbelianStratum([1]*8)
1335
sage: c = a.connected_components()[0]
1336
sage: c.genus()
1337
5
1338
"""
1339
return self._parent.genus()
1340
1341
def nintervals(self):
1342
r"""
1343
Returns the number of intervals of the representative.
1344
1345
OUTPUT:
1346
1347
integer -- the number of intervals in any representative
1348
1349
EXAMPLES:
1350
1351
::
1352
1353
sage: a = AbelianStratum(6,4,2,0,0)
1354
sage: c_odd, c_even = a.connected_components()
1355
sage: c_odd.nintervals()
1356
18
1357
sage: c_even.nintervals()
1358
18
1359
1360
::
1361
1362
sage: a = AbelianStratum([1]*8)
1363
sage: c = a.connected_components()[0]
1364
sage: c.nintervals()
1365
17
1366
"""
1367
return self.parent().nintervals()
1368
1369
def rauzy_diagram(self, reduced=True):
1370
r"""
1371
Returns the Rauzy diagram associated to this connected component.
1372
1373
OUTPUT:
1374
1375
rauzy diagram -- the Rauzy diagram associated to this stratum
1376
1377
EXAMPLES:
1378
1379
::
1380
1381
sage: c = AbelianStratum(0).connected_components()[0]
1382
sage: r = c.rauzy_diagram()
1383
"""
1384
return self.representative(reduced=reduced).rauzy_diagram()
1385
1386
def __cmp__(self, other):
1387
r"""
1388
TESTS::
1389
1390
sage: a1 = AbelianStratum(1,1,1,1)
1391
sage: c1 = a1.connected_components()[0]
1392
sage: a2 = AbelianStratum(3,1)
1393
sage: c2 = a2.connected_components()[0]
1394
sage: c1 == c1
1395
True
1396
sage: c1 == c2
1397
False
1398
sage: a1 = AbelianStratum(1,1,1,1)
1399
sage: c1 = a1.connected_components()[0]
1400
sage: a2 = AbelianStratum(2, 2)
1401
sage: c2_hyp, c2_odd = a2.connected_components()
1402
sage: c1 != c1
1403
False
1404
sage: c1 != c2_hyp
1405
True
1406
sage: c2_hyp != c2_odd
1407
True
1408
sage: c1 == True
1409
Traceback (most recent call last):
1410
...
1411
TypeError: other must be a connected component
1412
"""
1413
if not isinstance(other, CCA):
1414
raise TypeError("other must be a connected component")
1415
1416
if type(self) == type(other):
1417
if self._parent._zeroes > other._parent._zeroes:
1418
return 1
1419
elif self._parent._zeroes < other._parent._zeroes:
1420
return -1
1421
return 0
1422
1423
return cmp(type(self), type(other))
1424
1425
CCA = ConnectedComponentOfAbelianStratum
1426
1427
1428
class HypConnectedComponentOfAbelianStratum(CCA):
1429
"""
1430
Hyperelliptic component of Abelian stratum.
1431
1432
.. warning::
1433
1434
Internal class! Do not use directly!
1435
"""
1436
_name = 'hyp'
1437
1438
def representative(self, reduced=True, alphabet=None):
1439
r"""
1440
Returns the Zorich representative of this connected component.
1441
1442
Zorich constructs explicitely interval exchange
1443
transformations for each stratum in [Zor08]_.
1444
1445
INPUT:
1446
1447
- ``reduced`` - boolean (defaut: ``True``): whether you obtain
1448
a reduced or labelled permutation
1449
1450
- ``alphabet`` - alphabet or ``None`` (defaut: ``None``):
1451
whether you want to specify an alphabet for your
1452
representative
1453
1454
EXAMPLES:
1455
1456
::
1457
1458
sage: c = AbelianStratum(0).connected_components()[0]
1459
sage: c
1460
H_hyp(0)
1461
sage: p = c.representative(alphabet="01")
1462
sage: p
1463
0 1
1464
1 0
1465
sage: p.connected_component()
1466
H_hyp(0)
1467
1468
::
1469
1470
sage: c = AbelianStratum(0,0).connected_components()[0]
1471
sage: c
1472
H_hyp(0, 0)
1473
sage: p = c.representative(alphabet="abc")
1474
sage: p
1475
a b c
1476
c b a
1477
sage: p.connected_component()
1478
H_hyp(0, 0)
1479
1480
::
1481
1482
sage: c = AbelianStratum(2).connected_components()[0]
1483
sage: c
1484
H_hyp(2)
1485
sage: p = c.representative(alphabet="ABCD")
1486
sage: p
1487
A B C D
1488
D C B A
1489
sage: p.connected_component()
1490
H_hyp(2)
1491
1492
::
1493
1494
sage: c = AbelianStratum(1,1).connected_components()[0]
1495
sage: c
1496
H_hyp(1, 1)
1497
sage: p = c.representative(alphabet="01234")
1498
sage: p
1499
0 1 2 3 4
1500
4 3 2 1 0
1501
sage: p.connected_component()
1502
H_hyp(1, 1)
1503
"""
1504
g = self._parent._genus
1505
n = self._parent._zeroes.count(0)
1506
m = len(self._parent._zeroes) - n
1507
1508
if m == 0: # on the torus
1509
if n == 1:
1510
l0 = [0, 1]
1511
l1 = [1, 0]
1512
elif n == 2:
1513
l0 = [0, 1, 2]
1514
l1 = [2, 1, 0]
1515
else:
1516
l0 = range(1, n+2)
1517
l1 = [n+1] + range(1, n+1)
1518
1519
elif m == 1: # H(2g-2,0^n) or H(0,2g-2,0^(n-1))
1520
l0 = range(1, 2*g+1)
1521
l1 = range(2*g, 0, -1)
1522
interval = range(2*g+1, 2*g+n+1)
1523
1524
if self._parent._zeroes[0] == 0:
1525
l0[-1:-1] = interval
1526
l1[-1:-1] = interval
1527
else:
1528
l0[1:1] = interval
1529
l1[1:1] = interval
1530
1531
else: # H(g-1,g-1,0^n) or H(0,g-1,g-1,0^(n-1))
1532
l0 = range(1, 2*g+2)
1533
l1 = range(2*g+1, 0, -1)
1534
interval = range(2*g+2, 2*g+n+2)
1535
1536
if self._parent._zeroes[0] == 0:
1537
l0[-1:-1] = interval
1538
l1[-1:-1] = interval
1539
else:
1540
l0[1:1] = interval
1541
l1[1:1] = interval
1542
1543
if self._parent._marked_separatrix == 'in':
1544
l0.reverse()
1545
l1.reverse()
1546
1547
if reduced:
1548
from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET
1549
return ReducedPermutationIET([l0, l1], alphabet=alphabet)
1550
1551
else:
1552
from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET
1553
return LabelledPermutationIET([l0, l1], alphabet=alphabet)
1554
1555
HypCCA = HypConnectedComponentOfAbelianStratum
1556
1557
1558
class NonHypConnectedComponentOfAbelianStratum(CCA):
1559
"""
1560
Non hyperelliptic component of Abelian stratum.
1561
1562
.. warning::
1563
1564
Internal class! Do not use directly!
1565
"""
1566
_name = 'nonhyp'
1567
1568
NonHypCCA = NonHypConnectedComponentOfAbelianStratum
1569
1570
1571
class EvenConnectedComponentOfAbelianStratum(CCA):
1572
"""
1573
Connected component of Abelian stratum with even spin structure.
1574
1575
.. warning::
1576
1577
Internal class! Do not use directly!
1578
"""
1579
_name = 'even'
1580
1581
def representative(self, reduced=True, alphabet=None):
1582
r"""
1583
Returns the Zorich representative of this connected component.
1584
1585
Zorich constructs explicitely interval exchange
1586
transformations for each stratum in [Zor08]_.
1587
1588
EXAMPLES:
1589
1590
::
1591
1592
sage: c = AbelianStratum(6).connected_components()[2]
1593
sage: c
1594
H_even(6)
1595
sage: p = c.representative(alphabet=range(8))
1596
sage: p
1597
0 1 2 3 4 5 6 7
1598
5 4 3 2 7 6 1 0
1599
sage: p.connected_component()
1600
H_even(6)
1601
1602
::
1603
1604
sage: c = AbelianStratum(4,4).connected_components()[2]
1605
sage: c
1606
H_even(4, 4)
1607
sage: p = c.representative(alphabet=range(11))
1608
sage: p
1609
0 1 2 3 4 5 6 7 8 9 10
1610
5 4 3 2 6 8 7 10 9 1 0
1611
sage: p.connected_component()
1612
H_even(4, 4)
1613
"""
1614
zeroes = filter(lambda x: x > 0, self._parent._zeroes)
1615
n = self._parent._zeroes.count(0)
1616
g = self._parent._genus
1617
1618
l0 = range(3*g-2)
1619
l1 = [6, 5, 4, 3, 2, 7, 9, 8]
1620
for k in range(10, 3*g-4, 3):
1621
l1 += [k, k+2, k+1]
1622
l1 += [1, 0]
1623
1624
k = 4
1625
for d in zeroes:
1626
for i in range(d/2-1):
1627
del l0[l0.index(k)]
1628
del l1[l1.index(k)]
1629
k += 3
1630
k += 3
1631
1632
# if there are marked points we transform 0 in [3g-2, 3g-3, ...]
1633
if n != 0:
1634
interval = range(3*g-2, 3*g - 2 + n)
1635
1636
if self._parent._zeroes[0] == 0:
1637
k = l0.index(6)
1638
l0[k:k] = interval
1639
l1[-1:-1] = interval
1640
else:
1641
l0[1:1] = interval
1642
l1.extend(interval)
1643
1644
if self._parent._marked_separatrix == 'in':
1645
l0.reverse()
1646
l1.reverse()
1647
1648
if reduced:
1649
from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET
1650
return ReducedPermutationIET([l0, l1], alphabet=alphabet)
1651
1652
else:
1653
from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET
1654
return LabelledPermutationIET([l0, l1], alphabet=alphabet)
1655
1656
EvenCCA = EvenConnectedComponentOfAbelianStratum
1657
1658
1659
class OddConnectedComponentOfAbelianStratum(CCA):
1660
r"""
1661
Connected component of an Abelian stratum with odd spin parity.
1662
1663
.. warning::
1664
1665
Internal class! Do not use directly!
1666
"""
1667
_name = 'odd'
1668
1669
def representative(self, reduced=True, alphabet=None):
1670
"""
1671
Returns the Zorich representative of this connected component.
1672
1673
Zorich constructs explicitely interval exchange
1674
transformations for each stratum in [Zor08]_.
1675
1676
EXAMPLES:
1677
1678
::
1679
1680
sage: a = AbelianStratum(6).connected_components()[1]
1681
sage: print a.representative(alphabet=range(8))
1682
0 1 2 3 4 5 6 7
1683
3 2 5 4 7 6 1 0
1684
1685
::
1686
1687
sage: a = AbelianStratum(4,4).connected_components()[1]
1688
sage: print a.representative(alphabet=range(11))
1689
0 1 2 3 4 5 6 7 8 9 10
1690
3 2 5 4 6 8 7 10 9 1 0
1691
"""
1692
zeroes = filter(lambda x: x > 0, self._parent._zeroes)
1693
zeroes = map(lambda x: x/2, zeroes)
1694
1695
n = self._parent._zeroes.count(0)
1696
g = self._parent._genus
1697
1698
l0 = range(3*g-2)
1699
l1 = [3, 2]
1700
for k in range(4, 3*g-4, 3):
1701
l1 += [k, k+2, k+1]
1702
l1 += [1, 0]
1703
1704
k = 4
1705
for d in zeroes:
1706
for i in range(d-1):
1707
del l0[l0.index(k)]
1708
del l1[l1.index(k)]
1709
k += 3
1710
k += 3
1711
1712
# marked points
1713
if n != 0:
1714
interval = range(3*g-2, 3*g-2+n)
1715
1716
if self._parent._zeroes[0] == 0:
1717
k = l0.index(3)
1718
l0[k:k] = interval
1719
l1[-1:-1] = interval
1720
else:
1721
l0[1:1] = interval
1722
l1.extend(interval)
1723
1724
if self._parent._marked_separatrix == 'in':
1725
l0.reverse()
1726
l1.reverse()
1727
1728
if reduced:
1729
from sage.dynamics.interval_exchanges.reduced import ReducedPermutationIET
1730
return ReducedPermutationIET([l0, l1], alphabet=alphabet)
1731
1732
else:
1733
from sage.dynamics.interval_exchanges.labelled import LabelledPermutationIET
1734
return LabelledPermutationIET([l0, l1], alphabet=alphabet)
1735
1736
OddCCA = OddConnectedComponentOfAbelianStratum
1737
1738