Path: blob/master/sage/algebras/steenrod/steenrod_algebra_misc.py
4145 views
"""1Miscellaneous functions for the Steenrod algebra and its elements23AUTHORS:45- John H. Palmieri (2008-07-30): initial version (as the file6steenrod_algebra_element.py)78- John H. Palmieri (2010-06-30): initial version of steenrod_misc.py.9Implemented profile functions. Moved most of the methods for10elements to the ``Element`` subclass of11:class:`sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra_generic`.1213The main functions here are1415- :func:`get_basis_name`. This function takes a string as input and16attempts to interpret it as the name of a basis for the Steenrod17algebra; it returns the canonical name attached to that basis. This18allows for the use of synonyms when defining bases, while the19resulting algebras will be identical.2021- :func:`normalize_profile`. This function returns the canonical (and22hashable) description of any profile function. See23:mod:`sage.algebras.steenrod.steenrod_algebra` and24:func:`SteenrodAlgebra <sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra>`25for information on profile functions.2627- functions named ``*_mono_to_string`` where ``*`` is a basis name28(:func:`milnor_mono_to_string`, etc.). These convert tuples29representing basis elements to strings, for _repr_ and _latex_30methods.31"""3233#*****************************************************************************34# Copyright (C) 2008-2010 John H. Palmieri <[email protected]>35# Distributed under the terms of the GNU General Public License (GPL)36#*****************************************************************************3738######################################################39# basis names4041_steenrod_milnor_basis_names = ['milnor']42_steenrod_serre_cartan_basis_names = ['serre_cartan', 'serre-cartan', 'sc',43'adem', 'admissible']4445def get_basis_name(basis, p):46"""47Return canonical basis named by string basis at the prime p.4849INPUT:5051- ``basis`` - string5253- ``p`` - positive prime number5455OUTPUT:5657- ``basis_name`` - string5859Specify the names of the implemented bases. The input is60converted to lower-case, then processed to return the canonical61name for the basis.6263For the Milnor and Serre-Cartan bases, use the list of synonyms64defined by the variables :data:`_steenrod_milnor_basis_names` and65:data:`_steenrod_serre_cartan_basis_names`. Their canonical names66are 'milnor' and 'serre-cartan', respectively.6768For the other bases, use pattern-matching rather than a list of69synonyms:7071- Search for 'wood' and 'y' or 'wood' and 'z' to get the Wood72bases. Canonical names 'woody', 'woodz'.7374- Search for 'arnon' and 'c' for the Arnon C basis. Canonical75name: 'arnonc'.7677- Search for 'arnon' (and no 'c') for the Arnon A basis. Also see78if 'long' is present, for the long form of the basis. Canonical79names: 'arnona', 'arnona_long'.8081- Search for 'wall' for the Wall basis. Also see if 'long' is82present. Canonical names: 'wall', 'wall_long'.8384- Search for 'pst' for P^s_t bases, then search for the order85type: 'rlex', 'llex', 'deg', 'revz'. Canonical names:86'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz'.8788- For commutator types, search for 'comm', an order type, and also89check to see if 'long' is present. Canonical names:90'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz',91'comm_rlex_long', 'comm_llex_long', 'comm_deg_long',92'comm_revz_long'.9394EXAMPLES::9596sage: from sage.algebras.steenrod.steenrod_algebra_misc import get_basis_name97sage: get_basis_name('adem', 2)98'serre-cartan'99sage: get_basis_name('milnor', 2)100'milnor'101sage: get_basis_name('MiLNoR', 5)102'milnor'103sage: get_basis_name('pst-llex', 2)104'pst_llex'105sage: get_basis_name('wood_abcdedfg_y', 2)106'woody'107sage: get_basis_name('arnon--hello--long', 2)108'arnona_long'109sage: get_basis_name('arnona_long', p=5)110Traceback (most recent call last):111...112ValueError: arnona_long is not a recognized basis at the prime 5.113sage: get_basis_name('NOT_A_BASIS', 2)114Traceback (most recent call last):115...116ValueError: not_a_basis is not a recognized basis at the prime 2.117"""118basis = basis.lower()119if basis in _steenrod_milnor_basis_names:120result = 'milnor'121elif basis in _steenrod_serre_cartan_basis_names:122result = 'serre-cartan'123elif basis.find('pst') >= 0:124if basis.find('rlex') >= 0:125result = 'pst_rlex'126elif basis.find('llex') >= 0:127result = 'pst_llex'128elif basis.find('deg') >= 0:129result = 'pst_deg'130elif basis.find('revz') >= 0:131result = 'pst_revz'132else:133result = 'pst_revz'134elif basis.find('comm') >= 0:135if basis.find('rlex') >= 0:136result = 'comm_rlex'137elif basis.find('llex') >= 0:138result = 'comm_llex'139elif basis.find('deg') >= 0:140result = 'comm_deg'141elif basis.find('revz') >= 0:142result = 'comm_revz'143else:144result = 'comm_revz'145if basis.find('long') >= 0:146result = result + '_long'147elif p == 2 and basis.find('wood') >= 0:148if basis.find('y') >= 0:149result = 'woody'150elif basis.find('z') >= 0:151result = 'woodz'152elif p == 2 and basis.find('arnon') >= 0:153if basis.find('c') >= 0:154result = 'arnonc'155else:156result = 'arnona'157if basis.find('long') >= 0:158result = result + '_long'159elif p == 2 and basis.find('wall') >= 0:160result = 'wall'161if basis.find('long') >= 0:162result = result + '_long'163else:164raise ValueError("%s is not a recognized basis at the prime %s." % (basis, p))165return result166167######################################################168# profile functions169170def is_valid_profile(profile, truncation_type, p=2):171"""172True if ``profile``, together with ``truncation_type``, is a valid173profile at the prime `p`.174175INPUT:176177- ``profile`` - when `p=2`, a tuple or list of numbers; when `p`178is odd, a pair of such lists179180- ``truncation_type`` - either 0 or `\infty`181182- `p` - prime number, optional, default 2183184OUTPUT: True if the profile function is valid, False otherwise.185186See the documentation for :mod:`sage.algebras.steenrod.steenrod_algebra`187for descriptions of profile functions and how they correspond to188sub-Hopf algebras of the Steenrod algebra. Briefly: at the prime1892, a profile function `e` is valid if it satisfies the condition190191- `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`.192193At odd primes, a pair of profile functions `e` and `k` are valid194if they satisfy195196- `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`.197198- if `k(i+j) = 1`, then either `e(i) \leq j` or `k(j) = 1` for all199`i \geq 1`, `j \geq 0`.200201In this function, profile functions are lists or tuples, and202``truncation_type`` is appended as the last element of the list203`e` before testing.204205EXAMPLES:206207`p=2`::208209sage: from sage.algebras.steenrod.steenrod_algebra_misc import is_valid_profile210sage: is_valid_profile([3,2,1], 0)211True212sage: is_valid_profile([3,2,1], Infinity)213True214sage: is_valid_profile([1,2,3], 0)215False216sage: is_valid_profile([6,2,0], Infinity)217False218sage: is_valid_profile([0,3], 0)219False220sage: is_valid_profile([0,0,4], 0)221False222sage: is_valid_profile([0,0,0,4,0], 0)223True224225Odd primes::226227sage: is_valid_profile(([0,0,0], [2,1,1,1,2,2]), 0, p=3)228True229sage: is_valid_profile(([1], [2,2]), 0, p=3)230True231sage: is_valid_profile(([1], [2]), 0, p=7)232False233sage: is_valid_profile(([1,2,1], []), 0, p=7)234True235"""236from sage.rings.infinity import Infinity237if p == 2:238pro = list(profile) + [truncation_type]*len(profile)239r = 0240for pro_r in pro:241r += 1 # index of pro_r242if pro_r < Infinity:243for i in range(1,r):244if pro_r < min(pro[r-i-1] - i, pro[i-1]):245return False246else:247# p odd:248e = list(profile[0]) + [truncation_type]*len(profile[0])249k = list(profile[1])250if not set(k).issubset(set([1,2])):251return False252if truncation_type > 0:253k = k + [2]254else:255k = k + [1]*len(profile[0])256if len(k) > len(e):257e = e + [truncation_type] * (len(k) - len(e))258r = 0259for e_r in e:260r += 1 # index of e_r261if e_r < Infinity:262for i in range(1,r):263if e_r < min(e[r-i-1] - i, e[i-1]):264return False265r = -1266for k_r in k:267r += 1 # index of k_r268if k_r == 1:269for j in range(r):270i = r-j271if e[i-1] > j and k[j] == 2:272return False273return True274275def normalize_profile(profile, precision=None, truncation_type='auto', p=2):276"""277Given a profile function and related data, return it in a standard form,278suitable for hashing and caching as data defining a sub-Hopf279algebra of the Steenrod algebra.280281INPUT:282283- ``profile`` - a profile function in form specified below284- ``precision`` - integer or ``None``, optional, default ``None``285- ``truncation_type`` - 0 or `\infty` or 'auto', optional, default 'auto'286- `p` - prime, optional, default 2287288OUTPUT: a triple ``profile, precision, truncation_type``, in289standard form as described below.290291The "standard form" is as follows: ``profile`` should be a tuple292of integers (or `\infty`) with no trailing zeroes when `p=2`, or a293pair of such when `p` is odd. ``precision`` should be a positive294integer. ``truncation_type`` should be 0 or `\infty`.295Furthermore, this must be a valid profile, as determined by the296funtion :func:`is_valid_profile`. See also the documentation for297the module :mod:`sage.algebras.steenrod.steenrod_algebra` for information298about profile functions.299300For the inputs: when `p=2`, ``profile`` should be a valid profile301function, and it may be entered in any of the following forms:302303- a list or tuple, e.g., ``[3,2,1,1]``304- a function from positive integers to non-negative integers (and305`\infty`), e.g., ``lambda n: n+2``. This corresponds to the306list ``[3, 4, 5, ...]``.307- ``None`` or ``Infinity`` - use this for the profile function for308the whole Steenrod algebra. This corresponds to the list309``[Infinity, Infinity, Infinity, ...]``310311To make this hashable, it gets turned into a tuple. In the first312case it is clear how to do this; also in this case, ``precision``313is set to be one more than the length of this tuple. In the314second case, construct a tuple of length one less than315``precision`` (default value 100). In the last case, the empty316tuple is returned and ``precision`` is set to 1.317318Once a sub-Hopf algebra of the Steenrod algebra has been defined319using such a profile function, if the code requires any remaining320terms (say, terms after the 100th), then they are given by321``truncation_type`` if that is 0 or `\infty`. If322``truncation_type`` is 'auto', then in the case of a tuple, it323gets set to 0, while for the other cases it gets set to `\infty`.324325See the examples below.326327When `p` is odd, ``profile`` is a pair of "functions", so it may328have the following forms:329330- a pair of lists or tuples, the second of which takes values in331the set `\{1,2\}`, e.g., ``([3,2,1,1], [1,1,2,2,1])``.332333- a pair of functions, one (called `e`) from positive integers to334non-negative integers (and `\infty`), one (called `k`) from335non-negative integers to the set `\{1,2\}`, e.g.,336``(lambda n: n+2, lambda n: 1)``. This corresponds to the337pair ``([3, 4, 5, ...], [1, 1, 1, ...])``.338339- ``None`` or ``Infinity`` - use this for the profile function for340the whole Steenrod algebra. This corresponds to the pair341``([Infinity, Infinity, Infinity, ...], [2, 2, 2, ...])``.342343You can also mix and match the first two, passing a pair with344first entry a list and second entry a function, for instance. The345values of ``precision`` and ``truncation_type`` are determined by346the first entry.347348EXAMPLES:349350`p=2`::351352sage: from sage.algebras.steenrod.steenrod_algebra_misc import normalize_profile353sage: normalize_profile([1,2,1,0,0])354((1, 2, 1), 0)355356The full mod 2 Steenrod algebra::357358sage: normalize_profile(Infinity)359((), +Infinity)360sage: normalize_profile(None)361((), +Infinity)362sage: normalize_profile(lambda n: Infinity)363((), +Infinity)364365The ``precision`` argument has no effect when the first argument366is a list or tuple::367368sage: normalize_profile([1,2,1,0,0], precision=12)369((1, 2, 1), 0)370371If the first argument is a function, then construct a list of372length one less than ``precision``, by plugging in the numbers 1,3732, ..., ``precision`` - 1::374375sage: normalize_profile(lambda n: 4-n, precision=4)376((3, 2, 1), +Infinity)377sage: normalize_profile(lambda n: 4-n, precision=4, truncation_type=0)378((3, 2, 1), 0)379380Negative numbers in profile functions are turned into zeroes::381382sage: normalize_profile(lambda n: 4-n, precision=6)383((3, 2, 1, 0, 0), +Infinity)384385If it doesn't give a valid profile, an error is raised::386387sage: normalize_profile(lambda n: 3, precision=4, truncation_type=0)388Traceback (most recent call last):389...390ValueError: Invalid profile391sage: normalize_profile(lambda n: 3, precision=4, truncation_type = Infinity)392((3, 3, 3), +Infinity)393394When `p` is odd, the behavior is similar::395396sage: normalize_profile(([2,1], [2,2,2]), p=13)397(((2, 1), (2, 2, 2)), 0)398399The full mod `p` Steenrod algebra::400401sage: normalize_profile(None, p=7)402(((), ()), +Infinity)403sage: normalize_profile(Infinity, p=11)404(((), ()), +Infinity)405sage: normalize_profile((lambda n: Infinity, lambda n: 2), p=17)406(((), ()), +Infinity)407408Note that as at the prime 2, the ``precision`` argument has no409effect on a list or tuple in either entry of ``profile``. If410``truncation_type`` is 'auto', then it gets converted to either411``0`` or ``+Infinity`` depending on the *first* entry of412``profile``::413414sage: normalize_profile(([2,1], [2,2,2]), precision=84, p=13)415(((2, 1), (2, 2, 2)), 0)416sage: normalize_profile((lambda n: 0, lambda n: 2), precision=4, p=11)417(((0, 0, 0), ()), +Infinity)418sage: normalize_profile((lambda n: 0, (1,1,1,1,1,1,1)), precision=4, p=11)419(((0, 0, 0), (1, 1, 1, 1, 1, 1, 1)), +Infinity)420sage: normalize_profile(((4,3,2,1), lambda n: 2), precision=6, p=11)421(((4, 3, 2, 1), (2, 2, 2, 2, 2)), 0)422sage: normalize_profile(((4,3,2,1), lambda n: 1), precision=3, p=11, truncation_type=Infinity)423(((4, 3, 2, 1), (1, 1)), +Infinity)424425As at the prime 2, negative numbers in the first component are426converted to zeroes. Numbers in the second component must be427either 1 and 2, or else an error is raised::428429sage: normalize_profile((lambda n: -n, lambda n: 1), precision=4, p=11)430(((0, 0, 0), (1, 1, 1)), +Infinity)431sage: normalize_profile([[0,0,0], [1,2,3,2,1]], p=11)432Traceback (most recent call last):433...434ValueError: Invalid profile435"""436from inspect import isfunction437from sage.rings.infinity import Infinity438if truncation_type == 'zero':439truncation_type = 0440if truncation_type == 'infinity':441truncation_type = Infinity442if p == 2:443if profile is None or profile == Infinity:444# no specified profile or infinite profile: return profile445# for the entire Steenrod algebra446new_profile = ()447truncation_type = Infinity448elif isinstance(profile, (list, tuple)):449# profile is a list or tuple: use it as is. if450# truncation_type not specified, set it to 'zero'. remove451# trailing zeroes if truncation_type is 'auto' or 'zero'.452if truncation_type == 'auto':453truncation_type = 0454# remove trailing zeroes or Infinitys455while len(profile) > 0 and profile[-1] == truncation_type:456profile = profile[:-1]457new_profile = tuple(profile)458elif isfunction(profile):459# profile is a function: turn it into a tuple. if460# truncation_type not specified, set it to 'infinity' if461# the function is ever infinite; otherwise set it to462# 0. remove trailing zeroes if truncation_type is463# 0, trailing Infinitys if truncation_type is oo.464if precision is None:465precision = 100466if truncation_type == 'auto':467truncation_type = Infinity468new_profile = [max(0, profile(i)) for i in range(1, precision)]469# remove trailing zeroes or Infinitys:470while len(new_profile) > 0 and new_profile[-1] == truncation_type:471del new_profile[-1]472new_profile = tuple(new_profile)473if is_valid_profile(new_profile, truncation_type, p):474return new_profile, truncation_type475else:476raise ValueError("Invalid profile")477else: # p odd478if profile is None or profile == Infinity:479# no specified profile or infinite profile: return profile480# for the entire Steenrod algebra481new_profile = ((), ())482truncation_type = Infinity483else: # profile should be a list or tuple of length 2484assert isinstance(profile, (list, tuple)) and len(profile) == 2, \485"Invalid form for profile"486e = profile[0]487k = profile[1]488if isinstance(e, (list, tuple)):489# e is a list or tuple: use it as is. if490# truncation_type not specified, set it to 0. remove491# appropriate trailing terms.492if truncation_type == 'auto':493truncation_type = 0494# remove trailing terms495while len(e) > 0 and e[-1] == truncation_type:496e = e[:-1]497e = tuple(e)498elif isfunction(e):499# e is a function: turn it into a tuple. if500# truncation_type not specified, set it to 'infinity'501# if the function is ever infinite; otherwise set it502# to 0. remove appropriate trailing terms.503if precision is None:504e_precision = 100505else:506e_precision = precision507if truncation_type == 'auto':508truncation_type = Infinity509e = [max(0, e(i)) for i in range(1, e_precision)]510# remove trailing terms511while len(e) > 0 and e[-1] == truncation_type:512del e[-1]513e = tuple(e)514if isinstance(k, (list, tuple)):515# k is a list or tuple: use it as is.516k = tuple(k)517elif isfunction(k):518# k is a function: turn it into a tuple.519if precision is None:520k_precision = 100521else:522k_precision = precision523k = tuple([k(i) for i in range(k_precision-1)])524# Remove trailing ones from k if truncation_type is 'zero',525# remove trailing twos if truncation_type is 'Infinity'.526if truncation_type == 0:527while len(k) > 0 and k[-1] == 1:528k = k[:-1]529else:530while len(k) > 0 and k[-1] == 2:531k = k[:-1]532new_profile = (e, k)533if is_valid_profile(new_profile, truncation_type, p):534return new_profile, truncation_type535else:536raise ValueError("Invalid profile")537538######################################################539# string representations for elements540541def milnor_mono_to_string(mono, latex=False, p=2):542"""543String representation of element of the Milnor basis.544545This is used by the _repr_ and _latex_ methods.546547INPUT:548549- ``mono`` - if `p=2`, tuple of non-negative integers (a,b,c,...);550if `p>2`, pair of tuples of non-negative integers ((e0, e1, e2,551...), (r1, r2, ...))552553- ``latex`` - boolean (optional, default False), if true, output554LaTeX string555556- ``p`` - positive prime number (optional, default 2)557558OUTPUT: ``rep`` - string559560This returns a string like ``Sq(a,b,c,...)`` when p=2, or a string561like ``Q_e0 Q_e1 Q_e2 ... P(r1, r2, ...)`` when p is odd.562563EXAMPLES::564565sage: from sage.algebras.steenrod.steenrod_algebra_misc import milnor_mono_to_string566sage: milnor_mono_to_string((1,2,3,4))567'Sq(1,2,3,4)'568sage: milnor_mono_to_string((1,2,3,4),latex=True)569'\\text{Sq}(1,2,3,4)'570sage: milnor_mono_to_string(((1,0), (2,3,1)), p=3)571'Q_{1} Q_{0} P(2,3,1)'572sage: milnor_mono_to_string(((1,0), (2,3,1)), latex=True, p=3)573'Q_{1} Q_{0} \\mathcal{P}(2,3,1)'574575The empty tuple represents the unit element::576577sage: milnor_mono_to_string(())578'1'579sage: milnor_mono_to_string((), p=5)580'1'581"""582if latex:583if p == 2:584sq = "\\text{Sq}"585P = "\\text{Sq}"586else:587P = "\\mathcal{P}"588else:589if p == 2:590sq = "Sq"591P = "Sq"592else:593P = "P"594if mono == () or mono == (0,) or (p > 2 and len(mono[0]) + len(mono[1]) == 0):595return "1"596else:597if p == 2:598string = sq + "(" + str(mono[0])599for n in mono[1:]:600string = string + "," + str(n)601string = string + ")"602else:603string = ""604if len(mono[0]) > 0:605for e in mono[0]:606string = string + "Q_{" + str(e) + "} "607if len(mono[1]) > 0:608string = string + P + "(" + str(mono[1][0])609for n in mono[1][1:]:610string = string + "," + str(n)611string = string + ")"612return string.strip(" ")613614def serre_cartan_mono_to_string(mono, latex=False, p=2):615r"""616String representation of element of the Serre-Cartan basis.617618This is used by the _repr_ and _latex_ methods.619620INPUT:621622- ``mono`` - tuple of positive integers (a,b,c,...) when `p=2`,623or tuple (e0, n1, e1, n2, ...) when `p>2`, where each ei is 0 or6241, and each ni is positive625626- ``latex`` - boolean (optional, default False), if true, output627LaTeX string628629- ``p`` - positive prime number (optional, default 2)630631OUTPUT: ``rep`` - string632633This returns a string like ``Sq^{a} Sq^{b} Sq^{c} ...`` when634`p=2`, or a string like635``\beta^{e0} P^{n1} \beta^{e1} P^{n2} ...`` when `p`636is odd.637638EXAMPLES::639640sage: from sage.algebras.steenrod.steenrod_algebra_misc import serre_cartan_mono_to_string641sage: serre_cartan_mono_to_string((1,2,3,4))642'Sq^{1} Sq^{2} Sq^{3} Sq^{4}'643sage: serre_cartan_mono_to_string((1,2,3,4),latex=True)644'\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{4}'645sage: serre_cartan_mono_to_string((0,5,1,1,0), p=3)646'P^{5} beta P^{1}'647sage: serre_cartan_mono_to_string((0,5,1,1,0), p=3, latex=True)648'\\mathcal{P}^{5} \\beta \\mathcal{P}^{1}'649650The empty tuple represents the unit element 1::651652sage: serre_cartan_mono_to_string(())653'1'654sage: serre_cartan_mono_to_string((), p=7)655'1'656"""657if latex:658if p == 2:659sq = "\\text{Sq}"660P = "\\text{Sq}"661else:662P = "\\mathcal{P}"663else:664if p == 2:665sq = "Sq"666P = "Sq"667else:668P = "P"669if len(mono) == 0 or mono == (0,):670return "1"671else:672if p == 2:673string = ""674for n in mono:675string = string + sq + "^{" + str(n) + "} "676else:677string = ""678index = 0679for n in mono:680from sage.misc.functional import is_even681if is_even(index):682if n == 1:683if latex:684string = string + "\\beta "685else:686string = string + "beta "687else:688string = string + P + "^{" + str(n) + "} "689index += 1690return string.strip(" ")691692def wood_mono_to_string(mono, latex=False):693"""694String representation of element of Wood's Y and Z bases.695696This is used by the _repr_ and _latex_ methods.697698INPUT:699700- ``mono`` - tuple of pairs of non-negative integers (s,t)701702- ``latex`` - boolean (optional, default False), if true, output703LaTeX string704705OUTPUT: ``string`` - concatenation of strings of the form706``Sq^{2^s (2^{t+1}-1)}`` for each pair (s,t)707708EXAMPLES::709710sage: from sage.algebras.steenrod.steenrod_algebra_misc import wood_mono_to_string711sage: wood_mono_to_string(((1,2),(3,0)))712'Sq^{14} Sq^{8}'713sage: wood_mono_to_string(((1,2),(3,0)),latex=True)714'\\text{Sq}^{14} \\text{Sq}^{8}'715716The empty tuple represents the unit element::717718sage: wood_mono_to_string(())719'1'720"""721if latex:722sq = "\\text{Sq}"723else:724sq = "Sq"725if len(mono) == 0:726return "1"727else:728string = ""729for (s,t) in mono:730string = string + sq + "^{" + \731str(2**s * (2**(t+1)-1)) + "} "732return string.strip(" ")733734def wall_mono_to_string(mono, latex=False):735"""736String representation of element of Wall's basis.737738This is used by the _repr_ and _latex_ methods.739740INPUT:741742- ``mono`` - tuple of pairs of non-negative integers (m,k) with `m743>= k`744745- ``latex`` - boolean (optional, default False), if true, output746LaTeX string747748OUTPUT: ``string`` - concatenation of strings ``Q^{m}_{k}`` for749each pair (m,k)750751EXAMPLES::752753sage: from sage.algebras.steenrod.steenrod_algebra_misc import wall_mono_to_string754sage: wall_mono_to_string(((1,2),(3,0)))755'Q^{1}_{2} Q^{3}_{0}'756sage: wall_mono_to_string(((1,2),(3,0)),latex=True)757'Q^{1}_{2} Q^{3}_{0}'758759The empty tuple represents the unit element::760761sage: wall_mono_to_string(())762'1'763"""764if len(mono) == 0:765return "1"766else:767string = ""768for (m,k) in mono:769string = string + "Q^{" + str(m) + "}_{" \770+ str(k) + "} "771return string.strip(" ")772773def wall_long_mono_to_string(mono, latex=False):774"""775Alternate string representation of element of Wall's basis.776777This is used by the _repr_ and _latex_ methods.778779INPUT:780781- ``mono`` - tuple of pairs of non-negative integers (m,k) with `m782>= k`783784- ``latex`` - boolean (optional, default False), if true, output785LaTeX string786787OUTPUT: ``string`` - concatenation of strings of the form788``Sq^(2^m)``789790EXAMPLES::791792sage: from sage.algebras.steenrod.steenrod_algebra_misc import wall_long_mono_to_string793sage: wall_long_mono_to_string(((1,2),(3,0)))794'Sq^{1} Sq^{2} Sq^{4} Sq^{8}'795sage: wall_long_mono_to_string(((1,2),(3,0)),latex=True)796'\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{4} \\text{Sq}^{8}'797798The empty tuple represents the unit element::799800sage: wall_long_mono_to_string(())801'1'802"""803if latex:804sq = "\\text{Sq}"805else:806sq = "Sq"807if len(mono) == 0:808return "1"809else:810string = ""811for (m,k) in mono:812for i in range(k,m+1):813string = string + sq + "^{" + str(2**i) + "} "814return string.strip(" ")815816def arnonA_mono_to_string(mono, latex=False, p=2):817"""818String representation of element of Arnon's A basis.819820This is used by the _repr_ and _latex_ methods.821822INPUT:823824- ``mono`` - tuple of pairs of non-negative integers825(m,k) with `m >= k`826827- ``latex`` - boolean (optional, default False), if true, output828LaTeX string829830OUTPUT: ``string`` - concatenation of strings of the form831``X^{m}_{k}`` for each pair (m,k)832833EXAMPLES::834835sage: from sage.algebras.steenrod.steenrod_algebra_misc import arnonA_mono_to_string836sage: arnonA_mono_to_string(((1,2),(3,0)))837'X^{1}_{2} X^{3}_{0}'838sage: arnonA_mono_to_string(((1,2),(3,0)),latex=True)839'X^{1}_{2} X^{3}_{0}'840841The empty tuple represents the unit element::842843sage: arnonA_mono_to_string(())844'1'845"""846if len(mono) == 0:847return "1"848else:849string = ""850for (m,k) in mono:851string = string + "X^{" + str(m) + "}_{" \852+ str(k) + "} "853return string.strip(" ")854855def arnonA_long_mono_to_string(mono, latex=False, p=2):856"""857Alternate string representation of element of Arnon's A basis.858859This is used by the _repr_ and _latex_ methods.860861INPUT:862863- ``mono`` - tuple of pairs of non-negative integers (m,k) with `m864>= k`865866- ``latex`` - boolean (optional, default False), if true, output867LaTeX string868869OUTPUT: ``string`` - concatenation of strings of the form870``Sq(2^m)``871872EXAMPLES::873874sage: from sage.algebras.steenrod.steenrod_algebra_misc import arnonA_long_mono_to_string875sage: arnonA_long_mono_to_string(((1,2),(3,0)))876'Sq^{8} Sq^{4} Sq^{2} Sq^{1}'877sage: arnonA_long_mono_to_string(((1,2),(3,0)),latex=True)878'\\text{Sq}^{8} \\text{Sq}^{4} \\text{Sq}^{2} \\text{Sq}^{1}'879880The empty tuple represents the unit element::881882sage: arnonA_long_mono_to_string(())883'1'884"""885if latex:886sq = "\\text{Sq}"887else:888sq = "Sq"889if len(mono) == 0:890return "1"891else:892string = ""893for (m,k) in mono:894for i in range(m,k-1,-1):895string = string + sq + "^{" + str(2**i) + "} "896return string.strip(" ")897898def pst_mono_to_string(mono, latex=False, p=2):899r"""900String representation of element of a `P^s_t`-basis.901902This is used by the _repr_ and _latex_ methods.903904INPUT:905906- ``mono`` - tuple of pairs of integers (s,t) with `s >= 0`, `t >9070`908909- ``latex`` - boolean (optional, default False), if true, output910LaTeX string911912- ``p`` - positive prime number (optional, default 2).913914OUTPUT: ``string`` - concatenation of strings of the form915``P^{s}_{t}`` for each pair (s,t)916917EXAMPLES::918919sage: from sage.algebras.steenrod.steenrod_algebra_misc import pst_mono_to_string920sage: pst_mono_to_string(((1,2),(0,3)), p=2)921'P^{1}_{2} P^{0}_{3}'922sage: pst_mono_to_string(((1,2),(0,3)),latex=True, p=2)923'P^{1}_{2} P^{0}_{3}'924sage: pst_mono_to_string(((1,4), (((1,2), 1),((0,3), 2))), p=3)925'Q_{1} Q_{4} P^{1}_{2} (P^{0}_{3})^2'926sage: pst_mono_to_string(((1,4), (((1,2), 1),((0,3), 2))), latex=True, p=3)927'Q_{1} Q_{4} P^{1}_{2} (P^{0}_{3})^{2}'928929The empty tuple represents the unit element::930931sage: pst_mono_to_string(())932'1'933"""934if len(mono) == 0:935return "1"936else:937string = ""938if p == 2:939for (s,t) in mono:940string = string + "P^{" + str(s) + "}_{" \941+ str(t) + "} "942else:943for e in mono[0]:944string = string + "Q_{" + str(e) + "} "945for ((s,t), n) in mono[1]:946if n == 1:947string = string + "P^{" + str(s) + "}_{" \948+ str(t) + "} "949else:950if latex:951pow = "{%s}" % n952else:953pow = str(n)954string = string + "(P^{" + str(s) + "}_{" \955+ str(t) + "})^" + pow + " "956return string.strip(" ")957958def comm_mono_to_string(mono, latex=False, p=2):959r"""960String representation of element of a commutator basis.961962This is used by the _repr_ and _latex_ methods.963964INPUT:965966- ``mono`` - tuple of pairs of integers (s,t) with `s >= 0`, `t >9670`968969- ``latex`` - boolean (optional, default False), if true, output970LaTeX string971972- ``p`` - positive prime number (optional, default 2)973974OUTPUT: ``string`` - concatenation of strings of the form975``c_{s,t}`` for each pair (s,t)976977EXAMPLES::978979sage: from sage.algebras.steenrod.steenrod_algebra_misc import comm_mono_to_string980sage: comm_mono_to_string(((1,2),(0,3)), p=2)981'c_{1,2} c_{0,3}'982sage: comm_mono_to_string(((1,2),(0,3)), latex=True, p=2)983'c_{1,2} c_{0,3}'984sage: comm_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), p=5)985'Q_{1} Q_{4} c_{1,2} c_{0,3}^2'986sage: comm_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), latex=True, p=5)987'Q_{1} Q_{4} c_{1,2} c_{0,3}^{2}'988989The empty tuple represents the unit element::990991sage: comm_mono_to_string(())992'1'993"""994if len(mono) == 0:995return "1"996else:997string = ""998if p == 2:999for (s,t) in mono:1000string = string + "c_{" + str(s) + "," \1001+ str(t) + "} "1002else:1003for e in mono[0]:1004string = string + "Q_{" + str(e) + "} "1005for ((s,t), n) in mono[1]:1006string = string + "c_{" + str(s) + "," \1007+ str(t) + "}"1008if n > 1:1009if latex:1010pow = "^{%s}" % n1011else:1012pow = "^%s" % n1013string = string + pow1014string = string + " "1015return string.strip(" ")10161017def comm_long_mono_to_string(mono, latex=False, p=2):1018r"""1019Alternate string representation of element of a commutator basis.10201021Okay in low dimensions, but gets unwieldy as the dimension1022increases.10231024INPUT:10251026- ``mono`` - tuple of pairs of integers (s,t) with `s >= 0`, `t >10270`10281029- ``latex`` - boolean (optional, default False), if true, output1030LaTeX string10311032- ``p`` - positive prime number (optional, default 2).10331034OUTPUT: ``string`` - concatenation of strings of the form ``s_{2^s1035... 2^(s+t-1)}`` for each pair (s,t)10361037EXAMPLES::10381039sage: from sage.algebras.steenrod.steenrod_algebra_misc import comm_long_mono_to_string1040sage: comm_long_mono_to_string(((1,2),(0,3)))1041's_{24} s_{124}'1042sage: comm_long_mono_to_string(((1,2),(0,3)),latex=True)1043's_{24} s_{124}'1044sage: comm_long_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), p=5)1045'Q_{1} Q_{4} s_{5,25} s_{1,5,25}^2'1046sage: comm_long_mono_to_string(((1, 4), (((1,2), 1),((0,3), 2))), latex=True, p=3)1047'Q_{1} Q_{4} s_{3,9} s_{1,3,9}^{2}'10481049The empty tuple represents the unit element::10501051sage: comm_long_mono_to_string(())1052'1'1053"""1054if len(mono) == 0:1055return "1"1056else:1057string = ""1058if p == 2:1059for (s,t) in mono:1060if s + t > 4:1061comma = ","1062else:1063comma = ""1064string = string + "s_{"1065for i in range(t):1066string = string + str(2**(s+i)) + comma1067string = string.strip(",") + "} "1068else:1069for e in mono[0]:1070string = string + "Q_{" + str(e) + "} "1071for ((s,t), n) in mono[1]:1072string = string + "s_{"1073for i in range(t):1074string = string + str(p**(s+i)) + ","1075string = string.strip(",") + "}"1076if n > 1:1077if latex:1078pow = "^{%s}" % n1079else:1080pow = "^%s" % n1081string = string + pow1082string = string + " "1083return string.strip(" ")10841085# miscellany:10861087def convert_perm(m):1088"""1089Convert tuple m of non-negative integers to a permutation in1090one-line form.10911092INPUT:10931094- ``m`` - tuple of non-negative integers with no repetitions10951096OUTPUT: ``list`` - conversion of ``m`` to a permutation of the set10971,2,...,len(m)10981099If ``m=(3,7,4)``, then one can view ``m`` as representing the1100permutation of the set `(3,4,7)` sending 3 to 3, 4 to 7, and 7 to11014. This function converts ``m`` to the list ``[1,3,2]``, which1102represents essentially the same permutation, but of the set1103`(1,2,3)`. This list can then be passed to :func:`Permutation1104<sage.combinat.permutation.Permutation>`, and its signature can be1105computed.11061107EXAMPLES::11081109sage: sage.algebras.steenrod.steenrod_algebra_misc.convert_perm((3,7,4))1110[1, 3, 2]1111sage: sage.algebras.steenrod.steenrod_algebra_misc.convert_perm((5,0,6,3))1112[3, 1, 4, 2]1113"""1114m2 = sorted(m)1115return [list(m2).index(x)+1 for x in m]111611171118