Ticket #3397: 3397-with-odd-primes.patch

File 3397-with-odd-primes.patch, 199.9 KB (added by jhpalmieri, 11 years ago)
  • sage/algebras/all.py

    # HG changeset patch
    # User J. H. Palmieri <palmieri@math.washington.edu>
    # Date 1216143896 25200
    # Node ID 0dfaa3830fdad9a70fed104b41b0b06b35ee6555
    # Parent  96e35b9306b1c3ba8c066e4877187ca1c18066a8
    Steenrod algebra
    
    diff -r 96e35b9306b1 -r 0dfaa3830fda sage/algebras/all.py
    a b from quaternion_algebra import (Quaterni 
    3131     hilbert_symbol, fundamental_discriminant)
    3232from quaternion_order import QuaternionOrderWithBasis, QuaternionDefiningOrder
    3333from quaternion_order_ideal import QuaternionOrderLeftIdeal, QuaternionOrderRightIdeal, QuaternionOrderTwoSidedIdeal
     34from steenrod_algebra import SteenrodAlgebra, steenrod_set_basis, Sq
     35from steenrod_algebra_bases import steenrod_algebra_basis
    3436
    3537   
    3638def is_R_algebra(Q, R):
    3739    # TODO: do something nontrivial when morphisms are defined.
    3840    return True
    39 
    40 
    41 
    42 
  • new file sage/algebras/steenrod_algebra.py

    diff -r 96e35b9306b1 -r 0dfaa3830fda sage/algebras/steenrod_algebra.py
    - +  
     1r"""
     2Computations in the mod p Steenrod algebra.
     3
     4AUTHORS:
     5    - John H. Palmieri (2008-07-15: version 0.7)
     6
     7This package provides for basic algebra in the mod $p$ Steenrod
     8algebra.  In this package, elements in the Steenrod algebra are
     9represented, by default, using the Milnor basis.
     10
     11EXAMPLES:
     12Basic arithmetic, $p=2$.  To construct an element of the mod 2
     13Steenrod algebra, use the function 'Sq':
     14    sage: a = Sq(1,2)
     15    sage: b = Sq(4,1)
     16    sage: z = a + b
     17    sage: z
     18    Sq(1,2) + Sq(4,1)
     19    sage: Sq(4) * Sq(1,2)
     20    Sq(1,1,1) + Sq(2,3) + Sq(5,2)
     21    sage: z**2          # non-negative exponents work as they should
     22    Sq(1,2,1) + Sq(4,1,1)
     23    sage: z**0
     24    Sq(0)
     25
     26Basic arithmetic, $p>2$.  To construct an element of the mod $p$
     27Steenrod algebra when $p$ is odd, you should first define a Steenrod
     28algebra, using the 'SteenrodAlgebra' command:
     29    sage: SteenrodAlgebra()   # 2 is the default prime
     30    mod 2 Steenrod algebra
     31    sage: A3 = SteenrodAlgebra(3)
     32    sage: A3
     33    mod 3 Steenrod algebra
     34
     35Having done this, the newly created algebra 'A3' has methods 'Q' and
     36'P' which construct elements of A3:   
     37    sage: c = A3.Q(1,3,6); c
     38    Q_1 Q_3 Q_6
     39    sage: d = A3.P(2,0,1); d
     40    P(2,0,1)
     41    sage: c * d
     42    Q_1 Q_3 Q_6 P(2,0,1)
     43    sage: e = A3.P(3)
     44    sage: d * e
     45    P(5,0,1)
     46    sage: e * d
     47    P(1,1,1) + P(5,0,1)
     48    sage: c * c
     49    0
     50    sage: e ** 3
     51    2 P(1,2)
     52
     53Note that one can construct an element like 'c' above in one step,
     54without first constructing the algebra:
     55    sage: c = SteenrodAlgebra(3).Q(1,3,6)
     56    sage: c
     57    Q_1 Q_3 Q_6
     58
     59And of course, you can do similar constructions with the mod 2
     60Steenrod algebra:
     61    sage: A = SteenrodAlgebra(2); A
     62    mod 2 Steenrod algebra
     63    sage: A.Sq(2,3,5)
     64    Sq(2,3,5)
     65    sage: A.P(2,3,5)   # when p=2, P = Sq
     66    Sq(2,3,5)
     67    sage: A.Q(1,4)     # when p=2, this gives a product of Milnor primitives
     68    Sq(0,1,0,0,1)
     69   
     70Regardless of the prime, each element has an 'excess', and if the
     71element is homogeneous, a 'degree'.  The excess of
     72$\text{Sq}(i_1,i_2,i_3,...)$ is $i_1 + i_2 + i_3 + ...$; when $p$
     73is odd, the excess of $Q_{0}^{\epsilon_0} Q_{1}^{\epsilon_1}
     74... \mathcal{P}(r_1, r_2, ...)$ is $\sum epsilon_i + 2 \sum r_i$.  The
     75excess of a linear combination of Milnor basis elements is the minimum
     76of the excesses of those basis elements.
     77
     78The degree of $\text{Sq}(i_1,i_2,i_3,...) is $i_1 + 3 i_2 + 7 i_3 +
     79... + (2^n-1) i_n + ...$, and when $p$ is odd, the degree of
     80$Q_{0}^{\epsilon_0} Q_{1}^{\epsilon_1} ... \mathcal{P}(r_1, r_2, ...)$
     81is $\sum \epsilon_i (2p^i - 1) + \sum r_j (2p^j - 2)$.  The degree of
     82a linear combination of such terms is only defined if the terms all
     83have the same degree.
     84
     85Here are some simple examples:
     86    sage: z = Sq(1,2) + Sq(4,1)
     87    sage: z.degree()
     88    7
     89    sage: (Sq(0,0,1) + Sq(5,3)).degree()
     90    Element is not homogeneous.
     91    sage: Sq(7,2,1).excess()
     92    10
     93    sage: z.excess()
     94    3
     95    sage: B = SteenrodAlgebra(3)
     96    sage: x = B.Q(1,4)
     97    sage: y = B.P(1,2,3)
     98    sage: x.degree()
     99    166
     100    sage: x.excess()
     101    2
     102    sage: y.excess()
     103    12
     104           
     105Elements have a 'weight' in the May filtration, which (when $p=2$) is
     106related to the 'height' function defined by Wall:
     107    sage: Sq(2,1,5).may_weight()
     108    9
     109    sage: Sq(2,1,5).wall_height()
     110    [2, 3, 2, 1, 1]
     111    sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
     112    sage: b.may_weight()
     113    2
     114    sage: b.wall_height()
     115    [0, 0, 1, 1]
     116
     117Odd primary May weights:   
     118    sage: A5 = SteenrodAlgebra(5)
     119    sage: a = A5.Q(1,2,4)
     120    sage: b = A5.P(1,2,1)
     121    sage: a.may_weight()
     122    3
     123    sage: b.may_weight()
     124    8
     125    sage: (a * b).may_weight()
     126    11
     127    sage: A5.P(0,0,1).may_weight()
     128    3
     129
     130Since the Steenrod algebra is a Hopf algebra, every element has an
     131antipode.
     132    sage: d = Sq(0,0,1); d
     133    Sq(0,0,1)
     134    sage: d.antipode()
     135    Sq(0,0,1)
     136    sage: Sq(4).antipode()
     137    Sq(1,1) + Sq(4)
     138    sage: (Sq(4) * Sq(2)).antipode()
     139    Sq(6)
     140    sage: SteenrodAlgebra(7).P(3,1).antipode()
     141    3 P(3,1) + 4 P(11)
     142
     143Applying the antipode twice returns the original element:
     144    sage: y = Sq(8)*Sq(4)
     145    sage: y == (y.antipode()).antipode()
     146    True
     147
     148You can treat elements of the Steenrod algebra like lists of Milnor
     149basis elements:
     150    sage: y = Sq(4) * Sq(1,2); y
     151    Sq(1,1,1) + Sq(2,3) + Sq(5,2)
     152    sage: for m in y: m
     153    Sq(1,1,1)
     154    Sq(2,3)
     155    Sq(5,2)
     156    sage: [(m.degree(),m.excess()) for m in y]
     157    [(11, 3), (11, 5), (11, 7)]
     158
     159Once you've define a Steenrod algebra, the method pst(s,t) is another
     160way to define elements of it: pst(s,t) is the Margolis element
     161$P^{s}_{t}$, the basis element $\mathcal{P}(0,...,0,p^s)$ with $p^s$
     162in position $t$:
     163    sage: A2 = SteenrodAlgebra(2)
     164    sage: Q2 = A2.pst(0,3)
     165    sage: Q2
     166    Sq(0,0,1)
     167    sage: Q2*Q2
     168    0
     169    sage: A2.pst(1,2) == Sq(2)*Sq(4) + Sq(4)*Sq(2)
     170    True
     171    sage: A5 = SteenrodAlgebra(5)
     172    sage: A5.pst(2,2)
     173    P(0,25)
     174
     175Different bases for the Steenrod algebra.
     176   
     177There are two standard vector space bases for the mod $p$ Steenrod
     178algebra: the Milnor basis and the Serre-Cartan basis.  When $p=2$,
     179there are also several other, less well-known, bases.  A number of
     180these have been implemented in this package.
     181
     182The 'current basis' is specified by calling the function
     183'steenrod_set_basis', with a string as an argument.  The default basis
     184is 'milnor'.  The choices are
     185
     186  * 'milnor': Milnor basis.  When $p=2$, the Milnor basis consists of
     187     symbols of the form $\text{Sq}(m_1, m_2, ..., m_t)$, where each
     188     $m_i$ is a non-negative integer and if $t>1$, then the last entry
     189     $m_t \neq 0$.  When $p$ is odd, the Milnor basis consists of
     190     symbols of the form $Q_{e_1} Q_{e_2} ... \mathcal{P}(m_1, m_2,
     191     ..., m_t)$, where $0 \leq e_1 < e_2 < ...$, each $m_i$ is a
     192     non-negative integer, and if $t>1$, then the last entry $m_t \neq
     193     0$.
     194
     195  * 'serre-cartan' or 'adem' or 'admissible': Serre-Cartan basis.  The
     196    Serre-Cartan basis consists of 'admissible monomials' in the
     197    Steenrod operations.  Thus at the prime 2, it consists of
     198    monomials $\text{Sq}^{m_1} \text{Sq}^{m_2} ... \text{Sq}^{m_t}$
     199    with $m_i \geq 2m_{i+1}$ for each $i$.  At odd primes, it consists
     200    of monomials $\beta^{\epsilon_0} \mathcal{P}^{s_1}
     201    \beta^{\epsilon_1} \mathcal{P}^{s_2} ...  \mathcal{P}^{s_k}
     202    \beta^{\epsilon_k}$ with each $\epsilon_i$ either 0 or 1, $s_i
     203    \geq p s_{i+1} + \epsilon_i$, and $s_k \geq 1$.
     204
     205When $p=2$, the element $\text{Sq}^a$ equals the Milnor element
     206$\text{Sq}(a)$; when $p$ is odd, $\mathcal{P}^a = \mathcal{P}(a)$ and
     207$\beta = Q_0$.  Hence for any Serre-Cartan basis element, one can
     208represent it in the Milnor basis by computing an appropriate product
     209using Milnor multiplication.
     210
     211The rest of these bases are only defined when $p=2$.
     212
     213  * 'wood_y': Wood's Y basis.  For pairs of non-negative integers
     214    $(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Y$
     215    basis consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with
     216    $(m_i,k_i) > (m_{i+1},k_{i+1})$, in left lex order.
     217
     218  * 'wood_z': Wood's Z basis.  For pairs of non-negative integers
     219    $(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Z$
     220    basis consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with
     221    $(m_i+k_i,m_i) > (m_{i+1}+k_{i+1},m_{i+1})$, in left lex order.
     222
     223  * 'wall': Wall's basis.  For any pair of integers $(m,k)$ with $m
     224    \geq k \geq 0$, let $Q^m_k = \text{Sq}^{2^k} \text{Sq}^{2^{k+1}}
     225    ... \text{Sq}^{2^m}$.  The elements of Wall's basis are monomials
     226    $Q^{m_0}_{k_0} ... Q^{m_t}_{k_t}$ with $(m_i, k_i) > (m_{i+1},
     227    k_{i+1})$, ordered left lexicographically.
     228
     229    The standard way of printing elements of the Wall basis is to
     230    write elements in terms of the $Q^m_k$.  If one sets the basis to
     231    'wall_long' instead of 'wall', then each $Q^m_k$ is expanded as a
     232    product of factors of the form $\text{Sq}^{2^i}$.
     233
     234  * 'arnon_a': Arnon's A basis.  For any pair of integers $(m,k)$ with
     235    $m \geq k \geq 0$, let $X^m_k = \text{Sq}^{2^m}
     236    \text{Sq}^{2^{m-1}} ... \text{Sq}^{2^k}$.  The elements of Arnon's
     237    A basis are monomials $X^{m_0}_{k_0} ... X^{m_t}_{k_t}$ with
     238    $(m_i, k_i) < (m_{i+1}, k_{i+1})$, ordered left lexicographically.
     239
     240    The standard way of printing elements of Arnon's A basis is to
     241    write elements in terms of the $X^m_k$.  If one sets the basis to
     242    'arnon_a_long' instead of 'arnon_a', then each $X^m_k$ is expanded
     243    as a product of factors of the form $\text{Sq}^{2^i}$.
     244
     245  * 'arnon_c': Arnon's C basis.  The elements of Arnon's C basis are
     246    monomials of the form $\text{Sq}^{t_1} ... \text{Sq}^{t_m}$ where
     247    for each $i$, we have $t_i \leq 2t_{i+1}$ and $2^i | t_{m-i}$.
     248
     249  * 'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz': various
     250    P^s_t-bases.  For integers $s \geq 0$ and $t > 0$, the element
     251    $P^s_t$ is the Milnor basis element $\text{Sq}(0, ..., 0, 2^s, 0,
     252    ...)$, with the nonzero entry in position $t$.  To obtain a
     253    $P^s_t$-basis, for each set $\{P^{s_1}_{t_1}, ...,
     254    P^{s_k}_{t_k}\}$ of (distinct) $P^s_t$'s, one chooses an ordering
     255    and forms the resulting monomial.  The set of all such monomials
     256    then forms a basis, and so one gets a basis by choosing an
     257    ordering on each monomial.
     258
     259    The strings 'rlex', 'llex', etc., correspond to the following
     260    orderings.  These are all 'global' -- they give a global ordering
     261    on the $P^s_t$'s, not different orderings depending on the
     262    monomial.  They order the $P^s_t$'s using the pair of integers
     263    $(s,t)$ as follows:
     264
     265      * 'rlex': right lexicographic ordering
     266
     267      * 'llex': left lexicographic ordering
     268
     269      * 'deg': ordered by degree, which is the same as left
     270        lexicographic ordering on the pair $(s+t,t)$
     271
     272      * 'revz': left lexicographic ordering on the pair $(s+t,s)$,
     273        which is the reverse of the ordering used (on elements in the
     274        same degrees as the $P^s_t$'s) in Wood's Z basis: 'revz'
     275        stands for 'reversed Z'.  This is the default: 'pst' is the
     276        same as 'pst_revz'.
     277
     278  * 'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz': various
     279    commutator bases.  Let $c_{i,1} = \text{Sq}^{2^i}$, let $c_{i,2} =
     280    [c_{i,1}, c_{i+1,1}]$, and inductively define $c_{i,k} =
     281    [c_{i,k-1}, c_{i+k-1,1}]$.  Thus $c_{i,k}$ is a $k$-fold iterated
     282    commutator of the elements $\text{Sq}^{2^i}$, ...,
     283    $\text{Sq}^{2^{i+k-1}}$.  Note that $\dim c_{i,k} = \dim P^i_k$.
     284
     285    To obtain a commutator basis, for each set $\{c_{s_1,t_1}, ...,
     286    c_{s_k,t_k}\}$ of (distinct) $c_{s,t}$'s, one chooses an ordering
     287    and forms the resulting monomial.  The set of all such monomials
     288    then forms a basis, and so one gets a basis by choosing an
     289    ordering on each monomial.  The strings 'rlex', etc., have the
     290    same meaning as for the orderings on $P^s_t$-bases.  As with the
     291    $P^s_t$-bases, 'comm_revz' is the default: 'comm' means
     292    'comm_revz'.
     293
     294    The commutator bases have alternative representations, obtained by
     295    appending 'long' to their names: instead of, say, $c_{2,2}$, the
     296    representation is $s_{48}$, indicating the commutator of
     297    $\text{Sq}^4$ and $\text{Sq}^8$, and $c_{0,3}$, which is equal to
     298    $[[\text{Sq}^1, \text{Sq}^2], \text{Sq}^4]$, is written as
     299    $s_{124}$.
     300
     301
     302Examples of these:
     303    sage: c = Sq(2) * Sq(1); c
     304    Sq(0,1) + Sq(3)
     305    sage: steenrod_set_basis('serre-cartan')
     306    'serre-cartan'
     307    sage: c
     308    Sq^{2} Sq^{1}
     309    sage: c.basis('milnor')
     310    Sq(0,1) + Sq(3)
     311    sage: steenrod_set_basis()   # no argument: print current basis
     312    'serre-cartan'
     313    sage: x = Sq(7,3,1)   # top class in the subalagebra A(2)
     314    sage: x
     315    Sq^{17} Sq^{5} Sq^{1}
     316    sage: steenrod_set_basis('pst')
     317    'pst'
     318    sage: x
     319    P^{0}_{1} P^{0}_{2} P^{1}_{1} P^{0}_{3} P^{1}_{2} P^{2}_{1}
     320    sage: x.basis('milnor')
     321    Sq(7,3,1)
     322    sage: a = Sq(0,0,2)
     323    sage: steenrod_set_basis('comm_revz')
     324    'comm_revz'
     325    sage: a
     326    c_{0,1} c_{1,1} c_{0,3} c_{2,1} + c_{0,2} c_{0,3} c_{2,1} + c_{1,3}
     327    sage: steenrod_set_basis('Beer')
     328    Warning: Beer is not a recognized basis, and is not implemented (unless
     329    you've done it yourself).
     330    'beer'
     331
     332As noted above, several of these ('arnon_a', 'wall', 'comm') have
     333alternate, longer, representations.  These provide ways of expressing
     334elements of the Steenrod algebra in terms of the $\text{Sq}^{2^n}$.
     335    sage: steenrod_set_basis('arnon_a_long')
     336    'arnon_a_long'
     337    sage: Sq(6)
     338    Sq^{1} Sq^{2} Sq^{1} Sq^{2} + Sq^{2} Sq^{4}
     339    sage: steenrod_set_basis('wall_long')
     340    'wall_long'
     341    sage: Sq(6)
     342    Sq^{2} Sq^{1} Sq^{2} Sq^{1} + Sq^{2} Sq^{4}
     343    sage: Sq(6).basis('comm_deg_long')
     344    s_{1} s_{2} s_{12} + s_{2} s_{4}
     345    sage: steenrod_set_basis('milnor')  # reset to the default
     346    'milnor'
     347
     348You can then test whether elements are contained in the Steenrod algebra:
     349    sage: w = Sq(2) * Sq(4)
     350    sage: w in SteenrodAlgebra(2)
     351    True
     352    sage: w in SteenrodAlgebra(17)
     353    False
     354   
     355Some properties of the Steenrod algebra are available:
     356    sage: A = SteenrodAlgebra(2)
     357    sage: A.ngens()  # number of generators
     358    +Infinity
     359    sage: A.gen(5)   # 5th generator
     360    Sq(32)
     361    sage: A.order()
     362    +Infinity
     363    sage: A.is_finite()
     364    False
     365    sage: A.is_commutative()
     366    False
     367    sage: A.is_noetherian()
     368    False
     369    sage: A.is_integral_domain()
     370    False
     371    sage: A.is_field()
     372    False
     373    sage: A.is_division_algebra()
     374    False
     375    sage: A.category()
     376    Category of algebras over Finite Field of size 2
     377
     378
     379Internal documentation for SteenrodAlgebraElement (for people who want
     380to delve into or extend the code):
     381
     382Attributes for a SteenrodAlgebraElement self:
     383
     384  self.base_field: GF(p), where p is the associated prime
     385
     386  self.prime: p
     387 
     388  self._raw: dictionary.  keys are basis names, taken from
     389    '_steenrod_basis_unique_names', and the associated values are
     390    dictionaries themselves; if the dictionary is nonempty, it gives
     391    the representation for that element in the given basis.  If it is
     392    empty, that means that the representation in that basis hasn't
     393    been computed yet.  The representation of an element with respect
     394    to a basis (other than the Milnor basis, which is how elements are
     395    stored internally) isn't computed until requested, either by
     396    calling the method _basis_dictionary('basis_name'), or more
     397    typically, by calling the method basis('basis_name') or setting
     398    the Steenrod algebra basis to 'basis' and then printing the
     399    element.
     400   
     401    The dictionaries are defined as follows.  In the Milnor basis at
     402    the prime 2, for example, since monomials are of the form
     403    Sq(a,b,c,...), then monomials are stored as tuples of integers
     404    (a,b,c,...).  Thus if y = Sq(5,3) + Sq(0,0,2), then
     405    y._raw['milnor'] is {{(0, 0, 2): 1, (5, 3): 1}.  (The 1's
     406    following the colons are the coefficients of the monomials
     407    associated to the tuples.)  Each basis has its own representation
     408    as a dictionary; Arnon's C basis represents basis elements as
     409    tuples of integers, just like the Milnor basis and the
     410    Serre-Cartan basis, while the other bases represent basis elements
     411    as tuples of pairs of integers.  From the descriptions of the
     412    bases given in the file 'steenrod_algebra_bases.py', it should be
     413    clear how to associate a tuple of pairs of integers to a basis
     414    element.  See also the function 'string_rep'.
     415
     416    When the element is initially defined by calling Sq() or
     417    SteenrodAlgebraElement(), typically only the 'milnor' dictionary
     418    is non-empty, while if the element is defined by the function
     419    'steenrod_algebra_basis', its dictionary for the given basis is
     420    also initialized correctly.  For example:
     421        sage: B = steenrod_algebra_basis(6,'adem'); B
     422        (Sq(6), Sq(3,1), Sq(0,2) + Sq(3,1) + Sq(6))
     423        sage: x = B[1]; x
     424        Sq(3,1)
     425        sage: x._raw
     426        {'milnor': {(3, 1): 1}, 'pst_revz': {}, 'wall': {}, 'pst_rlex': {},
     427        'comm_rlex': {}, 'pst_llex': {}, 'pst_deg': {}, 'comm_revz': {},
     428        'arnona': {}, 'comm_llex': {}, 'arnonc': {}, 'woody': {}, 'woodz': {},
     429        'serre-cartan': {(5, 1): 1}, 'comm_deg': {}}
     430       
     431    Note that the keys 'milnor' and 'serre-cartan' (a synonym for
     432    'adem') have nonempty associated values.
     433   
     434    When any element is converted to another basis (by changing the
     435    basis and then printing the element), its dictionary for that
     436    basis gets stored, as well:
     437        sage: steenrod_set_basis('arnona')
     438        'arnona'
     439        sage: x
     440        X^{0}_{0} X^{1}_{0} X^{1}_{1}
     441        sage: x._raw
     442        {'milnor': {(3, 1): 1}, 'pst_revz': {}, 'wall': {}, 'pst_rlex': {},
     443        'comm_rlex': {}, 'pst_llex': {}, 'pst_deg': {}, 'comm_revz': {},
     444        'arnona': {((0, 0), (1, 0), (1, 1)): 1}, 'comm_llex': {}, 'arnonc': {},
     445        'woody': {}, 'woodz': {}, 'serre-cartan': {(5, 1): 1}, 'comm_deg': {}}
     446        sage: steenrod_set_basis('milnor')
     447        'milnor'
     448
     449Methods for a SteenrodAlgebraElement self:
     450
     451Most of these are self-explanatory.
     452
     453    _mul_: multiply two elements.  This is done using Milnor
     454    multiplication, the code for which is in a separate file,
     455    'steenrod_milnor_multiplication'.  In a long computation, it seems
     456    that a lot of time is spent here, so one way to speed things up
     457    would be to optimize the Milnor multiplication routine.
     458
     459    _basis_dictionary: compute the dictionary of the element with
     460    respect to the given basis.  This is basically done by doing a
     461    basis conversion from the Milnor basis to the given basis.  There
     462    are two parts to this function; first, some elements (e.g.,
     463    Sq(2^n)) may be easy to convert directly.  This is done one basis
     464    at a time, and so takes up most of the lines of code.  If the
     465    element is not recognizable as being easy to convert, then the
     466    function 'milnor_convert' from the file 'steenrod_algebra_bases'
     467    is called.  This does linear algebra: computes the Milnor basis
     468    and the new basis in the appropriate dimension, computes the
     469    change-of-basis matrix, etc.
     470
     471    basis: display the element in the given basis.
     472
     473    _repr_ and _latex_ call the function string_rep, which has cases
     474    depending on the basis.
     475
     476If you want to implement a new basis for the Steenrod algebra:
     477
     478    In this file ('steenrod_algebra.py'):
     479
     480        add a variable (like '_steenrod_milnor_basis_names') with the
     481        synonyms for basis, and include this variable among all of the
     482        others in 'steenrod_set_basis'
     483
     484        add name of basis to '_steenrod_basis_unique_names'
     485
     486        add functionality to basis and string_rep, and add a
     487        BASIS_mono_to_string function
     488
     489    In the file 'steenrod_algebra_bases.py':
     490
     491        add appropriate lines to 'milnor_convert' and 'steenrod_algebra_basis'
     492
     493        add a function to compute the basis in a given dimension (to be
     494        called by 'steenrod_algebra_basis')
     495
     496   
     497REFERENCES:
     498    [Mil] J. W. Milnor, "The Steenrod algebra and its dual," Ann. of Math.
     499          (2) 67 (1958), 150--171.
     500    [Mon] K. G. Monks, "Change of basis, monomial relations, and $P^s_t$
     501          bases for the Steenrod algebra," J. Pure Appl. Algebra 125 (1998),
     502          no. 1-3, 235--260.
     503    [Woo] R. M. W. Wood, "Problems in the Steenrod algebra," Bull. London
     504          Math. Soc. 30 (1998), no. 5, 449--517.
     505"""
     506
     507#*****************************************************************************
     508#       Copyright (C) 2008 William Stein <wstein@gmail.com>
     509#       Copyright (C) 2008 John H. Palmieri <palmieri@math.washington.edu>
     510#  Distributed under the terms of the GNU General Public License (GPL)
     511#*****************************************************************************
     512
     513from sage.rings.ring import Algebra
     514from sage.algebras.algebra_element import AlgebraElement
     515from sage.structure.parent_gens import ParentWithGens
     516from sage.structure.element import RingElement
     517from sage.rings.all import GF
     518from sage.misc.functional import parent
     519from sage.rings.integer import Integer
     520
     521# Default prime for working with the Steenrod algebra.
     522_steenrod_prime = 2
     523
     524class SteenrodAlgebra(Algebra):
     525    r"""
     526    The mod $p$ Steenrod algebra.
     527
     528    EXAMPLES:
     529        sage: SteenrodAlgebra()   # 2 is the default prime
     530        mod 2 Steenrod algebra
     531        sage: SteenrodAlgebra(5)
     532        mod 5 Steenrod algebra
     533
     534    Some properties of the Steenrod algebra are available:
     535        sage: A = SteenrodAlgebra(2)
     536        sage: A.ngens()  # number of generators
     537        +Infinity
     538        sage: A.gen(5)   # 5th generator
     539        Sq(32)
     540        sage: A.order()
     541        +Infinity
     542        sage: A.is_finite()
     543        False
     544        sage: A.is_commutative()
     545        False
     546        sage: A.is_noetherian()
     547        False
     548        sage: A.is_integral_domain()
     549        False
     550        sage: A.is_field()
     551        False
     552        sage: A.is_division_algebra()
     553        False
     554        sage: A.category()
     555        Category of algebras over Finite Field of size 2
     556
     557    There are methods for constructing elements of the Steenrod algebra:
     558        sage: A2 = SteenrodAlgebra(2); A2
     559        mod 2 Steenrod algebra
     560        sage: A2.Sq(1,2,6)
     561        Sq(1,2,6)
     562        sage: A2.Q(3,4)  # product of Milnor primitives Q_3 and Q_4
     563        Sq(0,0,0,1,1)
     564        sage: A2.pst(2,3)  # Margolis pst element
     565        Sq(0,0,4)
     566        sage: A5 = SteenrodAlgebra(5); A5
     567        mod 5 Steenrod algebra
     568        sage: A5.P(1,2,6)
     569        P(1,2,6)
     570        sage: A5.Q(3,4)
     571        Q_3 Q_4
     572        sage: A5.Q(3,4) * A5.P(1,2,6)
     573        Q_3 Q_4 P(1,2,6)
     574        sage: A5.pst(2,3)
     575        P(0,0,25)
     576    """
     577
     578    def __init__(self, p=None):
     579        """
     580        INPUT:
     581            p (optional, default = 2) -- positive prime integer
     582       
     583        OUTPUT:
     584            mod p Steenrod algebra
     585
     586        EXAMPLES:
     587            sage: SteenrodAlgebra()   # 2 is the default prime
     588            mod 2 Steenrod algebra
     589            sage: SteenrodAlgebra(5)
     590            mod 5 Steenrod algebra
     591        """
     592        from sage.rings.arith import is_prime
     593        if p is None: p = _steenrod_prime
     594        if is_prime(p):
     595            self.prime = p
     596            ParentWithGens.__init__(self, GF(p))
     597        else:
     598            raise ValueError, "%s is not prime." % p
     599
     600
     601    def _repr_(self):
     602        """
     603        Printed representation of the Steenrod algebra.
     604
     605        EXAMPLES:
     606            sage: SteenrodAlgebra(3)
     607            mod 3 Steenrod algebra
     608            sage: B = SteenrodAlgebra(2003)
     609            sage: B
     610            mod 2003 Steenrod algebra
     611            sage: B._repr_()
     612            'mod 2003 Steenrod algebra'
     613        """
     614        return "mod %d Steenrod algebra" % self.prime
     615   
     616
     617    def _latex_(self):
     618        """
     619        LaTeX representation of the Steenrod algebra.
     620       
     621        EXAMPLES:
     622            sage: C = SteenrodAlgebra(3)
     623            sage: C
     624            mod 3 Steenrod algebra
     625            sage: C._latex_()
     626            '\\mathcal{A}_{3}'
     627        """
     628        return "\\mathcal{A}_{%s}" % self.prime
     629   
     630
     631    def ngens(self):
     632        """
     633        Number of generators of the Steenrod algebra.
     634
     635        This returns infinity, since the Steenrod algebra is infinitely
     636        generated.
     637
     638        EXAMPLES:
     639            sage: A = SteenrodAlgebra(3)
     640            sage: A.ngens()
     641            +Infinity
     642        """
     643        from sage.rings.infinity import Infinity
     644        return Infinity
     645
     646
     647    def gen(self, i=0):
     648        """
     649        The ith generator of the Steenrod algebra.
     650
     651        INPUT:
     652            i -- non-negative integer
     653
     654        OUTPUT: The ith generator of the Steenrod algebra: Sq(2**i) at
     655            the prime 2; when p is odd, the 0th generator is beta =
     656            Q(0), and for i>0, the ith generator is P(p**(i-1)).
     657
     658        EXAMPLES:
     659            sage: A = SteenrodAlgebra(2)
     660            sage: A.gen(4)
     661            Sq(16)
     662            sage: B = SteenrodAlgebra(5)
     663            sage: B.gen(0)
     664            Q_0
     665            sage: B.gen(2)
     666            P(5)
     667        """
     668        if not isinstance(i, (Integer, int)) and i >= 0:
     669            raise ValueError, "%s is not a non-negative integer" % i
     670        if self.prime == 2:
     671            return self.Sq(self.prime**i)
     672        else:
     673            if i == 0:
     674                return self.Q(0)
     675            else:
     676                return self.P(self.prime**(i-1))
     677
     678    def __cmp__(self,right):
     679        """
     680        Two Steenrod algebras are equal <=> their associated primes are equal.
     681
     682        EXAMPLES:
     683            sage: A = SteenrodAlgebra(2)
     684            sage: B = SteenrodAlgebra(2)
     685            sage: cmp(A, B)
     686            0
     687            sage: A.__cmp__(B)
     688            0
     689            sage: A is B
     690            False
     691            sage: C = SteenrodAlgebra(17)
     692            sage: cmp(A,C)
     693            -1
     694        """
     695        if type(self) == type(right) and self.prime == right.prime:
     696            return 0
     697        else:
     698            return -1
     699
     700
     701    def __call__(self, x):
     702        if isinstance(x, SteenrodAlgebraElement) and x.parent() == self:
     703            return x
     704        else:
     705            return SteenrodAlgebraElement(x,p=self.prime)
     706
     707
     708    def _coerce_impl(self, x):
     709        """
     710        Return the coercion of x into this Steenrod algebra.
     711
     712        INPUT:
     713            x -- a SteenrodAlgebraElement or an element of F_p
     714
     715        OUTPUT:
     716            coercion of x into the Steenrod algebra
     717       
     718        EXAMPLES:
     719            sage: A = SteenrodAlgebra(); A
     720            mod 2 Steenrod algebra
     721            sage: A(1)     # convert 1 to an element of A
     722            Sq(0)
     723            sage: A(Sq(3))
     724            Sq(3)
     725       
     726        The algebras that coerce into the mod p Steenrod algebra are:
     727       
     728           * the mod p Steenrod algebra
     729           * its base field GF(p)
     730        """
     731        return self._coerce_try(x, [self.base_ring()])
     732       
     733
     734    def __contains__(self, x):
     735        """
     736        Instances of the class SteenrodAlgebraElement with the same
     737        prime are contained in the Steenrod algebra.
     738
     739        EXAMPLES:
     740            sage: A = SteenrodAlgebra()
     741            sage: x = Sq(2) * Sq(1); x
     742            Sq(0,1) + Sq(3)
     743            sage: x in A
     744            True
     745            sage: x in SteenrodAlgebra(5)
     746            False
     747        """
     748        return (isinstance(x, SteenrodAlgebraElement) and x.parent() == self) \
     749            or (GF(self.prime).__contains__(x))
     750
     751
     752    def is_commutative(self):
     753        """
     754        The Steenrod algebra is not commutative.
     755       
     756        EXAMPLES:
     757            sage: A = SteenrodAlgebra(3)
     758            sage: A.is_commutative()
     759            False
     760        """
     761        return False
     762
     763
     764    def is_finite(self):
     765        """
     766        The Steenrod algebra is not finite.
     767       
     768        EXAMPLES:
     769            sage: A = SteenrodAlgebra(3)
     770            sage: A.is_finite()
     771            False
     772        """
     773        return False
     774
     775
     776    def order(self):
     777        """
     778        The Steenrod algebra has infinite order.
     779       
     780        EXAMPLES:
     781            sage: A = SteenrodAlgebra(3)
     782            sage: A.order()
     783            +Infinity
     784        """
     785        from sage.rings.infinity import Infinity
     786        return Infinity
     787
     788
     789    def is_division_algebra(self):
     790        """
     791        The Steenrod algebra is not a division algebra.
     792       
     793        EXAMPLES:
     794            sage: A = SteenrodAlgebra(3)
     795            sage: A.is_division_algebra()
     796            False
     797        """
     798        return False
     799   
     800
     801    def is_field(self):
     802        """
     803        The Steenrod algebra is not a field.
     804       
     805        EXAMPLES:
     806            sage: A = SteenrodAlgebra(3)
     807            sage: A.is_field()
     808            False
     809        """
     810        return False
     811   
     812
     813    def is_integral_domain(self):
     814        """
     815        The Steenrod algebra is not an integral domain.
     816       
     817        EXAMPLES:
     818            sage: A = SteenrodAlgebra(3)
     819            sage: A.is_integral_domain()
     820            False
     821        """
     822        return False
     823   
     824
     825    def is_noetherian(self):
     826        """
     827        The Steenrod algebra is not noetherian.
     828       
     829        EXAMPLES:
     830            sage: A = SteenrodAlgebra(3)
     831            sage: A.is_noetherian()
     832            False
     833        """
     834        return False
     835       
     836
     837    def category(self):
     838        """
     839        The Steenrod algebra is an algebra over $F_p$.
     840       
     841        EXAMPLES:
     842            sage: A = SteenrodAlgebra(3)
     843            sage: A.category()
     844            Category of algebras over Finite Field of size 3
     845        """
     846        from sage.categories.category_types import Algebras
     847        return Algebras(GF(self.prime))
     848
     849
     850    def Sq(self, *nums):
     851        r"""
     852        Milnor element $\text{Sq}(a,b,c,...)$.
     853
     854        INPUT:
     855            nums -- tuple of non-negative integers
     856       
     857        OUTPUT:
     858            element of the Steenrod algebra given by the single basis
     859            element Sq(a, b, c, ...)
     860   
     861        EXAMPLES:
     862            sage: A = SteenrodAlgebra(2)
     863            sage: A.Sq(5)
     864            Sq(5)
     865            sage: A.Sq(5,0,2)
     866            Sq(5,0,2)
     867
     868        Entries must be non-negative integers; otherwise, an error results.
     869        """
     870        if self.prime == 2:
     871            dict = {nums: 1}
     872            return SteenrodAlgebraElement(dict, p=2)
     873        else:
     874            raise ValueError, "Sq is only defined at the prime 2"
     875
     876
     877    def P(self, *nums):
     878        r"""
     879        The element $\mathcal{P}(n_1, n_2, ...)$
     880
     881        INPUT:
     882            nums -- tuple of non-negative integers
     883           
     884        OUTPUT:
     885            element of the Steenrod algebra given by the single basis
     886            element P(n_1, n_2, ...)
     887
     888        Note that at the prime 2, this is the same element as Sq(n_1, n_2, ...)
     889
     890        EXAMPLES:
     891            sage: A = SteenrodAlgebra(2)
     892            sage: A.P(5)
     893            Sq(5)
     894            sage: B = SteenrodAlgebra(3)
     895            sage: B.P(5,1,1)
     896            P(5,1,1)
     897        """
     898        if self.prime == 2:
     899            dict = {nums: 1}
     900        else:
     901            dict = {((), nums): 1}
     902        return SteenrodAlgebraElement(dict,p=self.prime)
     903
     904
     905    def Q_exp(self, *nums):
     906        r"""
     907        The element $Q_0^{e_0} Q_1^{e_1} ...$, given by specifying the exponents.
     908       
     909        INPUT:
     910            nums -- tuple of 0s and 1s, say (e_0, e_1, ...)
     911
     912        OUTPUT:
     913            The element Q_0^{e_0} Q_1^{e_1} ...
     914       
     915        Note that at the prime 2, $Q_n$ is the element
     916        $\text{Sq}(0,0,...,1)$, where the 1 is in the $n+1$st
     917        position.
     918       
     919        Compare this to the method 'Q', which defines a similar
     920        element, but by specifying the tuple of subscripts of terms
     921        with exponent 1.
     922
     923        EXAMPLES:
     924            sage: A2 = SteenrodAlgebra(2)
     925            sage: A5 = SteenrodAlgebra(5)
     926            sage: A2.Q_exp(0,0,1,1,0)
     927            Sq(0,0,1,1)
     928            sage: A5.Q_exp(0,0,1,1,0)
     929            Q_2 Q_3
     930            sage: A5.Q(2,3)
     931            Q_2 Q_3
     932            sage: A5.Q_exp(0,0,1,1,0) == A5.Q(2,3)
     933            True
     934        """
     935        if not set(nums).issubset(set((0,1))):
     936            raise ValueError, "The tuple %s should consist " % (nums,) + \
     937                "only of 0's and 1's"
     938        else:
     939            if self.prime == 2:
     940                answer = Sq(0)
     941                index = 0
     942                for n in nums:
     943                    if n == 1:
     944                        answer = answer * self.pst(0,index+1)
     945                    index += 1
     946                return answer
     947            else:
     948                mono = ()
     949                index = 0
     950                for e in nums:
     951                    if e == 1:
     952                        mono = mono + (index,)
     953                    index += 1
     954                dict = {((mono), ()): 1}
     955                return SteenrodAlgebraElement(dict,p=self.prime)
     956
     957           
     958    def Q(self, *nums):
     959        r"""
     960        The element $Q_n0 Q_n1 ...$, given by specifying the subscripts.
     961       
     962        INPUT:
     963            nums -- tuple of non-negative integers, say (n_0, n_1, ...)
     964
     965        OUTPUT:
     966            The element Q_n0 Q_n1 ...
     967
     968        Note that at the prime 2, $Q_n$ is the element
     969        $\text{Sq}(0,0,...,1)$, where the 1 is in the $n+1$st
     970        position.
     971       
     972        Compare this to the method 'Q_exp', which defines a similar element,
     973        but by specifying the tuple of exponents.
     974
     975        EXAMPLES:
     976            sage: A2 = SteenrodAlgebra(2)
     977            sage: A5 = SteenrodAlgebra(5)
     978            sage: A2.Q(2,3)
     979            Sq(0,0,1,1)
     980            sage: A5.Q(1,4)
     981            Q_1 Q_4
     982            sage: A5.Q(1,4) == A5.Q_exp(0,1,0,0,1)
     983            True
     984        """
     985        if len(nums) != len(set(nums)):
     986            return self(0)
     987        else:
     988            if self.prime == 2:
     989                if len(nums) == 0:
     990                    return Sq(0)
     991                else:
     992                    list = (1+max(nums)) * [0]
     993                    for i in nums:
     994                        list[i] = 1
     995                    return SteenrodAlgebraElement({tuple(list): 1}, p=2)
     996            else:
     997                return SteenrodAlgebraElement({(nums, ()): 1}, p=self.prime)
     998
     999
     1000    def pst(self,s,t):
     1001        r"""
     1002        The Margolis element $P^s_t$.
     1003       
     1004        INPUT:
     1005            s -- non-negative integer
     1006            t -- positive integer
     1007            p -- positive prime number
     1008       
     1009        OUTPUT:
     1010            The Margolis element P^s_t of the mod p Steenrod algebra: the
     1011            element equal to P(0,0,...,0,p^s), where the p^s is in
     1012            position t.
     1013
     1014        EXAMPLES:
     1015            sage: A2 = SteenrodAlgebra(2)
     1016            sage: A2.pst(3,5)
     1017            Sq(0,0,0,0,8)
     1018            sage: A2.pst(1,2) == Sq(4)*Sq(2) + Sq(2)*Sq(4)
     1019            True
     1020            sage: SteenrodAlgebra(5).pst(3,5)
     1021            P(0,0,0,0,125)
     1022        """
     1023        if not isinstance(s, (Integer, int)) and s >= 0:
     1024            raise ValueError, "%s is not a non-negative integer" % s
     1025        if not isinstance(t, (Integer, int)) and t > 0:
     1026            raise ValueError, "%s is not a positive integer" % t
     1027        nums = (0,)*(t-1) + (self.prime**s,)
     1028        if self.prime == 2:
     1029            return SteenrodAlgebraElement({nums: 1}, p=2)
     1030        else:
     1031            return SteenrodAlgebraElement({((), nums): 1}, p=self.prime)
     1032
     1033       
     1034# The variable 'steenrod_basis' is used for determining the output
     1035# format for manipulations in the Steenrod algebra.  The default value
     1036# is 'milnor', and this can be changed using the function
     1037# 'steenrod_set_basis'.
     1038steenrod_basis = 'milnor'
     1039
     1040# These are the recognized basis names.
     1041_steenrod_serre_cartan_basis_names = ['serre_cartan', 'serre-cartan', 'sc', \
     1042                                         'adem', 'admissible']
     1043_steenrod_milnor_basis_names = ['milnor', 'mil']
     1044_steenrod_woodY_basis_names = ['woody', 'wood_y', 'wood-y']
     1045_steenrod_woodZ_basis_names = ['woodz', 'wood_z', 'wood-z']
     1046_steenrod_arnonA_basis_names = ['arnona', 'arnon_a', 'arnon-a',
     1047                               'arnona_long', 'arnon_a_long', 'arnon-a-long']
     1048_steenrod_wall_basis_names = ['wall', 'wall_long', 'wall-long']
     1049_steenrod_arnonC_basis_names = ['arnonc', 'arnon_c', 'arnon-c']
     1050_steenrod_pst_basis_names = ['pst', 'pst_', 'pst_rlex', 'pst-rlex', 'pstrlex', \
     1051                                'pst_llex', 'pst-llex', 'pstllex', \
     1052                                'pst_deg', 'pst-deg', 'pstdeg', \
     1053                                'pst_revz', 'pst-revz', 'pstrevz']
     1054_steenrod_commutator_basis_names = ['commutator', 'comm', \
     1055                                       'commutator_long', 'commutator-long', \
     1056                                       'comm_long', 'comm-long', \
     1057                                       'comm_rlex', 'comm-rlex',
     1058                                       'comm_rlex_long', 'comm-rlex-long',
     1059                                       'comm_llex', 'comm-llex',
     1060                                       'comm_llex_long', 'comm-llex-long',
     1061                                       'comm_deg', 'comm-deg',
     1062                                       'comm_deg_long', 'comm-deg-long',
     1063                                       'comm_revz', 'comm-revz',
     1064                                       'comm_revz_long', 'comm-revz-long']
     1065
     1066# These are for internal use only; they are the names used in the code
     1067# to represent each basis.
     1068_steenrod_basis_unique_names =  ('serre-cartan', 'milnor', 'woody', \
     1069                                      'woodz', 'arnona', 'arnonc', 'wall', \
     1070                                      'pst_rlex', 'pst_llex', 'pst_deg', \
     1071                                      'pst_revz', 'comm_rlex', 'comm_llex', \
     1072                                      'comm_deg', 'comm_revz')
     1073_steenrod_basis_unique_names_odd =  ('serre-cartan', 'milnor')
     1074
     1075
     1076def steenrod_set_basis(string=None):
     1077    r"""
     1078    Set the default basis for Steenrod algebra computations
     1079
     1080    INPUT:
     1081        string (optional) -- 'milnor' or 'mil' for the Milnor basis.
     1082        'serre-cartan', 'serre_cartan', 'sc', 'adem', 'admissible' for the
     1083            Serre-Cartan basis.
     1084        'wood_y' for Wood's Y basis.
     1085        'wood_z' for Wood's Z basis.
     1086        'wall' for Wall's basis.
     1087        'wall_long' for Wall's basis, alternate representation
     1088        'arnon_a' for Arnon's A basis.
     1089        'arnon_a_long' for Arnon's A basis, alternate representation.
     1090        'arnon_c' for Arnon's C basis.
     1091        'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz' for various
     1092            P^s_t-bases.
     1093        'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz' for various
     1094            commutator bases.
     1095        'comm_long', 'comm_rlex_long', etc., for commutator bases, alternate
     1096            representations.
     1097
     1098    OUTPUT:
     1099        Name of basis.  If the argument 'string' is present, set the
     1100        basis to be string, and return that, converted to lowercase.
     1101        If it is omitted, return the name of the current basis.
     1102
     1103    See documentation for the function 'steenrod_algebra_basis' for
     1104    descriptions of the different bases.
     1105
     1106    EXAMPLES:
     1107        sage: c = Sq(2) * Sq(1); c
     1108        Sq(0,1) + Sq(3)
     1109        sage: steenrod_set_basis('serre-cartan')
     1110        'serre-cartan'
     1111        sage: steenrod_set_basis('SeRrE-caRTAN')
     1112        'serre-cartan'
     1113        sage: c
     1114        Sq^{2} Sq^{1}
     1115        sage: steenrod_set_basis()   # no argument: print basis
     1116        'serre-cartan'
     1117        sage: x = Sq(7,3,1)   # top class in A(2)
     1118        sage: x
     1119        Sq^{17} Sq^{5} Sq^{1}
     1120        sage: steenrod_set_basis('pst')
     1121        'pst'
     1122        sage: x
     1123        P^{0}_{1} P^{0}_{2} P^{1}_{1} P^{0}_{3} P^{1}_{2} P^{2}_{1}
     1124        sage: steenrod_set_basis('Beer')
     1125        Warning: Beer is not a recognized basis, and is not implemented (unless
     1126        you've done it yourself).
     1127        'beer'
     1128
     1129    The 'alternate' representations provide ways of expressing elements
     1130    of the Steenrod algebra in terms of the elements $\text{Sq}^{2^n}$.
     1131        sage: steenrod_set_basis('arnon_a_long')
     1132        'arnon_a_long'
     1133        sage: Sq(6)
     1134        Sq^{1} Sq^{2} Sq^{1} Sq^{2} + Sq^{2} Sq^{4}
     1135        sage: steenrod_set_basis('wall_long')
     1136        'wall_long'
     1137        sage: Sq(6)
     1138        Sq^{2} Sq^{1} Sq^{2} Sq^{1} + Sq^{2} Sq^{4}
     1139        sage: steenrod_set_basis('comm_long')
     1140        'comm_long'
     1141        sage: Sq(6)
     1142        s_{1} s_{12} s_{2} + s_{2} s_{4}
     1143        sage: steenrod_set_basis('milnor')  # reset to the default
     1144        'milnor'
     1145    """
     1146    global steenrod_basis
     1147    if string is not None:
     1148        if string.lower() not in (_steenrod_serre_cartan_basis_names
     1149            + _steenrod_milnor_basis_names + _steenrod_woodY_basis_names
     1150            + _steenrod_woodZ_basis_names + _steenrod_wall_basis_names
     1151            + _steenrod_arnonA_basis_names + _steenrod_arnonC_basis_names
     1152            + _steenrod_pst_basis_names + _steenrod_commutator_basis_names):
     1153            print "Warning: %s is not a recognized basis, and " % string + \
     1154                "is not implemented (unless you've done it yourself)."
     1155        steenrod_basis = string.lower()
     1156    return steenrod_basis
     1157
     1158
     1159def check_and_trim(nums):
     1160    """
     1161    Check that list or tuple consists of non-negative integers, and
     1162    strip trailing zeroes.
     1163
     1164    INPUT:
     1165        nums -- a list or tuple
     1166
     1167    OUTPUT:
     1168        If nums contains anything other than a non-negative integer,
     1169        raise an exception.  Otherwise, return a new list or tuple, obtained
     1170        from nums by omitting any zeroes from the end.
     1171       
     1172    EXAMPLES:
     1173        sage: from sage.algebras.steenrod_algebra import check_and_trim
     1174        sage: check_and_trim([3,4,1])
     1175        [3, 4, 1]
     1176        sage: a=[3,2,1,0,0]
     1177        sage: check_and_trim(a)
     1178        [3, 2, 1]
     1179        sage: a    # check_and_trim doesn't affect its input
     1180        [3, 2, 1, 0, 0]
     1181        sage: check_and_trim([0]*127)
     1182        []
     1183        sage: check_and_trim((1,2,3,4,0,0,0))  # works on tuples, too
     1184        (1, 2, 3, 4)
     1185       
     1186    If input contains anything other than non-negative integer, return
     1187    an error.  The right-most problematic entry is identified.
     1188    """
     1189    index = len(nums)
     1190    for i in range(index-1, -1, -1):
     1191        if nums[i] == 0 and i == index - 1:
     1192            index = i
     1193        if not (isinstance(nums[i], (Integer, int)) and nums[i] >= 0):
     1194            raise ValueError, "%s is not a non-negative integer" % nums[i]
     1195    return nums[:index]
     1196
     1197
     1198def convert_perm(m):
     1199    """
     1200    Convert tuple m of non-negative integers to a permutation in one-line form.
     1201
     1202    INPUT:
     1203        m -- tuple of non-negative integers with no repetitions
     1204    OUTPUT:
     1205        list -- conversion of m to a permutation of the set {1,2,...,len(m)}
     1206
     1207    If m=(3,7,4), then one can view m as representing the permutation
     1208    of the set {3,4,7} sending 3 to 3, 4 to 7, and 7 to 4.  This
     1209    function converts m to the list [1,3,2], which represents
     1210    essentially the same permutation, but of the set {1,2,3}.  This
     1211    list can then be passed to Permutation, and its signature can be
     1212    computed.
     1213
     1214    EXAMPLES:
     1215        sage: sage.algebras.steenrod_algebra.convert_perm((3,7,4))
     1216        [1, 3, 2]
     1217        sage: sage.algebras.steenrod_algebra.convert_perm((5,0,6,3))
     1218        [2, 4, 1, 3]
     1219    """   
     1220    m2 = list(m)
     1221    m2.sort()
     1222    return [list(m).index(x)+1 for x in m2]
     1223
     1224
     1225def base_p_expansion(n, p):
     1226    r"""
     1227    Return list of digits in the base p expansion of n.
     1228
     1229    INPUT:
     1230        n -- non-negative integer
     1231        p -- positive prime number
     1232
     1233    OUTPUT:
     1234        list of digits in the base p expansion of n
     1235
     1236    EXAMPLES:
     1237        sage: sage.algebras.steenrod_algebra.base_p_expansion(10,2)
     1238        [0, 1, 0, 1]
     1239        sage: sage.algebras.steenrod_algebra.base_p_expansion(10,3)
     1240        [1, 0, 1]
     1241        sage: sage.algebras.steenrod_algebra.base_p_expansion(10,5)
     1242        [0, 2]
     1243        sage: sage.algebras.steenrod_algebra.base_p_expansion(10,7)
     1244        [3, 1]
     1245        sage: sage.algebras.steenrod_algebra.base_p_expansion(0,7)
     1246        []
     1247    """
     1248    result = []
     1249    while n > 0:
     1250        remainder = n % p
     1251        result.append(remainder)
     1252        n = int((n - remainder)/p)
     1253    return result
     1254
     1255
     1256def integer_base_2_log(n):
     1257    """
     1258    Largest integer k so that 2^k <= n
     1259
     1260    INPUT:
     1261        n -- positive integer
     1262
     1263    OUTPUT:
     1264        k -- integer so that 2^k <= n, 2^{k+1} > n
     1265
     1266    EXAMPLES:
     1267        sage: sage.algebras.steenrod_algebra.integer_base_2_log(7)
     1268        2
     1269        sage: sage.algebras.steenrod_algebra.integer_base_2_log(8)
     1270        3
     1271        sage: sage.algebras.steenrod_algebra.integer_base_2_log(9)
     1272        3
     1273    """
     1274    answer = 0
     1275    while 2**(answer+1) <= n:
     1276        answer += 1
     1277    return answer
     1278
     1279
     1280# This dictionary is for caching Steenrod algebras at various primes,
     1281# to make sure that SteenrodAlgebraElements defined at the same prime
     1282# have the same parent.
     1283_steenrod_algebras = {}
     1284
     1285class SteenrodAlgebraElement(AlgebraElement):
     1286    r"""
     1287    Element of the mod p Steenrod algebra.
     1288
     1289    At the prime 2, use the function 'Sq' to define these, as in
     1290    'w=Sq(4,3,3)' or 'z=Sq(1,2)+Sq(4,1)' or 'q=Sq(8)*Sq(4) + Sq(12)'.
     1291
     1292    At odd primes, use the methods 'P' and 'Q' to define these, as
     1293    in 'w=SteenrodAlgebra(3).Q(1,5) * SteenrodAlgebra(3).P(4,3)'.
     1294
     1295    EXAMPLES:
     1296        sage: w = Sq(4,3,3)
     1297        sage: w
     1298        Sq(4,3,3)
     1299
     1300    The function 'Sq', together with addition, provides an easy way to
     1301    define elements when $p=2$:
     1302        sage: b = Sq(3) + Sq(0,1)
     1303        sage: b
     1304        Sq(0,1) + Sq(3)
     1305        sage: b.degree()
     1306        3
     1307        sage: (Sq(2,1) + Sq(0,1)).degree()
     1308        Element is not homogeneous.
     1309        sage: b.excess()
     1310        1
     1311
     1312    When $p$ is odd, first define a Steenrod algebra to specify the
     1313    prime, and then use the methods 'P' and 'Q', together with
     1314    multiplication and addition:
     1315        sage: A7 = SteenrodAlgebra(7)
     1316        sage: u = A7.Q(0,4); u
     1317        Q_0 Q_4
     1318        sage: v = A7.P(1,2,3); v
     1319        P(1,2,3)
     1320        sage: u * v
     1321        Q_0 Q_4 P(1,2,3)
     1322        sage: 10 * u * v
     1323        3 Q_0 Q_4 P(1,2,3)
     1324        sage: u + v
     1325        P(1,2,3) + Q_0 Q_4
     1326        sage: (u + v).excess()
     1327        2
     1328        sage: (u + v).degree()
     1329        Element is not homogeneous.
     1330
     1331    Multiplication and (non-negative) exponents work as they should:
     1332        sage: c = Sq(3)
     1333        sage: c * c
     1334        Sq(3,1)
     1335        sage: c ** 2
     1336        Sq(3,1)
     1337        sage: c ** 0
     1338        Sq(0)
     1339        sage: d = SteenrodAlgebra(3).P(3)
     1340        sage: d ** 3
     1341        2 P(1,2)
     1342
     1343    Printed representations, different bases.  The Milnor basis is how
     1344    things are written, by default:
     1345        sage: b = Sq(3) + Sq(0,1)
     1346        sage: b
     1347        Sq(0,1) + Sq(3)
     1348        sage: latex(b)
     1349        \text{Sq}(0,1) + \text{Sq}(3)
     1350        sage: steenrod_set_basis('adem')
     1351        'adem'
     1352        sage: b
     1353        Sq^{2} Sq^{1}
     1354        sage: steenrod_set_basis('wood_y')
     1355        'wood_y'
     1356        sage: c = Sq(4) ** 2; c
     1357        Sq^{7} Sq^{1} + Sq^{6} Sq^{2}
     1358        sage: c.basis('wall')
     1359        Q^{2}_{0} Q^{0}_{0} + Q^{2}_{1} Q^{1}_{1}
     1360       
     1361    Iteration: elements of the Steenrod algebra can be viewed as
     1362    being lists of basis elements, and one can loop over them:
     1363        sage: steenrod_set_basis('milnor')
     1364        'milnor'
     1365        sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     1366        sage: z
     1367        Sq(3,0,1) + Sq(4,2) + Sq(7,1)
     1368        sage: for m in z: print m
     1369        Sq(3,0,1)
     1370        Sq(4,2)
     1371        Sq(7,1)
     1372        sage: [m.excess() for m in z]
     1373        [4, 6, 8]
     1374        sage: for m in z: m*m
     1375        0
     1376        Sq(4,3,1) + Sq(7,2,1)
     1377        0
     1378
     1379    Other operations and functions:
     1380        sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     1381        sage: z.is_unit()    # z is not a unit
     1382        False
     1383        sage: u = 1 + Sq(3,1)
     1384        sage: u == Sq(0) + Sq(3,1)
     1385        True
     1386        sage: u.is_unit()
     1387        True
     1388        sage: u.additive_order()
     1389        2
     1390    """
     1391   
     1392    def __init__(self, poly, p=None):
     1393        r"""
     1394        INPUT:
     1395            poly -- dictionary with entries of form (monomial: coefficient)
     1396            Each coefficient is in GF(p), and each monomial is a tuple
     1397            of non-negative integers (a, b, c, ...), corresponding to
     1398            the Milnor basis element Sq(a, b, c, ...).
     1399
     1400            At odd primes, the monomials are pairs of tuples: they are
     1401            of the form ((e0, e1, e2, ...), (r1, r2, ...)),
     1402            corresponding to the element $Q_{e_0} Q_{e_1} ... \mathcal{P}(r_1, r_2, ...)$.
     1403
     1404            Alternatively, poly can be an integer n, in which case it
     1405            is viewed as being in the field GF(p): the resulting
     1406            element is n * Sq(0).
     1407           
     1408            p -- positive prime number (default 2)
     1409
     1410        EXAMPLES:
     1411            sage: from sage.algebras.steenrod_algebra import SteenrodAlgebraElement
     1412            sage: SteenrodAlgebraElement({(1,2,3): 1}, 2)
     1413            Sq(1,2,3)
     1414            sage: SteenrodAlgebraElement({(1,2,3): 4}, 2)
     1415            0
     1416            sage: SteenrodAlgebraElement({((0,3), (1,2)): 5}, 7)
     1417            5 Q_0 Q_3 P(1,2)
     1418            sage: SteenrodAlgebraElement({((0,3), (1,2)): 5}, p=7)
     1419            5 Q_0 Q_3 P(1,2)
     1420
     1421        The input can also be an integer, in which case it is treated
     1422        as a multiple, mod p, of the unit element P(0) (a.k.a. Sq(0)
     1423        at the prime 2):
     1424            sage: SteenrodAlgebraElement(3,2)
     1425            Sq(0)
     1426            sage: SteenrodAlgebraElement(6)   # p=2 is the default prime
     1427            0
     1428            sage: SteenrodAlgebraElement(6, p=5)
     1429            P(0)
     1430        """
     1431        from sage.rings.arith import is_prime
     1432        if p is None: p = _steenrod_prime
     1433        if not is_prime(p):
     1434            raise ValueError, "%s is not prime." % p
     1435        else:
     1436            # get cached Steenrod algebra at the prime p
     1437            if _steenrod_algebras.has_key(p):
     1438                alg = _steenrod_algebras[p]
     1439            else:
     1440                _steenrod_algebras[p] = SteenrodAlgebra(p)
     1441                alg = _steenrod_algebras[p]
     1442            if isinstance(poly, SteenrodAlgebraElement):
     1443                if poly.parent().prime == p:
     1444                    self._raw = poly._raw
     1445                else:
     1446                    raise ValueError, "Mismatch: %s is defined at the prime %s, \
     1447not %s" % (poly, poly.parent().prime, p)
     1448            # basic initializations:
     1449            RingElement.__init__(self, alg)
     1450            F = parent(self).base_ring()
     1451            self.base_field = F
     1452            self.prime = p
     1453            if p == 2:
     1454                basis_list = _steenrod_basis_unique_names
     1455            else:
     1456                basis_list = _steenrod_basis_unique_names_odd
     1457            # now comes most of the work:
     1458            if isinstance(poly, dict):
     1459                new_poly = {}
     1460                for mono in poly:
     1461                    if p == 2:
     1462                        # when p=2, mono is a tuple of integers
     1463                        trimmed = check_and_trim(mono)
     1464                        if new_poly.has_key(trimmed):
     1465                            coeff = F(poly[mono] + new_poly[trimmed])
     1466                        else:
     1467                            coeff = F(poly[mono])
     1468                        if not coeff.is_zero():
     1469                            new_poly[trimmed] = coeff
     1470                    else:
     1471                        # when p is odd, mono is either an empty tuple
     1472                        # or a pair of tuples
     1473                        if len(mono) == 0:
     1474                            if new_poly.has_key(mono):
     1475                                coeff = F(poly[mono] + new_poly[mono])
     1476                            else:
     1477                                coeff = F(poly[mono])
     1478                            if not coeff.is_zero():
     1479                                new_poly[mono] = coeff
     1480                        else:
     1481                            # mono is a pair of tuples
     1482                            mono1, mono2 = mono
     1483                            multiplier = 1
     1484                            # see if there are any repetitions in the Q monomial:
     1485                            if len(mono1) != len(set(mono1)):
     1486                                return self(0)
     1487                            # if not, sort them and introduce the correct sign:
     1488                            if len(mono1) > 0:
     1489                                from sage.combinat.permutation import Permutation
     1490                                multiplier = Permutation(
     1491                                    convert_perm(mono1)).signature()
     1492                                mono1 = tuple(sorted(mono1))
     1493                            trimmed2 = check_and_trim(mono2)
     1494                            if len(mono1) + len(trimmed2) > 0:
     1495                                if new_poly.has_key((mono1,trimmed2)):
     1496                                    coeff = F(multiplier * poly[mono] \
     1497                                                  + new_poly[(mono1, trimmed2)])
     1498                                else:
     1499                                    coeff = F(multiplier * poly[mono])
     1500                                if not coeff.is_zero():
     1501                                    new_poly[(mono1,trimmed2)] = coeff
     1502                            else:
     1503                                if new_poly.has_key(()):
     1504                                    coeff = F(poly[mono] + new_poly[()])
     1505                                else:
     1506                                    coeff = F(poly[mono])
     1507                                if not coeff.is_zero():
     1508                                    new_poly[()] = coeff
     1509                # now define the _raw attribute: a dictionary keyed by the
     1510                # basis names.  set the 'milnor' value to by new_poly
     1511                self._raw = {}
     1512                for basis in basis_list:
     1513                    self._raw[basis] = {}
     1514                self._raw['milnor'] = new_poly
     1515            elif isinstance(poly, (Integer, int)) or poly.parent() == F:
     1516                # a scalar, i.e., a scalar multiple of Sq(0) or P(0)
     1517                if F(poly) != 0:
     1518                    new_poly = {(): F(poly)}
     1519                else:
     1520                    new_poly = {}
     1521                self._raw = {}
     1522                for basis in basis_list:
     1523                    self._raw[basis] = new_poly
     1524            elif isinstance(poly, SteenrodAlgebraElement):
     1525                self._raw = poly._raw
     1526            else:
     1527                raise ValueError, "%s is not of the correct form" % poly
     1528   
     1529
     1530    def is_unit(self):
     1531        """
     1532        True if element has a scalar multiple of P(0) as a summand, False otherwise.
     1533
     1534        EXAMPLES:
     1535            sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     1536            sage: z.is_unit()
     1537            False
     1538            sage: u = 1 + Sq(3,1)
     1539            sage: u == Sq(0) + Sq(3,1)
     1540            True
     1541            sage: u.is_unit()
     1542            True
     1543            sage: A5 = SteenrodAlgebra(5)
     1544            sage: v = A5.P(0)
     1545            sage: (v + v + v).is_unit()
     1546            True
     1547        """
     1548        if self._raw['milnor'].has_key(()):
     1549            return True
     1550        else:
     1551            return False
     1552
     1553    def is_nilpotent(self):
     1554        """
     1555        True if element is not a unit, False otherwise.
     1556
     1557        EXAMPLES:
     1558            sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     1559            sage: z.is_nilpotent()
     1560            True
     1561            sage: u = 1 + Sq(3,1)
     1562            sage: u == Sq(0) + Sq(3,1)
     1563            True
     1564            sage: u.is_nilpotent()
     1565            False
     1566        """
     1567        return not self.is_unit()
     1568
     1569
     1570    def _add_(self, other):
     1571        """
     1572        Addition for elements of the Steenrod algebra.
     1573
     1574        EXAMPLES:
     1575            sage: a = Sq(3,1) + Sq(6)
     1576            sage: b = Sq(0,2)
     1577            sage: c = Sq(6) + Sq(0,2)
     1578            sage: a + b
     1579            Sq(0,2) + Sq(3,1) + Sq(6)
     1580            sage: b + c
     1581            Sq(6)
     1582            sage: A7 = SteenrodAlgebra(7)
     1583            sage: x = A7.P(1,2); y = A7.Q(3,4) * A7.P(1,2)
     1584            sage: x + 3 * y
     1585            P(1,2) + 3 Q_3 Q_4 P(1,2)
     1586            sage: x + 10 * y
     1587            P(1,2) + 3 Q_3 Q_4 P(1,2)
     1588        """
     1589        F = self.base_field
     1590        poly1 = self._raw['milnor']
     1591        poly2 = other._raw['milnor']
     1592        result = poly1.copy()
     1593        for mono in poly2:
     1594            if result.has_key(mono):
     1595                coeff = F(result[mono] + poly2[mono])
     1596            else:
     1597                coeff = F(poly2[mono])
     1598            if coeff == 0:
     1599                del result[mono]
     1600            else:
     1601                result[mono] = coeff
     1602        sum = SteenrodAlgebraElement(result, p=self.prime)
     1603        return sum
     1604
     1605
     1606    def _neg_(self):
     1607        """
     1608        Multiply every coefficient by the base field element -1.
     1609
     1610        EXAMPLES:
     1611            sage: a = Sq(4,2) + Sq(5)
     1612            sage: -a
     1613            Sq(4,2) + Sq(5)
     1614            sage: A5 = SteenrodAlgebra(5)
     1615            sage: b = 2 * A5.P(2,0,1)
     1616            sage: b
     1617            2 P(2,0,1)
     1618            sage: -b
     1619            3 P(2,0,1)
     1620        """
     1621        p = self.prime
     1622        if p == 2:
     1623            return self
     1624        else:
     1625            F = self.base_field
     1626            dict = self._raw['milnor']
     1627            for mono in dict:
     1628                dict[mono] = F(-dict[mono])
     1629            return SteenrodAlgebraElement(dict,p)
     1630
     1631
     1632    def _sub_(self, other):
     1633        """
     1634        Subtraction for elements of the Steenrod algebra.
     1635
     1636        EXAMPLES:
     1637            sage: A7 = SteenrodAlgebra(7)
     1638            sage: A7.P(2,1) - A7.Q(0,3)
     1639            P(2,1) + 6 Q_0 Q_3
     1640        """
     1641        return self._add_(other._neg_())
     1642
     1643
     1644    def _mul_(self, other):
     1645        """
     1646        Multiplication for elements of the Steenrod algebra.
     1647
     1648        EXAMPLES:
     1649            sage: Sq(2) * Sq(1)
     1650            Sq(0,1) + Sq(3)
     1651            sage: Sq(0) * (Sq(6,2) + Sq(9,1))
     1652            Sq(6,2) + Sq(9,1)
     1653            sage: 1 * (Sq(6,2) + Sq(9,1))
     1654            Sq(6,2) + Sq(9,1)
     1655            sage: 4 * (Sq(6,2) + Sq(9,1))
     1656            0
     1657            sage: A5 = SteenrodAlgebra(5)
     1658            sage: A5.P(5) * A5.P(1,2)
     1659            3 P(0,3) + P(6,2)
     1660            sage: A5.Q(1,2,3) * A5.Q(0,5)
     1661            4 Q_0 Q_1 Q_2 Q_3 Q_5
     1662            sage: A5.Q(1,2,3) * A5.Q(0,3)
     1663            0
     1664        """
     1665        p = self.prime
     1666        if p == 2:
     1667            from steenrod_milnor_multiplication import milnor_multiplication
     1668        else:
     1669            from steenrod_milnor_multiplication_odd import milnor_multiplication_odd
     1670        F = self.base_field
     1671        poly1 = self._raw['milnor']
     1672        poly2 = other._raw['milnor']
     1673        result = {}
     1674        for mono1 in poly1:
     1675            for mono2 in poly2:
     1676                if len(mono1) == 0:    # multiplying by scalar multiple of one
     1677                    if result.has_key(mono2):
     1678                        result[mono2] = F(result[mono2] + poly1[mono1]
     1679                                          * poly2[mono2])
     1680                    else:
     1681                        result[mono2] = F(poly1[mono1] * poly2[mono2])
     1682                elif len(mono2) == 0:    # multiplying by scalar multiple of one
     1683                    if result.has_key(mono1):
     1684                        result[mono1] = F(result[mono1] + poly1[mono1]
     1685                                          * poly2[mono2])
     1686                    else:
     1687                        result[mono1] = F(poly1[mono1] * poly2[mono2])
     1688                else:
     1689                    if p == 2:
     1690                        new_dict = milnor_multiplication(mono1, mono2)
     1691                    else:
     1692                        new_dict = milnor_multiplication_odd(mono1, mono2, p=p)
     1693                    for new_mono in new_dict:
     1694                        if result.has_key(new_mono):
     1695                            result[new_mono] = F(result[new_mono]
     1696                                                 + new_dict[new_mono]
     1697                                                 * poly1[mono1] * poly2[mono2])
     1698                        else:
     1699                            result[new_mono] = F(new_dict[new_mono]
     1700                                                 * poly1[mono1] * poly2[mono2])
     1701        return SteenrodAlgebraElement(result, p=p)
     1702
     1703
     1704    def __cmp_not_in_use__(self,other):
     1705        """
     1706        Two elements are equal if their difference is zero.
     1707
     1708        EXAMPLES:
     1709             sage: A5 = SteenrodAlgebra(5)
     1710             sage: cmp(A5.P(0,1), A5.P(0,2))
     1711             -1
     1712             sage: cmp(A5.P(0,1), A5.pst(0,2))
     1713             0
     1714        """
     1715        if isinstance(self, SteenrodAlgebraElement) \
     1716                and isinstance(other, SteenrodAlgebraElement) \
     1717                and self.parent() == other.parent():
     1718            difference = self - other
     1719            if len(difference._raw['milnor']) == 0:
     1720                return 0
     1721            else:
     1722                return -1
     1723        else:
     1724            return -1
     1725
     1726    def __cmp__(self,other):
     1727        """
     1728        Two elements are equal if their difference is zero.
     1729
     1730        EXAMPLES:
     1731             sage: A5 = SteenrodAlgebra(5)
     1732             sage: cmp(A5.P(0,1), A5.P(0,2))
     1733             -1
     1734             sage: cmp(A5.P(0,1), A5.pst(0,2))
     1735             0
     1736        """
     1737        difference = self - other
     1738        if len(difference._raw['milnor']) == 0:
     1739            return 0
     1740        else:
     1741            return -1
     1742
     1743
     1744    def _basis_dictionary(self,basis):
     1745        r"""
     1746        Dictionary of terms of the form (mono: coeff), where mono
     1747        is a monomial in the given basis.
     1748
     1749        INPUT:
     1750            basis -- string, basis in which to work
     1751
     1752        EXAMPLES:
     1753            sage: c = Sq(2) * Sq(1)
     1754            sage: c._basis_dictionary('milnor')
     1755            {(0, 1): 1, (3,): 1}
     1756            sage: steenrod_set_basis('milnor')
     1757            'milnor'
     1758            sage: c
     1759            Sq(0,1) + Sq(3)
     1760            sage: c._basis_dictionary('serre-cartan')
     1761            {(2, 1): 1}
     1762            sage: c.basis('serre-cartan')
     1763            Sq^{2} Sq^{1}
     1764            sage: d = Sq(0,0,1)
     1765            sage: d._basis_dictionary('arnonc')
     1766            {(7,): 1, (2, 5): 1, (4, 3): 1, (4, 2, 1): 1}
     1767            sage: d.basis('arnonc')
     1768            Sq^{2} Sq^{5} + Sq^{4} Sq^{2} Sq^{1} + Sq^{4} Sq^{3} + Sq^{7}
     1769
     1770        At odd primes:
     1771            sage: steenrod_set_basis('milnor')
     1772            'milnor'
     1773            sage: e = 2 * SteenrodAlgebra(3).P(1,2)
     1774            sage: e._basis_dictionary('milnor')
     1775            {((), (1, 2)): 2}
     1776            sage: e
     1777            2 P(1,2)
     1778            sage: e._basis_dictionary('serre-cartan')
     1779            {(0, 7, 0, 2, 0): 2}
     1780            sage: e.basis('adem')
     1781            2 P^{7} P^{2}
     1782
     1783        Implementation: to compute this, take the Milnor representation
     1784        and change bases.  Store the result in self._raw[basis], for later
     1785        use; this way, an element only needs to be converted once.
     1786        """
     1787        if basis in _steenrod_milnor_basis_names:
     1788            return self._raw['milnor']
     1789        from steenrod_algebra_bases import milnor_convert
     1790        def is_power_of_two(n):
     1791            while n != 0 and n%2 == 0:
     1792                n = n >> 1
     1793            return n == 1
     1794
     1795        p = self.prime
     1796        if self._raw.has_key(basis) and len(self._raw[basis])>0:
     1797            return self._raw[basis]
     1798        elif p == 2:
     1799            dict = {}
     1800            for mono in self._raw['milnor']:
     1801                converted = False
     1802                if dict.has_key(mono):
     1803                    old_coeff = dict[mono]
     1804                else:
     1805                    old_coeff = 0
     1806                new_coeff = old_coeff + self._raw['milnor'][mono]
     1807                if len(mono) == 0:   # length 0: no conversion
     1808                    if new_coeff != 0:
     1809                        dict[mono] = new_coeff
     1810                    else:
     1811                        del dict[mono]
     1812                    converted = True
     1813                elif basis in _steenrod_serre_cartan_basis_names:
     1814                    if len(mono) == 1:   # length 1: Sq(n) = Sq^{n}, so no conversion
     1815                        if dict.has_key(mono):
     1816                            new_coeff = dict[mono] + self._raw['milnor'][mono]
     1817                            if new_coeff != 0:
     1818                                dict[mono] = new_coeff
     1819                            else:
     1820                                del dict[mono]
     1821                        else:
     1822                            dict[mono] = self._raw['milnor'][mono]
     1823                        converted = True
     1824                elif basis in _steenrod_woodY_basis_names:
     1825                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1826                        if new_coeff != 0:
     1827                            dict[((integer_base_2_log(mono[0]),0),)] = new_coeff
     1828                        else:
     1829                            del dict[((integer_base_2_log(mono[0]),0),)]
     1830                        converted = True
     1831                elif basis in _steenrod_woodZ_basis_names:
     1832                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1833                        if new_coeff != 0:
     1834                            dict[((integer_base_2_log(mono[0]),0),)] = new_coeff
     1835                        else:
     1836                            del dict[((integer_base_2_log(mono[0]),0),)]
     1837                        converted = True
     1838                elif basis in _steenrod_wall_basis_names:
     1839                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1840                        m = integer_base_2_log(mono[0])
     1841                        if new_coeff != 0:
     1842                            dict[((m,m),)] = new_coeff
     1843                        else:
     1844                            del dict[((m,m),)]
     1845                        converted = True
     1846                elif basis in _steenrod_arnonA_basis_names:
     1847                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1848                        m = integer_base_2_log(mono[0])
     1849                        if new_coeff != 0:
     1850                            dict[((m,m),)] = new_coeff
     1851                        else:
     1852                            del dict[((m,m),)]
     1853                        converted = True
     1854                elif basis in _steenrod_arnonC_basis_names:
     1855                    if len(mono) == 1:   # no conversion
     1856                        if dict.has_key(mono):
     1857                            new_coeff = dict[mono] + self._raw['milnor'][mono]
     1858                            if new_coeff != 0:
     1859                                dict[mono] = new_coeff
     1860                            else:
     1861                                del dict[mono]
     1862                        else:
     1863                            dict[mono] = self._raw['milnor'][mono]
     1864                        converted = True
     1865                if not converted:
     1866                    conversion = milnor_convert(  # conversion required
     1867                        SteenrodAlgebraElement({mono: 1}),
     1868                        basis)
     1869                    for new_mono in conversion:
     1870                        if dict.has_key(new_mono):
     1871                            new_coeff = dict[new_mono] + conversion[new_mono]
     1872                            if new_coeff != 0:
     1873                                dict[new_mono] = new_coeff
     1874                            else:
     1875                                del dict[new_mono]
     1876                        else:
     1877                            dict[new_mono] = conversion[new_mono]
     1878            self._raw[basis] = dict
     1879            return dict
     1880        else:  # p odd
     1881            dict = {}
     1882            for mono in self._raw['milnor']:
     1883                converted = False
     1884                if dict.has_key(mono):
     1885                    old_coeff = dict[mono]
     1886                else:
     1887                    old_coeff = 0
     1888                new_coeff = old_coeff + self._raw['milnor'][mono]
     1889                if len(mono) == 0:   # length 0: no conversion
     1890                    if new_coeff != 0:
     1891                        dict[mono] = new_coeff
     1892                    else:
     1893                        del dict[mono]
     1894                    converted = True
     1895                elif basis in _steenrod_serre_cartan_basis_names:
     1896                    if len(mono[0]) == 0 and len(mono[1]) == 1:
     1897                        # length 1: Sq(n) = Sq^{n}, so no conversion
     1898                        new_mono = (0,mono[1][0], 0)
     1899                        if dict.has_key(new_mono):
     1900                            new_coeff = dict[new_mono] + self._raw['milnor'][mono]
     1901                            if new_coeff != 0:
     1902                                dict[new_mono] = new_coeff
     1903                            else:
     1904                                del dict[new_mono]
     1905                        else:
     1906                            dict[new_mono] = self._raw['milnor'][mono]
     1907                        converted = True
     1908                if not converted:
     1909                    conversion = milnor_convert(  # conversion required
     1910                        SteenrodAlgebraElement({mono: self._raw['milnor'][mono]},
     1911                                               p),
     1912                        basis)
     1913                    for new_mono in conversion:
     1914                        if dict.has_key(new_mono):
     1915                            new_coeff = dict[new_mono] + conversion[new_mono]
     1916                            if new_coeff != 0:
     1917                                dict[new_mono] = new_coeff
     1918                            else:
     1919                                del dict[new_mono]
     1920                        else:
     1921                            dict[new_mono] = conversion[new_mono]
     1922            self._raw[basis] = dict
     1923            return dict
     1924
     1925
     1926    def basis(self,basis):
     1927        r"""
     1928        Representation of element with respect to basis.
     1929
     1930        INPUT:
     1931            basis -- string, basis in which to work.  The choices are:
     1932            'milnor' or 'mil' for the Milnor basis.
     1933            'serre-cartan', 'serre_cartan', 'sc', 'adem', 'admissible' for
     1934                the Serre-Cartan basis.
     1935            'wood_y' for Wood's Y basis.
     1936            'wood_z' for Wood's Z basis.
     1937            'wall' for Wall's basis.
     1938            'wall_long' for Wall's basis, alternate representation
     1939            'arnon_a' for Arnon's A basis.
     1940            'arnon_a_long' for Arnon's A basis, alternate representation.
     1941            'arnon_c' for Arnon's C basis.
     1942            'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz' for various
     1943                P^s_t-bases.
     1944            'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz' for
     1945                various commutator bases.
     1946            'comm_long', 'comm_rlex_long', etc., for commutator bases, alternate
     1947                representations.
     1948
     1949        OUTPUT:
     1950            None
     1951
     1952        See documentation for the function 'steenrod_algebra_basis' for
     1953        descriptions of the different bases.
     1954
     1955        This prints the representation of element in the given basis.
     1956        Note that it only prints the representation; it does not
     1957        actually return a value.  Thus evaluating
     1958        "y = x.basis('milnor')" will set y to be None.
     1959
     1960        EXAMPLES:
     1961            sage: c = Sq(2) * Sq(1)
     1962            sage: c.basis('milnor')
     1963            Sq(0,1) + Sq(3)
     1964            sage: c.basis('serre-cartan')
     1965            Sq^{2} Sq^{1}
     1966            sage: d = Sq(0,0,1)
     1967            sage: d.basis('arnonc')
     1968            Sq^{2} Sq^{5} + Sq^{4} Sq^{2} Sq^{1} + Sq^{4} Sq^{3} + Sq^{7}
     1969        """
     1970        try:
     1971            from sage.misc.latex import print_or_typeset
     1972            temp = steenrod_set_basis()
     1973            steenrod_set_basis(basis)
     1974            print_or_typeset(self)
     1975        finally:
     1976            steenrod_set_basis(temp)
     1977
     1978
     1979    def degree(self):
     1980        r"""
     1981        Degree of element.
     1982
     1983        The degree of $\text{Sq}(i_1,i_2,i_3,...)$ is
     1984        $i_1 + 3 i_2 + 7 i_3 + ... + (2^n - 1) i_n + ...$.
     1985        When $p$ is odd, the degree of
     1986        $Q_{0}^{\epsilon_0} Q_{1}^{\epsilon_1} ... \mathcal{P}(r_1, r_2, ...)$
     1987        is $\sum \epsilon_i (2p^i - 1) + \sum r_j (2p^j - 2)$.
     1988       
     1989        The degree of a sum is undefined, unless each summand has the
     1990        same degree: that is, unless the element is homogeneous.
     1991
     1992        EXAMPLES:
     1993            sage: a = Sq(1,2,1)
     1994            sage: a.degree()
     1995            14
     1996            sage: for a in Sq(3) + Sq(5,1): a.degree()
     1997            3
     1998            8
     1999            sage: (Sq(3) + Sq(5,1)).degree()
     2000            Element is not homogeneous.
     2001            sage: B = SteenrodAlgebra(3)
     2002            sage: x = B.Q(1,4)
     2003            sage: y = B.P(1,2,3)
     2004            sage: x.degree()
     2005            166
     2006            sage: y.degree()
     2007            192
     2008        """
     2009        def p_degree(m, mult=1, prime=2):
     2010            """
     2011            For m=(n_1, n_2, n_3, ...), Sum_i 2*n_i*(p^i - 1)
     2012            """
     2013            i = 0
     2014            deg = 0
     2015            for n in m:
     2016                i += 1
     2017                deg += n*mult*(prime**i - 1)
     2018            return deg
     2019       
     2020        def q_degree(m, prime=3):
     2021            """
     2022            For m=(n_0, n_1, n_2, ...), Sum_i 2*p^{n_i} - 1
     2023            """
     2024            deg = 0
     2025            for n in m:
     2026                deg += 2*prime**n - 1
     2027            return deg
     2028       
     2029        p = self.prime
     2030        if p == 2:
     2031            degrees = [p_degree(mono) for mono in self._raw['milnor']]
     2032        else:
     2033            degrees = [q_degree(mono1, prime=p)
     2034                           + p_degree(mono2, prime=p, mult=2)
     2035                           for (mono1, mono2) in self._raw['milnor']]
     2036        if min(degrees) == max(degrees):
     2037            return min(degrees)
     2038        else:
     2039            print "Element is not homogeneous."
     2040            return None
     2041
     2042
     2043    def excess(self):
     2044        r"""
     2045        Excess of element.
     2046
     2047        The excess of $\text{Sq}(a,b,c,...)$ is $a + b + c + ...$.
     2048        When $p$ is odd, the excess of
     2049        $Q_{0}^{\epsilon_0} Q_{1}^{\epsilon_1} ... \mathcal{P}(r_1, r_2, ...)$
     2050        is $\sum epsilon_i + 2 \sum r_i$.
     2051       
     2052        The excess of a linear combination of Milnor basis elements is
     2053        the minimum of the excesses of those basis elements.
     2054
     2055        See [Kra] for the proofs of these assertions.
     2056
     2057        EXAMPLES:
     2058            sage: steenrod_set_basis('milnor')
     2059            'milnor'
     2060            sage: a = Sq(1,2,3)
     2061            sage: a.excess()
     2062            6
     2063            sage: (Sq(0,0,1) + Sq(4,1) + Sq(7)).excess()
     2064            1
     2065            sage: [m.excess() for m in (Sq(0,0,1) + Sq(4,1) + Sq(7))]
     2066            [1, 5, 7]
     2067            sage: [m for m in (Sq(0,0,1) + Sq(4,1) + Sq(7))]
     2068            [Sq(0,0,1), Sq(4,1), Sq(7)]
     2069            sage: B = SteenrodAlgebra(7)
     2070            sage: a = B.Q(1,2,5)
     2071            sage: b = B.P(2,2,3)
     2072            sage: a.excess()
     2073            3
     2074            sage: b.excess()
     2075            14
     2076            sage: (a + b).excess()
     2077            3
     2078            sage: (a * b).excess()
     2079            17
     2080
     2081        REFERENCES:
     2082            [Kra] D. Kraines, "On excess in the Milnor basis," Bull. London
     2083                Math. Soc. 3 (1971), 363-365.
     2084        """
     2085        def excess_odd(mono):
     2086            if len(mono) == 0:
     2087                return 0
     2088            else:
     2089                return len(mono[0]) + 2 * sum(mono[1])
     2090           
     2091        p = self.prime
     2092        if p == 2:
     2093            excesses = [sum(mono) for mono in self._raw['milnor']]
     2094        else:
     2095            excesses = [excess_odd(mono) for mono in self._raw['milnor']]
     2096        return min(excesses)
     2097
     2098
     2099    def may_weight(self):
     2100        r"""
     2101        May's 'weight' of element.
     2102
     2103        If we let $F_* (A)$ be the May filtration of the Steenrod
     2104        algebra, the weight of an element $x$ is the integer $k$ so
     2105        that $x$ is in $F_k(A)$ and not in $F_{k+1}(A)$.  According to
     2106        Theorem 2.6 in May's thesis [May], the weight of a Milnor
     2107        basis element is computed as follows: first, to compute the
     2108        weight of $\mathcal{P}(r_1,r2, ...)$, write each $r_i$ in base
     2109        $p$ as $r_i = \sum_j p^j r_{ij}$.  Then each nonzero binary
     2110        digit $r_{ij}$ contributes $i$ to the weight: the weight is
     2111        $\sum_{i,j} i r_{ij}$.  When $p$ is odd, the weight of $Q_i$
     2112        is $i+1$, so the weight of a product $Q_{i_1} Q_{i_2} ...$ is
     2113        equal $(i_1+1) + (i_2+1) + ...$.  Then the weight of $Q_{i_1}
     2114        Q_{i_2} ...\mathcal{P}(r_1,r2, ...)$ is the sum of $(i_1+1) +
     2115        (i_2+1) + ...$ and $\sum_{i,j} i r_{ij}$.
     2116       
     2117        The weight of a sum of basis elements is the minimum of the
     2118        weights of the summands.
     2119
     2120        When $p=2$, we compute the weight on Milnor basis elements by
     2121        adding up the terms in their 'height' -- see the method
     2122        'wall_height' for documentation.  (When $p$ is odd, the height
     2123        of an element is not defined.)
     2124
     2125        EXAMPLES:
     2126            sage: Sq(0).may_weight()
     2127            0
     2128            sage: a = Sq(4)
     2129            sage: a.may_weight()
     2130            1
     2131            sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
     2132            sage: b.may_weight()
     2133            2
     2134            sage: Sq(2,1,5).wall_height()
     2135            [2, 3, 2, 1, 1]
     2136            sage: Sq(2,1,5).may_weight()
     2137            9
     2138            sage: A5 = SteenrodAlgebra(5)
     2139            sage: a = A5.Q(1,2,4)
     2140            sage: b = A5.P(1,2,1)
     2141            sage: a.may_weight()
     2142            10
     2143            sage: b.may_weight()
     2144            8
     2145            sage: (a * b).may_weight()
     2146            18
     2147            sage: A5.P(0,0,1).may_weight()
     2148            3
     2149
     2150        REFERENCES:
     2151            [May]: J. P. May, "The cohomology of restricted Lie algebras
     2152                and of Hopf algebras; application to the Steenrod
     2153                algebra." Thesis, Princeton Univ., 1964.
     2154        """
     2155        from sage.rings.infinity import Infinity
     2156        p = self.prime
     2157        if self == 0:
     2158            return Infinity
     2159        elif self.is_unit():
     2160            return 0
     2161        elif p == 2:
     2162            wt = Infinity
     2163            for mono in self:
     2164                wt = min(wt, sum(mono.wall_height()))
     2165            return wt
     2166        else: # p odd
     2167            wt = Infinity
     2168            for (mono1, mono2) in self._raw['milnor']:
     2169                P_wt = 0
     2170                index = 1
     2171                for n in mono2:
     2172                    P_wt += index * sum(base_p_expansion(n,p))
     2173                    index += 1
     2174                wt = min(wt, sum(mono1) + len(mono1) + P_wt)
     2175            return wt
     2176
     2177
     2178    def is_decomposable(self):
     2179        r"""
     2180        return True if element is decomposable, False otherwise.
     2181
     2182        That is, if element is in the square of the augmentation
     2183        ideal, return True; otherwise, return False.
     2184
     2185        EXAMPLES:
     2186            sage: a = Sq(6)
     2187            sage: a.is_decomposable()
     2188            True
     2189            sage: for i in range(9):
     2190            ...       if not Sq(i).is_decomposable():
     2191            ...           print Sq(i)
     2192            Sq(0)
     2193            Sq(1)
     2194            Sq(2)
     2195            Sq(4)
     2196            Sq(8)
     2197        """
     2198        return self.may_weight() > 1       
     2199
     2200
     2201    def wall_height(self):
     2202        r"""
     2203        Wall's 'height' of element.
     2204
     2205        The height of an element of the mod 2 Steenrod algebra is a
     2206        list of non-negative integers, defined as follows: if the
     2207        element is a monomial in the generators $\text{Sq}(2^i)$, then
     2208        the $i$th entry in the list is the number of times
     2209        $\text{Sq}(2^i)$ appears.  For an arbitrary element, write it
     2210        as a sum of such monomials; then its height is the maximum,
     2211        ordered right-lexicographically, of the heights of those
     2212        monomials.
     2213
     2214        When $p$ is odd, the height of an element is not defined.
     2215
     2216        According to Theorem 3 in [Wall], the height of the Milnor
     2217        basis element $\text{Sq}(r_1, r_2, ...)$ is obtained as
     2218        follows: write each $r_i$ in binary as $r_i = \sum_j 2^j r_{ij}$. 
     2219        Then each nonzero binary digit $r_{ij}$ contributes 1 to the
     2220        $k$th entry in the height, for $j \leq k \leq i+j-1$.
     2221
     2222        EXAMPLES:
     2223            sage: Sq(0).wall_height()
     2224            []
     2225            sage: a = Sq(4)
     2226            sage: a.wall_height()
     2227            [0, 0, 1]
     2228            sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
     2229            sage: b.wall_height()
     2230            [0, 0, 1, 1]
     2231            sage: Sq(0,0,3).wall_height()
     2232            [1, 2, 2, 1]
     2233
     2234        REFERENCES:
     2235            [Wall]: C. T. C. Wall, "Generators and relations for the
     2236                Steenrod algebra," Ann. of Math. (2) \textbf{72} (1960),
     2237                429--444.
     2238        """
     2239        def mono_degree(m):
     2240            i = 0
     2241            deg = 0
     2242            for n in m:
     2243                i += 1
     2244                deg += n*(2**i - 1)
     2245            return deg
     2246
     2247        if self.prime > 2:
     2248            raise NotImplementedError, "Wall height is not defined at odd primes."
     2249        if self == 0 or self == 1:
     2250            return []
     2251        result = []
     2252        for r in self._raw['milnor']:
     2253            h = [0]*(1+mono_degree(r))
     2254            i = 1
     2255            for x in r:
     2256                if x > 0:
     2257                    for j in range(1+integer_base_2_log(x)):
     2258                        if (2**j & x) != 0:
     2259                            for k in range(j,i+j):
     2260                                h[k] += 1
     2261                i=i+1
     2262            h.reverse()
     2263            result = max(h, result)
     2264        result.reverse()
     2265        return check_and_trim(result)
     2266           
     2267
     2268    def antipode(self):
     2269        """
     2270        Antipode of element.
     2271
     2272        Algorithm: according to a result of Milnor's, the antipode of
     2273        Sq(n) is the sum of all of the Milnor basis elements in
     2274        dimension n.  So: convert the element to the Serre-Cartan
     2275        basis and use this formula for the antipode of Sq(n), together
     2276        with the fact that the antipode is an antihomomorphism: if we
     2277        call the antipode c, then c(ab) = c(b) c(a).
     2278
     2279        At odd primes, a similar method is used: the antipode of P(n)
     2280        is the sum of the Milnor basis elements in dimension n*2(p-1),
     2281        and the antipode of beta = Q_0 is -Q_0.  So convert to the
     2282        Serre-Cartan basis, as in the p=2 case.
     2283
     2284        EXAMPLES:
     2285            sage: d = Sq(0,0,1); d
     2286            Sq(0,0,1)
     2287            sage: d.antipode()
     2288            Sq(0,0,1)
     2289            sage: Sq(4).antipode()
     2290            Sq(1,1) + Sq(4)
     2291            sage: (Sq(4) * Sq(2)).antipode()
     2292            Sq(6)
     2293            sage: A3 = SteenrodAlgebra(3)
     2294            sage: A3.P(2).antipode()
     2295            P(2)
     2296            sage: A3.P(2,1).antipode()
     2297            2 P(2,1)
     2298            sage: a = SteenrodAlgebra(7).P(3,1)
     2299            sage: a.antipode()
     2300            3 P(3,1) + 4 P(11)
     2301
     2302        Applying the antipode twice returns the original element:
     2303            sage: y = Sq(8)*Sq(4)
     2304            sage: y == (y.antipode()).antipode()
     2305            True
     2306        """
     2307        def sum_of_basis(n,p):
     2308            """
     2309            Antipode of P(n) (i.e., of Sq(n) when p=2).
     2310
     2311            INPUT:
     2312                n -- integer
     2313                p -- positive prime number
     2314           
     2315            OUTPUT:
     2316                elt -- element of the Steenrod algebra
     2317
     2318            This returns the sum of all of the elements P(...) in the
     2319            Milnor basis in dimension $n$ at the prime p
     2320            """
     2321            from steenrod_algebra_bases import steenrod_algebra_basis
     2322            return sum(steenrod_algebra_basis(n,'milnor',p=p))
     2323        from steenrod_algebra_bases import milnor_convert
     2324        result = 0
     2325        p = self.prime
     2326        if p == 2:
     2327            for mono in self._basis_dictionary('serre_cartan'):
     2328                antipode = Sq(0)
     2329                for n in mono:
     2330                    antipode = sum_of_basis(n, p) * antipode
     2331                result = result + antipode
     2332        else:
     2333            from sage.misc.functional import is_even
     2334            for mono in self._basis_dictionary('serre_cartan'):
     2335                antipode = SteenrodAlgebra(p).P(0)
     2336                index = 0
     2337                for n in mono:
     2338                    if is_even(index) and n != 0:
     2339                        antipode = -SteenrodAlgebra(p).Q(0) * antipode
     2340                    else:
     2341                        antipode = sum_of_basis(n*2*(p-1),p) * antipode
     2342                    index += 1
     2343                result = result + antipode
     2344        return result
     2345
     2346
     2347    def _repr_(self):
     2348        """
     2349        String representation of element.
     2350       
     2351        Default is to use the Milnor basis, but this can be changed by
     2352        using the function steenrod_set_basis.
     2353
     2354        EXAMPLES:
     2355            sage: steenrod_set_basis('milnor')
     2356            'milnor'
     2357            sage: A7 = SteenrodAlgebra(7)
     2358            sage: x = A7.Q(0,3) * A7.P(2,2)
     2359            sage: x._repr_()
     2360            'Q_0 Q_3 P(2,2)'
     2361            sage: x
     2362            Q_0 Q_3 P(2,2)
     2363            sage: a = Sq(0,0,2)
     2364            sage: a
     2365            Sq(0,0,2)
     2366            sage: steenrod_set_basis('admissible')
     2367            'admissible'
     2368            sage: a
     2369            Sq^{8} Sq^{4} Sq^{2} + Sq^{9} Sq^{4} Sq^{1} + Sq^{10} Sq^{3} Sq^{1} +
     2370            Sq^{10} Sq^{4} + Sq^{11} Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{13} Sq^{1}
     2371            + Sq^{14}
     2372            sage: steenrod_set_basis('woodz')
     2373            'woodz'
     2374            sage: a
     2375            Sq^{6} Sq^{7} Sq^{1} + Sq^{14} + Sq^{4} Sq^{7} Sq^{3} + Sq^{4} Sq^{7}
     2376            Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{8} Sq^{6} + Sq^{8} Sq^{4} Sq^{2}
     2377            sage: steenrod_set_basis('arnonc')
     2378            'arnonc'
     2379            sage: a
     2380            Sq^{4} Sq^{2} Sq^{8} + Sq^{4} Sq^{4} Sq^{6} + Sq^{4} Sq^{6} Sq^{4} +
     2381            Sq^{6} Sq^{8} + Sq^{8} Sq^{4} Sq^{2} + Sq^{8} Sq^{6}
     2382            sage: steenrod_set_basis('pst_llex')
     2383            'pst_llex'
     2384            sage: a
     2385            P^{1}_{3}
     2386            sage: steenrod_set_basis('comm_revz')
     2387            'comm_revz'
     2388            sage: a
     2389            c_{0,1} c_{1,1} c_{0,3} c_{2,1} + c_{0,2} c_{0,3} c_{2,1} + c_{1,3}
     2390        """
     2391        if len(self._raw['milnor']) == 0:
     2392            return "0"
     2393        else:
     2394            return string_rep(self)
     2395
     2396
     2397    def _latex_(self):
     2398        """
     2399        LaTeX representation of element.
     2400       
     2401        Default is to use the Milnor basis, but this can be changed by
     2402        using the function steenrod_set_basis.
     2403
     2404        For any element x in the Steenrod algebra, use 'view(x)' to
     2405        see the typeset LaTeX representation.
     2406
     2407        EXAMPLES:
     2408            sage: steenrod_set_basis('milnor')
     2409            'milnor'
     2410            sage: A7 = SteenrodAlgebra(7)
     2411            sage: x = A7.Q(0,3) * A7.P(2,2)
     2412            sage: x._latex_()
     2413            'Q_{0} Q_{3} \\mathcal{P}(2,2)'
     2414            sage: latex(x)
     2415            Q_{0} Q_{3} \mathcal{P}(2,2)
     2416            sage: b = Sq(0,2)
     2417            sage: steenrod_set_basis('admissible')
     2418            'admissible'
     2419            sage: b._latex_()
     2420            '\\text{Sq}^{4} \\text{Sq}^{2} + \\text{Sq}^{5} \\text{Sq}^{1} +
     2421            \\text{Sq}^{6}'
     2422            sage: steenrod_set_basis('woody')
     2423            'woody'
     2424            sage: b._latex_()
     2425            '\\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{1} + \\text{Sq}^{6} +
     2426            \\text{Sq}^{4} \\text{Sq}^{2}'
     2427            sage: steenrod_set_basis('arnona')
     2428            'arnona'
     2429            sage: b._latex_()
     2430            'X^{1}_{1} X^{2}_{2}  + X^{2}_{1}'
     2431            sage: steenrod_set_basis('pst_deg')
     2432            'pst_deg'
     2433            sage: b._latex_()
     2434            'P^{1}_{2}'
     2435            sage: steenrod_set_basis('comm_llex')
     2436            'comm_llex'
     2437            sage: b._latex_()
     2438            'c_{1,2}'
     2439            sage: steenrod_set_basis('milnor')
     2440            'milnor'
     2441            sage: b._latex_()
     2442            '\\text{Sq}(0,2)'
     2443        """
     2444        if len(self._raw['milnor']) == 0:
     2445            return "0"
     2446        else:
     2447            return string_rep(self,LaTeX=True)
     2448
     2449
     2450    def __iter__(self):
     2451        """
     2452        Iterator for looping through summands in an element of the
     2453        Steenrod algebra.
     2454
     2455        EXAMPLES:
     2456            sage: z = Sq(0,0,1) + Sq(4,1) + Sq(7)
     2457            sage: [m for m in z]
     2458            [Sq(0,0,1), Sq(4,1), Sq(7)]
     2459            sage: [m.excess() for m in z]
     2460            [1, 5, 7]
     2461            sage: for m in z: m * Sq(2)
     2462            Sq(2,0,1)
     2463            Sq(0,3) + Sq(6,1)
     2464            Sq(3,2)
     2465            sage: a = SteenrodAlgebra(5).P(5,5)
     2466            sage: a * a
     2467            P(3,6,1) + 2 P(4,11) + P(9,5,1) + 4 P(10,10)
     2468            sage: for m in a * a: m
     2469            P(3,6,1)
     2470            2 P(4,11)
     2471            P(9,5,1)
     2472            4 P(10,10)
     2473
     2474        This loops through the summands in the Milnor basis
     2475        representation of the element.  The element w defined below is
     2476        a single monomial in the Serre-Cartan basis, but a sum of four
     2477        monomials in the Milnor basis:
     2478            sage: steenrod_set_basis('serre_cartan')
     2479            'serre_cartan'
     2480            sage: w = Sq(4) * Sq(2) * Sq(1)
     2481            sage: w
     2482            Sq^{4} Sq^{2} Sq^{1}
     2483            sage: for m in w: m
     2484            Sq^{4} Sq^{2} Sq^{1} + Sq^{5} Sq^{2} + Sq^{6} Sq^{1} + Sq^{7}
     2485            Sq^{5} Sq^{2} + Sq^{7}
     2486            Sq^{6} Sq^{1} + Sq^{7}
     2487            Sq^{7}
     2488            sage: steenrod_set_basis('milnor')
     2489            'milnor'
     2490            sage: w
     2491            Sq(0,0,1) + Sq(1,2) + Sq(4,1) + Sq(7)
     2492            sage: for m in w: m
     2493            Sq(0,0,1)
     2494            Sq(1,2)
     2495            Sq(4,1)
     2496            Sq(7)
     2497        """
     2498        for m in sorted(self._raw['milnor'].keys()):
     2499            yield SteenrodAlgebraElement({m: self._raw['milnor'][m]},
     2500                                         p = self.prime)
     2501       
     2502
     2503    def additive_order(self):
     2504        """
     2505        The additive order of any element of the mod p Steenrod algebra is p.
     2506
     2507        EXAMPLES:
     2508            sage: z = Sq(4) + Sq(6) + Sq(0)
     2509            sage: z.additive_order()
     2510            2
     2511        """
     2512        return self.prime
     2513
     2514
     2515def Sq(*nums):
     2516    """
     2517    Milnor element Sq(a,b,c,...).
     2518
     2519    INPUT:
     2520        nums -- list of non-negative integers
     2521       
     2522    OUTPUT:
     2523        element of the Steenrod algebra given by the single basis
     2524        element Sq(a, b, c, ...)
     2525   
     2526    EXAMPLES:
     2527        sage: Sq(5)
     2528        Sq(5)
     2529        sage: Sq(5) + Sq(2,1) + Sq(5)  # addition is mod 2:
     2530        Sq(2,1)   
     2531        sage: (Sq(4,3) + Sq(7,2)).degree()
     2532        13
     2533
     2534    Entries must be non-negative integers; otherwise, an error results.
     2535       
     2536    This function is a good way to define elements of the Steenrod algebra.
     2537    """
     2538    dict = {nums: 1}
     2539    return SteenrodAlgebraElement(dict, p=2)
     2540
     2541
     2542def pst(s,t,p=None):
     2543    """
     2544    The Margolis element P^s_t.
     2545
     2546    INPUT:
     2547        s -- non-negative integer
     2548        t -- positive integer
     2549        p (optional, default 2) -- positive prime number
     2550       
     2551    OUTPUT:
     2552        The Margolis element P^s_t of the mod p Steenrod algebra: the
     2553        element equal to P(0,0,...,0,p^s), where the p^s is in
     2554        position t.
     2555
     2556    EXAMPLES:
     2557        sage: from sage.algebras.steenrod_algebra import pst
     2558        sage: pst(3,5)
     2559        Sq(0,0,0,0,8)
     2560        sage: pst(1,2) + Sq(4)*Sq(2) + Sq(2)*Sq(4)
     2561        0
     2562        sage: pst(3,5,5)
     2563        P(0,0,0,0,125)
     2564        sage: pst(3,5,p=5)
     2565        P(0,0,0,0,125)
     2566    """
     2567    if p is None: p = _steenrod_prime
     2568    return SteenrodAlgebra(p).pst(s,t)
     2569
     2570
     2571def degree(x):
     2572    r"""
     2573    Degree of x.
     2574   
     2575    The degree of $\text{Sq}(i_1,i_2,i_3,...)$ is
     2576    $i_1 + 3 i_2 + 7 i_3 + ... + (2^n - 1) i_n + ...$.
     2577    When $p$ is odd, the degree of
     2578    $Q_{0}^{\epsilon_0} Q_{1}^{\epsilon_1} ... \mathcal{P}(r_1, r_2, ...)$
     2579    is $\sum \epsilon_i (2p^i - 1) + \sum r_j (2p^j - 2)$.
     2580       
     2581    The degree of a sum is undefined, unless each summand has the
     2582    same degree: that is, unless the element is homogeneous.
     2583   
     2584    INPUT:
     2585        x -- element of the Steenrod algebra
     2586
     2587    OUTPUT:
     2588        degree -- non-negative integer, or None if element is not
     2589        homogeneous
     2590   
     2591    EXAMPLES:
     2592        sage: from sage.algebras.steenrod_algebra import degree
     2593        sage: a = Sq(1,2,1)
     2594        sage: degree(a)
     2595        14
     2596        sage: degree(Sq(3) + Sq(5,1))
     2597        Element is not homogeneous.
     2598        sage: B = SteenrodAlgebra(3)
     2599        sage: x = B.Q(1,4)
     2600        sage: y = B.P(1,2,3)
     2601        sage: degree(x)
     2602        166
     2603        sage: degree(y)
     2604        192
     2605    """
     2606    return x.degree()
     2607
     2608
     2609def excess(x):
     2610    r"""
     2611    Excess of x.
     2612   
     2613    The excess of $\text{Sq}(a,b,c,...)$ is $a + b + c + ...$.
     2614    When $p$ is odd, the excess of
     2615    $Q_{0}^{\epsilon_0} Q_{1}^{\epsilon_1} ... \mathcal{P}(r_1, r_2, ...)$
     2616    is $\sum epsilon_i + 2 \sum r_i$.
     2617       
     2618    The excess of a linear combination of Milnor basis elements is
     2619    the minimum of the excesses of those basis elements.
     2620
     2621    INPUT:
     2622        x -- element of the Steenrod algebra
     2623
     2624    OUTPUT:
     2625        excess -- non-negative integer, the excess of x
     2626   
     2627    EXAMPLES:
     2628        sage: from sage.algebras.steenrod_algebra import excess
     2629        sage: a = Sq(1,2,3)
     2630        sage: excess(a)
     2631        6
     2632        sage: excess(Sq(0,0,1) + Sq(4,1) + Sq(7))
     2633        1
     2634        sage: [excess(m) for m in (Sq(0,0,1) + Sq(4,1) + Sq(7))]
     2635        [1, 5, 7]
     2636        sage: B = SteenrodAlgebra(7)
     2637        sage: a = B.Q(1,2,5)
     2638        sage: b = B.P(2,2,3)
     2639        sage: excess(a)
     2640        3
     2641        sage: excess(b)
     2642        14
     2643        sage: excess(a + b)
     2644        3
     2645        sage: excess(a * b)
     2646        17
     2647    """
     2648    return x.excess()
     2649
     2650
     2651def milnor(x):
     2652    r"""
     2653    Milnor representation of x.
     2654
     2655    INPUT:
     2656        x -- element of the Steenrod algebra
     2657
     2658    OUTPUT:
     2659        None
     2660
     2661    This prints the representation of x in the Milnor basis.  Note
     2662    that it only prints the representation; it does not actually
     2663    return a value.  Thus evaluating "y = milnor(x)" will set
     2664    y to be None.
     2665
     2666    EXAMPLES:
     2667        sage: from sage.algebras.steenrod_algebra import milnor
     2668        sage: steenrod_set_basis('adem')
     2669        'adem'
     2670        sage: x = Sq(5) * Sq(2) * Sq(1); x
     2671        Sq^{5} Sq^{2} Sq^{1}
     2672        sage: milnor(x)
     2673        Sq(1,0,1) + Sq(5,1)
     2674    """
     2675    return x.basis('milnor')
     2676
     2677
     2678def serre_cartan(x):
     2679    r"""
     2680    Serre-Cartan representation of x.
     2681
     2682    INPUT:
     2683        x -- element of the Steenrod algebra
     2684
     2685    OUTPUT:
     2686        None
     2687
     2688    This prints the representation of x in the Serre-Cartan basis.
     2689    Note that it only prints the representation; it does not actually
     2690    return a value.  Thus evaluating "y = serre_cartan(x)" will set y
     2691    to be None.
     2692
     2693    EXAMPLES:
     2694        sage: from sage.algebras.steenrod_algebra import serre_cartan
     2695        sage: steenrod_set_basis('milnor')
     2696        'milnor'
     2697        sage: x = Sq(3,2); x
     2698        Sq(3,2)
     2699        sage: serre_cartan(x)
     2700        Sq^{7} Sq^{2}
     2701    """
     2702    return x.basis('adem')
     2703
     2704adem = serre_cartan
     2705admissible = serre_cartan
     2706
     2707## string representations
     2708
     2709def string_rep(element,LaTeX=False,sort=True):
     2710    """
     2711    String representation of element.
     2712
     2713    INPUT:
     2714        element -- element of the Steenrod algebra
     2715        LaTeX (optional, default False) -- If True, output LaTeX string
     2716        sort (optional, default True) -- If True, sort output
     2717
     2718    OUTPUT:
     2719        string -- string representation of element in current basis
     2720
     2721    If LaTeX is True, output a string suitable for LaTeX; otherwise,
     2722    output a plain string.  If sort is True, sort element left
     2723    lexicographically; otherwise, no sorting is done, and so the
     2724    order in which the summands are printed may be unpredictable.
     2725   
     2726    EXAMPLES:
     2727        sage: from sage.algebras.steenrod_algebra import string_rep
     2728        sage: a = Sq(0,0,2)
     2729        sage: steenrod_set_basis('admissible')
     2730        'admissible'
     2731        sage: string_rep(a)
     2732        'Sq^{8} Sq^{4} Sq^{2} + Sq^{9} Sq^{4} Sq^{1} + Sq^{10} Sq^{3} Sq^{1} +
     2733        Sq^{10} Sq^{4} + Sq^{11} Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{13} Sq^{1}
     2734        + Sq^{14}'
     2735        sage: b = Sq(0,2)
     2736        sage: string_rep(b,LaTeX=True)
     2737        '\\text{Sq}^{4} \\text{Sq}^{2} + \\text{Sq}^{5} \\text{Sq}^{1} +
     2738        \\text{Sq}^{6}'
     2739        sage: steenrod_set_basis('woodz')
     2740        'woodz'
     2741        sage: string_rep(a)
     2742        'Sq^{6} Sq^{7} Sq^{1} + Sq^{14} + Sq^{4} Sq^{7} Sq^{3} + Sq^{4} Sq^{7}
     2743        Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{8} Sq^{6} + Sq^{8} Sq^{4} Sq^{2}'
     2744        sage: steenrod_set_basis('arnonc')
     2745        'arnonc'
     2746        sage: string_rep(a,sort=False)
     2747        'Sq^{4} Sq^{4} Sq^{6} + Sq^{6} Sq^{8} + Sq^{4} Sq^{2} Sq^{8} + Sq^{4}
     2748        Sq^{6} Sq^{4} + Sq^{8} Sq^{4} Sq^{2} + Sq^{8} Sq^{6}'
     2749        sage: string_rep(a)
     2750        'Sq^{4} Sq^{2} Sq^{8} + Sq^{4} Sq^{4} Sq^{6} + Sq^{4} Sq^{6} Sq^{4} +
     2751        Sq^{6} Sq^{8} + Sq^{8} Sq^{4} Sq^{2} + Sq^{8} Sq^{6}'
     2752        sage: steenrod_set_basis('pst_llex')
     2753        'pst_llex'
     2754        sage: string_rep(a)
     2755        'P^{1}_{3}'
     2756        sage: steenrod_set_basis('comm_revz')
     2757        'comm_revz'
     2758        sage: string_rep(a,LaTeX=True,sort=False)
     2759        'c_{0,2} c_{0,3} c_{2,1} + c_{1,3} + c_{0,1} c_{1,1} c_{0,3} c_{2,1}'
     2760        sage: string_rep(a,LaTeX=True)
     2761        'c_{0,1} c_{1,1} c_{0,3} c_{2,1} + c_{0,2} c_{0,3} c_{2,1} + c_{1,3}'
     2762        sage: steenrod_set_basis('milnor')
     2763        'milnor'
     2764        sage: string_rep(a)
     2765        'Sq(0,0,2)'
     2766        sage: string_rep(a,LaTeX=True)
     2767        '\\text{Sq}(0,0,2)'
     2768
     2769    Some odd primary examples:
     2770        sage: A5 = SteenrodAlgebra(5)
     2771        sage: a = A5.P(5,1); b = A5.Q(0,1,3)
     2772        sage: string_rep(b)
     2773        'Q_0 Q_1 Q_3'
     2774        sage: string_rep(a, LaTeX=True)
     2775        '\\mathcal{P}(5,1)'
     2776        sage: steenrod_set_basis('adem')
     2777        'adem'
     2778        sage: string_rep(a)
     2779        'P^{10} P^{1} + 4 P^{11}'
     2780        sage: steenrod_set_basis('milnor')
     2781        'milnor'
     2782    """
     2783    if len(element._raw['milnor']) == 0:
     2784        return "0"
     2785    p = element.prime
     2786    if steenrod_basis in _steenrod_milnor_basis_names:
     2787        dict = element._basis_dictionary('milnor')
     2788        mono_to_string = milnor_mono_to_string
     2789    elif steenrod_basis in _steenrod_serre_cartan_basis_names:
     2790        dict = element._basis_dictionary('serre-cartan')
     2791        mono_to_string = sc_mono_to_string
     2792    elif p==2 and steenrod_basis in _steenrod_woodY_basis_names:
     2793        dict = element._basis_dictionary('woody')
     2794        mono_to_string = wood_mono_to_string
     2795    elif p==2 and steenrod_basis in _steenrod_woodZ_basis_names:
     2796        dict = element._basis_dictionary('woodz')
     2797        mono_to_string = wood_mono_to_string
     2798    elif p==2 and steenrod_basis in _steenrod_wall_basis_names:
     2799        dict = element._basis_dictionary('wall')
     2800        if steenrod_basis.find('long') >= 0:
     2801            mono_to_string = wall_long_mono_to_string
     2802        else:
     2803            mono_to_string = wall_mono_to_string
     2804    elif p==2 and steenrod_basis in _steenrod_arnonA_basis_names:
     2805        dict = element._basis_dictionary('arnona')
     2806        if steenrod_basis.find('long') >= 0:
     2807            mono_to_string = arnonA_long_mono_to_string
     2808        else:
     2809            mono_to_string = arnonA_mono_to_string
     2810    elif p==2 and steenrod_basis in _steenrod_arnonC_basis_names:
     2811        dict = element._basis_dictionary('arnonc')
     2812        mono_to_string = sc_mono_to_string
     2813    elif p==2 and steenrod_basis in _steenrod_pst_basis_names:
     2814        mono_to_string = pst_mono_to_string
     2815        if steenrod_basis.find('rlex') >= 0:
     2816            dict = element._basis_dictionary('pst_rlex')
     2817        elif steenrod_basis.find('llex') >= 0:
     2818            dict = element._basis_dictionary('pst_llex')
     2819        elif steenrod_basis.find('deg') >= 0:
     2820            dict = element._basis_dictionary('pst_deg')
     2821        elif steenrod_basis.find('revz') >= 0:
     2822            dict = element._basis_dictionary('pst_revz')
     2823        else:
     2824            dict = element._basis_dictionary('pst_revz')
     2825    elif p==2 and steenrod_basis in _steenrod_commutator_basis_names:
     2826        if steenrod_basis.find('long') >= 0:
     2827            mono_to_string = comm_long_mono_to_string
     2828        else:
     2829            mono_to_string = comm_mono_to_string
     2830        if steenrod_basis.find('rlex') >= 0:
     2831            dict = element._basis_dictionary('comm_rlex')
     2832        elif steenrod_basis.find('llex') >= 0:
     2833            dict = element._basis_dictionary('comm_llex')
     2834        elif steenrod_basis.find('deg') >= 0:
     2835            dict = element._basis_dictionary('comm_deg')
     2836        elif steenrod_basis.find('revz') >= 0:
     2837            dict = element._basis_dictionary('comm_revz')
     2838        else:
     2839            dict = element._basis_dictionary('comm_revz')
     2840    else:
     2841        if p==2:
     2842            raise NotImplementedError, "Don't know how to deal with basis %s." \
     2843                % steenrod_basis
     2844        else:
     2845            raise NotImplementedError, "Don't know how to deal with basis " + \
     2846                "%s at the prime %s." % (steenrod_basis, p)
     2847    output = ""
     2848    if sort:
     2849        sorted_list = sorted(dict.keys())
     2850    else:
     2851        sorted_list = dict
     2852    for mono in sorted_list:
     2853        if dict[mono] != 1:
     2854            coeff = str(dict[mono]) + " "
     2855        else:
     2856            coeff = ""
     2857        output = output + coeff + mono_to_string(mono,LaTeX,
     2858                                                 p=element.parent().prime) + " + "
     2859    return output.strip(" +")
     2860
     2861
     2862def milnor_mono_to_string(mono,LaTeX=False,p=None):
     2863    """
     2864    String representation of element of the Milnor basis.
     2865
     2866    This is used by the _repr_ and _latex_ methods.
     2867
     2868    INPUT:
     2869        mono -- if p=2, tuple of non-negative integers (a,b,c,...);
     2870                if p>2, pair of tuples of non-negative integers
     2871                ((n0, n1, n2, ...), (r1, r2, ...))
     2872        LaTeX (optional, default False) -- if true, output LaTeX string
     2873        p (optional, default 2) -- work in the mod p Steenrod algebra
     2874
     2875    OUTPUT:
     2876        string -- string Sq(a,b,c,...) when p=2, or string
     2877                  Q_n0 Q_n1 Q_n2 ... P(r1, r2, ...) when p>2
     2878       
     2879    EXAMPLES:
     2880        sage: from sage.algebras.steenrod_algebra import milnor_mono_to_string
     2881        sage: milnor_mono_to_string((1,2,3,4))
     2882        'Sq(1,2,3,4)'
     2883        sage: milnor_mono_to_string((1,2,3,4),LaTeX=True)
     2884        '\\text{Sq}(1,2,3,4)'
     2885        sage: milnor_mono_to_string(((1,0), (2,3,1)), p=3)
     2886        'Q_1 Q_0 P(2,3,1)'
     2887        sage: milnor_mono_to_string(((1,0), (2,3,1)), LaTeX=True, p=3)
     2888        'Q_{1} Q_{0} \\mathcal{P}(2,3,1)'
     2889
     2890    The empty tuple represents the unit element Sq(0) (or P(0) at an odd prime):
     2891        sage: milnor_mono_to_string(())
     2892        'Sq(0)'
     2893        sage: milnor_mono_to_string((), p=5)
     2894        'P(0)'
     2895    """
     2896    if p is None: p = _steenrod_prime
     2897    if LaTeX:
     2898        if p == 2:
     2899            sq = "\\text{Sq}"
     2900            P = "\\text{Sq}"
     2901        else:
     2902            P = "\\mathcal{P}"
     2903    else:
     2904        if p == 2:
     2905            sq = "Sq"
     2906            P = "Sq"
     2907        else:
     2908            P = "P"
     2909    if len(mono) == 0 or (p > 2 and len(mono[0]) + len(mono[1]) == 0):
     2910        return P + "(0)"
     2911    else:
     2912        if p == 2:
     2913            string = sq + "(" + str(mono[0])
     2914            for n in mono[1:]:
     2915                string = string + "," + str(n)
     2916            string = string + ")"
     2917        else:
     2918            string = ""
     2919            if len(mono[0]) > 0:
     2920                for e in mono[0]:
     2921                    if LaTeX:
     2922                        string = string + "Q_{" + str(e) + "} "
     2923                    else:
     2924                        string = string + "Q_" + str(e) + " "
     2925            if len(mono[1]) > 0:
     2926                string = string + P + "(" + str(mono[1][0])
     2927                for n in mono[1][1:]:
     2928                    string = string + "," + str(n)
     2929                string = string + ")"
     2930        return string.strip(" ")
     2931   
     2932
     2933def sc_mono_to_string(mono,LaTeX=False,p=None):
     2934    """
     2935    String representation of element of the Serre-Cartan basis.
     2936
     2937    This is used by the _repr_ and _latex_ methods.
     2938
     2939    INPUT:
     2940        mono -- tuple of positive integers (a,b,c,...) when p=2, or tuple
     2941                (e0, n1, e1, n2, ...) when p>2, where each ei is 0 or 1, and
     2942                each ni is positive
     2943        LaTeX (optional, default False) -- if true, output LaTeX string
     2944        p (optional, default 2) -- work in the mod p Steenrod algebra
     2945
     2946    OUTPUT:
     2947        string -- string Sq^{a} Sq^{b} Sq^{c} ... when p=2, or string
     2948                  beta^{e0} P^{n1} beta^{e1} P^{n2} ...
     2949       
     2950    EXAMPLES:
     2951        sage: from sage.algebras.steenrod_algebra import sc_mono_to_string
     2952        sage: sc_mono_to_string((1,2,3,4))
     2953        'Sq^{1} Sq^{2} Sq^{3} Sq^{4}'
     2954        sage: sc_mono_to_string((1,2,3,4),LaTeX=True)
     2955        '\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{4}'
     2956        sage: sc_mono_to_string((0,5,1,1,0), p=3)
     2957        'P^{5} beta P^{1}'
     2958        sage: sc_mono_to_string((0,5,1,1,0), p=3, LaTeX=True)
     2959        '\\mathcal{P}^{5} \\beta \\mathcal{P}^{1}'
     2960
     2961    The empty tuple represents the unit element Sq^0 (or P^0 at an odd prime):
     2962        sage: sc_mono_to_string(())
     2963        'Sq^{0}'
     2964        sage: sc_mono_to_string((), p=7)
     2965        'P^{0}'
     2966    """
     2967    if p is None: p = _steenrod_prime
     2968    if LaTeX:
     2969        if p == 2:
     2970            sq = "\\text{Sq}"
     2971            P = "\\text{Sq}"
     2972        else:
     2973            P = "\\mathcal{P}"
     2974    else:
     2975        if p == 2:
     2976            sq = "Sq"
     2977            P = "Sq"
     2978        else:
     2979            P = "P"
     2980    if len(mono) == 0:
     2981        return P + "^{0}"
     2982    else:
     2983        if p == 2:
     2984            string = ""
     2985            for n in mono:
     2986                string = string + sq + "^{" + str(n) + "} "
     2987        else:
     2988            string = ""
     2989            index = 0
     2990            for n in mono:
     2991                from sage.misc.functional import is_even
     2992                if is_even(index):
     2993                    if n == 1:
     2994                        if LaTeX:
     2995                            string = string + "\\beta "
     2996                        else:
     2997                            string = string + "beta "
     2998                else:
     2999                    string = string + P + "^{" + str(n) + "} "
     3000                index += 1
     3001        return string.strip(" ")
     3002
     3003
     3004def wood_mono_to_string(mono,LaTeX=False,p=2):
     3005    """
     3006    String representation of element of Wood's Y and Z bases.
     3007
     3008    This is used by the _repr_ and _latex_ methods.
     3009
     3010    INPUT:
     3011        mono -- tuple of pairs of non-negative integers (s,t)
     3012
     3013    OUTPUT:
     3014        string -- concatenation of 'Sq^{2^s (2^{t+1}-1)}' for each pair (s,t)
     3015       
     3016    EXAMPLES:
     3017        sage: from sage.algebras.steenrod_algebra import wood_mono_to_string
     3018        sage: wood_mono_to_string(((1,2),(3,0)))
     3019        'Sq^{14} Sq^{8}'
     3020        sage: wood_mono_to_string(((1,2),(3,0)),LaTeX=True)
     3021        '\\text{Sq}^{14} \\text{Sq}^{8}'
     3022
     3023    The empty tuple represents the unit element Sq(0):
     3024        sage: wood_mono_to_string(())
     3025        'Sq(0)'
     3026    """
     3027    if LaTeX:
     3028        sq = "\\text{Sq}"
     3029    else:
     3030        sq = "Sq"
     3031    if len(mono) == 0:
     3032        return sq + "(0)"
     3033    else:
     3034        string = ""
     3035        for (s,t) in mono:
     3036            string = string + sq + "^{" + \
     3037                str(2**s * (2**(t+1)-1)) + "} "
     3038        return string.strip(" ")
     3039
     3040
     3041def wall_mono_to_string(mono,LaTeX=False,p=2):
     3042    """
     3043    String representation of element of Wall's basis.
     3044
     3045    This is used by the _repr_ and _latex_ methods.
     3046
     3047    INPUT:
     3048        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     3049
     3050    OUTPUT:
     3051        string -- concatenation of 'Q^{m}_{k}' for each pair (m,k)
     3052       
     3053    EXAMPLES:
     3054        sage: from sage.algebras.steenrod_algebra import wall_mono_to_string
     3055        sage: wall_mono_to_string(((1,2),(3,0)))
     3056        'Q^{1}_{2} Q^{3}_{0}'
     3057        sage: wall_mono_to_string(((1,2),(3,0)),LaTeX=True)
     3058        'Q^{1}_{2} Q^{3}_{0}'
     3059
     3060    The empty tuple represents the unit element Sq(0):
     3061        sage: wall_mono_to_string(())
     3062        'Sq(0)'
     3063    """
     3064    if LaTeX:
     3065        sq = "\\text{Sq}"
     3066    else:
     3067        sq = "Sq"
     3068    if len(mono) == 0:
     3069        return sq + "(0)"
     3070    else:
     3071        string = ""
     3072        for (m,k) in mono:
     3073            string = string + "Q^{" + str(m) + "}_{" \
     3074                + str(k) + "} "
     3075        return string.strip(" ")
     3076
     3077
     3078def wall_long_mono_to_string(mono,LaTeX=False,p=2):
     3079    """
     3080    Alternate string representation of element of Wall's basis.
     3081
     3082    This is used by the _repr_ and _latex_ methods.
     3083
     3084    INPUT:
     3085        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     3086
     3087    OUTPUT:
     3088        string -- concatenation of terms of the form 'Sq^(2^m)'
     3089       
     3090    EXAMPLES:
     3091        sage: from sage.algebras.steenrod_algebra import wall_long_mono_to_string
     3092        sage: wall_long_mono_to_string(((1,2),(3,0)))
     3093        'Sq^{1} Sq^{2} Sq^{4} Sq^{8}'
     3094        sage: wall_long_mono_to_string(((1,2),(3,0)),LaTeX=True)
     3095        '\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{4} \\text{Sq}^{8}'
     3096
     3097    The empty tuple represents the unit element Sq(0):
     3098        sage: wall_long_mono_to_string(())
     3099        'Sq(0)'
     3100    """
     3101    if LaTeX:
     3102        sq = "\\text{Sq}"
     3103    else:
     3104        sq = "Sq"
     3105    if len(mono) == 0:
     3106        return sq + "(0)"
     3107    else:
     3108        string = ""
     3109        for (m,k) in mono:
     3110            for i in range(k,m+1):
     3111                string = string + sq + "^{" + str(2**i) + "} "
     3112        return string.strip(" ")
     3113
     3114
     3115def arnonA_mono_to_string(mono,LaTeX=False,p=2):
     3116    """
     3117    String representation of element of Arnon's A basis.
     3118
     3119    This is used by the _repr_ and _latex_ methods.
     3120
     3121    INPUT:
     3122        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     3123
     3124    OUTPUT:
     3125        string -- concatenation of 'X^{m}_{k}' for each pair (m,k)
     3126       
     3127    EXAMPLES:
     3128        sage: from sage.algebras.steenrod_algebra import arnonA_mono_to_string
     3129        sage: arnonA_mono_to_string(((1,2),(3,0)))
     3130        'X^{1}_{2} X^{3}_{0}'
     3131        sage: arnonA_mono_to_string(((1,2),(3,0)),LaTeX=True)
     3132        'X^{1}_{2} X^{3}_{0}'
     3133
     3134    The empty tuple represents the unit element Sq(0):
     3135        sage: arnonA_mono_to_string(())
     3136        'Sq(0)'
     3137    """
     3138    if LaTeX:
     3139        sq = "\\text{Sq}"
     3140    else:
     3141        sq = "Sq"
     3142    if len(mono) == 0:
     3143        return sq + "(0)"
     3144    else:
     3145        string = ""
     3146        for (m,k) in mono:
     3147            string = string + "X^{" + str(m) + "}_{" \
     3148                + str(k) + "} "
     3149        return string.strip(" ")
     3150   
     3151
     3152def arnonA_long_mono_to_string(mono,LaTeX=False,p=2):
     3153    """
     3154    Alternate string representation of element of Arnon's A basis.
     3155
     3156    This is used by the _repr_ and _latex_ methods.
     3157
     3158    INPUT:
     3159        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     3160
     3161    OUTPUT:
     3162        string -- concatenation of strings of the form 'Sq(2^m)'
     3163       
     3164    EXAMPLES:
     3165        sage: from sage.algebras.steenrod_algebra import arnonA_long_mono_to_string
     3166        sage: arnonA_long_mono_to_string(((1,2),(3,0)))
     3167        'Sq^{8} Sq^{4} Sq^{2} Sq^{1}'
     3168        sage: arnonA_long_mono_to_string(((1,2),(3,0)),LaTeX=True)
     3169        '\\text{Sq}^{8} \\text{Sq}^{4} \\text{Sq}^{2} \\text{Sq}^{1}'
     3170
     3171    The empty tuple represents the unit element Sq(0):
     3172        sage: arnonA_long_mono_to_string(())
     3173        'Sq(0)'
     3174    """
     3175    if LaTeX:
     3176        sq = "\\text{Sq}"
     3177    else:
     3178        sq = "Sq"
     3179    if len(mono) == 0:
     3180        return sq + "(0)"
     3181    else:
     3182        string = ""
     3183        for (m,k) in mono:
     3184            for i in range(m,k-1,-1):
     3185                string = string + sq + "^{" + str(2**i) + "} "
     3186        return string.strip(" ")
     3187   
     3188
     3189def pst_mono_to_string(mono,LaTeX=False,p=2):
     3190    r"""
     3191    String representation of element of a $P^s_t$-basis.
     3192
     3193    This is used by the _repr_ and _latex_ methods.
     3194
     3195    INPUT:
     3196        mono -- tuple of pairs of integers (s,t) with s >= 0, t > 0
     3197
     3198    OUTPUT:
     3199        string -- concatenation of 'P^{s}_{t}' for each pair (s,t)
     3200       
     3201    EXAMPLES:
     3202        sage: from sage.algebras.steenrod_algebra import pst_mono_to_string
     3203        sage: pst_mono_to_string(((1,2),(0,3)))
     3204        'P^{1}_{2} P^{0}_{3}'
     3205        sage: pst_mono_to_string(((1,2),(0,3)),LaTeX=True)
     3206        'P^{1}_{2} P^{0}_{3}'
     3207
     3208    The empty tuple represents the unit element Sq(0):
     3209        sage: pst_mono_to_string(())
     3210        'Sq(0)'
     3211    """
     3212    if LaTeX:
     3213        sq = "\\text{Sq}"
     3214    else:
     3215        sq = "Sq"
     3216    if len(mono) == 0:
     3217        return sq + "(0)"
     3218    else:
     3219        string = ""
     3220        for (s,t) in mono:
     3221            string = string + "P^{" + str(s) + "}_{" \
     3222                + str(t) + "} "
     3223        return string.strip(" ")
     3224
     3225
     3226def comm_mono_to_string(mono,LaTeX=False,p=2):
     3227    r"""
     3228    String representation of element of a commutator basis.
     3229
     3230    This is used by the _repr_ and _latex_ methods.
     3231
     3232    INPUT:
     3233        mono -- tuple of pairs of integers (s,t) with s >= 0, t > 0
     3234
     3235    OUTPUT:
     3236        string -- concatenation of 'c_{s,t}' for each pair (s,t)
     3237       
     3238    EXAMPLES:
     3239        sage: from sage.algebras.steenrod_algebra import comm_mono_to_string
     3240        sage: comm_mono_to_string(((1,2),(0,3)))
     3241        'c_{1,2} c_{0,3}'
     3242        sage: comm_mono_to_string(((1,2),(0,3)),LaTeX=True)
     3243        'c_{1,2} c_{0,3}'
     3244
     3245    The empty tuple represents the unit element Sq(0):
     3246        sage: comm_mono_to_string(())
     3247        'Sq(0)'
     3248    """
     3249    if LaTeX:
     3250        sq = "\\text{Sq}"
     3251    else:
     3252        sq = "Sq"
     3253    if len(mono) == 0:
     3254        return sq + "(0)"
     3255    else:
     3256        string = ""
     3257        for (s,t) in mono:
     3258            string = string + "c_{" + str(s) + "," \
     3259                + str(t) + "} "
     3260        return string.strip(" ")
     3261
     3262
     3263def comm_long_mono_to_string(mono,LaTeX=False,p=2):
     3264    r"""
     3265    Alternate string representation of element of a commutator basis.
     3266
     3267    Okay in low dimensions, but gets unwieldy as the dimension increases.
     3268
     3269    INPUT:
     3270        mono -- tuple of pairs of integers (s,t) with s >= 0, t > 0
     3271
     3272    OUTPUT:
     3273        string -- concatenation of 's_{2^s ... 2^(s+t-1)}' for each pair (s,t)
     3274       
     3275    EXAMPLES:
     3276        sage: from sage.algebras.steenrod_algebra import comm_long_mono_to_string
     3277        sage: comm_long_mono_to_string(((1,2),(0,3)))
     3278        's_{24} s_{124}'
     3279        sage: comm_long_mono_to_string(((1,2),(0,3)),LaTeX=True)
     3280        's_{24} s_{124}'
     3281
     3282    The empty tuple represents the unit element Sq(0):
     3283        sage: comm_long_mono_to_string(())
     3284        'Sq(0)'
     3285    """
     3286    if LaTeX:
     3287        sq = "\\text{Sq}"
     3288    else:
     3289        sq = "Sq"
     3290    if len(mono) == 0:
     3291        return sq + "(0)"
     3292    else:
     3293        string = ""
     3294        for (s,t) in mono:
     3295            if s + t > 4:
     3296                comma = ","
     3297            else:
     3298                comma = ""
     3299            string = string + "s_{"
     3300            for i in range(t):
     3301                string = string + str(2**(s+i)) + comma
     3302            string = string.strip(",") + "} "
     3303        return string.strip(" ")
  • new file sage/algebras/steenrod_algebra_bases.py

    diff -r 96e35b9306b1 -r 0dfaa3830fda sage/algebras/steenrod_algebra_bases.py
    - +  
     1r"""
     2Vector space bases for the mod p Steenrod algebra.
     3
     4AUTHORS:
     5    - John H. Palmieri (2008-07-15: version 0.7)
     6
     7This package defines functions for computing various bases of the
     8Steenrod algebra, and for converting between the Milnor basis and any
     9other basis.
     10
     11A number of different bases have been implemented, at least at the
     12prime 2.  The first two are the most familiar and most standard ones,
     13and all of the others are defined in terms of one of these.  See the
     14papers by Monks [M] and Wood [W] for more information about most of
     15these.  For commutator bases, see the preprint by Palmieri and Zhang
     16[PZ].
     17
     18  * 'milnor': Milnor basis.  When $p=2$, the Milnor basis consists of
     19    symbols of the form $\text{Sq}(m_1, m_2, ..., m_t)$, where each
     20    $m_i$ is a non-negative integer and if $t>1$, then the last entry
     21    $m_t \neq 0$.  When $p$ is odd, the Milnor basis consists of
     22    symbols of the form $Q_{e_1} Q_{e_2} ... \mathcal{P}(m_1, m_2,
     23    ..., m_t)$, where $0 \leq e_1 < e_2 < ...$, each $m_i$ is a
     24    non-negative integer, and if $t>1$, then the last entry $m_t \neq
     25    0$.
     26
     27  * 'serre-cartan' or 'adem' or 'admissible': Serre-Cartan basis.  The
     28    Serre-Cartan basis consists of 'admissible monomials' in the
     29    Steenrod operations.  Thus at the prime 2, it consists of
     30    monomials $\text{Sq}^{m_1} \text{Sq}^{m_2} ... \text{Sq}^{m_t}$
     31    with $m_i \geq 2m_{i+1}$ for each $i$.  At odd primes, it consists
     32    of monomials $\beta^{\epsilon_0} \mathcal{P}^{s_1}
     33    \beta^{\epsilon_1} \mathcal{P}^{s_2} ...  \mathcal{P}^{s_k}
     34    \beta^{\epsilon_k}$ with each $\epsilon_i$ either 0 or 1, $s_i
     35    \geq p s_{i+1} + \epsilon_i$, and $s_k \geq 1$.
     36
     37    When $p=2$, the element $\text{Sq}^a$ equals the Milnor element
     38    $\text{Sq}(a)$; when $p$ is odd, $\mathcal{P}^a = \mathcal{P}(a)$
     39    and $\beta = Q_0$.  Hence one can represent any Serre-Cartan basis
     40    element in the Milnor basis by computing an appropriate product
     41    using Milnor multiplication.
     42
     43The other bases implemented are as follows; these are only
     44defined when $p=2$:
     45
     46  * 'wood_y': Wood's Y basis.  For pairs of non-negative integers
     47    $(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Y$
     48    basis consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with
     49    $(m_i,k_i) > (m_{i+1},k_{i+1})$, in left lex order.
     50
     51  * 'wood_z': Wood's Z basis.  For pairs of non-negative integers
     52    $(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Z$
     53    basis consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with
     54    $(m_i+k_i,m_i) > (m_{i+1}+k_{i+1},m_{i+1})$, in left lex order.
     55
     56  * 'wall': Wall's basis.  For any pair of integers $(m,k)$ with $m
     57    \geq k \geq 0$, let $Q^m_k = \text{Sq}^{2^k} \text{Sq}^{2^{k+1}}
     58    ... \text{Sq}^{2^m}$.  The elements of Wall's basis are monomials
     59    $Q^{m_0}_{k_0} ... Q^{m_t}_{k_t}$ with $(m_i, k_i) > (m_{i+1},
     60    k_{i+1})$, ordered left lexicographically.
     61
     62    The standard way of printing elements of the Wall basis is to
     63    write elements in terms of the $Q^m_k$.  If one sets the basis to
     64    'wall_long' instead of 'wall', then each $Q^m_k$ is expanded as a
     65    product of factors of the form $\text{Sq}^{2^i}$.
     66
     67  * 'arnon_a': Arnon's A basis. For any pair of integers $(m,k)$ with
     68    $m \geq k \geq 0$, let $X^m_k = \text{Sq}^{2^m}
     69    \text{Sq}^{2^{m-1}} ... \text{Sq}^{2^k}$.  The elements of Arnon's
     70    A basis are monomials $X^{m_0}_{k_0} ... X^{m_t}_{k_t}$ with
     71    $(m_i, k_i) < (m_{i+1}, k_{i+1})$, ordered left lexicographically.
     72
     73    The standard way of printing elements of Arnon's A basis is to
     74    write elements in terms of the $X^m_k$.  If one sets the basis to
     75    'arnon_a_long' instead of 'arnon_a', then each $X^m_k$ is expanded
     76    as a product of factors of the form $\text{Sq}^{2^i}$.
     77
     78  * 'arnon_c': Arnon's C basis. The elements of Arnon's C basis are
     79    monomials of the form $\text{Sq}^{t_1} ... \text{Sq}^{t_m}$ where
     80    for each $i$, we have $t_i \leq 2t_{i+1}$ and $2^i | t_{m-i}$.
     81
     82  * 'pst' or 'pst_ORDER': Various $P^s_t$-bases. For integers $s \geq
     83    0$ and $t > 0$, the element $P^s_t$ is the Milnor basis element
     84    $\text{Sq}(0, ..., 0, 2^s, 0, ...)$, with the nonzero entry in
     85    position $t$.  To obtain a $P^s_t$-basis, for each set
     86    $\{P^{s_1}_{t_1}, ..., P^{s_k}_{t_k}\}$ of (distinct) $P^s_t$'s,
     87    one chooses an ordering and forms the resulting monomial.  The set
     88    of all such monomials then forms a basis, and so one gets a basis
     89    by choosing an ordering on each monomial.
     90
     91    The string ORDER corresponds to the following orderings.  These
     92    are all 'global' -- they give a global ordering on the $P^s_t$'s,
     93    not different orderings depending on the monomial.  They order the
     94    $P^s_t$'s using the pair of integers $(s,t)$ as follows:
     95
     96      * 'rlex': right lexicographic ordering
     97
     98      * 'llex': left lexicographic ordering
     99
     100      * 'deg': ordered by degree, which is the same as left
     101        lexicographic ordering on the pair $(s+t,t)$
     102
     103      * 'revz': left lexicographic ordering on the pair $(s+t,s)$,
     104        which is the reverse of the ordering used (on elements in the
     105        same degrees as the $P^s_t$'s) in Wood's Z basis: 'revz'
     106        stands for 'reversed Z'.  This is the default: if ORDER is
     107        omitted, this ordering is used.
     108
     109  * 'comm' or 'comm_ORDER': Various commutator bases.  Let $c_{i,1} =
     110    \text{Sq}^{2^i}$, let $c_{i,2} = [c_{i,1}, c_{i+1,1}]$, and
     111    inductively define $c_{i,k} = [c_{i,k-1}, c_{i+k-1,1}]$.  Thus
     112    $c_{i,k}$ is a $k$-fold iterated commutator of the elements
     113    $\text{Sq}^{2^i}$, ..., $\text{Sq}^{2^{i+k-1}}$.  Note that $\dim
     114    c_{i,k} = \dim P^i_k$.
     115
     116    To obtain a commutator basis, for each set $\{c_{s_1,t_1}, ...,
     117    c_{s_k,t_k}\}$ of (distinct) $c_{s,t}$'s, one chooses an ordering
     118    and forms the resulting monomial.  The set of all such monomials
     119    then forms a basis, and so one gets a basis by choosing an
     120    ordering on each monomial.  The string ORDER has the same meaning
     121    as for the orderings on $P^s_t$-bases.
     122
     123    The commutator bases have alternative representations, obtained by
     124    appending 'long' to their names: instead of, say, $c_{2,2}$, the
     125    representation is $s_{48}$, indicating the commutator of
     126    $\text{Sq}^4$ and $\text{Sq}^8$, and $c_{0,3}$, which is equal to
     127    $[[\text{Sq}^1, \text{Sq}^2], \text{Sq}^4]$, is written as
     128    $s_{124}$.
     129
     130EXAMPLES:
     131    sage: steenrod_algebra_basis(7,'milnor')
     132    (Sq(0,0,1), Sq(1,2), Sq(4,1), Sq(7))
     133    sage: steenrod_algebra_basis(5)   # milnor basis is the default
     134    (Sq(2,1), Sq(5))
     135
     136The third (optional) argument to 'steenrod_algebra_basis' is the prime p:
     137    sage: steenrod_algebra_basis(9, 'milnor', p=3)
     138    (Q_1 P(1), Q_0 P(2))
     139    sage: steenrod_algebra_basis(9, 'milnor', 3)
     140    (Q_1 P(1), Q_0 P(2))
     141    sage: steenrod_algebra_basis(17, 'milnor', 3)
     142    (Q_2, Q_1 P(3), Q_0 P(0,1), Q_0 P(4))
     143
     144Note that the Milnor basis is the default way of representing
     145elements, even when asking for another basis.  Thus you might
     146want to use this in conjunction with 'steenrod_set_basis'.
     147    sage: steenrod_algebra_basis(7,'admissible')
     148    (Sq(7), Sq(4,1) + Sq(7), Sq(0,0,1) + Sq(1,2) + Sq(4,1) + Sq(7), Sq(1,2)
     149    + Sq(7))
     150    sage: steenrod_algebra_basis(13,'admissible',p=3)
     151    (Q_0 P(3), Q_0 P(3) + Q_1 P(2))
     152    sage: steenrod_set_basis('admissible')
     153    'admissible'
     154    sage: steenrod_algebra_basis(7,'admissible')
     155    (Sq^{7}, Sq^{6} Sq^{1}, Sq^{4} Sq^{2} Sq^{1}, Sq^{5} Sq^{2})
     156    sage: steenrod_algebra_basis(13,'admissible',p=3)
     157    (beta P^{3}, P^{3} beta)
     158    sage: steenrod_set_basis('pst-rlex')
     159    'pst-rlex'
     160    sage: steenrod_algebra_basis(5,'admissible')
     161    (P^{0}_{1} P^{2}_{1}, P^{0}_{1} P^{2}_{1} + P^{1}_{1} P^{0}_{2})
     162    sage: steenrod_algebra_basis(5,'wall')
     163    (P^{1}_{1} P^{0}_{2}, P^{0}_{1} P^{2}_{1} + P^{1}_{1} P^{0}_{2})
     164    sage: steenrod_algebra_basis(5,'pst-rlex')
     165    (P^{0}_{1} P^{2}_{1}, P^{1}_{1} P^{0}_{2})
     166    sage: steenrod_set_basis('wall')
     167    'wall'
     168    sage: steenrod_algebra_basis(7,'wall')
     169    (Q^{2}_{0}, Q^{2}_{1} Q^{0}_{0}, Q^{2}_{2} Q^{1}_{0}, Q^{2}_{2}
     170    Q^{1}_{1} Q^{0}_{0})
     171    sage: steenrod_set_basis('wall_long')
     172    'wall_long'
     173    sage: steenrod_algebra_basis(7,'wall')
     174    (Sq^{1} Sq^{2} Sq^{4}, Sq^{2} Sq^{4} Sq^{1}, Sq^{4} Sq^{1} Sq^{2},
     175    Sq^{4} Sq^{2} Sq^{1})
     176    sage: steenrod_algebra_basis(5,'my-great-basis')
     177    Unrecognized basis: my-great-basis
     178
     179This file also contains a function 'milnor_convert' which converts
     180elements from the (default) Milnor basis representation to a
     181representation in another basis.  The output is a dictionary which
     182gives the new representation; its form depends on the chosen basis.
     183For example, in the basis of admissible sequences (a.k.a. the
     184Serre-Cartan basis), each basis element is of the form $\text{Sq}^a
     185\text{Sq}^b ...$, and so is represented by a tuple $(a,b,...)$ of
     186integers.  Thus the dictionary has such tuples as keys, with the
     187coefficient of the basis element as the associated value:
     188    sage: from sage.algebras.steenrod_algebra_bases import milnor_convert
     189    sage: milnor_convert(Sq(2)*Sq(4) + Sq(2)*Sq(5), 'admissible')
     190    {(5, 1): 1, (6, 1): 1, (6,): 1}
     191    sage: milnor_convert(Sq(2)*Sq(4) + Sq(2)*Sq(5), 'pst')
     192    {((1, 1), (2, 1)): 1, ((0, 1), (1, 1), (2, 1)): 1, ((0, 2), (2, 1)): 1}
     193
     194Users shouldn't need to call 'milnor_convert'; they should just use
     195'steenrod_set_basis' to change the basis in which elements are being
     196represented, like this:
     197    sage: steenrod_set_basis('milnor')
     198    'milnor'
     199    sage: Sq(2)*Sq(4) + Sq(2)*Sq(5)
     200    Sq(3,1) + Sq(4,1) + Sq(6) + Sq(7)
     201    sage: steenrod_set_basis('adem')
     202    'adem'
     203    sage: Sq(2)*Sq(4) + Sq(2)*Sq(5)
     204    Sq^{5} Sq^{1} + Sq^{6} + Sq^{6} Sq^{1}
     205    sage: steenrod_set_basis('pst')
     206    'pst'
     207    sage: Sq(2)*Sq(4) + Sq(2)*Sq(5)
     208    P^{0}_{1} P^{1}_{1} P^{2}_{1} + P^{0}_{2} P^{2}_{1} + P^{1}_{1}
     209    P^{2}_{1}
     210
     211
     212REFERENCES:
     213    [M]  K. G. Monks, "Change of basis, monomial relations, and $P^s_t$
     214         bases for the Steenrod algebra," J. Pure Appl. Algebra 125 (1998),
     215         no. 1-3, 235--260.
     216    [PZ] J. H. Palmieri and J. J. Zhang, "Commutators in the Steenrod
     217         algebra," preprint (2008)
     218    [W]  R. M. W. Wood, "Problems in the Steenrod algebra," Bull. London
     219         Math. Soc. 30 (1998), no. 5, 449--517.
     220"""
     221
     222#*****************************************************************************
     223#       Copyright (C) 2008 William Stein <wstein@gmail.com>
     224#       Copyright (C) 2008 John H. Palmieri <palmieri@math.washington.edu>
     225#  Distributed under the terms of the GNU General Public License (GPL)
     226#*****************************************************************************
     227
     228from sage.rings.integer import Integer
     229from sage.rings.all import GF
     230
     231from steenrod_algebra import SteenrodAlgebra, SteenrodAlgebraElement, \
     232    Sq, pst, \
     233    _steenrod_serre_cartan_basis_names, _steenrod_milnor_basis_names, \
     234    _steenrod_pst_basis_names, _steenrod_arnonA_basis_names, \
     235    _steenrod_arnonC_basis_names, _steenrod_woodY_basis_names, \
     236    _steenrod_woodZ_basis_names, _steenrod_wall_basis_names, \
     237    _steenrod_commutator_basis_names
     238
     239
     240class memoize:
     241    """
     242    Taken from the web page
     243    <http://avinashv.net/2008/04/python-decorators-syntactic-sugar/>
     244    """
     245    def __init__(self, function):
     246        self.function = function
     247        self.memoized = {}
     248
     249    def __call__(self, *args):
     250        try:
     251            return self.memoized[args]
     252        except KeyError:
     253            self.memoized[args] = self.function(*args)
     254            return self.memoized[args]
     255
     256@memoize
     257def convert_to_milnor_matrix(n, basis, p=2):
     258    r"""
     259    Change-of-basis matrix, 'basis' to Milnor, in dimension $n$, at the prime $p$.
     260
     261    INPUT:
     262        n -- non-negative integer, the dimension
     263        basis -- string, the basis from which to convert
     264        p (optional, default 2) -- positive prime number
     265
     266    OUTPUT:
     267        matrix -- change-of-basis matrix, a square matrix over GF(p)
     268
     269    (This is not really intended for casual users, so no error
     270    checking is made on the integer $n$, the basis name, or the prime.)
     271
     272    EXAMPLES:
     273        sage: from sage.algebras.steenrod_algebra_bases import convert_to_milnor_matrix
     274        sage: convert_to_milnor_matrix(5, 'adem')
     275        [0 1]
     276        [1 1]
     277        sage: convert_to_milnor_matrix(45, 'milnor')
     278        111 x 111 dense matrix over Finite Field of size 2
     279        sage: convert_to_milnor_matrix(12,'wall')
     280        [1 0 0 1 0 0 0]
     281        [1 1 0 0 0 1 0]
     282        [0 1 0 1 0 0 0]
     283        [0 0 0 1 0 0 0]
     284        [1 1 0 0 1 0 0]
     285        [0 0 1 1 1 0 1]
     286        [0 0 0 0 1 0 1]
     287
     288    The function takes an optional argument, the prime p over which to work:
     289        sage: convert_to_milnor_matrix(17,'adem',3)
     290        [0 0 1 1]
     291        [0 0 0 1]
     292        [1 1 1 1]
     293        [0 1 0 1]
     294        sage: convert_to_milnor_matrix(48,'adem',5)
     295        [0 1]
     296        [1 1]
     297    """
     298    from sage.matrix.constructor import matrix
     299    milnor_base = steenrod_algebra_basis(n,'milnor',p)
     300    rows = []
     301    for poly in steenrod_algebra_basis(n,basis,p):
     302        for v in milnor_base:
     303            if v in poly: rows = rows + [1]
     304            else: rows = rows + [0]
     305    d = len(milnor_base)
     306    return matrix(GF(p),d,d,rows)
     307
     308
     309def convert_from_milnor_matrix(n, basis, p=2):
     310    r"""
     311    Change-of-basis matrix, Milnor to 'basis', in dimension $n$.
     312
     313    INPUT:
     314        n -- non-negative integer, the dimension
     315        basis -- string, the basis to which to convert
     316        p (optional, default 2) -- positive prime number
     317
     318    OUTPUT:
     319        matrix -- change-of-basis matrix, a square matrix over GF(p)
     320
     321    (This is not really intended for casual users, so no error
     322    checking is made on the integer $n$, the basis name, or the prime.)
     323
     324    EXAMPLES:
     325        sage: from sage.algebras.steenrod_algebra_bases import convert_from_milnor_matrix, convert_to_milnor_matrix
     326        sage: convert_from_milnor_matrix(12,'wall')
     327        [1 0 0 1 0 0 0]
     328        [0 0 1 1 0 0 0]
     329        [0 0 0 1 0 1 1]
     330        [0 0 0 1 0 0 0]
     331        [1 0 1 0 1 0 0]
     332        [1 1 1 0 0 0 0]
     333        [1 0 1 0 1 0 1]
     334        sage: convert_from_milnor_matrix(38,'serre_cartan')
     335        72 x 72 dense matrix over Finite Field of size 2
     336        sage: x = convert_to_milnor_matrix(20,'wood_y')
     337        sage: y = convert_from_milnor_matrix(20,'wood_y')
     338        sage: x*y
     339        [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     340        [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     341        [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     342        [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0]
     343        [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
     344        [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
     345        [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]
     346        [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
     347        [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
     348        [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
     349        [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
     350        [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
     351        [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0]
     352        [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0]
     353        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0]
     354        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]
     355        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
     356
     357       
     358    The function takes an optional argument, the prime p over which to work:
     359        sage: convert_from_milnor_matrix(17,'adem',3)
     360        [2 1 1 2]
     361        [0 2 0 1]
     362        [1 2 0 0]
     363        [0 1 0 0]
     364    """
     365    mat = convert_to_milnor_matrix(n,basis,p)
     366    if mat.nrows() != 0:
     367        return convert_to_milnor_matrix(n,basis,p).inverse()
     368    else:
     369        return mat
     370
     371
     372def make_elt_homogeneous(poly):
     373    """
     374    Break element of the Steenrod algebra into a list of homogeneous pieces.
     375
     376    INPUT:
     377        poly -- an element of the Steenrod algebra
     378
     379    OUTPUT:
     380        list of homogeneous elements of the Steenrod algebra whose sum is poly
     381
     382    EXAMPLES:
     383        sage: from sage.algebras.steenrod_algebra_bases import make_elt_homogeneous
     384        sage: make_elt_homogeneous(Sq(2)*Sq(4) + Sq(2)*Sq(5))
     385        [Sq(3,1) + Sq(6), Sq(4,1) + Sq(7)]
     386    """
     387    degrees = set([m.degree() for m in poly])   # set of degrees in poly
     388    result = []
     389    for d in degrees:
     390        result_d = 0
     391        for m in poly:
     392            if m.degree() == d:
     393                result_d = result_d + m
     394        result.append(result_d)
     395    return result
     396
     397
     398def milnor_convert(poly, basis):
     399    """
     400    Convert an element of the Steenrod algebra in the Milnor basis
     401    to its representation in the chosen basis.
     402
     403    INPUT:
     404        poly -- element of the Steenrod algebra
     405        basis -- basis to which to convert
     406
     407    OUTPUT:
     408        dict -- dictionary of terms of the form (mono: coeff), where
     409        mono is a monomial in 'basis'.  The form of mono depends on
     410        the chosen basis.
     411   
     412    EXAMPLES:
     413        sage: from sage.algebras.steenrod_algebra_bases import milnor_convert
     414        sage: milnor_convert(Sq(2)*Sq(4) + Sq(2)*Sq(5), 'adem')
     415        {(5, 1): 1, (6, 1): 1, (6,): 1}
     416        sage: A3 = SteenrodAlgebra(3)
     417        sage: a = A3.Q(1) * A3.P(2,2); a
     418        Q_1 P(2,2)
     419        sage: milnor_convert(a, 'adem')
     420        {(0, 9, 1, 2, 0): 1, (1, 9, 0, 2, 0): 2}
     421        sage: milnor_convert(2 * a, 'adem')
     422        {(0, 9, 1, 2, 0): 2, (1, 9, 0, 2, 0): 1}
     423        sage: steenrod_set_basis('adem')
     424        'adem'
     425        sage: Sq(2)*Sq(4) + Sq(2)*Sq(5)
     426        Sq^{5} Sq^{1} + Sq^{6} + Sq^{6} Sq^{1}
     427        sage: a
     428        P^{9} beta P^{2} + 2 beta P^{9} P^{2}
     429        sage: milnor_convert(Sq(2)*Sq(4) + Sq(2)*Sq(5), 'pst')
     430        {((1, 1), (2, 1)): 1, ((0, 1), (1, 1), (2, 1)): 1, ((0, 2), (2, 1)): 1}
     431        sage: steenrod_set_basis('pst')
     432        'pst'
     433        sage: Sq(2)*Sq(4) + Sq(2)*Sq(5)
     434        P^{0}_{1} P^{1}_{1} P^{2}_{1} + P^{0}_{2} P^{2}_{1} + P^{1}_{1}
     435        P^{2}_{1}
     436        sage: steenrod_set_basis('milnor')
     437        'milnor'
     438    """
     439    from sage.matrix.constructor import matrix
     440    p = poly.prime
     441    if basis in _steenrod_milnor_basis_names: return poly._raw['milnor']
     442    dict = {}
     443    for x in make_elt_homogeneous(poly):
     444        dim = x.degree()
     445        vec = []
     446        for mono in steenrod_algebra_basis(dim,'milnor',p):
     447            if mono._raw['milnor'].keys()[0] in x._raw['milnor'].keys():
     448                for entry in mono._raw['milnor']:
     449                    coeff =  x._raw['milnor'][entry]
     450                vec = vec + [coeff]
     451            else:
     452                vec = vec + [0]
     453        new_vec = (matrix(GF(p),1,len(vec),vec)
     454                   * convert_from_milnor_matrix(dim,basis,p)).row(0)
     455        for (mono,coeff) in zip(steenrod_algebra_basis(dim,basis,p), new_vec):
     456            if coeff != 0:
     457                if basis in _steenrod_serre_cartan_basis_names:
     458                    old_dict = mono._raw['serre-cartan']
     459                elif basis in _steenrod_pst_basis_names:
     460                    if basis.find('rlex') >= 0:
     461                        old_dict = mono._raw['pst_rlex']
     462                    elif basis.find('llex') >= 0:
     463                        old_dict = mono._raw['pst_llex']
     464                    elif basis.find('deg') >= 0:
     465                        old_dict = mono._raw['pst_deg']
     466                    elif basis.find('revz') >= 0:
     467                        old_dict = mono._raw['pst_revz']
     468                    else:
     469                        old_dict = mono._raw['pst_revz']
     470                elif basis in _steenrod_arnonA_basis_names:
     471                    old_dict = mono._raw['arnona']
     472                elif basis in _steenrod_arnonC_basis_names:
     473                    old_dict = mono._raw['arnonc']
     474                elif basis in _steenrod_woodY_basis_names:
     475                    old_dict = mono._raw['woody']
     476                elif basis in _steenrod_woodZ_basis_names:
     477                    old_dict = mono._raw['woodz']
     478                elif basis in _steenrod_wall_basis_names:
     479                    old_dict = mono._raw['wall']
     480                elif basis in _steenrod_commutator_basis_names:
     481                    if basis.find('rlex') >= 0:
     482                        old_dict = mono._raw['comm_rlex']
     483                    elif basis.find('llex') >= 0:
     484                        old_dict = mono._raw['comm_llex']
     485                    elif basis.find('deg') >= 0:
     486                        old_dict = mono._raw['comm_deg']
     487                    elif basis.find('revz') >= 0:
     488                        old_dict = mono._raw['comm_revz']
     489                    else:
     490                        old_dict = mono._raw['comm_revz']
     491                for entry in old_dict:
     492                    dict[entry] = coeff
     493    return dict
     494
     495
     496_steenrod_bases = {}
     497
     498def steenrod_algebra_basis(n, basis=None, p=2):
     499    r"""
     500    Basis for the Steenrod algebra in degree $n$.
     501
     502    INPUT:
     503        n -- non-negative integer
     504        basis (optional) -- string, which basis to use.  If omitted,
     505            use the current basis
     506        p (optional, default = 2) -- positive prime number
     507
     508    OUTPUT:
     509        tuple of basis elements for the Steenrod algebra in dimension n
     510
     511    The choices for the string basis are as follows:
     512   
     513    'milnor': Milnor basis.  At the prime 2, the Milnor basis consists
     514    of symbols of the form $\text{Sq}(m_1, m_2, ..., m_t)$, where each
     515    $m_i$ is a non-negative integer and if $t>1$, then $m_t \neq 0$.
     516    At odd primes, it consists of symbols of the form $Q_{e_1} Q_{e_2}
     517    ... P(m_1, m_2, ..., m_t)$, where $0 \leq e_1 < e_2 < ...$, each
     518    $m_i$ is a non-negative integer, and if $t>1$, then $m_t \neq 0$.
     519
     520    'serre-cartan' or 'adem' or 'admissible': Serre-Cartan basis.
     521    The Serre-Cartan basis consists of 'admissible monomials in the
     522    Steenrod squares'.  Thus at the prime 2, it consists of monomials
     523    $\text{Sq}^{m_1} \text{Sq}^{m_2} ... \text{Sq}^{m_t}$ with $m_i
     524    \geq 2m_{i+1}$ for each $i$.  At odd primes, it consists of
     525    monomials $\beta^{\epsilon_0} \mathcal{P}^{s_1} \beta^{\epsilon_1}
     526    \mathcal{P}^{s_2} ...  \mathcal{P}^{s_k} \beta^{\epsilon_k}$ with
     527    each $\epsilon_i$ either 0 or 1, $s_i \geq p s_{i+1} +
     528    \epsilon_i$, and $s_k \geq 1$.
     529
     530    The rest of the bases are only defined when $p=2$.
     531
     532    'wood_y': Wood's Y basis.  For pairs of non-negative integers
     533    $(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Y$
     534    basis consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with
     535    $(m_i,k_i) > (m_{i+1},k_{i+1})$, in left lex order.
     536
     537    'wood_z': Wood's Z basis.  For pairs of non-negative integers
     538    $(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Z$
     539    basis consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with
     540    $(m_i+k_i,m_i) > (m_{i+1}+k_{i+1},m_{i+1})$, in left lex order.
     541
     542    'wall': Wall's basis.  For any pair of integers $(m,k)$ with $m
     543    \geq k \geq 0$, let $Q^m_k = \text{Sq}^{2^k} \text{Sq}^{2^{k+1}}
     544    ... \text{Sq}^{2^m}$.  The elements of Wall's basis are
     545    monomials $Q^{m_0}_{k_0} ... Q^{m_t}_{k_t}$ with $(m_i, k_i) >
     546    (m_{i+1}, k_{i+1})$, ordered left lexicographically.
     547
     548    The standard way of printing elements of the Wall basis is to write
     549    elements in terms of the $Q^m_k$.  If one sets the basis to
     550    'wall_long' instead of 'wall', then each $Q^m_k$ is expanded as a
     551    product of factors of the form $\text{Sq}^{2^i}$.
     552
     553    'arnon_a': Arnon's A basis. For any pair of integers $(m,k)$ with
     554    $m \geq k \geq 0$, let $X^m_k = \text{Sq}^{2^m}
     555    \text{Sq}^{2^{m-1}} ... \text{Sq}^{2^k}$.  The elements of
     556    Arnon's A basis are monomials $X^{m_0}_{k_0} ... X^{m_t}_{k_t}$
     557    with $(m_i, k_i) < (m_{i+1}, k_{i+1})$, ordered left
     558    lexicographically.
     559
     560    The standard way of printing elements of Arnon's A basis is to
     561    write elements in terms of the $X^m_k$.  If one sets the basis to
     562    'arnon_a_long' instead of 'arnon_a', then each $X^m_k$ is expanded
     563    as a product of factors of the form $\text{Sq}^{2^i}$.
     564
     565    'arnon_c': Arnon's C basis. The elements of Arnon's C basis are
     566    monomials of the form $\text{Sq}^{t_1} ... \text{Sq}^{t_m}$
     567    where for each $i$, we have $t_i \leq 2t_{i+1}$ and $2^i |
     568    t_{m-i}$.
     569
     570    'pst' or 'pst_ORDER': Various $P^s_t$-bases. To obtain a
     571    $P^s_t$-basis, for each set $\{P^{s_1}_{t_1}, ...,
     572    P^{s_k}_{t_k}\}$ of (distinct) $P^s_t$'s, one chooses an ordering
     573    and forms the resulting monomial.  The set of all such monomials
     574    then forms a basis, and so one gets a basis by choosing an
     575    ordering on each monomial.
     576   
     577    The string ORDER corresponds to the following orderings.  These
     578    are all 'global' -- they give a global ordering on the $P^s_t$'s,
     579    not different orderings depending on the monomial.  They order the
     580    $P^s_t$'s using the pair of integers $(s,t)$ as follows:
     581
     582        'rlex': right lexicographic ordering
     583        'llex': left lexicographic ordering
     584        'deg': ordered by degree, which is the same as left lexicographic
     585            ordering on the pair $(s+t,t)$
     586        'revz': left lexicographic ordering on the pair $(s+t,s)$, which is
     587            the reverse of the ordering used (on elements in the same
     588            degrees as the $P^s_t$'s) in Wood's Z basis: 'revz' stands
     589            for 'reversed Z'.  This is the default: if ORDER is omitted,
     590            this ordering is used.
     591
     592    'comm' or 'comm_ORDER': Various commutator bases.  Let $c_{i,1} =
     593    \text{Sq}^{2^i}$, let $c_{i,2} = [c_{i,1}, c_{i+1,1}]$, and
     594    inductively define $c_{i,k} = [c_{i,k-1}, c_{i+k-1,1}]$.  Thus
     595    $c_{i,k}$ is a $k$-fold iterated commutator of the elements
     596    $\text{Sq}^{2^i}$, ..., $\text{Sq}^{2^{i+k-1}}$, and $\dim
     597    c_{i,k} = \dim P^i_k$.
     598       
     599    To obtain a commutator basis, for each set $\{c_{s_1,t_1}, ...,
     600    c_{s_k,t_k}\}$ of (distinct) $c_{s,t}$'s, one chooses an ordering
     601    and forms the resulting monomial.  The set of all such monomials
     602    then forms a basis, and so one gets a basis by choosing an
     603    ordering on each monomial.  The string ORDER has the same meaning
     604    as for the orderings on $P^s_t$-bases.
     605
     606    The commutator bases have alternative representations, obtained by
     607    appending 'long' to their names: instead of, say, $c_{2,2}$, the
     608    representation is $s_{48}$, indicating the commutator of
     609    $\text{Sq}^4$ and $\text{Sq}^8$, and $c_{0,3}$, which is equal to
     610    $[[\text{Sq}^1, \text{Sq}^2], \text{Sq}^4]$, is written as
     611    $s_{124}$.
     612
     613    EXAMPLES:
     614        sage: steenrod_algebra_basis(7,'milnor')
     615        (Sq(0,0,1), Sq(1,2), Sq(4,1), Sq(7))
     616        sage: steenrod_algebra_basis(5)   # milnor basis is the default
     617        (Sq(2,1), Sq(5))
     618
     619    The third (optional) argument to 'steenrod_algebra_basis' is the prime p:
     620        sage: steenrod_algebra_basis(9, 'milnor', p=3)
     621        (Q_1 P(1), Q_0 P(2))
     622        sage: steenrod_algebra_basis(9, 'milnor', 3)
     623        (Q_1 P(1), Q_0 P(2))
     624        sage: steenrod_algebra_basis(17, 'milnor', 3)
     625        (Q_2, Q_1 P(3), Q_0 P(0,1), Q_0 P(4))
     626
     627    Note that the Milnor basis is the default way of representing
     628    elements, even when asking for another basis.  Thus you might
     629    want to use this in conjunction with 'steenrod_set_basis'.
     630        sage: steenrod_algebra_basis(7,'admissible')
     631        (Sq(7), Sq(4,1) + Sq(7), Sq(0,0,1) + Sq(1,2) + Sq(4,1) + Sq(7), Sq(1,2)
     632        + Sq(7))
     633        sage: steenrod_algebra_basis(13,'admissible',p=3)
     634        (Q_0 P(3), Q_0 P(3) + Q_1 P(2))
     635        sage: steenrod_set_basis('admissible')
     636        'admissible'
     637        sage: steenrod_algebra_basis(7,'admissible')
     638        (Sq^{7}, Sq^{6} Sq^{1}, Sq^{4} Sq^{2} Sq^{1}, Sq^{5} Sq^{2})
     639        sage: steenrod_algebra_basis(13,'admissible',p=3)
     640        (beta P^{3}, P^{3} beta)
     641        sage: steenrod_algebra_basis(7)  # no second arg: use current basis
     642        (Sq^{7}, Sq^{6} Sq^{1}, Sq^{4} Sq^{2} Sq^{1}, Sq^{5} Sq^{2})
     643        sage: steenrod_set_basis('pst-rlex')
     644        'pst-rlex'
     645        sage: steenrod_algebra_basis(5,'admissible')
     646        (P^{0}_{1} P^{2}_{1}, P^{0}_{1} P^{2}_{1} + P^{1}_{1} P^{0}_{2})
     647        sage: steenrod_algebra_basis(5,'wall')
     648        (P^{0}_{1} P^{2}_{1} + P^{1}_{1} P^{0}_{2}, P^{1}_{1} P^{0}_{2})
     649        sage: steenrod_algebra_basis(5,'pst-rlex')
     650        (P^{0}_{1} P^{2}_{1}, P^{1}_{1} P^{0}_{2})
     651        sage: steenrod_set_basis('wall')
     652        'wall'
     653        sage: steenrod_algebra_basis(7,'wall')
     654        (Q^{2}_{2} Q^{1}_{1} Q^{0}_{0},
     655        Q^{2}_{1} Q^{0}_{0},
     656        Q^{2}_{2} Q^{1}_{0},
     657        Q^{2}_{0})
     658        sage: steenrod_set_basis('wall_long')
     659        'wall_long'
     660        sage: steenrod_algebra_basis(7,'wall')
     661        (Sq^{4} Sq^{2} Sq^{1},
     662        Sq^{2} Sq^{4} Sq^{1},
     663        Sq^{4} Sq^{1} Sq^{2},
     664        Sq^{1} Sq^{2} Sq^{4})
     665        sage: steenrod_algebra_basis(5,'my-great-basis')
     666        Unrecognized basis: my-great-basis
     667        sage: steenrod_set_basis('milnor')
     668        'milnor'
     669    """
     670    from steenrod_algebra import steenrod_basis
     671    if not (isinstance(n, (Integer, int)) and n >= 0):
     672        raise ValueError, "%s is not a non-negative integer." % n
     673    if basis is None: basis = steenrod_basis
     674    ## Milnor basis
     675    if basis.lower() in _steenrod_milnor_basis_names:
     676        return milnor_basis(n,p)
     677    ## Serre-Cartan basis
     678    elif basis.lower() in _steenrod_serre_cartan_basis_names:
     679        return serre_cartan_basis(n,p)
     680    ## Wood 'Y' basis
     681    elif p == 2 and basis.lower() in _steenrod_woodY_basis_names:
     682        return atomic_basis(n,'woody')
     683    ## Wood 'Z' basis
     684    elif p == 2 and basis.lower() in _steenrod_woodZ_basis_names:
     685        return atomic_basis(n,'woodz')
     686    ## Wall basis
     687    elif p == 2 and basis.lower() in _steenrod_wall_basis_names:
     688        return atomic_basis(n,'wall')
     689    ## Arnon 'A' basis
     690    elif p == 2 and basis.lower() in _steenrod_arnonA_basis_names:
     691        return atomic_basis(n,'arnona')
     692    ## Arnon 'C' basis
     693    elif p == 2 and basis.lower() in _steenrod_arnonC_basis_names:
     694        return arnonC_basis(n)
     695    ## pst basis
     696    elif p == 2 and basis.lower() in _steenrod_pst_basis_names:
     697        str = basis.lower()
     698        if str.find('rlex') >= 0:
     699            return atomic_basis(n,'pst_rlex')
     700        elif str.find('llex') >= 0:
     701            return atomic_basis(n,'pst_llex')
     702        elif str.find('deg') >= 0:
     703            return atomic_basis(n,'pst_deg')
     704        elif str.find('revz') >= 0:
     705            return atomic_basis(n,'pst_revz')
     706        else:
     707            return atomic_basis(n,'pst_revz')
     708    ## commutator basis
     709    elif p == 2 and basis.lower() in _steenrod_commutator_basis_names:
     710        str = basis.lower()
     711        if str.find('rlex') >= 0:
     712            return atomic_basis(n,'comm_rlex')
     713        elif str.find('llex') >= 0:
     714            return atomic_basis(n,'comm_llex')
     715        elif str.find('deg') >= 0:
     716            return atomic_basis(n,'comm_deg')
     717        elif str.find('revz') >= 0:
     718            return atomic_basis(n,'comm_revz')
     719        else:
     720            return atomic_basis(n,'comm_revz')
     721    else:
     722        print "Unrecognized basis: %s" % basis
     723        return None
     724
     725
     726def restricted_partitions(n, list, no_repeats=False):
     727    """
     728    List of 'restricted' partitions of n: partitions with parts taken from list.
     729
     730    INPUT:
     731        n -- non-negative integer
     732        list -- list of positive integers
     733        no_repeats (optional, default = False) -- if True, only return
     734            partitions with no repeated parts
     735
     736    This seems to be faster than RestrictedPartitions, although I
     737    don't know why.  Maybe because all I want is the list of
     738    partitions (with each partitions represented as a list), not the
     739    extra stuff provided by RestrictedPartitions.
     740
     741    EXAMPLES:
     742        sage: from sage.algebras.steenrod_algebra_bases import restricted_partitions
     743        sage: restricted_partitions(10, [7,5,1])
     744        [[7, 1, 1, 1], [5, 5], [5, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
     745        sage: restricted_partitions(10, [6,5,4,3,2,1], no_repeats=True)
     746        [[6, 4], [6, 3, 1], [5, 4, 1], [5, 3, 2], [4, 3, 2, 1]]
     747        sage: restricted_partitions(10, [6,4,2])
     748        [[6, 4], [6, 2, 2], [4, 4, 2], [4, 2, 2, 2], [2, 2, 2, 2, 2]]
     749        sage: restricted_partitions(10, [6,4,2], no_repeats=True)
     750        [[6, 4]]
     751
     752    'list' may have repeated elements.  If 'no_repeats' is False, this
     753    has no effect.  If 'no_repeats' is True, and if the repeated
     754    elements appear consecutively in list, then each element may be
     755    used only as many times as it appears in 'list':
     756        sage: restricted_partitions(10, [6,4,2,2], no_repeats=True)
     757        [[6, 4], [6, 2, 2]]
     758        sage: restricted_partitions(10, [6,4,2,2,2], no_repeats=True)
     759        [[6, 4], [6, 2, 2], [4, 2, 2, 2]]
     760
     761    (If the repeated elements don't appear consecutively, the results
     762    are likely meaningless, containing several partitions more than
     763    once, for example.)
     764
     765    In the following examples, 'no_repeats' is False:
     766        sage: restricted_partitions(10, [6,4,2])
     767        [[6, 4], [6, 2, 2], [4, 4, 2], [4, 2, 2, 2], [2, 2, 2, 2, 2]]
     768        sage: restricted_partitions(10, [6,4,2,2,2])
     769        [[6, 4], [6, 2, 2], [4, 4, 2], [4, 2, 2, 2], [2, 2, 2, 2, 2]]
     770        sage: restricted_partitions(10, [6,4,4,4,2,2,2,2,2,2])
     771        [[6, 4], [6, 2, 2], [4, 4, 2], [4, 2, 2, 2], [2, 2, 2, 2, 2]]
     772    """
     773    if n < 0:
     774        return []
     775    elif n == 0:
     776        return [[]]
     777    else:
     778        results = []
     779        if no_repeats:
     780            index = 1
     781        else:
     782            index = 0
     783        old_i = 0
     784        for i in list:
     785            if old_i != i:
     786                for sigma in restricted_partitions(n-i, list[index:], no_repeats):
     787                    results.append([i] + sigma)
     788            index += 1
     789            old_i = i
     790        return results
     791
     792
     793def list_to_hist(list):
     794    """
     795    Given list of positive integers [a,b,c,...], return corresponding 'histogram'.
     796
     797    That is, in the output [n1, n2, ...], n1 is the number of 1's in
     798    the original list, n2 is the number of 2's, etc.
     799
     800    INPUT:
     801        list -- list of positive integers
     802    OUTPUT:
     803        list -- list of non-negative integers
     804
     805    EXAMPLES:
     806        sage: from sage.algebras.steenrod_algebra_bases import list_to_hist
     807        sage: list_to_hist([1,2,3,4,2,1,2])
     808        [2, 3, 1, 1]
     809        sage: list_to_hist([2,2,2,2])
     810        [0, 4]
     811    """
     812    if len(list) == 0:
     813        return list
     814    else:
     815        answer = [0] * max(list)
     816        for i in list:
     817            answer[i-1] += 1
     818        return answer
     819
     820
     821"""
     822Functions for defining bases. They work like this:
     823
     824First, check to see if the basis has been computed already: look for
     825  the cached result in _steenrod_bases.  If so, filter the result
     826  based on the optional argument bound.
     827
     828Second, if there is no cached result, build directly or recursively,
     829  whichever is faster.  Except for the Milnor basis, recursion seems
     830  faster right now.  The details are documented for each basis.  As
     831  each basis element is constructed, so is its dictionary for the
     832  current basis.  For example, in 'serre_cartan_basis', each new
     833  element is obtained by taking an element in a lower-dimensional
     834  basis and multiplying, on the right, by Sq(last).  Call this
     835  element 'new'.  Then set new._raw['serre-cartan'] to be the
     836  dictionary of Serre-Cartan monomials describing this element.
     837  This makes conversion of the element to the chosen basis
     838  instantaneous; this is useful on its own, and crucial for
     839  computing change-of-basis matrices for general conversion.
     840
     841Finally, if there is no cached result, cache the result.
     842"""
     843
     844def milnor_basis(n, p=2):
     845    r"""
     846    Milnor basis in dimension $n$.
     847
     848    INPUT:
     849        n -- non-negative integer
     850        p (optional, default 2) -- positive prime number
     851
     852    OUTPUT:
     853        tuple of mod p Milnor basis elements in dimension n
     854
     855    At the prime 2, the Milnor basis consists of symbols of the form
     856    $\text{Sq}(m_1, m_2, ..., m_t)$, where each $m_i$ is a
     857    non-negative integer and if $t>1$, then $m_t \neq 0$.
     858    At odd primes, it consists of symbols of the form
     859    $Q_{e_1} Q_{e_2} ... P(m_1, m_2, ..., m_t)$, where
     860    $0 \leq e_1 < e_2 < ...$, each $m_i$ is a non-negative integer,
     861    and if $t>1$, then $m_t \neq 0$.
     862
     863    EXAMPLES:
     864        sage: from sage.algebras.steenrod_algebra_bases import milnor_basis
     865        sage: milnor_basis(7)
     866        (Sq(0,0,1), Sq(1,2), Sq(4,1), Sq(7))
     867        sage: milnor_basis(7, 2)
     868        (Sq(0,0,1), Sq(1,2), Sq(4,1), Sq(7))
     869        sage: milnor_basis(9, 3)
     870        (Q_1 P(1), Q_0 P(2))
     871        sage: milnor_basis(17, 3)
     872        (Q_2, Q_1 P(3), Q_0 P(0,1), Q_0 P(4))
     873        sage: milnor_basis(48, p=5)
     874        (P(0,1), P(6))
     875        sage: len(milnor_basis(100,3))
     876        13
     877        sage: len(milnor_basis(200,7))
     878        0
     879        sage: len(milnor_basis(240,7))
     880        3
     881    """
     882    def xi_degrees(n,p=2):
     883        r"""
     884        When p=2: decreasing list of the degrees of the $\xi_i$'s with
     885        degree at most n.
     886       
     887        At odd primes: decreasing list of these degrees, each divided
     888        by 2(p-1).
     889        """
     890        result = []
     891        deg = 1
     892        while deg <= n:
     893            result.insert(0,deg)
     894            deg = p*deg + 1
     895        return result
     896
     897    if n == 0:
     898        if p == 2:
     899            return (Sq(0),)
     900        else:
     901            return (SteenrodAlgebra(p).P(0),)
     902    else:
     903        result = []
     904        if _steenrod_bases.has_key(('milnor',n,p)):
     905            result = _steenrod_bases[('milnor',n,p)]
     906        else:
     907            if p == 2:
     908                # build basis from partitions of n, with parts taken
     909                # from the list xi_degrees(n)
     910                for sigma in restricted_partitions(n,xi_degrees(n)):
     911                    sigma_exp = list_to_hist(sigma)
     912                    deg = 1
     913                    i = 0
     914                    exponents = []
     915                    while deg <= len(sigma_exp):
     916                        exponents.insert(i,sigma_exp[deg-1])
     917                        deg = 2*deg + 1
     918                        i = i + 1
     919                    result.append(SteenrodAlgebraElement({tuple(exponents): 1}))
     920                    _steenrod_bases[('milnor',n,p)] = tuple(result)
     921            else:  # p odd
     922                # first find the P part of each basis element.
     923                # in this part of the code (the P part), all dimensions are
     924                # divided by 2(p-1).
     925                for dim in range(n/(2*(p-1)) + 1):
     926                    if dim == 0:
     927                        P_result = [[0]]
     928                    else:
     929                        P_result = []
     930                    for sigma in restricted_partitions(dim, xi_degrees(dim,p)):
     931                        sigma_exp = list_to_hist(sigma)
     932                        deg = 1
     933                        i = 0
     934                        p_mono = []
     935                        while deg <= len(sigma_exp):
     936                            p_mono.insert(i, sigma_exp[deg-1])
     937                            deg = p*deg + 1
     938                            i = i + 1
     939                        if len(p_mono) > 0:
     940                            P_result.append(p_mono)
     941                    # now find the Q part of the basis element.
     942                    # dimensions here are back to normal.
     943                    for p_mono in P_result:
     944                        deg = n - 2*dim*(p-1)
     945                        q_degrees = [1+2*(p-1)*d for d in
     946                                     xi_degrees((deg - 1)/(2*(p-1)), p)] + [1]
     947                        q_degrees_decrease = q_degrees
     948                        q_degrees.reverse()
     949                        if deg % (2*(p-1)) <= len(q_degrees):
     950                            # if this inequality fails, no way to have a partition
     951                            # with distinct parts.
     952                            for sigma in restricted_partitions(deg,
     953                                                               q_degrees_decrease,
     954                                                               no_repeats = True):
     955                                index = 0
     956                                q_mono = []
     957                                for q in q_degrees:
     958                                    if q in sigma:
     959                                        q_mono.append(index)
     960                                    index += 1
     961                                result.append(SteenrodAlgebraElement(
     962                                        {(tuple(q_mono), tuple(p_mono)): 1}, p))
     963                _steenrod_bases[('milnor',n,p)] = tuple(result)
     964        return tuple(result)
     965
     966
     967def serre_cartan_basis(n, p=2, bound=1):
     968    r"""
     969    Serre-Cartan basis in dimension $n$.
     970
     971    INPUT:
     972        n -- non-negative integer
     973        bound (optional) -- positive integer
     974        prime (optional, default 2) -- positive prime number
     975
     976    OUTPUT:
     977        tuple of mod p Serre-Cartan basis elements in dimension n
     978
     979    The Serre-Cartan basis consists of 'admissible monomials in the
     980    Steenrod squares'.  Thus at the prime 2, it consists of monomials
     981    $\text{Sq}^{m_1} \text{Sq}^{m_2} ... \text{Sq}^{m_t}$ with $m_i
     982    \geq 2m_{i+1}$ for each $i$.  At odd primes, it consists of
     983    monomials $\beta^{\epsilon_0} \mathcal{P}^{s_1} \beta^{\epsilon_1}
     984    \mathcal{P}^{s_2} ...  \mathcal{P}^{s_k} \beta^{\epsilon_k}$ with
     985    each $\epsilon_i$ either 0 or 1, $s_i \geq p s_{i+1} +
     986    \epsilon_i$, and $s_k \geq 1$.
     987
     988    EXAMPLES:
     989        sage: steenrod_set_basis('milnor')
     990        'milnor'
     991        sage: from sage.algebras.steenrod_algebra_bases import serre_cartan_basis
     992        sage: serre_cartan_basis(7)
     993        (Sq(7), Sq(4,1) + Sq(7), Sq(0,0,1) + Sq(1,2) + Sq(4,1) + Sq(7), Sq(1,2)
     994        + Sq(7))
     995        sage: steenrod_set_basis('serre_cartan')
     996        'serre_cartan'
     997        sage: serre_cartan_basis(7)
     998        (Sq^{7}, Sq^{6} Sq^{1}, Sq^{4} Sq^{2} Sq^{1}, Sq^{5} Sq^{2})
     999        sage: serre_cartan_basis(13,3)
     1000        (beta P^{3}, P^{3} beta)
     1001        sage: serre_cartan_basis(50,5)
     1002        (beta P^{5} P^{1} beta, beta P^{6} beta)
     1003
     1004    If optional argument bound is present, include only those
     1005    monomials whose last term is at least bound (when p=2), or those
     1006    for which s_k - epsilon_k >= bound (when p is odd).
     1007        sage: steenrod_set_basis('serre_cartan')
     1008        'serre_cartan'
     1009        sage: serre_cartan_basis(7, bound=2)
     1010        (Sq^{7}, Sq^{5} Sq^{2})
     1011        sage: serre_cartan_basis(13, 3, bound=3)
     1012        (beta P^{3},)
     1013        sage: steenrod_set_basis('milnor')
     1014        'milnor'
     1015    """
     1016    if not (isinstance(bound, (Integer, int)) and bound >= 1):
     1017        raise ValueError, "%s is not a positive integer." % bound
     1018    if n == 0:
     1019        if p == 2:
     1020            return (Sq(0),)
     1021        else:
     1022            return (SteenrodAlgebra(p).P(0),)
     1023    else:
     1024        if _steenrod_bases.has_key(('serre-cartan',n,p)):
     1025            result = []
     1026            lookup = _steenrod_bases[('serre-cartan',n,p)]
     1027            for vec in lookup:
     1028                for mono in vec._basis_dictionary('serre-cartan'):
     1029                    if (bound == 1) or \
     1030                            (p == 2 and mono[-1] >= bound) or \
     1031                            (p > 2 and (len(mono)<2 or mono[-2] - mono[-1] >= bound)):
     1032                        result.append(vec)
     1033        else:
     1034            if p == 2:
     1035                # Build basis recursively.  last = last term.
     1036                # last is >= bound, and we will append (last,) to the end of
     1037                # elements from serre_cartan_basis (n - last, bound=2 * last).
     1038                # This means that 2 last <= n - last, or 3 last <= n.
     1039                result = [Sq(n)]
     1040                for last in range(bound, 1+n/3):
     1041                    for vec in serre_cartan_basis(n - last, bound = 2*last):
     1042                        new = vec * Sq(last)
     1043                        for m in vec._basis_dictionary('serre-cartan'):
     1044                            sc_mono = m
     1045                        new._raw['serre-cartan'] = {sc_mono + (last,): 1}
     1046                        result.append(new)
     1047                if bound == 1: _steenrod_bases[('serre-cartan',n,p)] = tuple(result)
     1048            else: # p odd
     1049                if n % (2 * (p-1)) == 0 and n/(2 * (p-1)) >= bound:
     1050                    a = SteenrodAlgebra(p).P(int(n/(2 * (p-1))))
     1051                    a._raw['serre-cartan'] = {(0,int(n/(2 * (p-1))),0): 1}
     1052                    result = [a]
     1053                elif n == 1:
     1054                    a = SteenrodAlgebra(p).Q(0)
     1055                    a._raw['serre-cartan'] = {(1,): 1}
     1056                    result = [a]
     1057                else:
     1058                    result = []
     1059                # 2 cases: append P^{last}, or append P^{last} beta
     1060                # case 1: append P^{last}
     1061                for last in range(bound, 1+n/(2*(p - 1))):
     1062                    if n - 2*(p-1)*last > 0:
     1063                        for vec in serre_cartan_basis(n - 2*(p-1)*last,
     1064                                                      p, p*last):
     1065                            new = vec * SteenrodAlgebra(p).P(last,)
     1066                            for m in vec._basis_dictionary('serre-cartan'):
     1067                                sc_mono = m
     1068                            new._raw['serre-cartan'] = {sc_mono + (last,0): 1}
     1069                            result.append(new)
     1070                # case 2: append P^{last} beta
     1071                if bound == 1:
     1072                    bound = 0
     1073                for last in range(bound+1, 1+n/(2*(p - 1))):
     1074                    basis = serre_cartan_basis(n - 2*(p-1)*last - 1,
     1075                                               p, p*last)
     1076                    for vec in basis:
     1077                        if vec == 1:
     1078                            vec._raw['serre-cartan'] = {(0,): 1}
     1079                        new = vec * SteenrodAlgebra(p).P(last,) * SteenrodAlgebra(p).Q(0)
     1080                        for m in vec._basis_dictionary('serre-cartan'):
     1081                            sc_mono = m
     1082                        new._raw['serre-cartan'] = {sc_mono + (last,1): 1}
     1083                        result.append(new)
     1084                if bound <= 1: _steenrod_bases[('serre-cartan',n,p)] = tuple(result)
     1085        return tuple(result)
     1086
     1087
     1088def atomic_basis(n, basis):
     1089    r"""
     1090    Basis for dimension $n$ made of elements in 'atomic' degrees:
     1091    degrees of the form $2^i (2^j - 1)$.
     1092
     1093    This includes Wood's Y and Z bases, Wall's basis, Arnon's A basis,
     1094    the $P^s_t$-bases, and the commutator bases.  (All of these bases
     1095    are constructed similarly, hence their constructions have been
     1096    consolidated into a single function.)
     1097
     1098    INPUT:
     1099        n -- non-negative integer
     1100        basis -- string, the name of the basis
     1101
     1102    OUTPUT:
     1103        tuple of basis elements in dimension n
     1104
     1105    Wood's $Y$ and $Z$ bases are defined as follows.  For pairs of
     1106    non-negative integers $(m,k)$, let $w(m,k) = \text{Sq}^{2^m
     1107    (2^{k+1}-1)}$.  The $Y$ basis consists of monomials $w(m_0,k_0)
     1108    ... w(m_t, k_t)$ with $(m_i,k_i) > (m_{i+1},k_{i+1})$, in left
     1109    lex order.  The $Z$ basis consists of monomials $w(m_0,k_0) ...
     1110    w(m_t, k_t)$ with $(m_i+k_i,m_i) > (m_{i+1}+k_{i+1},m_{i+1})$,
     1111    also in left lex order.
     1112
     1113    EXAMPLES:
     1114        sage: from sage.algebras.steenrod_algebra_bases import atomic_basis
     1115        sage: atomic_basis(6,'woody')
     1116        (Sq(3,1), Sq(0,2) + Sq(3,1) + Sq(6), Sq(6))
     1117        sage: steenrod_set_basis('woody')
     1118        'woody'
     1119        sage: atomic_basis(6,'woody')
     1120        (Sq^{2} Sq^{3} Sq^{1}, Sq^{4} Sq^{2}, Sq^{6})
     1121        sage: atomic_basis(8,'woodz')
     1122        (Sq^{4} Sq^{3} Sq^{1}, Sq^{7} Sq^{1}, Sq^{6} Sq^{2}, Sq^{8})
     1123        sage: atomic_basis(6,'woodz') == atomic_basis(6, 'woody')
     1124        True
     1125        sage: atomic_basis(9,'woodz') == atomic_basis(9, 'woody')
     1126        False
     1127
     1128    Wall's basis: for any pair of integers $(m,k)$ with $m \geq k \geq
     1129    0$, let $Q^m_k = \text{Sq}^{2^k} \text{Sq}^{2^{k+1}} ...
     1130    \text{Sq}^{2^m}$.  The elements of Wall's basis are monomials
     1131    $Q^{m_0}_{k_0} ... Q^{m_t}_{k_t}$ with $(m_i, k_i) > (m_{i+1},
     1132    k_{i+1})$, ordered left lexicographically.
     1133
     1134    (Note that $Q^m_k$ is the reverse of the element $X^m_k$ used in
     1135    defining Arnon's A basis.)
     1136        sage: steenrod_set_basis('milnor')
     1137        'milnor'
     1138        sage: atomic_basis(6,'wall')
     1139        (Sq(3,1), Sq(0,2) + Sq(3,1) + Sq(6), Sq(3,1) + Sq(6))
     1140        sage: steenrod_set_basis('wall')
     1141        'wall'
     1142        sage: atomic_basis(6,'wall')
     1143        (Q^{1}_{1} Q^{1}_{0} Q^{0}_{0}, Q^{2}_{2} Q^{1}_{1}, Q^{2}_{1})
     1144
     1145    Arnon's A basis: for any pair of integers $(m,k)$ with $m \geq k
     1146    \geq 0$, let $X^m_k = \text{Sq}^{2^m} \text{Sq}^{2^{m-1}} ...
     1147    \text{Sq}^{2^k}$.  The elements of Arnon's A basis are monomials
     1148    $X^{m_0}_{k_0} ... X^{m_t}_{k_t}$ with $(m_i, k_i) < (m_{i+1},
     1149    k_{i+1})$, ordered left lexicographically.
     1150
     1151    (Note that $X^m_k$ is the reverse of the element $Q^m_k$ used in
     1152    defining Wall's basis.)
     1153        sage: steenrod_set_basis('milnor')
     1154        'milnor'
     1155        sage: atomic_basis(7,'arnona')
     1156        (Sq(7),
     1157        Sq(1,2) + Sq(7),
     1158        Sq(4,1) + Sq(7),
     1159        Sq(0,0,1) + Sq(1,2) + Sq(4,1) + Sq(7))
     1160        sage: steenrod_set_basis('arnonA')
     1161        'arnona'
     1162        sage: atomic_basis(7,'arnona')
     1163        (X^{0}_{0} X^{1}_{1} X^{2}_{2},
     1164        X^{0}_{0} X^{2}_{1},
     1165        X^{1}_{0} X^{2}_{2},
     1166        X^{2}_{0})
     1167
     1168    To obtain a $P^s_t$-basis, for each set $\{P^{s_1}_{t_1}, ...,
     1169    P^{s_k}_{t_k}\}$ of (distinct) $P^s_t$'s, one chooses an ordering
     1170    and forms the resulting monomial.  The set of all such monomials
     1171    then forms a basis, and so one gets a basis by choosing an ordering
     1172    on each monomial.
     1173   
     1174    The name of the basis has the form 'pst_ORDER', where ORDER is a
     1175    string corresponding to one of the following orderings.  These are
     1176    all 'global' -- they give a global ordering on the $P^s_t$'s, not
     1177    different orderings depending on the monomial.  They order the
     1178    $P^s_t$'s using the pair of integers $(s,t)$ as follows:
     1179
     1180        'rlex': right lexicographic ordering
     1181        'llex': left lexicographic ordering
     1182        'deg': ordered by degree, which is the same as left lexicographic
     1183            ordering on the pair $(s+t,t)$
     1184        'revz': left lexicographic ordering on the pair $(s+t,s)$, which is
     1185            the reverse of the ordering used (on elements in the same
     1186            degrees as the $P^s_t$'s) in Wood's Z basis: 'revz' stands
     1187            for 'reversed Z'.
     1188
     1189    Here are some examples:
     1190        sage: steenrod_set_basis('milnor')
     1191        'milnor'
     1192        sage: atomic_basis(7,'pst_rlex')
     1193        (Sq(7), Sq(1,2), Sq(0,0,1) + Sq(4,1), Sq(0,0,1))
     1194        sage: steenrod_set_basis('pst_rlex')
     1195        'pst_rlex'
     1196        sage: atomic_basis(7,'pst_rlex')
     1197        (P^{0}_{1} P^{1}_{1} P^{2}_{1},
     1198        P^{0}_{1} P^{1}_{2},
     1199        P^{2}_{1} P^{0}_{2},
     1200        P^{0}_{3})
     1201        sage: steenrod_set_basis('pst_llex')
     1202        'pst_llex'
     1203        sage: atomic_basis(7,'pst_llex')
     1204        (P^{0}_{1} P^{1}_{1} P^{2}_{1},
     1205        P^{0}_{1} P^{1}_{2},
     1206        P^{0}_{2} P^{2}_{1},
     1207        P^{0}_{3})
     1208        sage: steenrod_set_basis('pst_deg')
     1209        'pst_deg'
     1210        sage: atomic_basis(7,'pst_deg')
     1211        (P^{0}_{1} P^{1}_{1} P^{2}_{1},
     1212        P^{0}_{1} P^{1}_{2},
     1213        P^{0}_{2} P^{2}_{1},
     1214        P^{0}_{3})
     1215        sage: steenrod_set_basis('pst_revz')
     1216        'pst_revz'
     1217        sage: atomic_basis(7,'pst_revz')
     1218        (P^{0}_{1} P^{1}_{1} P^{2}_{1},
     1219        P^{0}_{1} P^{1}_{2},
     1220        P^{0}_{2} P^{2}_{1},
     1221        P^{0}_{3})
     1222
     1223    Commutator bases: let $c_{i,1} = \text{Sq}^{2^i}$, let $c_{i,2} =
     1224    [c_{i,1}, c_{i+1,1}]$, and inductively define $c_{i,k} =
     1225    [c_{i,k-1}, c_{i+k-1,1}]$.  Thus $c_{i,k}$ is a $k$-fold iterated
     1226    commutator of the elements $\text{Sq}^{2^i}$, ...,
     1227    $\text{Sq}^{2^{i+k-1}}$, and $\dim c_{i,k} = \dim P^i_k$.
     1228       
     1229    To obtain a commutator basis, for each set $\{c_{s_1,t_1}, ...,
     1230    c_{s_k,t_k}\}$ of (distinct) $c_{s,t}$'s, one chooses an ordering
     1231    and forms the resulting monomial.  The set of all such monomials
     1232    then forms a basis, and so one gets a basis by choosing an ordering
     1233    on each monomial.
     1234   
     1235    The name of the basis has the form 'comm_ORDER', where ORDER is a
     1236    string corresponding to an ordering, just as with the pst bases.
     1237        sage: steenrod_set_basis('milnor')
     1238        'milnor'
     1239        sage: atomic_basis(7,'comm_rlex')
     1240        (Sq(7), Sq(1,2), Sq(0,0,1) + Sq(4,1), Sq(0,0,1))
     1241        sage: steenrod_set_basis('comm_rlex')
     1242        'comm_rlex'
     1243        sage: atomic_basis(7,'comm_rlex')
     1244        (c_{0,1} c_{1,1} c_{2,1}, c_{0,1} c_{1,2}, c_{2,1} c_{0,2}, c_{0,3})
     1245        sage: steenrod_set_basis('comm_llex')
     1246        'comm_llex'
     1247        sage: atomic_basis(7,'comm_llex')
     1248        (c_{0,1} c_{1,1} c_{2,1}, c_{0,1} c_{1,2}, c_{0,2} c_{2,1}, c_{0,3})
     1249        sage: steenrod_set_basis('comm_deg')
     1250        'comm_deg'
     1251        sage: atomic_basis(7,'comm_deg')
     1252        (c_{0,1} c_{1,1} c_{2,1}, c_{0,1} c_{1,2}, c_{0,2} c_{2,1}, c_{0,3})
     1253        sage: steenrod_set_basis('comm_revz')
     1254        'comm_revz'
     1255        sage: atomic_basis(7,'comm_revz')
     1256        (c_{0,1} c_{1,1} c_{2,1}, c_{0,1} c_{1,2}, c_{0,2} c_{2,1}, c_{0,3})
     1257    """
     1258    def degree_dictionary(n, basis):
     1259        """
     1260        Dictionary of atomic degrees for basis up to degree n.
     1261
     1262        The keys for the dictionary are the atomic degrees -- the
     1263        numbers of the form 2^i (2^j - 1) -- which are less than or
     1264        equal to n.  The value associated to such a degree depends on
     1265        basis; it has the form ((s,t), x), where (s,t) is a pair of
     1266        integers which indexes the corresponding element, and x is the
     1267        element in the Milnor basis.
     1268        """
     1269        dict = {}
     1270        if basis.find('wood') >= 0:
     1271            k=0
     1272            m=0
     1273            deg = 2**m * (2**(k+1) - 1)
     1274            while deg <= n:
     1275                dict[deg] = ((m,k), Sq(deg))
     1276                if m>0:
     1277                    m = m - 1
     1278                    k = k + 1
     1279                else:
     1280                    m = k + 1
     1281                    k = 0
     1282                deg = 2**m * (2**(k+1) - 1)
     1283        elif basis.find('wall') >= 0 or basis.find('arnon') >= 0:
     1284            k=0
     1285            m=0
     1286            deg = 2**k * (2**(m-k+1) - 1)
     1287            while deg <= n:
     1288                dict[deg] = ((m,k), Q(m,k,basis))
     1289                if k == 0:
     1290                    m = m + 1
     1291                    k = m
     1292                else:
     1293                    k = k - 1
     1294                deg = 2**k * (2**(m-k+1) - 1)
     1295        elif basis.find('pst') >= 0 or basis.find('comm') >= 0:
     1296            s=0
     1297            t=1
     1298            deg = 2**s * (2**t - 1)
     1299            while deg <= n:
     1300                if basis.find('pst') >= 0:
     1301                    dict[deg] = ((s,t), pst(s,t))
     1302                else:  # comm
     1303                    dict[deg] = ((s,t), commutator(s,t))
     1304                if s == 0:
     1305                    s = t
     1306                    t = 1
     1307                else:
     1308                    s = s - 1
     1309                    t = t + 1
     1310                deg = 2**s * (2**t - 1)
     1311        return dict
     1312   
     1313    def sorting_pair(s,t,basis):   # pair used for sorting the basis
     1314        if basis.find('wood') >= 0 and basis.find('z') >= 0:
     1315            # return (s+t,s)
     1316            return (-s-t,-s)
     1317        elif basis.find('wood') >= 0 or basis.find('wall') >= 0 or \
     1318                basis.find('arnon') >= 0:
     1319            #return (s,t)
     1320            return (-s,-t)
     1321        elif basis.find('rlex') >= 0:
     1322            return (t,s)
     1323        elif basis.find('llex') >= 0:
     1324            return (s,t)
     1325        elif basis.find('deg') >= 0:
     1326            return (s+t,t)
     1327        elif basis.find('revz') >= 0:
     1328            return (s+t,s)
     1329
     1330    from sage.misc.misc import prod
     1331    if n == 0:
     1332        return (Sq(0),)
     1333    else:
     1334        result = []
     1335        if _steenrod_bases.has_key((basis,n)):
     1336            result = _steenrod_bases[(basis,n)]
     1337        else:
     1338            degrees_etc = degree_dictionary(n, basis)
     1339            degrees = degrees_etc.keys()
     1340            for sigma in restricted_partitions(n, degrees, no_repeats=True):
     1341                big_list = [degrees_etc[part] for part in sigma]
     1342                big_list.sort(key=lambda x: x[0],
     1343                              cmp = lambda x, y: cmp(sorting_pair(x[0], x[1], basis),
     1344                                                     sorting_pair(y[0], y[1], basis)))
     1345                # reverse = True)
     1346                # arnon: sort like wall, then reverse end result
     1347                if basis.find('arnon') >= 0:
     1348                    big_list.reverse()
     1349                list_of_pairs = [d[0] for d in big_list]
     1350                mono_list = [d[1] for d in big_list]
     1351                new = prod(mono_list)
     1352                new._raw[basis] = {tuple(list_of_pairs): 1}
     1353                result.append(new)
     1354            _steenrod_bases[(basis,n)] = tuple(result)
     1355        return tuple(result)
     1356
     1357
     1358def Q(m,k,basis):
     1359    r"""
     1360    Compute Q^m_k (Wall basis) and X^m_k (Arnon's A basis).
     1361
     1362    INPUT:
     1363        m,k -- non-negative integers with m >= k
     1364        basis -- 'wall' or 'arnona'
     1365       
     1366    OUTPUT:
     1367        if basis is 'wall', Q^m_k = Sq(2^k) Sq(2^(k+1)) ... Sq(2^m)
     1368        if basis is 'arnona', the reverse of this:
     1369            X^m_k = Sq(2^m) ... Sq(2^(k+1)) Sq(2^k)
     1370
     1371    EXAMPLES:
     1372        sage: steenrod_set_basis('milnor')
     1373        'milnor'
     1374        sage: from sage.algebras.steenrod_algebra_bases import Q
     1375        sage: Q(2,2,'wall')
     1376        Sq(4)
     1377        sage: Q(2,2,'arnona')
     1378        Sq(4)
     1379        sage: Q(3,2,'wall')
     1380        Sq(6,2) + Sq(12)
     1381        sage: Q(3,2,'arnona')
     1382        Sq(0,4) + Sq(3,3) + Sq(6,2) + Sq(12)
     1383    """
     1384    exponent = 2**k
     1385    result = Sq(exponent)
     1386    for i in range(m-k):
     1387        exponent = exponent * 2
     1388        if basis == 'wall':
     1389            result = result * Sq(exponent)
     1390        elif basis == 'arnona':
     1391            result = Sq(exponent) * result
     1392    return result
     1393
     1394
     1395def arnonC_basis(n,bound=1):
     1396    r"""
     1397    Arnon's C basis in dimension $n$.
     1398
     1399    INPUT:
     1400        n -- non-negative integer
     1401        bound (optional) -- positive integer
     1402
     1403    OUTPUT:
     1404        tuple of basis elements in dimension n
     1405
     1406    The elements of Arnon's C basis are monomials of the form
     1407    $\text{Sq}^{t_1} ... \text{Sq}^{t_m}$ where for each $i$, we
     1408    have $t_i \leq 2t_{i+1}$ and $2^i | t_{m-i}$.
     1409
     1410    EXAMPLES:
     1411        sage: from sage.algebras.steenrod_algebra_bases import arnonC_basis
     1412        sage: arnonC_basis(7)
     1413        (Sq(7), Sq(4,1) + Sq(7), Sq(1,2) + Sq(7), Sq(0,0,1) + Sq(1,2) + Sq(4,1)
     1414        + Sq(7))
     1415        sage: steenrod_set_basis('arnonc')
     1416        'arnonc'
     1417        sage: arnonC_basis(7)
     1418        (Sq^{7}, Sq^{2} Sq^{5}, Sq^{4} Sq^{3}, Sq^{4} Sq^{2} Sq^{1})
     1419
     1420    If optional argument bound is present, include only those monomials whose
     1421    first term is at least as large as bound:
     1422        sage: arnonC_basis(7,3)
     1423        (Sq^{7}, Sq^{4} Sq^{3}, Sq^{4} Sq^{2} Sq^{1})
     1424        sage: steenrod_set_basis('milnor')
     1425        'milnor'
     1426    """
     1427    if not (isinstance(bound, (Integer, int)) and bound >= 1):
     1428        raise ValueError, "%s is not a positive integer." % bound
     1429    if n == 0:
     1430        return (Sq(0),)
     1431    else:
     1432        if _steenrod_bases.has_key(('arnonc',n)):
     1433            result = []
     1434            lookup = _steenrod_bases[('arnonc',n)]
     1435            for vec in lookup:
     1436                for mono in vec._basis_dictionary('arnonc'):
     1437                    if mono[0] >= bound:
     1438                        result.append(vec)
     1439        else:
     1440            # Build basis recursively.  first = first term.
     1441            # first is >= bound, and we will prepend (first,) to the
     1442            # elements from arnonC_basis (n - first, first / 2).
     1443            # first also must be divisible by 2**(len(old-basis-elt))
     1444            # This means that 3 first <= 2 n.
     1445            result = [Sq(n)]
     1446            for first in range(bound,1+2*n/3):
     1447                for vec in arnonC_basis(n - first, max(first/2,1)):
     1448                    if len(vec._basis_dictionary('arnonc')) > 1: print "Error in Arnon's C basis!"
     1449                    for m in vec._basis_dictionary('arnonc'):
     1450                        arnonc_mono = m
     1451                    if first % 2**len(arnonc_mono) == 0:
     1452                        new = Sq(first) * vec
     1453                        new._raw['arnonc'] = {(first,) + arnonc_mono: 1}
     1454                        result.append(new)
     1455            if bound == 1: _steenrod_bases[('arnonc',n)] = tuple(result)
     1456        return tuple(result)
     1457
     1458
     1459@memoize
     1460def commutator(s,t):
     1461    r"""
     1462    $t$th iterated commutator of consecutive $\text{Sq}^2^i$'s.
     1463
     1464    INPUT:
     1465        s, t: integers
     1466       
     1467    OUTPUT:
     1468        If t=1, return Sq(2^s).  Otherwise, return the commutator
     1469        [commutator(s,t-1), Sq(2^{s+t-1})].
     1470
     1471    EXAMPLES:
     1472        sage: from sage.algebras.steenrod_algebra_bases import commutator
     1473        sage: commutator(1,2)
     1474        Sq(0,2)
     1475        sage: commutator(0,4)
     1476        Sq(0,0,0,1)
     1477        sage: commutator(2,2)
     1478        Sq(0,4) + Sq(3,3)
     1479
     1480    NOTES:
     1481        commutator(0,n) is equal to $\text{Sq}(0,...,0,1)$, with the
     1482        1 in the $n$th spot.  commutator(i,n) always has
     1483        $\text{Sq}(0,...,0,2^i)$, with $2^i$ in the $n$th spot, as a
     1484        summand, but there may be other terms, as the example of
     1485        commutator(2,2) illustrates.
     1486
     1487        That is, commutator(s,t) is equal to $P^s_t$, possibly plus
     1488        other Milnor basis elements.
     1489    """
     1490    if t == 1:
     1491        return Sq(2**s)
     1492    else:
     1493        x = commutator(s,t-1)
     1494        y = Sq(2**(s+t-1))
     1495        return x*y + y*x
     1496
     1497   
     1498#############################################################################
     1499def steenrod_basis_error_check(dim,p):
     1500    """
     1501    This performs crude error checking.
     1502
     1503    INPUT:
     1504        dim -- non-negative integer
     1505        p -- positive prime number
     1506
     1507    OUTPUT:
     1508        None
     1509
     1510    This checks to see if the different bases have the same length,
     1511    and if the change-of-basis matrices are invertible.  If something
     1512    goes wrong, an error message is printed.
     1513   
     1514    This function checks at the prime p as the dimension goes up from
     1515    0, in which case the basis functions use the saved basis
     1516    computations in lower dimensions in the computations.  It also
     1517    checks as the dimension goes down from the top, in which case it
     1518    doesn't have access to the saved computations.  (The saved
     1519    computations are deleted first: the cache _steenrod_bases is set
     1520    to {} before doing the computations.)
     1521
     1522    EXAMPLES:
     1523        sage: sage.algebras.steenrod_algebra_bases.steenrod_basis_error_check(12,2)
     1524        p=2, in decreasing order of dimension, starting in dimension 12.
     1525        down to dimension  10
     1526        down to dimension  5
     1527        p=2, now in increasing order of dimension, up to dimension 12
     1528        up to dimension  0
     1529        up to dimension  5
     1530        up to dimension  10
     1531        done checking
     1532        sage: sage.algebras.steenrod_algebra_bases.steenrod_basis_error_check(30,3)
     1533        p=3, in decreasing order of dimension, starting in dimension 30.
     1534        down to dimension  30
     1535        down to dimension  25
     1536        down to dimension  20
     1537        down to dimension  15
     1538        down to dimension  10
     1539        down to dimension  5
     1540        p=3, now in increasing order of dimension, up to dimension 30
     1541        up to dimension  0
     1542        up to dimension  5
     1543        up to dimension  10
     1544        up to dimension  15
     1545        up to dimension  20
     1546        up to dimension  25
     1547        done checking
     1548    """
     1549    global _steenrod_bases
     1550   
     1551    _steenrod_bases = {}
     1552
     1553    if p == 2:
     1554        bases = ('adem','woody', 'woodz', 'wall', 'arnona', 'arnonc',
     1555                 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz',
     1556                 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz')
     1557    else:
     1558        bases = ('adem', 'milnor')
     1559
     1560    print "p=%s, in decreasing order of dimension, starting in dimension %s." % (p, dim)
     1561    for i in range(dim,0,-1):
     1562        if i % 5 == 0: print "down to dimension ", i
     1563        for B in bases:
     1564            if len(steenrod_algebra_basis(i,'milnor')) != len(steenrod_algebra_basis(i,B)):
     1565                print "problem with milnor/" + B + " in dimension ", i
     1566            mat = convert_to_milnor_matrix(i,B,p)
     1567            if mat.nrows() != 0 and not mat.is_invertible():
     1568                print "%s invertibility problem in dim %s at the prime %s" % (B, i, p)
     1569
     1570    _steenrod_bases = {}
     1571
     1572    print "p=%s, now in increasing order of dimension, up to dimension %s" % (p, dim)
     1573    for i in range(dim):
     1574        if i % 5 == 0: print "up to dimension ", i
     1575        for B in bases:
     1576            if len(steenrod_algebra_basis(i,'milnor')) != len(steenrod_algebra_basis(i,B)):
     1577                print "problem with milnor/" + B + " in dimension ", i
     1578            mat = convert_to_milnor_matrix(i,B,p)
     1579            if mat.nrows() != 0 and not mat.is_invertible():
     1580                print "%s invertibility problem in dim %s at the prime %s" % (B, i, p)
     1581
     1582    print "done checking"
  • new file sage/algebras/steenrod_milnor_multiplication.py

    diff -r 96e35b9306b1 -r 0dfaa3830fda sage/algebras/steenrod_milnor_multiplication.py
    - +  
     1r"""
     2Milnor multiplication for elements of the Steenrod algebra.
     3
     4AUTHORS:
     5    - John H. Palmieri (2008-07-15: version 0.7)
     6
     7See Milnor's paper [Mil] for proofs, etc.
     8
     9To multiply $\text{Sq}(r_1, r_2, ...)$ and $\text{Sq}(s_1,
     10s_2,...)$, form all possible matrices $M$ with rows and columns
     11indexed starting at 0, with position (0,0) deleted (or ignored), with
     12$s_i$ equal to the sum of column $i$ for each $i$, and with $r_j$
     13equal to the 'weighted' sum of row $j$.  The weights are as follows:
     14elements from column $i$ are multiplied by $2^i$.  For example, to
     15multiply $\text{Sq}(2)$ and $\text{Sq}(1,1)$, form the matrices
     16\[
     17\begin{Vmatrix}
     18* & 1 & 1 \\
     192 & 0 & 0
     20\end{Vmatrix}
     21\quad \text{and} \quad
     22\begin{Vmatrix}
     23* & 0 & 1 \\
     240 & 1 & 0
     25\end{Vmatrix}
     26\]
     27(The * is the ignored (0,0)-entry of the matrix.)  For each such
     28matrix $M$, compute a multinomial coefficient, mod 2: for each
     29diagonal $\{m_{ij}: i+j=n\}$, compute $(\sum m_{i,j}!) / (m_{0,n}!
     30m_{1,n-1}!  ... m_{n,0}!)$.  Multiply these together for all $n$.  (To
     31compute this mod 2, view the entries of the matrix as their base 2
     32expansions; then this coefficient is zero if and only if there is some
     33diagonal containing two numbers which have a summand in common in
     34their base 2 expansion.  For example, if 3 and 10 are in the same
     35diagonal, the coefficient is zero, because $3=1+2$ and $10=2+8$: they
     36both have a summand of 2.)
     37
     38Now, for each matrix with multinomial coefficient 1, let $t_n$ be
     39the sum of the nth diagonal in the matrix; then
     40\[
     41\text{Sq}(r_1, r_2, ...) \text{Sq}(s_1, s_2, ...) = \sum \text{Sq}(t_1, t_2, ...)
     42\]
     43
     44The function 'milnor_multiplication' takes as input two tuples of
     45non-negative integers, $r$ and $s$, which represent
     46$\text{Sq}(r)=\text{Sq}(r_1, r_2, ...)$ and
     47$\text{Sq}(s)=\text{Sq}(s_1, s_2, ...)$; it returns as output a
     48dictionary whose keys are tuples $t=(t_1, t_2, ...)$ of non-negative
     49integers, and for each tuple the associated value is the coefficient
     50of $\text{Sq}(t)$ in the product formula.  Since we are working mod 2,
     51this coefficient is 1 (if it is zero, the the element is omitted from
     52the dictionary altogether).
     53
     54EXAMPLES:
     55    sage: from sage.algebras.steenrod_milnor_multiplication import milnor_multiplication
     56    sage: milnor_multiplication((2,), (1,))
     57    {(0, 1): 1, (3,): 1}
     58    sage: milnor_multiplication((4,), (2,1))
     59    {(6, 1): 1, (0, 3): 1, (2, 0, 1): 1}
     60    sage: milnor_multiplication((2,4), (0,1))
     61    {(2, 5): 1, (2, 0, 0, 1): 1}
     62
     63These examples correspond to the following product computations:
     64\begin{gather*}
     65\text{Sq}(2) \text{Sq}(1) = \text{Sq}(0,1) + \text{Sq}(3)
     66\text{Sq}(4) \text{Sq}(2,1) = \text{Sq}(6,1) + \text{Sq}(0,3) + \text{Sq}(2,0,1)
     67\text{Sq}(2,4) \text{Sq}(0,1) = \text{Sq}(2, 5) + \text{Sq}(2, 0, 0, 1)
     68\end{gather*}
     69
     70REFERENCES:
     71    [Mil] J. W. Milnor, "The Steenrod algebra and its dual, Ann. of Math.
     72          (2) \textbf{67} (1958), 150--171.
     73"""
     74
     75#*****************************************************************************
     76#       Copyright (C) 2008 William Stein <wstein@gmail.com>
     77#       Copyright (C) 2008 John H. Palmieri <palmieri@math.washington.edu>
     78#  Distributed under the terms of the GNU General Public License (GPL)
     79#*****************************************************************************
     80
     81def milnor_multiplication(r,s):
     82    r"""
     83    Product of Milnor basis elements r and s.
     84
     85    INPUT:
     86        r -- tuple of non-negative integers
     87        s -- tuple of non-negative integers
     88
     89    OUTPUT:
     90        Dictionary of terms of the form (tuple: coeff), where 'tuple' is a
     91        tuple of non-negative integers and 'coeff' is 1.
     92
     93    This computes Milnor matrices for the product of $\text{Sq}(r)$
     94    and $\text{Sq}(s)$, computes their multinomial coefficients, and
     95    for each matrix whose coefficient is 1, add $\text{Sq}(t)$ to the
     96    output, where $t$ is the tuple formed by the diagonals sums from
     97    the matrix.
     98   
     99    EXAMPLES:
     100        sage: from sage.algebras.steenrod_milnor_multiplication import milnor_multiplication
     101        sage: milnor_multiplication((2,), (1,))
     102        {(0, 1): 1, (3,): 1}
     103        sage: milnor_multiplication((4,), (2,1))
     104        {(6, 1): 1, (0, 3): 1, (2, 0, 1): 1}
     105        sage: milnor_multiplication((2,4), (0,1))
     106        {(2, 5): 1, (2, 0, 0, 1): 1}
     107   
     108    This uses the same algorithm Monks does in his Maple package.
     109    """
     110    result = {}
     111    rows = len(r) + 1
     112    cols = len(s) + 1
     113    diags = len(r) + len(s)
     114    # initialize matrix
     115    M = range(rows)
     116    for i in range(rows):
     117        M[i] = [0]*cols
     118    for j in range(1,cols):
     119        M[0][j] = s[j-1]
     120    for i in range(1,rows):
     121        M[i][0] = r[i-1]
     122        for j in range(1,cols):
     123            M[i][j] = 0
     124    found = True
     125    while found:
     126        # check diagonals
     127        n = 1
     128        okay = 1
     129        diagonal = [0]*diags
     130        while n <= diags and okay is not None:
     131            nth_diagonal = [M[i][n-i] for i in range(max(0,n-cols+1), min(1+n,rows))]
     132            okay = multinomial(nth_diagonal)
     133            diagonal[n-1] = okay
     134            n = n + 1
     135        if okay is not None:
     136            i = diags - 1
     137            while i >= 0 and diagonal[i] == 0:
     138                i = i - 1
     139            t = tuple(diagonal[:i+1])
     140            # reduce mod two:
     141            if result.has_key(t):
     142                del result[t]
     143            else:
     144                result[t] = 1
     145        # now look for new matrices:
     146        found = False
     147        i = 1
     148        while not found and i < rows:
     149            sum = M[i][0]
     150            j = 1
     151            while not found and j < cols:
     152                # check to see if column index j is small enough
     153                if sum >= 2**j:
     154                    # now check to see if there's anything above this entry
     155                    # to add to it
     156                    temp_col_sum = 0
     157                    for k in range(i):
     158                        temp_col_sum += M[k][j]
     159                    if temp_col_sum != 0:
     160                        found = True
     161                        for row in range(1,i):
     162                            M[row][0] = r[row-1]
     163                            for col in range(1,cols):
     164                                M[0][col] = M[0][col] + M[row][col]
     165                                M[row][col] = 0
     166                        for col in range(1,j):
     167                            M[0][col] = M[0][col] + M[i][col]
     168                            M[i][col] = 0
     169                        M[0][j] = M[0][j] - 1
     170                        M[i][j] = M[i][j] + 1
     171                        M[i][0] = sum - 2**j
     172                    else:
     173                        sum = sum + M[i][j] * 2**j
     174                else:
     175                        sum = sum + M[i][j] * 2**j
     176                j = j + 1
     177            i = i + 1
     178    return result
     179
     180
     181def multinomial(list):
     182    """
     183    Multinomial coefficient of list, mod 2.
     184
     185    INPUT:
     186        list -- list of integers
     187
     188    OUTPUT:
     189        None if the multinomial coefficient is 0, or sum of list if it is 1
     190
     191    Given the input $[n_1, n_2, n_3, ...]$, this computes the
     192    multinomial coefficient $(n_1 + n_2 + n_3 + ...)! / (n_1! n_2!
     193    n_3! ...)$, mod 2.  The method is roughly this: expand each
     194    $n_i$ in binary.  If there is a 1 in the same digit for any $n_i$
     195    and $n_j$ with $i\neq j$, then the coefficient is 0; otherwise, it
     196    is 1.
     197
     198    EXAMPLES:
     199        sage: from sage.algebras.steenrod_milnor_multiplication import multinomial
     200        sage: multinomial([1,2,4])
     201        7
     202        sage: multinomial([1,2,5])
     203        sage: multinomial([1,2,12,192,256])
     204        463
     205
     206    This function does not compute any factorials, so the following are
     207    actually reasonable to do:
     208        sage: multinomial([1,65536])
     209        65537
     210        sage: multinomial([4,65535])
     211        sage: multinomial([32768,65536])
     212        98304
     213    """
     214    old_sum = list[0]
     215    okay = True
     216    i = 1
     217    while okay and i < len(list):
     218        j = 1
     219        while okay and j <= min(old_sum, list[i]):
     220            if j & old_sum == j:
     221                okay = (j & list[i] == 0)
     222            j = j << 1
     223        old_sum = old_sum + list[i]
     224        i = i + 1
     225    if okay:
     226        return old_sum
     227    else:
     228        return None
  • new file sage/algebras/steenrod_milnor_multiplication_odd.py

    diff -r 96e35b9306b1 -r 0dfaa3830fda sage/algebras/steenrod_milnor_multiplication_odd.py
    - +  
     1r"""
     2Milnor multiplication for elements of the Steenrod algebra, odd primes.
     3
     4AUTHORS:
     5    - John H. Palmieri (2008-07-15: version 0.7)
     6
     7See Milnor's paper [Mil] for proofs, etc.
     8
     9There are three steps to multiply Milnor basis elements
     10$Q_{f_1} Q_{f_2} ... \mathcal{P}(q_1, q_2, ...)$ and
     11$Q_{g_1} Q_{g_2} ... \mathcal{P}(s_1, s_2,...)$: first, use the formula
     12\[
     13\mathcal{P}(q_1, q_2, ...) Q_k = Q_k \mathcal{P}(q_1, q_2, ...)
     14  + Q_{k+1} \mathcal{P}(q_1 - p^k, q_2, ...)
     15  + Q_{k+2} \mathcal{P}(q_1, q_2 - p^k, ...)
     16  + ...
     17\]
     18Second, use the fact that the $Q_k$'s form an exterior algebra: $Q_k^2 =
     190$ for all $k$, and if $i \neq j$, then $Q_i$ and $Q_j$ anticommute:
     20$Q_i Q_j = -Q_j Q_i$.  After these two steps, the product is of the form
     21\[
     22\sum Q_{e_1} Q_{e_2} ... \mathcal{P}(r_1, r_2, ...) \mathcal{P}(s_1, s_2, ...).
     23\]
     24Finally, use Milnor matrices to multiply the pairs of
     25$\mathcal{P}(...)$ terms: form all possible matrices $M$ with rows and
     26columns indexed starting at 0, with position (0,0) deleted (or
     27ignored), with $s_i$ equal to the sum of column $i$ for each $i$, and
     28with $r_j$ equal to the 'weighted' sum of row $j$.  The weights are as
     29follows: elements from column $i$ are multiplied by $p^i$.  For
     30example when $p=5$, to multiply $\mathcal{P}(5)$ and $\mathcal{P}(1,1)$,
     31form the matrices
     32\[
     33\begin{Vmatrix}
     34* & 1 & 1 \\
     355 & 0 & 0
     36\end{Vmatrix}
     37\quad \text{and} \quad
     38\begin{Vmatrix}
     39* & 0 & 1 \\
     400 & 1 & 0
     41\end{Vmatrix}
     42\]
     43(The $*$ is the ignored (0,0)-entry of the matrix.)  For each such
     44matrix $M$, compute a multinomial coefficient, mod $p$: for each
     45diagonal $\{m_{ij}: i+j=n\}$, compute $(\sum m_{i,j}!) / (m_{0,n}!
     46m_{1,n-1}!  ... m_{n,0}!)$.  Multiply these together for all $n$.
     47
     48Now, for each matrix with nonzero multinomial coefficient $b_M$, let
     49$t_n$ be the sum of the $n$th diagonal in the matrix; then
     50\[
     51\mathcal{P}(r_1, r_2, ...) \mathcal{P}(s_1, s_2, ...) = \sum b_M \mathcal{P}(t_1, t_2, ...)
     52\]
     53For example when $p=5$, we have
     54\[
     55\mathcal{P}(5) \mathcal{P}(1,1) = \mathcal{P}(6,1) + 2 \mathcal{P}(0,2).
     56\]
     57The function 'milnor_multiplication' takes as input two pairs of tuples of
     58non-negative integers, $(g,q)$ and $(f,s)$, which represent
     59$Q_{g_1} Q_{g_2} ... \mathcal{P}(q_1, q_2, ...)$ and
     60$Q_{f_1} Q_{f_2} ... \mathcal{P}(s_1, s_2, ...)$.  It returns as output a
     61dictionary whose keys are pairs of tuples $(e,t)$ of non-negative
     62integers, and for each tuple the associated value is the coefficient
     63in the product formula.
     64
     65EXAMPLES:
     66    sage: from sage.algebras.steenrod_milnor_multiplication_odd import milnor_multiplication_odd
     67    sage: milnor_multiplication_odd(((0,2),(5,)), ((1,),(1,)), 5)
     68    {((0, 1, 2), (0, 1)): 4, ((0, 1, 2), (6,)): 4}
     69    sage: milnor_multiplication_odd(((0,2,4),()), ((1,3),()), 7)
     70    {((0, 1, 2, 3, 4), ()): 6}
     71    sage: milnor_multiplication_odd(((0,2,4),()), ((1,5),()), 7)
     72    {((0, 1, 2, 4, 5), ()): 1}
     73    sage: milnor_multiplication_odd(((),(6,)), ((),(2,)), 3)
     74    {((), (4, 1)): 1, ((), (8,)): 1, ((), (0, 2)): 1}
     75
     76These examples correspond to the following product computations:
     77\begin{gather*}
     78p=5: \quad Q_0 Q_2 \mathcal{P}(5) Q_1 \mathcal{P}(1) = 4 Q_0 Q_1 Q_2 \mathcal{P}(0,1) + 4 Q_0 Q_1 Q_2 \mathcal{P}(6) \\
     79p=7: \quad (Q_0 Q_2 Q_4) (Q_1 Q_3) = 6 Q_0 Q_1 Q_2 Q_3 Q_4 \\
     80p=7: \quad (Q_0 Q_2 Q_4) (Q_1 Q_5) = Q_0 Q_1 Q_2 Q_3 Q_5 \\
     81p=3: \quad \mathcal{P}(6) \mathcal{P}(2) = \mathcal{P}(0,2) + \mathcal{P}(4,1) + \mathcal{P}(8)
     82\end{gather*}
     83
     84REFERENCES:
     85    [Mil] J. W. Milnor, "The Steenrod algebra and its dual, Ann. of Math.
     86          (2) \textbf{67} (1958), 150--171.
     87"""
     88
     89#*****************************************************************************
     90#       Copyright (C) 2008 William Stein <wstein@gmail.com>
     91#       Copyright (C) 2008 John H. Palmieri <palmieri@math.washington.edu>
     92#  Distributed under the terms of the GNU General Public License (GPL)
     93#*****************************************************************************
     94
     95def milnor_multiplication_odd(m1,m2,p):
     96    r"""
     97    Product of Milnor basis elements defined by m1 and m2.
     98
     99    INPUT:
     100        m1 -- pair of tuples (e,r), where e is an increasing tuple of
     101            non-negative integers and r is a tuple of non-negative integers
     102        m2 -- pair of tuples (f,s), same format as m1
     103        p -- odd prime number
     104
     105    OUTPUT:
     106        Dictionary of terms of the form (tuple: coeff), where 'tuple' is a
     107        pair of tuples, as for r and s, and 'coeff' is an integer mod p.
     108
     109    This computes the product of the Milnor basis elements
     110    $Q_e1 Q_e2 ... P(r_1, r_2, ...)$ and
     111    $Q_f1 Q_f2 ... P(s_1, s_2, ...)$.
     112   
     113    EXAMPLES:
     114        sage: from sage.algebras.steenrod_milnor_multiplication_odd import milnor_multiplication_odd
     115        sage: milnor_multiplication_odd(((0,2),(5,)), ((1,),(1,)), 5)
     116        {((0, 1, 2), (0, 1)): 4, ((0, 1, 2), (6,)): 4}
     117        sage: milnor_multiplication_odd(((0,2,4),()), ((1,3),()), 7)
     118        {((0, 1, 2, 3, 4), ()): 6}
     119        sage: milnor_multiplication_odd(((0,2,4),()), ((1,5),()), 7)
     120        {((0, 1, 2, 4, 5), ()): 1}
     121        sage: milnor_multiplication_odd(((),(6,)), ((),(2,)), 3)
     122        {((), (4, 1)): 1, ((), (8,)): 1, ((), (0, 2)): 1}
     123   
     124    This uses the same algorithm Monks does in his Maple package to
     125    iterate through the possible matrices.
     126    """
     127    from sage.rings.all import GF
     128    F = GF(p)
     129    (f,s) = m2
     130    # First compute Q_e0 Q_e1 ... P(r1, r2, ...) Q_f0 Q_f1 ...
     131    # Store results (as dictionary of pairs of tuples) in 'answer'.
     132    answer = {m1: F(1)}
     133    for k in f:
     134        old_answer = answer
     135        answer = {}
     136        for mono in old_answer:
     137            if k not in mono[0]:
     138                q_mono = set(mono[0])
     139                if len(q_mono) > 0:
     140                    ind = len(q_mono.intersection(range(k,1+max(q_mono))))
     141                else:
     142                    ind = 0
     143                coeff = (-1)**ind * old_answer[mono]
     144                lst = list(mono[0])
     145                if ind == 0:
     146                    lst.append(k)
     147                else:
     148                    lst.insert(-ind,k)
     149                q_mono = tuple(lst)
     150                p_mono = mono[1]
     151                answer[(q_mono, p_mono)] = F(coeff)
     152            for i in range(1,1+len(mono[1])):
     153                if (k+i not in mono[0]) and (p**k <= mono[1][i-1]):
     154                    q_mono = set(mono[0])
     155                    if len(q_mono) > 0:
     156                        ind = len(q_mono.intersection(range(k+i,1+max(q_mono))))
     157                    else:
     158                        ind = 0
     159                    coeff = (-1)**ind
     160                    lst = list(mono[0])
     161                    if ind == 0:
     162                        lst.append(k+i)
     163                    else:
     164                        lst.insert(-ind,k+i)
     165                    q_mono = tuple(lst)
     166                    p_mono = list(mono[1])
     167                    p_mono[i-1] = p_mono[i-1] - p**k
     168                    answer[(q_mono, tuple(p_mono))] = F(coeff)
     169    # Now for the Milnor matrices.  For each entry '(e,r): coeff' in answer,
     170    # multiply r with s.  Record coefficient for matrix and multiply by coeff. 
     171    # Store in 'result'.
     172    if len(s) == 0:
     173        result = answer
     174    else:
     175        result = {}
     176        for (e, r) in answer:
     177            old_coeff = answer[(e,r)]
     178            # Milnor multiplication for r and s
     179            rows = len(r) + 1
     180            cols = len(s) + 1
     181            diags = len(r) + len(s)
     182            # initialize matrix
     183            M = range(rows)
     184            for i in range(rows):
     185                M[i] = [0]*cols
     186            for j in range(1,cols):
     187                M[0][j] = s[j-1]
     188            for i in range(1,rows):
     189                M[i][0] = r[i-1]
     190                for j in range(1,cols):
     191                    M[i][j] = 0
     192            found = True
     193            while found:
     194                # check diagonals
     195                n = 1
     196                coeff = old_coeff
     197                diagonal = [0]*diags
     198                while n <= diags and coeff != 0:
     199                    nth_diagonal = [M[i][n-i] for i in range(max(0,n-cols+1), min(1+n,rows))]
     200                    coeff = coeff * multinomial_odd(nth_diagonal,p)
     201                    diagonal[n-1] = sum(nth_diagonal)
     202                    n = n + 1
     203                if coeff != 0:
     204                    i = diags - 1
     205                    while i >= 0 and diagonal[i] == 0:
     206                        i = i - 1
     207                    t = tuple(diagonal[:i+1])
     208                    if result.has_key((e,t)):
     209                        result[(e,t)] = F(coeff + result[t])
     210                    else:
     211                        result[(e,t)] = F(coeff)
     212                    # now look for new matrices:
     213                found = False
     214                i = 1
     215                while not found and i < rows:
     216                    temp_sum = M[i][0]
     217                    j = 1
     218                    while not found and j < cols:
     219                        # check to see if column index j is small enough
     220                        if temp_sum >= p**j:
     221                            # now check to see if there's anything above this entry
     222                            # to add to it
     223                            temp_col_sum = 0
     224                            for k in range(i):
     225                                temp_col_sum += M[k][j]
     226                            if temp_col_sum != 0:
     227                                found = True
     228                                for row in range(1,i):
     229                                    M[row][0] = r[row-1]
     230                                    for col in range(1,cols):
     231                                        M[0][col] = M[0][col] + M[row][col]
     232                                        M[row][col] = 0
     233                                for col in range(1,j):
     234                                    M[0][col] = M[0][col] + M[i][col]
     235                                    M[i][col] = 0
     236                                M[0][j] = M[0][j] - 1
     237                                M[i][j] = M[i][j] + 1
     238                                M[i][0] = temp_sum - p**j
     239                            else:
     240                                temp_sum += M[i][j] * p**j
     241                        else:
     242                            temp_sum += M[i][j] * p**j
     243                        j = j + 1
     244                    i = i + 1
     245    return result
     246
     247
     248def multinomial_odd(list,p):
     249    """
     250    Multinomial coefficient of list, mod p.
     251
     252    INPUT:
     253        list -- list of integers
     254        p -- a prime number
     255
     256    OUTPUT:
     257        Associated multinomial coefficient, mod p
     258
     259    Given the input $[n_1, n_2, n_3, ...]$, this computes the
     260    multinomial coefficient $(n_1 + n_2 + n_3 + ...)! / (n_1! n_2!
     261    n_3! ...)$, mod $p$.  The method is this: expand each $n_i$ in
     262    base $p$: $n_i = \sum_j p^j n_{ij}$.  Do the same for the sum of
     263    the $n_i$'s, which we call $m$: $m = \sum_j p^j m_j$.  Then the
     264    multinomial coefficient is congruent, mod $p$, to the product of
     265    the multinomial coefficients $m_j! / (n_{1j}! n_{2j}! ...)$.
     266
     267    Furthermore, any multinomial coefficient $m! / (n_1! n_2! ...)$
     268    can be computed as a product of binomial coefficients: it equals
     269    \[
     270    \binom{n_1}{n_1} \binom{n_1 + n_2}{n_2} \binom{n_1 + n_2 + n_3}{n_3} ...
     271    \]
     272    This is convenient because Sage's binomial function returns
     273    integers, not rational numbers (as would be produced just by
     274    dividing factorials).
     275   
     276    EXAMPLES:
     277        sage: from sage.algebras.steenrod_milnor_multiplication_odd import multinomial_odd
     278        sage: multinomial_odd([1,2,4], 2)
     279        1
     280        sage: multinomial_odd([1,2,4], 7)
     281        0
     282        sage: multinomial_odd([1,2,4], 11)
     283        6
     284        sage: multinomial_odd([1,2,4], 101)
     285        4
     286        sage: multinomial_odd([1,2,4], 107)
     287        105
     288    """
     289    def expand(k,p):
     290        """
     291        Expand k as a sum of powers of p.  Return list of coefficients.
     292        """
     293        index = 0
     294        answer = []
     295        while k > 0:
     296            answer.append(k%p)
     297            k = int(k / p)
     298            index += 1
     299        return answer
     300   
     301    from sage.rings.arith import factorial
     302    from sage.rings.all import GF
     303    from sage.rings.arith import binomial
     304    n = sum(list)
     305    answer = 1
     306    F = GF(p)
     307    n_expansion = expand(n,p)
     308    list_expansion = [expand(k,p) for k in list]
     309    index = 0
     310    while answer != 0 and index < len(n_expansion):
     311        multi = F(1)
     312        partial_sum = 0
     313        for exp in list_expansion:
     314            if index < len(exp):
     315                partial_sum = partial_sum + exp[index]
     316                multi = F(multi * binomial(partial_sum, exp[index]))
     317        answer = F(answer * multi)
     318        index += 1
     319    return answer