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