Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/algebras/steenrod/steenrod_algebra_misc.py
4145 views
1
"""
2
Miscellaneous functions for the Steenrod algebra and its elements
3
4
AUTHORS:
5
6
- John H. Palmieri (2008-07-30): initial version (as the file
7
steenrod_algebra_element.py)
8
9
- John H. Palmieri (2010-06-30): initial version of steenrod_misc.py.
10
Implemented profile functions. Moved most of the methods for
11
elements to the ``Element`` subclass of
12
:class:`sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra_generic`.
13
14
The main functions here are
15
16
- :func:`get_basis_name`. This function takes a string as input and
17
attempts to interpret it as the name of a basis for the Steenrod
18
algebra; it returns the canonical name attached to that basis. This
19
allows for the use of synonyms when defining bases, while the
20
resulting algebras will be identical.
21
22
- :func:`normalize_profile`. This function returns the canonical (and
23
hashable) description of any profile function. See
24
:mod:`sage.algebras.steenrod.steenrod_algebra` and
25
:func:`SteenrodAlgebra <sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra>`
26
for information on profile functions.
27
28
- functions named ``*_mono_to_string`` where ``*`` is a basis name
29
(:func:`milnor_mono_to_string`, etc.). These convert tuples
30
representing basis elements to strings, for _repr_ and _latex_
31
methods.
32
"""
33
34
#*****************************************************************************
35
# Copyright (C) 2008-2010 John H. Palmieri <[email protected]>
36
# Distributed under the terms of the GNU General Public License (GPL)
37
#*****************************************************************************
38
39
######################################################
40
# basis names
41
42
_steenrod_milnor_basis_names = ['milnor']
43
_steenrod_serre_cartan_basis_names = ['serre_cartan', 'serre-cartan', 'sc',
44
'adem', 'admissible']
45
46
def get_basis_name(basis, p):
47
"""
48
Return canonical basis named by string basis at the prime p.
49
50
INPUT:
51
52
- ``basis`` - string
53
54
- ``p`` - positive prime number
55
56
OUTPUT:
57
58
- ``basis_name`` - string
59
60
Specify the names of the implemented bases. The input is
61
converted to lower-case, then processed to return the canonical
62
name for the basis.
63
64
For the Milnor and Serre-Cartan bases, use the list of synonyms
65
defined by the variables :data:`_steenrod_milnor_basis_names` and
66
:data:`_steenrod_serre_cartan_basis_names`. Their canonical names
67
are 'milnor' and 'serre-cartan', respectively.
68
69
For the other bases, use pattern-matching rather than a list of
70
synonyms:
71
72
- Search for 'wood' and 'y' or 'wood' and 'z' to get the Wood
73
bases. Canonical names 'woody', 'woodz'.
74
75
- Search for 'arnon' and 'c' for the Arnon C basis. Canonical
76
name: 'arnonc'.
77
78
- Search for 'arnon' (and no 'c') for the Arnon A basis. Also see
79
if 'long' is present, for the long form of the basis. Canonical
80
names: 'arnona', 'arnona_long'.
81
82
- Search for 'wall' for the Wall basis. Also see if 'long' is
83
present. Canonical names: 'wall', 'wall_long'.
84
85
- Search for 'pst' for P^s_t bases, then search for the order
86
type: 'rlex', 'llex', 'deg', 'revz'. Canonical names:
87
'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz'.
88
89
- For commutator types, search for 'comm', an order type, and also
90
check to see if 'long' is present. Canonical names:
91
'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz',
92
'comm_rlex_long', 'comm_llex_long', 'comm_deg_long',
93
'comm_revz_long'.
94
95
EXAMPLES::
96
97
sage: from sage.algebras.steenrod.steenrod_algebra_misc import get_basis_name
98
sage: get_basis_name('adem', 2)
99
'serre-cartan'
100
sage: get_basis_name('milnor', 2)
101
'milnor'
102
sage: get_basis_name('MiLNoR', 5)
103
'milnor'
104
sage: get_basis_name('pst-llex', 2)
105
'pst_llex'
106
sage: get_basis_name('wood_abcdedfg_y', 2)
107
'woody'
108
sage: get_basis_name('arnon--hello--long', 2)
109
'arnona_long'
110
sage: get_basis_name('arnona_long', p=5)
111
Traceback (most recent call last):
112
...
113
ValueError: arnona_long is not a recognized basis at the prime 5.
114
sage: get_basis_name('NOT_A_BASIS', 2)
115
Traceback (most recent call last):
116
...
117
ValueError: not_a_basis is not a recognized basis at the prime 2.
118
"""
119
basis = basis.lower()
120
if basis in _steenrod_milnor_basis_names:
121
result = 'milnor'
122
elif basis in _steenrod_serre_cartan_basis_names:
123
result = 'serre-cartan'
124
elif basis.find('pst') >= 0:
125
if basis.find('rlex') >= 0:
126
result = 'pst_rlex'
127
elif basis.find('llex') >= 0:
128
result = 'pst_llex'
129
elif basis.find('deg') >= 0:
130
result = 'pst_deg'
131
elif basis.find('revz') >= 0:
132
result = 'pst_revz'
133
else:
134
result = 'pst_revz'
135
elif basis.find('comm') >= 0:
136
if basis.find('rlex') >= 0:
137
result = 'comm_rlex'
138
elif basis.find('llex') >= 0:
139
result = 'comm_llex'
140
elif basis.find('deg') >= 0:
141
result = 'comm_deg'
142
elif basis.find('revz') >= 0:
143
result = 'comm_revz'
144
else:
145
result = 'comm_revz'
146
if basis.find('long') >= 0:
147
result = result + '_long'
148
elif p == 2 and basis.find('wood') >= 0:
149
if basis.find('y') >= 0:
150
result = 'woody'
151
elif basis.find('z') >= 0:
152
result = 'woodz'
153
elif p == 2 and basis.find('arnon') >= 0:
154
if basis.find('c') >= 0:
155
result = 'arnonc'
156
else:
157
result = 'arnona'
158
if basis.find('long') >= 0:
159
result = result + '_long'
160
elif p == 2 and basis.find('wall') >= 0:
161
result = 'wall'
162
if basis.find('long') >= 0:
163
result = result + '_long'
164
else:
165
raise ValueError("%s is not a recognized basis at the prime %s." % (basis, p))
166
return result
167
168
######################################################
169
# profile functions
170
171
def is_valid_profile(profile, truncation_type, p=2):
172
"""
173
True if ``profile``, together with ``truncation_type``, is a valid
174
profile at the prime `p`.
175
176
INPUT:
177
178
- ``profile`` - when `p=2`, a tuple or list of numbers; when `p`
179
is odd, a pair of such lists
180
181
- ``truncation_type`` - either 0 or `\infty`
182
183
- `p` - prime number, optional, default 2
184
185
OUTPUT: True if the profile function is valid, False otherwise.
186
187
See the documentation for :mod:`sage.algebras.steenrod.steenrod_algebra`
188
for descriptions of profile functions and how they correspond to
189
sub-Hopf algebras of the Steenrod algebra. Briefly: at the prime
190
2, a profile function `e` is valid if it satisfies the condition
191
192
- `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`.
193
194
At odd primes, a pair of profile functions `e` and `k` are valid
195
if they satisfy
196
197
- `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`.
198
199
- if `k(i+j) = 1`, then either `e(i) \leq j` or `k(j) = 1` for all
200
`i \geq 1`, `j \geq 0`.
201
202
In this function, profile functions are lists or tuples, and
203
``truncation_type`` is appended as the last element of the list
204
`e` before testing.
205
206
EXAMPLES:
207
208
`p=2`::
209
210
sage: from sage.algebras.steenrod.steenrod_algebra_misc import is_valid_profile
211
sage: is_valid_profile([3,2,1], 0)
212
True
213
sage: is_valid_profile([3,2,1], Infinity)
214
True
215
sage: is_valid_profile([1,2,3], 0)
216
False
217
sage: is_valid_profile([6,2,0], Infinity)
218
False
219
sage: is_valid_profile([0,3], 0)
220
False
221
sage: is_valid_profile([0,0,4], 0)
222
False
223
sage: is_valid_profile([0,0,0,4,0], 0)
224
True
225
226
Odd primes::
227
228
sage: is_valid_profile(([0,0,0], [2,1,1,1,2,2]), 0, p=3)
229
True
230
sage: is_valid_profile(([1], [2,2]), 0, p=3)
231
True
232
sage: is_valid_profile(([1], [2]), 0, p=7)
233
False
234
sage: is_valid_profile(([1,2,1], []), 0, p=7)
235
True
236
"""
237
from sage.rings.infinity import Infinity
238
if p == 2:
239
pro = list(profile) + [truncation_type]*len(profile)
240
r = 0
241
for pro_r in pro:
242
r += 1 # index of pro_r
243
if pro_r < Infinity:
244
for i in range(1,r):
245
if pro_r < min(pro[r-i-1] - i, pro[i-1]):
246
return False
247
else:
248
# p odd:
249
e = list(profile[0]) + [truncation_type]*len(profile[0])
250
k = list(profile[1])
251
if not set(k).issubset(set([1,2])):
252
return False
253
if truncation_type > 0:
254
k = k + [2]
255
else:
256
k = k + [1]*len(profile[0])
257
if len(k) > len(e):
258
e = e + [truncation_type] * (len(k) - len(e))
259
r = 0
260
for e_r in e:
261
r += 1 # index of e_r
262
if e_r < Infinity:
263
for i in range(1,r):
264
if e_r < min(e[r-i-1] - i, e[i-1]):
265
return False
266
r = -1
267
for k_r in k:
268
r += 1 # index of k_r
269
if k_r == 1:
270
for j in range(r):
271
i = r-j
272
if e[i-1] > j and k[j] == 2:
273
return False
274
return True
275
276
def normalize_profile(profile, precision=None, truncation_type='auto', p=2):
277
"""
278
Given a profile function and related data, return it in a standard form,
279
suitable for hashing and caching as data defining a sub-Hopf
280
algebra of the Steenrod algebra.
281
282
INPUT:
283
284
- ``profile`` - a profile function in form specified below
285
- ``precision`` - integer or ``None``, optional, default ``None``
286
- ``truncation_type`` - 0 or `\infty` or 'auto', optional, default 'auto'
287
- `p` - prime, optional, default 2
288
289
OUTPUT: a triple ``profile, precision, truncation_type``, in
290
standard form as described below.
291
292
The "standard form" is as follows: ``profile`` should be a tuple
293
of integers (or `\infty`) with no trailing zeroes when `p=2`, or a
294
pair of such when `p` is odd. ``precision`` should be a positive
295
integer. ``truncation_type`` should be 0 or `\infty`.
296
Furthermore, this must be a valid profile, as determined by the
297
funtion :func:`is_valid_profile`. See also the documentation for
298
the module :mod:`sage.algebras.steenrod.steenrod_algebra` for information
299
about profile functions.
300
301
For the inputs: when `p=2`, ``profile`` should be a valid profile
302
function, and it may be entered in any of the following forms:
303
304
- a list or tuple, e.g., ``[3,2,1,1]``
305
- a function from positive integers to non-negative integers (and
306
`\infty`), e.g., ``lambda n: n+2``. This corresponds to the
307
list ``[3, 4, 5, ...]``.
308
- ``None`` or ``Infinity`` - use this for the profile function for
309
the whole Steenrod algebra. This corresponds to the list
310
``[Infinity, Infinity, Infinity, ...]``
311
312
To make this hashable, it gets turned into a tuple. In the first
313
case it is clear how to do this; also in this case, ``precision``
314
is set to be one more than the length of this tuple. In the
315
second case, construct a tuple of length one less than
316
``precision`` (default value 100). In the last case, the empty
317
tuple is returned and ``precision`` is set to 1.
318
319
Once a sub-Hopf algebra of the Steenrod algebra has been defined
320
using such a profile function, if the code requires any remaining
321
terms (say, terms after the 100th), then they are given by
322
``truncation_type`` if that is 0 or `\infty`. If
323
``truncation_type`` is 'auto', then in the case of a tuple, it
324
gets set to 0, while for the other cases it gets set to `\infty`.
325
326
See the examples below.
327
328
When `p` is odd, ``profile`` is a pair of "functions", so it may
329
have the following forms:
330
331
- a pair of lists or tuples, the second of which takes values in
332
the set `\{1,2\}`, e.g., ``([3,2,1,1], [1,1,2,2,1])``.
333
334
- a pair of functions, one (called `e`) from positive integers to
335
non-negative integers (and `\infty`), one (called `k`) from
336
non-negative integers to the set `\{1,2\}`, e.g.,
337
``(lambda n: n+2, lambda n: 1)``. This corresponds to the
338
pair ``([3, 4, 5, ...], [1, 1, 1, ...])``.
339
340
- ``None`` or ``Infinity`` - use this for the profile function for
341
the whole Steenrod algebra. This corresponds to the pair
342
``([Infinity, Infinity, Infinity, ...], [2, 2, 2, ...])``.
343
344
You can also mix and match the first two, passing a pair with
345
first entry a list and second entry a function, for instance. The
346
values of ``precision`` and ``truncation_type`` are determined by
347
the first entry.
348
349
EXAMPLES:
350
351
`p=2`::
352
353
sage: from sage.algebras.steenrod.steenrod_algebra_misc import normalize_profile
354
sage: normalize_profile([1,2,1,0,0])
355
((1, 2, 1), 0)
356
357
The full mod 2 Steenrod algebra::
358
359
sage: normalize_profile(Infinity)
360
((), +Infinity)
361
sage: normalize_profile(None)
362
((), +Infinity)
363
sage: normalize_profile(lambda n: Infinity)
364
((), +Infinity)
365
366
The ``precision`` argument has no effect when the first argument
367
is a list or tuple::
368
369
sage: normalize_profile([1,2,1,0,0], precision=12)
370
((1, 2, 1), 0)
371
372
If the first argument is a function, then construct a list of
373
length one less than ``precision``, by plugging in the numbers 1,
374
2, ..., ``precision`` - 1::
375
376
sage: normalize_profile(lambda n: 4-n, precision=4)
377
((3, 2, 1), +Infinity)
378
sage: normalize_profile(lambda n: 4-n, precision=4, truncation_type=0)
379
((3, 2, 1), 0)
380
381
Negative numbers in profile functions are turned into zeroes::
382
383
sage: normalize_profile(lambda n: 4-n, precision=6)
384
((3, 2, 1, 0, 0), +Infinity)
385
386
If it doesn't give a valid profile, an error is raised::
387
388
sage: normalize_profile(lambda n: 3, precision=4, truncation_type=0)
389
Traceback (most recent call last):
390
...
391
ValueError: Invalid profile
392
sage: normalize_profile(lambda n: 3, precision=4, truncation_type = Infinity)
393
((3, 3, 3), +Infinity)
394
395
When `p` is odd, the behavior is similar::
396
397
sage: normalize_profile(([2,1], [2,2,2]), p=13)
398
(((2, 1), (2, 2, 2)), 0)
399
400
The full mod `p` Steenrod algebra::
401
402
sage: normalize_profile(None, p=7)
403
(((), ()), +Infinity)
404
sage: normalize_profile(Infinity, p=11)
405
(((), ()), +Infinity)
406
sage: normalize_profile((lambda n: Infinity, lambda n: 2), p=17)
407
(((), ()), +Infinity)
408
409
Note that as at the prime 2, the ``precision`` argument has no
410
effect on a list or tuple in either entry of ``profile``. If
411
``truncation_type`` is 'auto', then it gets converted to either
412
``0`` or ``+Infinity`` depending on the *first* entry of
413
``profile``::
414
415
sage: normalize_profile(([2,1], [2,2,2]), precision=84, p=13)
416
(((2, 1), (2, 2, 2)), 0)
417
sage: normalize_profile((lambda n: 0, lambda n: 2), precision=4, p=11)
418
(((0, 0, 0), ()), +Infinity)
419
sage: normalize_profile((lambda n: 0, (1,1,1,1,1,1,1)), precision=4, p=11)
420
(((0, 0, 0), (1, 1, 1, 1, 1, 1, 1)), +Infinity)
421
sage: normalize_profile(((4,3,2,1), lambda n: 2), precision=6, p=11)
422
(((4, 3, 2, 1), (2, 2, 2, 2, 2)), 0)
423
sage: normalize_profile(((4,3,2,1), lambda n: 1), precision=3, p=11, truncation_type=Infinity)
424
(((4, 3, 2, 1), (1, 1)), +Infinity)
425
426
As at the prime 2, negative numbers in the first component are
427
converted to zeroes. Numbers in the second component must be
428
either 1 and 2, or else an error is raised::
429
430
sage: normalize_profile((lambda n: -n, lambda n: 1), precision=4, p=11)
431
(((0, 0, 0), (1, 1, 1)), +Infinity)
432
sage: normalize_profile([[0,0,0], [1,2,3,2,1]], p=11)
433
Traceback (most recent call last):
434
...
435
ValueError: Invalid profile
436
"""
437
from inspect import isfunction
438
from sage.rings.infinity import Infinity
439
if truncation_type == 'zero':
440
truncation_type = 0
441
if truncation_type == 'infinity':
442
truncation_type = Infinity
443
if p == 2:
444
if profile is None or profile == Infinity:
445
# no specified profile or infinite profile: return profile
446
# for the entire Steenrod algebra
447
new_profile = ()
448
truncation_type = Infinity
449
elif isinstance(profile, (list, tuple)):
450
# profile is a list or tuple: use it as is. if
451
# truncation_type not specified, set it to 'zero'. remove
452
# trailing zeroes if truncation_type is 'auto' or 'zero'.
453
if truncation_type == 'auto':
454
truncation_type = 0
455
# remove trailing zeroes or Infinitys
456
while len(profile) > 0 and profile[-1] == truncation_type:
457
profile = profile[:-1]
458
new_profile = tuple(profile)
459
elif isfunction(profile):
460
# profile is a function: turn it into a tuple. if
461
# truncation_type not specified, set it to 'infinity' if
462
# the function is ever infinite; otherwise set it to
463
# 0. remove trailing zeroes if truncation_type is
464
# 0, trailing Infinitys if truncation_type is oo.
465
if precision is None:
466
precision = 100
467
if truncation_type == 'auto':
468
truncation_type = Infinity
469
new_profile = [max(0, profile(i)) for i in range(1, precision)]
470
# remove trailing zeroes or Infinitys:
471
while len(new_profile) > 0 and new_profile[-1] == truncation_type:
472
del new_profile[-1]
473
new_profile = tuple(new_profile)
474
if is_valid_profile(new_profile, truncation_type, p):
475
return new_profile, truncation_type
476
else:
477
raise ValueError("Invalid profile")
478
else: # p odd
479
if profile is None or profile == Infinity:
480
# no specified profile or infinite profile: return profile
481
# for the entire Steenrod algebra
482
new_profile = ((), ())
483
truncation_type = Infinity
484
else: # profile should be a list or tuple of length 2
485
assert isinstance(profile, (list, tuple)) and len(profile) == 2, \
486
"Invalid form for profile"
487
e = profile[0]
488
k = profile[1]
489
if isinstance(e, (list, tuple)):
490
# e is a list or tuple: use it as is. if
491
# truncation_type not specified, set it to 0. remove
492
# appropriate trailing terms.
493
if truncation_type == 'auto':
494
truncation_type = 0
495
# remove trailing terms
496
while len(e) > 0 and e[-1] == truncation_type:
497
e = e[:-1]
498
e = tuple(e)
499
elif isfunction(e):
500
# e is a function: turn it into a tuple. if
501
# truncation_type not specified, set it to 'infinity'
502
# if the function is ever infinite; otherwise set it
503
# to 0. remove appropriate trailing terms.
504
if precision is None:
505
e_precision = 100
506
else:
507
e_precision = precision
508
if truncation_type == 'auto':
509
truncation_type = Infinity
510
e = [max(0, e(i)) for i in range(1, e_precision)]
511
# remove trailing terms
512
while len(e) > 0 and e[-1] == truncation_type:
513
del e[-1]
514
e = tuple(e)
515
if isinstance(k, (list, tuple)):
516
# k is a list or tuple: use it as is.
517
k = tuple(k)
518
elif isfunction(k):
519
# k is a function: turn it into a tuple.
520
if precision is None:
521
k_precision = 100
522
else:
523
k_precision = precision
524
k = tuple([k(i) for i in range(k_precision-1)])
525
# Remove trailing ones from k if truncation_type is 'zero',
526
# remove trailing twos if truncation_type is 'Infinity'.
527
if truncation_type == 0:
528
while len(k) > 0 and k[-1] == 1:
529
k = k[:-1]
530
else:
531
while len(k) > 0 and k[-1] == 2:
532
k = k[:-1]
533
new_profile = (e, k)
534
if is_valid_profile(new_profile, truncation_type, p):
535
return new_profile, truncation_type
536
else:
537
raise ValueError("Invalid profile")
538
539
######################################################
540
# string representations for elements
541
542
def milnor_mono_to_string(mono, latex=False, p=2):
543
"""
544
String representation of element of the Milnor basis.
545
546
This is used by the _repr_ and _latex_ methods.
547
548
INPUT:
549
550
- ``mono`` - if `p=2`, tuple of non-negative integers (a,b,c,...);
551
if `p>2`, pair of tuples of non-negative integers ((e0, e1, e2,
552
...), (r1, r2, ...))
553
554
- ``latex`` - boolean (optional, default False), if true, output
555
LaTeX string
556
557
- ``p`` - positive prime number (optional, default 2)
558
559
OUTPUT: ``rep`` - string
560
561
This returns a string like ``Sq(a,b,c,...)`` when p=2, or a string
562
like ``Q_e0 Q_e1 Q_e2 ... P(r1, r2, ...)`` when p is odd.
563
564
EXAMPLES::
565
566
sage: from sage.algebras.steenrod.steenrod_algebra_misc import milnor_mono_to_string
567
sage: milnor_mono_to_string((1,2,3,4))
568
'Sq(1,2,3,4)'
569
sage: milnor_mono_to_string((1,2,3,4),latex=True)
570
'\\text{Sq}(1,2,3,4)'
571
sage: milnor_mono_to_string(((1,0), (2,3,1)), p=3)
572
'Q_{1} Q_{0} P(2,3,1)'
573
sage: milnor_mono_to_string(((1,0), (2,3,1)), latex=True, p=3)
574
'Q_{1} Q_{0} \\mathcal{P}(2,3,1)'
575
576
The empty tuple represents the unit element::
577
578
sage: milnor_mono_to_string(())
579
'1'
580
sage: milnor_mono_to_string((), p=5)
581
'1'
582
"""
583
if latex:
584
if p == 2:
585
sq = "\\text{Sq}"
586
P = "\\text{Sq}"
587
else:
588
P = "\\mathcal{P}"
589
else:
590
if p == 2:
591
sq = "Sq"
592
P = "Sq"
593
else:
594
P = "P"
595
if mono == () or mono == (0,) or (p > 2 and len(mono[0]) + len(mono[1]) == 0):
596
return "1"
597
else:
598
if p == 2:
599
string = sq + "(" + str(mono[0])
600
for n in mono[1:]:
601
string = string + "," + str(n)
602
string = string + ")"
603
else:
604
string = ""
605
if len(mono[0]) > 0:
606
for e in mono[0]:
607
string = string + "Q_{" + str(e) + "} "
608
if len(mono[1]) > 0:
609
string = string + P + "(" + str(mono[1][0])
610
for n in mono[1][1:]:
611
string = string + "," + str(n)
612
string = string + ")"
613
return string.strip(" ")
614
615
def serre_cartan_mono_to_string(mono, latex=False, p=2):
616
r"""
617
String representation of element of the Serre-Cartan basis.
618
619
This is used by the _repr_ and _latex_ methods.
620
621
INPUT:
622
623
- ``mono`` - tuple of positive integers (a,b,c,...) when `p=2`,
624
or tuple (e0, n1, e1, n2, ...) when `p>2`, where each ei is 0 or
625
1, and each ni is positive
626
627
- ``latex`` - boolean (optional, default False), if true, output
628
LaTeX string
629
630
- ``p`` - positive prime number (optional, default 2)
631
632
OUTPUT: ``rep`` - string
633
634
This returns a string like ``Sq^{a} Sq^{b} Sq^{c} ...`` when
635
`p=2`, or a string like
636
``\beta^{e0} P^{n1} \beta^{e1} P^{n2} ...`` when `p`
637
is odd.
638
639
EXAMPLES::
640
641
sage: from sage.algebras.steenrod.steenrod_algebra_misc import serre_cartan_mono_to_string
642
sage: serre_cartan_mono_to_string((1,2,3,4))
643
'Sq^{1} Sq^{2} Sq^{3} Sq^{4}'
644
sage: serre_cartan_mono_to_string((1,2,3,4),latex=True)
645
'\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{4}'
646
sage: serre_cartan_mono_to_string((0,5,1,1,0), p=3)
647
'P^{5} beta P^{1}'
648
sage: serre_cartan_mono_to_string((0,5,1,1,0), p=3, latex=True)
649
'\\mathcal{P}^{5} \\beta \\mathcal{P}^{1}'
650
651
The empty tuple represents the unit element 1::
652
653
sage: serre_cartan_mono_to_string(())
654
'1'
655
sage: serre_cartan_mono_to_string((), p=7)
656
'1'
657
"""
658
if latex:
659
if p == 2:
660
sq = "\\text{Sq}"
661
P = "\\text{Sq}"
662
else:
663
P = "\\mathcal{P}"
664
else:
665
if p == 2:
666
sq = "Sq"
667
P = "Sq"
668
else:
669
P = "P"
670
if len(mono) == 0 or mono == (0,):
671
return "1"
672
else:
673
if p == 2:
674
string = ""
675
for n in mono:
676
string = string + sq + "^{" + str(n) + "} "
677
else:
678
string = ""
679
index = 0
680
for n in mono:
681
from sage.misc.functional import is_even
682
if is_even(index):
683
if n == 1:
684
if latex:
685
string = string + "\\beta "
686
else:
687
string = string + "beta "
688
else:
689
string = string + P + "^{" + str(n) + "} "
690
index += 1
691
return string.strip(" ")
692
693
def wood_mono_to_string(mono, latex=False):
694
"""
695
String representation of element of Wood's Y and Z bases.
696
697
This is used by the _repr_ and _latex_ methods.
698
699
INPUT:
700
701
- ``mono`` - tuple of pairs of non-negative integers (s,t)
702
703
- ``latex`` - boolean (optional, default False), if true, output
704
LaTeX string
705
706
OUTPUT: ``string`` - concatenation of strings of the form
707
``Sq^{2^s (2^{t+1}-1)}`` for each pair (s,t)
708
709
EXAMPLES::
710
711
sage: from sage.algebras.steenrod.steenrod_algebra_misc import wood_mono_to_string
712
sage: wood_mono_to_string(((1,2),(3,0)))
713
'Sq^{14} Sq^{8}'
714
sage: wood_mono_to_string(((1,2),(3,0)),latex=True)
715
'\\text{Sq}^{14} \\text{Sq}^{8}'
716
717
The empty tuple represents the unit element::
718
719
sage: wood_mono_to_string(())
720
'1'
721
"""
722
if latex:
723
sq = "\\text{Sq}"
724
else:
725
sq = "Sq"
726
if len(mono) == 0:
727
return "1"
728
else:
729
string = ""
730
for (s,t) in mono:
731
string = string + sq + "^{" + \
732
str(2**s * (2**(t+1)-1)) + "} "
733
return string.strip(" ")
734
735
def wall_mono_to_string(mono, latex=False):
736
"""
737
String representation of element of Wall's basis.
738
739
This is used by the _repr_ and _latex_ methods.
740
741
INPUT:
742
743
- ``mono`` - tuple of pairs of non-negative integers (m,k) with `m
744
>= k`
745
746
- ``latex`` - boolean (optional, default False), if true, output
747
LaTeX string
748
749
OUTPUT: ``string`` - concatenation of strings ``Q^{m}_{k}`` for
750
each pair (m,k)
751
752
EXAMPLES::
753
754
sage: from sage.algebras.steenrod.steenrod_algebra_misc import wall_mono_to_string
755
sage: wall_mono_to_string(((1,2),(3,0)))
756
'Q^{1}_{2} Q^{3}_{0}'
757
sage: wall_mono_to_string(((1,2),(3,0)),latex=True)
758
'Q^{1}_{2} Q^{3}_{0}'
759
760
The empty tuple represents the unit element::
761
762
sage: wall_mono_to_string(())
763
'1'
764
"""
765
if len(mono) == 0:
766
return "1"
767
else:
768
string = ""
769
for (m,k) in mono:
770
string = string + "Q^{" + str(m) + "}_{" \
771
+ str(k) + "} "
772
return string.strip(" ")
773
774
def wall_long_mono_to_string(mono, latex=False):
775
"""
776
Alternate string representation of element of Wall's basis.
777
778
This is used by the _repr_ and _latex_ methods.
779
780
INPUT:
781
782
- ``mono`` - tuple of pairs of non-negative integers (m,k) with `m
783
>= k`
784
785
- ``latex`` - boolean (optional, default False), if true, output
786
LaTeX string
787
788
OUTPUT: ``string`` - concatenation of strings of the form
789
``Sq^(2^m)``
790
791
EXAMPLES::
792
793
sage: from sage.algebras.steenrod.steenrod_algebra_misc import wall_long_mono_to_string
794
sage: wall_long_mono_to_string(((1,2),(3,0)))
795
'Sq^{1} Sq^{2} Sq^{4} Sq^{8}'
796
sage: wall_long_mono_to_string(((1,2),(3,0)),latex=True)
797
'\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{4} \\text{Sq}^{8}'
798
799
The empty tuple represents the unit element::
800
801
sage: wall_long_mono_to_string(())
802
'1'
803
"""
804
if latex:
805
sq = "\\text{Sq}"
806
else:
807
sq = "Sq"
808
if len(mono) == 0:
809
return "1"
810
else:
811
string = ""
812
for (m,k) in mono:
813
for i in range(k,m+1):
814
string = string + sq + "^{" + str(2**i) + "} "
815
return string.strip(" ")
816
817
def arnonA_mono_to_string(mono, latex=False, p=2):
818
"""
819
String representation of element of Arnon's A basis.
820
821
This is used by the _repr_ and _latex_ methods.
822
823
INPUT:
824
825
- ``mono`` - tuple of pairs of non-negative integers
826
(m,k) with `m >= k`
827
828
- ``latex`` - boolean (optional, default False), if true, output
829
LaTeX string
830
831
OUTPUT: ``string`` - concatenation of strings of the form
832
``X^{m}_{k}`` for each pair (m,k)
833
834
EXAMPLES::
835
836
sage: from sage.algebras.steenrod.steenrod_algebra_misc import arnonA_mono_to_string
837
sage: arnonA_mono_to_string(((1,2),(3,0)))
838
'X^{1}_{2} X^{3}_{0}'
839
sage: arnonA_mono_to_string(((1,2),(3,0)),latex=True)
840
'X^{1}_{2} X^{3}_{0}'
841
842
The empty tuple represents the unit element::
843
844
sage: arnonA_mono_to_string(())
845
'1'
846
"""
847
if len(mono) == 0:
848
return "1"
849
else:
850
string = ""
851
for (m,k) in mono:
852
string = string + "X^{" + str(m) + "}_{" \
853
+ str(k) + "} "
854
return string.strip(" ")
855
856
def arnonA_long_mono_to_string(mono, latex=False, p=2):
857
"""
858
Alternate string representation of element of Arnon's A basis.
859
860
This is used by the _repr_ and _latex_ methods.
861
862
INPUT:
863
864
- ``mono`` - tuple of pairs of non-negative integers (m,k) with `m
865
>= k`
866
867
- ``latex`` - boolean (optional, default False), if true, output
868
LaTeX string
869
870
OUTPUT: ``string`` - concatenation of strings of the form
871
``Sq(2^m)``
872
873
EXAMPLES::
874
875
sage: from sage.algebras.steenrod.steenrod_algebra_misc import arnonA_long_mono_to_string
876
sage: arnonA_long_mono_to_string(((1,2),(3,0)))
877
'Sq^{8} Sq^{4} Sq^{2} Sq^{1}'
878
sage: arnonA_long_mono_to_string(((1,2),(3,0)),latex=True)
879
'\\text{Sq}^{8} \\text{Sq}^{4} \\text{Sq}^{2} \\text{Sq}^{1}'
880
881
The empty tuple represents the unit element::
882
883
sage: arnonA_long_mono_to_string(())
884
'1'
885
"""
886
if latex:
887
sq = "\\text{Sq}"
888
else:
889
sq = "Sq"
890
if len(mono) == 0:
891
return "1"
892
else:
893
string = ""
894
for (m,k) in mono:
895
for i in range(m,k-1,-1):
896
string = string + sq + "^{" + str(2**i) + "} "
897
return string.strip(" ")
898
899
def pst_mono_to_string(mono, latex=False, p=2):
900
r"""
901
String representation of element of a `P^s_t`-basis.
902
903
This is used by the _repr_ and _latex_ methods.
904
905
INPUT:
906
907
- ``mono`` - tuple of pairs of integers (s,t) with `s >= 0`, `t >
908
0`
909
910
- ``latex`` - boolean (optional, default False), if true, output
911
LaTeX string
912
913
- ``p`` - positive prime number (optional, default 2).
914
915
OUTPUT: ``string`` - concatenation of strings of the form
916
``P^{s}_{t}`` for each pair (s,t)
917
918
EXAMPLES::
919
920
sage: from sage.algebras.steenrod.steenrod_algebra_misc import pst_mono_to_string
921
sage: pst_mono_to_string(((1,2),(0,3)), p=2)
922
'P^{1}_{2} P^{0}_{3}'
923
sage: pst_mono_to_string(((1,2),(0,3)),latex=True, p=2)
924
'P^{1}_{2} P^{0}_{3}'
925
sage: pst_mono_to_string(((1,4), (((1,2), 1),((0,3), 2))), p=3)
926
'Q_{1} Q_{4} P^{1}_{2} (P^{0}_{3})^2'
927
sage: pst_mono_to_string(((1,4), (((1,2), 1),((0,3), 2))), latex=True, p=3)
928
'Q_{1} Q_{4} P^{1}_{2} (P^{0}_{3})^{2}'
929
930
The empty tuple represents the unit element::
931
932
sage: pst_mono_to_string(())
933
'1'
934
"""
935
if len(mono) == 0:
936
return "1"
937
else:
938
string = ""
939
if p == 2:
940
for (s,t) in mono:
941
string = string + "P^{" + str(s) + "}_{" \
942
+ str(t) + "} "
943
else:
944
for e in mono[0]:
945
string = string + "Q_{" + str(e) + "} "
946
for ((s,t), n) in mono[1]:
947
if n == 1:
948
string = string + "P^{" + str(s) + "}_{" \
949
+ str(t) + "} "
950
else:
951
if latex:
952
pow = "{%s}" % n
953
else:
954
pow = str(n)
955
string = string + "(P^{" + str(s) + "}_{" \
956
+ str(t) + "})^" + pow + " "
957
return string.strip(" ")
958
959
def comm_mono_to_string(mono, latex=False, p=2):
960
r"""
961
String representation of element of a commutator basis.
962
963
This is used by the _repr_ and _latex_ methods.
964
965
INPUT:
966
967
- ``mono`` - tuple of pairs of integers (s,t) with `s >= 0`, `t >
968
0`
969
970
- ``latex`` - boolean (optional, default False), if true, output
971
LaTeX string
972
973
- ``p`` - positive prime number (optional, default 2)
974
975
OUTPUT: ``string`` - concatenation of strings of the form
976
``c_{s,t}`` for each pair (s,t)
977
978
EXAMPLES::
979
980
sage: from sage.algebras.steenrod.steenrod_algebra_misc import comm_mono_to_string
981
sage: comm_mono_to_string(((1,2),(0,3)), p=2)
982
'c_{1,2} c_{0,3}'
983
sage: comm_mono_to_string(((1,2),(0,3)), latex=True, p=2)
984
'c_{1,2} c_{0,3}'
985
sage: comm_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), p=5)
986
'Q_{1} Q_{4} c_{1,2} c_{0,3}^2'
987
sage: comm_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), latex=True, p=5)
988
'Q_{1} Q_{4} c_{1,2} c_{0,3}^{2}'
989
990
The empty tuple represents the unit element::
991
992
sage: comm_mono_to_string(())
993
'1'
994
"""
995
if len(mono) == 0:
996
return "1"
997
else:
998
string = ""
999
if p == 2:
1000
for (s,t) in mono:
1001
string = string + "c_{" + str(s) + "," \
1002
+ str(t) + "} "
1003
else:
1004
for e in mono[0]:
1005
string = string + "Q_{" + str(e) + "} "
1006
for ((s,t), n) in mono[1]:
1007
string = string + "c_{" + str(s) + "," \
1008
+ str(t) + "}"
1009
if n > 1:
1010
if latex:
1011
pow = "^{%s}" % n
1012
else:
1013
pow = "^%s" % n
1014
string = string + pow
1015
string = string + " "
1016
return string.strip(" ")
1017
1018
def comm_long_mono_to_string(mono, latex=False, p=2):
1019
r"""
1020
Alternate string representation of element of a commutator basis.
1021
1022
Okay in low dimensions, but gets unwieldy as the dimension
1023
increases.
1024
1025
INPUT:
1026
1027
- ``mono`` - tuple of pairs of integers (s,t) with `s >= 0`, `t >
1028
0`
1029
1030
- ``latex`` - boolean (optional, default False), if true, output
1031
LaTeX string
1032
1033
- ``p`` - positive prime number (optional, default 2).
1034
1035
OUTPUT: ``string`` - concatenation of strings of the form ``s_{2^s
1036
... 2^(s+t-1)}`` for each pair (s,t)
1037
1038
EXAMPLES::
1039
1040
sage: from sage.algebras.steenrod.steenrod_algebra_misc import comm_long_mono_to_string
1041
sage: comm_long_mono_to_string(((1,2),(0,3)))
1042
's_{24} s_{124}'
1043
sage: comm_long_mono_to_string(((1,2),(0,3)),latex=True)
1044
's_{24} s_{124}'
1045
sage: comm_long_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), p=5)
1046
'Q_{1} Q_{4} s_{5,25} s_{1,5,25}^2'
1047
sage: comm_long_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), latex=True, p=3)
1048
'Q_{1} Q_{4} s_{3,9} s_{1,3,9}^{2}'
1049
1050
The empty tuple represents the unit element::
1051
1052
sage: comm_long_mono_to_string(())
1053
'1'
1054
"""
1055
if len(mono) == 0:
1056
return "1"
1057
else:
1058
string = ""
1059
if p == 2:
1060
for (s,t) in mono:
1061
if s + t > 4:
1062
comma = ","
1063
else:
1064
comma = ""
1065
string = string + "s_{"
1066
for i in range(t):
1067
string = string + str(2**(s+i)) + comma
1068
string = string.strip(",") + "} "
1069
else:
1070
for e in mono[0]:
1071
string = string + "Q_{" + str(e) + "} "
1072
for ((s,t), n) in mono[1]:
1073
string = string + "s_{"
1074
for i in range(t):
1075
string = string + str(p**(s+i)) + ","
1076
string = string.strip(",") + "}"
1077
if n > 1:
1078
if latex:
1079
pow = "^{%s}" % n
1080
else:
1081
pow = "^%s" % n
1082
string = string + pow
1083
string = string + " "
1084
return string.strip(" ")
1085
1086
# miscellany:
1087
1088
def convert_perm(m):
1089
"""
1090
Convert tuple m of non-negative integers to a permutation in
1091
one-line form.
1092
1093
INPUT:
1094
1095
- ``m`` - tuple of non-negative integers with no repetitions
1096
1097
OUTPUT: ``list`` - conversion of ``m`` to a permutation of the set
1098
1,2,...,len(m)
1099
1100
If ``m=(3,7,4)``, then one can view ``m`` as representing the
1101
permutation of the set `(3,4,7)` sending 3 to 3, 4 to 7, and 7 to
1102
4. This function converts ``m`` to the list ``[1,3,2]``, which
1103
represents essentially the same permutation, but of the set
1104
`(1,2,3)`. This list can then be passed to :func:`Permutation
1105
<sage.combinat.permutation.Permutation>`, and its signature can be
1106
computed.
1107
1108
EXAMPLES::
1109
1110
sage: sage.algebras.steenrod.steenrod_algebra_misc.convert_perm((3,7,4))
1111
[1, 3, 2]
1112
sage: sage.algebras.steenrod.steenrod_algebra_misc.convert_perm((5,0,6,3))
1113
[3, 1, 4, 2]
1114
"""
1115
m2 = sorted(m)
1116
return [list(m2).index(x)+1 for x in m]
1117
1118