Ticket #3397: 3397.patch

File 3397.patch, 153.5 KB (added by jhpalmieri, 11 years ago)

Steenrod algebra calculations

  • sage/algebras/all.py

    # HG changeset patch
    # User J. H. Palmieri <palmieri@math.washington.edu>
    # Date 1213163078 25200
    # Node ID b175ce22e8693ae44c45087c803c113a7043c3f7
    # Parent  2615becf7bdb6c86bbf262dd3ea24a6aa641d745
    Steenrod algebra computations
    
    diff -r 2615becf7bdb -r b175ce22e869 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
    34 
     34from steenrod_algebra import SteenrodAlgebra, steenrod_set_basis, Sq, pst, SteenrodAlgebraElement
     35from steenrod_algebra_bases import steenrod_algebra_basis
     36 
    3537   
    3638def is_R_algebra(Q, R):
    3739    # TODO: do something nontrivial when morphisms are defined.
  • new file sage/algebras/steenrod_algebra.py

    diff -r 2615becf7bdb -r b175ce22e869 sage/algebras/steenrod_algebra.py
    - +  
     1r"""
     2Computations in the Steenrod algebra.
     3
     4AUTHORS:
     5    - John H. Palmieri (2008-06-05: version 0.1.4)
     6
     7There are two standard vector space bases for the mod 2 Steenrod
     8algebra: the Milnor basis and the Serre-Cartan basis.  There are also
     9several other, less well-known, bases.  This package provides for
     10basic algebra in the Steenrod algebra in any of these various bases.
     11
     12The Milnor basis: the elements of the Milnor basis are symbols of the
     13form $\text{Sq}(a,b,c,...)$ where $a,b,c,...$ is a finite list of
     14non-negative integers.  The element $\text{Sq}(0)$ is the identity
     15element.  Trailing zeroes can be ignored, so $\text{Sq}(5,0,0) =
     16\text{Sq}(5)$.  Otherwise, distinct sequences of non-negative integers
     17give distinct basis elements.
     18
     19In his 1958 paper [Mil], Milnor described how to write the product of
     20two such basis elements as a linear combination of basis elements.
     21The method is a little complicated; details are given in the
     22documentation for the file 'steenrod_milnor_multiplication.py'.
     23
     24Some other bases for the Steenrod algebra are described in the papers
     25by Monks [Mon] and Wood [Woo].  These are listed below.  See the
     26documentation for the function 'steenrod_algebra_basis' or for the
     27file 'steenrod_algebra_bases.py' for full descriptions of these
     28bases.
     29
     30In this package, elements in the Steenrod algebra are represented, by
     31default, using the Milnor basis.
     32
     33EXAMPLES:
     34Basic arithmetic:
     35    sage: a = Sq(1,2)
     36    sage: b = Sq(4,1)
     37    sage: z = a + b
     38    sage: z
     39    Sq(1,2) + Sq(4,1)
     40    sage: Sq(4) * Sq(1,2)
     41    Sq(1,1,1) + Sq(2,3) + Sq(5,2)
     42    sage: z**2          # non-negative exponents work as they should
     43    Sq(1,2,1) + Sq(4,1,1)
     44    sage: z**0
     45    Sq(0)
     46   
     47Each element has an 'excess', and if the element is homogeneous, a
     48'degree'.  The excess of $\text{Sq}(i_1,i_2,i_3,...)$ is $i_1 + i_2
     49+ i_3 + ...$, and the excess of a linear combination of such terms
     50is the minimum of their excesses.  The degree of
     51$\text{Sq}(i_1,i_2,i_3,...) is $i_1 + 3 i_2 + 7 i_3 + ... + (2^n-1)
     52i_n + ...$, and the degree of a linear combination of such terms is
     53only defined if the terms all have the same degree:
     54    sage: z = Sq(1,2) + Sq(4,1)
     55    sage: z.degree()
     56    7
     57    sage: (Sq(0,0,1) + Sq(5,3)).degree()
     58    Element is not homogeneous.
     59    sage: Sq(7,2,1).excess()
     60    10
     61    sage: z.excess()
     62    3
     63
     64Elements have a 'weight' in the May filtration, which is related to the
     65'height' function defined by Wall:
     66    sage: Sq(2,1,5).may_weight()
     67    9
     68    sage: Sq(2,1,5).wall_height()
     69    [2, 3, 2, 1, 1]
     70    sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
     71    sage: b.may_weight()
     72    2
     73    sage: b.wall_height()
     74    [0, 0, 1, 1]
     75
     76Since the Steenrod algebra is a Hopf algebra, every element has an
     77antipode.
     78    sage: d = pst(0,3); d
     79    Sq(0,0,1)
     80    sage: d.antipode()
     81    Sq(0,0,1)
     82    sage: Sq(4).antipode()
     83    Sq(1,1) + Sq(4)
     84    sage: (Sq(4) * Sq(2)).antipode()
     85    Sq(6)
     86
     87Applying the antipode twice returns the original element:
     88    sage: y = Sq(8)*Sq(4)
     89    sage: y == (y.antipode()).antipode()
     90    True
     91
     92You can treat elements of the Steenrod algebra like lists of Milnor
     93basis elements:
     94    sage: y = Sq(4) * Sq(1,2); y
     95    Sq(1,1,1) + Sq(2,3) + Sq(5,2)
     96    sage: for m in y: m
     97    Sq(1,1,1)
     98    Sq(2,3)
     99    Sq(5,2)
     100    sage: [(m.degree(),m.excess()) for m in y]
     101    [(11, 3), (11, 5), (11, 7)]
     102   
     103The function pst(s,t) is another way to define elements of the
     104Steenrod algebra: pst(s,t) is the Margolis element $P^{s}_{t}$, the
     105basis element with $2^s$ in position $t$, zeroes elsewhere:
     106    sage: Q2 = pst(0,3)
     107    sage: Q2
     108    Sq(0,0,1)
     109    sage: Q2*Q2
     110    0
     111    sage: pst(1,2) == Sq(2)*Sq(4) + Sq(4)*Sq(2)
     112    True
     113
     114The function 'steenrod_set_basis(basis)' sets the basis to use when
     115printing elements of the Steenrod algebra.  Regardless of the default
     116basis, you can always print an element's representation in any basis
     117using the 'basis' method.
     118
     119The default basis is 'milnor'; the choices are
     120\begin{itemize}
     121\item 'milnor' or 'mil': the Milnor basis.  The Milnor basis consists
     122of symbols of the form $\text{Sq}(m_1, m_2, ..., m_t)$, where each
     123$m_i$ is a non-negative integer and if $t>1$, then $m_t \neq 0$.
     124
     125\item 'serre-cartan', 'serre_cartan', 'sc', 'adem', 'admissible' : the
     126Serre-Cartan basis.  The Serre-Cartan basis consists of 'admissible
     127monomials in the Steenrod squares'.  That is, it consists of monomials
     128$\text{Sq}^{m_1} \text{Sq}^{m_2} ... \text{Sq}^{m_t}$ with $m_i \geq
     1292m_{i+1}$ for each $i$.  The element $\text{Sq}^a$ equals the Milnor
     130element $\text{Sq}(a)$; hence one can represent any Serre-Cartan basis
     131element $\text{Sq}^{m_1} \text{Sq}^{m_2} ... \text{Sq}^{m_t}$ in the
     132Milnor basis by computing the product $\text{Sq}(m_1) \text{Sq}(m_2)
     133...  \text{Sq}(m_t)$ using Milnor multiplication.
     134
     135\item 'wood_y': Wood's Y basis.  For pairs of non-negative integers
     136$(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Y$ basis
     137consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with $(m_i,k_i) >
     138(m_{i+1},k_{i+1})$, in left lex order.
     139
     140\item 'wood_z': Wood's Z basis.  For pairs of non-negative integers
     141$(m,k)$, let $w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}$.  Wood's $Z$ basis
     142consists of monomials $w(m_0,k_0) ... w(m_t, k_t)$ with $(m_i+k_i,m_i)
     143> (m_{i+1}+k_{i+1},m_{i+1})$, in left lex order.
     144
     145\item 'wall': Wall's basis.  For any pair of integers $(m,k)$ with $m
     146\geq k \geq 0$, let $Q^m_k = \text{Sq}^{2^k} \text{Sq}^{2^{k+1}}
     147... \text{Sq}^{2^m}$.  The elements of Wall's basis are monomials
     148$Q^{m_0}_{k_0} ... Q^{m_t}_{k_t}$ with $(m_i, k_i) > (m_{i+1},
     149k_{i+1})$, ordered left lexicographically.
     150
     151The standard way of printing elements of the Wall basis is to write
     152elements in terms of the $Q^m_k$.  If one sets the basis to
     153'wall_long' instead of 'wall', then each $Q^m_k$ is expanded as a
     154product of factors of the form $\text{Sq}^{2^i}$.
     155
     156\item 'arnon_a': Arnon's A basis.  For any pair of integers $(m,k)$
     157with $m \geq k \geq 0$, let $X^m_k = \text{Sq}^{2^m}
     158\text{Sq}^{2^{m-1}} ... \text{Sq}^{2^k}$.  The elements of Arnon's A
     159basis are monomials $X^{m_0}_{k_0} ... X^{m_t}_{k_t}$ with $(m_i, k_i)
     160< (m_{i+1}, k_{i+1})$, ordered left lexicographically.
     161
     162The standard way of printing elements of Arnon's A basis is to write
     163elements in terms of the $X^m_k$.  If one sets the basis to
     164'arnon_a_long' instead of 'arnon_a', then each $X^m_k$ is expanded as a
     165product of factors of the form $\text{Sq}^{2^i}$.
     166
     167\item 'arnon_c': Arnon's C basis.  The elements of Arnon's C basis are
     168monomials of the form $\text{Sq}^{t_1} ... \text{Sq}^{t_m}$ where for
     169each $i$, we have $t_i \leq 2t_{i+1}$ and $2^i | t_{m-i}$.
     170
     171\item 'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz': various
     172P^s_t-bases.  For integers $s \geq 0$ and $t > 0$, the element $P^s_t$
     173is the Milnor basis element $\text{Sq}(0, ..., 0, 2^s, 0, ...)$, with
     174the nonzero entry in position $t$.  To obtain a $P^s_t$-basis, for
     175each set $\{P^{s_1}_{t_1}, ..., P^{s_k}_{t_k}\}$ of (distinct)
     176$P^s_t$'s, one chooses an ordering and forms the resulting monomial.
     177The set of all such monomials then forms a basis, and so one gets a
     178basis by choosing an ordering on each monomial.
     179
     180The strings 'rlex', 'llex', etc., correspond to the following
     181orderings.  These are all 'global' -- they give a global ordering on
     182the $P^s_t$'s, not different orderings depending on the monomial.
     183They order the $P^s_t$'s using the pair of integers $(s,t)$ as
     184follows:
     185
     186\begin{itemize}
     187\item 'rlex': right lexicographic ordering
     188
     189\item 'llex': left lexicographic ordering
     190
     191\item 'deg': ordered by degree, which is the same as left lexicographic
     192ordering on the pair $(s+t,t)$
     193
     194\item 'revz': left lexicographic ordering on the pair $(s+t,s)$, which
     195is the reverse of the ordering used (on elements in the same degrees
     196as the $P^s_t$'s) in Wood's Z basis: 'revz' stands for 'reversed Z'.
     197This is the default: 'pst' is the same as 'pst_revz'.
     198\end{itemize}
     199
     200\item 'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz':
     201various commutator bases.  Let $c_{i,1} = \text{Sq}^{2^i}$, let
     202$c_{i,2} = [c_{i,1}, c_{i+1,1}]$, and inductively define $c_{i,k} =
     203[c_{i,k-1}, c_{i+k-1,1}]$.  Thus $c_{i,k}$ is a $k$-fold iterated
     204commutator of the elements $\text{Sq}^{2^i}$, ...,
     205$\text{Sq}^{2^{i+k-1}}$.  Note that $\dim c_{i,k} = \dim P^i_k$.
     206
     207To obtain a commutator basis, for each set $\{c_{s_1,t_1}, ...,
     208c_{s_k,t_k}\}$ of (distinct) $c_{s,t}$'s, one chooses an ordering and
     209forms the resulting monomial.  The set of all such monomials then
     210forms a basis, and so one gets a basis by choosing an ordering on each
     211monomial.  The strings 'rlex', etc., have the same meaning as for the
     212orderings on $P^s_t$-bases.  As with the $P^s_t$-bases, 'comm_revz' is
     213the default: 'comm' means 'comm_revz'.
     214
     215The commutator bases have alternative representations, obtained by
     216appending 'long' to their names: instead of, say, $c_{2,2}$, the
     217representation is $s_{48}$, indicating the commutator of
     218$\text{Sq}^4$ and $\text{Sq}^8$, and $c_{0,3}$, which is equal to
     219$[[\text{Sq}^1, \text{Sq}^2], \text{Sq}^4]$, is written as $s_{124}$.
     220\end{itemize}
     221
     222Examples of these:
     223    sage: c = Sq(2) * Sq(1); c
     224    Sq(0,1) + Sq(3)
     225    sage: steenrod_set_basis('serre-cartan')
     226    'serre-cartan'
     227    sage: c
     228    Sq^{2} Sq^{1}
     229    sage: c.basis('milnor')
     230    Sq(0,1) + Sq(3)
     231    sage: steenrod_set_basis()   # no argument: print current basis
     232    'serre-cartan'
     233    sage: x = Sq(7,3,1)   # top class in the subalagebra A(2)
     234    sage: x
     235    Sq^{17} Sq^{5} Sq^{1}
     236    sage: steenrod_set_basis('pst')
     237    'pst'
     238    sage: x
     239    P^{0}_{1} P^{0}_{2} P^{1}_{1} P^{0}_{3} P^{1}_{2} P^{2}_{1}
     240    sage: x.basis('milnor')
     241    Sq(7,3,1)
     242    sage: a = Sq(0,0,2)
     243    sage: steenrod_set_basis('comm_revz')
     244    'comm_revz'
     245    sage: a
     246    c_{0,1} c_{1,1} c_{0,3} c_{2,1} + c_{0,2} c_{0,3} c_{2,1} + c_{1,3}
     247    sage: steenrod_set_basis('Beer')
     248    Warning: Beer is not a recognized basis, and is not implemented (unless
     249    you've done it yourself).
     250    'beer'
     251
     252As noted above, several of these ('arnon_a', 'wall', 'comm') have
     253alternate, longer, representations.  These provide ways of expressing
     254elements of the Steenrod algebra in terms of the $\text{Sq}^{2^n}$.
     255    sage: steenrod_set_basis('arnon_a_long')
     256    'arnon_a_long'
     257    sage: Sq(6)
     258    Sq^{1} Sq^{2} Sq^{1} Sq^{2} + Sq^{2} Sq^{4}
     259    sage: steenrod_set_basis('wall_long')
     260    'wall_long'
     261    sage: Sq(6)
     262    Sq^{2} Sq^{1} Sq^{2} Sq^{1} + Sq^{2} Sq^{4}
     263    sage: Sq(6).basis('comm_deg_long')
     264    s_{1} s_{2} s_{12} + s_{2} s_{4}
     265    sage: steenrod_set_basis('milnor')  # reset to the default
     266    'milnor'
     267
     268You can use SteenrodAlgebra(p) to define the mod $p$ Steenrod algebra:
     269    sage: SteenrodAlgebra()   # 2 is the default prime
     270    mod 2 Steenrod algebra
     271
     272You can then test whether elements are contained in the Steenrod algebra:
     273    sage: w = Sq(2) * Sq(4)
     274    sage: w in SteenrodAlgebra(2)
     275    True
     276    sage: w in SteenrodAlgebra(17)
     277    False
     278   
     279Some properties of the Steenrod algebra are available:
     280    sage: A = SteenrodAlgebra(2)
     281    sage: A.ngens()  # number of generators
     282    +Infinity
     283    sage: A.gen(5)   # 5th generator
     284    Sq(32)
     285    sage: A.order()
     286    +Infinity
     287    sage: A.is_finite()
     288    False
     289    sage: A.is_commutative()
     290    False
     291    sage: A.is_noetherian()
     292    False
     293    sage: A.is_integral_domain()
     294    False
     295    sage: A.is_field()
     296    False
     297    sage: A.is_division_algebra()
     298    False
     299    sage: A.category()
     300    Category of algebras over Finite Field of size 2
     301
     302
     303Internal documentation for SteenrodAlgebraElement (for people who want
     304to delve into or extend the code):
     305
     306Attributes for a SteenrodAlgebraElement self:
     307
     308  self.base_field: GF(p), where p is the associated prime
     309 
     310  self._raw: dictionary.  keys are basis names, taken from
     311    '_steenrod_basis_unique_names', and the associated values are
     312    dictionaries themselves; if the dictionary is nonempty, it gives
     313    the representation for that element in the given basis.  If it is
     314    empty, that means that the representation in that basis hasn't
     315    been computed yet.  The representation of an element with respect
     316    to a basis (other than the Milnor basis, which is how elements are
     317    stored internally) isn't computed until requested, either by
     318    calling the method _basis_dictionary('basis_name'), or more
     319    typically, by calling the method basis('basis_name') or setting
     320    the Steenrod algebra basis to 'basis' and then printing the
     321    element.
     322   
     323    The dictionaries are defined as follows.  In the Milnor basis, for
     324    example, since monomials are of the form Sq(a,b,c,...), then
     325    monomials are stored as tuples of integers (a,b,c,...).  Thus if y
     326    = Sq(5,3) + Sq(0,0,2), then y._raw['milnor'] is {{(0, 0, 2): 1, (5,
     327    3): 1}.  (The 1's following the colons are the coefficients of the
     328    monomials associated to the tuples.)  Each basis has its own
     329    representation as a dictionary; Arnon's C basis represents basis
     330    elements as tuples of integers, just like the Milnor basis and the
     331    Serre-Cartan basis, while the other bases represent basis elements
     332    as tuples of pairs of integers.  From the descriptions of the
     333    bases given in the file 'steenrod_algebra_bases.py', it should be
     334    clear how to associate a tuple of pairs of integers to a basis
     335    element.  See also the function 'string_rep'.
     336
     337    When the element is initially defined by calling Sq() or pst() or
     338    SteenrodAlgebraElement(), typically only the 'milnor' dictionary
     339    is non-empty, while if the element is defined by the function
     340    'steenrod_algebra_basis', its dictionary for the given basis is
     341    also initialized correctly.  For example:
     342        sage: B = steenrod_algebra_basis(6,'adem'); B
     343        (Sq(6), Sq(3,1), Sq(0,2) + Sq(3,1) + Sq(6))
     344        sage: x = B[1]; x
     345        Sq(3,1)
     346        sage: x._raw
     347        {'milnor': {(3, 1): 1}, 'pst_revz': {}, 'wall': {}, 'pst_rlex': {},
     348        'comm_rlex': {}, 'pst_llex': {}, 'pst_deg': {}, 'comm_revz': {},
     349        'arnona': {}, 'comm_llex': {}, 'arnonc': {}, 'woody': {}, 'woodz': {},
     350        'serre-cartan': {(5, 1): 1}, 'comm_deg': {}}
     351       
     352    Note that the keys 'milnor' and 'serre-cartan' (a synonym for
     353    'adem') have nonempty associated values.
     354   
     355    When any element is converted to another basis (by changing the
     356    basis and then printing the element), its dictionary for that
     357    basis gets stored, as well:
     358        sage: steenrod_set_basis('arnona')
     359        'arnona'
     360        sage: x
     361        X^{0}_{0} X^{1}_{0} X^{1}_{1}
     362        sage: x._raw
     363        {'milnor': {(3, 1): 1}, 'pst_revz': {}, 'wall': {}, 'pst_rlex': {},
     364        'comm_rlex': {}, 'pst_llex': {}, 'pst_deg': {}, 'comm_revz': {},
     365        'arnona': {((0, 0), (1, 0), (1, 1)): 1}, 'comm_llex': {}, 'arnonc': {},
     366        'woody': {}, 'woodz': {}, 'serre-cartan': {(5, 1): 1}, 'comm_deg': {}}
     367        sage: steenrod_set_basis('milnor')
     368        'milnor'
     369
     370Methods for a SteenrodAlgebraElement self:
     371
     372Most of these are self-explanatory.
     373
     374    _mul_: multiply two elements.  This is done using Milnor
     375    multiplication, the code for which is in a separate file,
     376    'steenrod_milnor_multiplication'.  In a long computation, it seems
     377    that a lot of time is spent here, so one way to speed things up
     378    would be to optimize the Milnor multiplication routine.
     379
     380    _basis_dictionary: compute the dictionary of the element with
     381    respect to the given basis.  This is basically done by doing a
     382    basis conversion from the Milnor basis to the given basis.  There
     383    are two parts to this function; first, some elements (e.g.,
     384    Sq(2^n)) may be easy to convert directly.  This is done one basis
     385    at a time, and so takes up most of the lines of code.  If the
     386    element is not recognizable as being easy to convert, then the
     387    function 'milnor_convert' from the file 'steenrod_algebra_bases'
     388    is called.  This does linear algebra: computes the Milnor basis
     389    and the new basis in the appropriate dimension, computes the
     390    change-of-basis matrix, etc.
     391
     392    basis: display the element in the given basis.
     393
     394    _repr_ and _latex_ call the function string_rep, which has cases
     395    depending on the basis.
     396
     397If you want to implement a new basis for the Steenrod algebra:
     398
     399    In this file ('steenrod_algebra.py'):
     400
     401        add a variable (like '_steenrod_milnor_basis_names') with the
     402        synonyms for basis, and include this variable among all of the
     403        others in 'steenrod_set_basis'
     404
     405        add name of basis to '_steenrod_basis_unique_names'
     406
     407        add functionality to basis and string_rep, and add a
     408        BASIS_mono_to_string function
     409
     410    In the file 'steenrod_algebra_bases.py':
     411
     412        add appropriate lines to 'milnor_convert' and 'steenrod_algebra_basis'
     413
     414        add a function to compute the basis in a given dimension (to be
     415        called by 'steenrod_algebra_basis')
     416
     417   
     418REFERENCES:
     419    [Mil] J. W. Milnor, "The Steenrod algebra and its dual," Ann. of Math.
     420          (2) \textbf{67} (1958), 150--171.
     421    [Mon] K. G. Monks, "Change of basis, monomial relations, and $P^s_t$
     422          bases for the Steenrod algebra," J. Pure Appl. Algebra 125 (1998),
     423          no. 1-3, 235--260.
     424    [Woo] R. M. W. Wood, "Problems in the Steenrod algebra," Bull. London
     425          Math. Soc. 30 (1998), no. 5, 449--517.
     426"""
     427
     428#*****************************************************************************
     429#       Copyright (C) 2008 William Stein <wstein@gmail.com>
     430#       Copyright (C) 2008 John H. Palmieri <palmieri@math.washington.edu>
     431#  Distributed under the terms of the GNU General Public License (GPL)
     432#*****************************************************************************
     433
     434from sage.rings.ring import Algebra
     435from sage.algebras.algebra_element import AlgebraElement
     436from sage.rings.arith import is_prime
     437from sage.structure.parent_gens import ParentWithGens
     438from sage.structure.element import RingElement
     439from sage.rings.all import GF
     440from sage.misc.functional import parent
     441from sage.rings.integer import Integer
     442from sage.rings.infinity import Infinity
     443
     444# Default prime for working with the Steenrod algebra.  Right now,
     445# things are only implemented when p=2.
     446steenrod_prime = 2
     447
     448
     449class SteenrodAlgebra(Algebra):
     450    r"""
     451    The mod $p$ Steenrod algebra.
     452
     453    Caveat: this not really implemented when p is odd.
     454
     455    EXAMPLES:
     456        sage: SteenrodAlgebra()   # 2 is the default prime
     457        mod 2 Steenrod algebra
     458        sage: SteenrodAlgebra(5)
     459        mod 5 Steenrod algebra
     460
     461    Some properties of the Steenrod algebra are available:
     462        sage: A = SteenrodAlgebra(2)
     463        sage: A.ngens()  # number of generators
     464        +Infinity
     465        sage: A.gen(5)   # 5th generator
     466        Sq(32)
     467        sage: A.order()
     468        +Infinity
     469        sage: A.is_finite()
     470        False
     471        sage: A.is_commutative()
     472        False
     473        sage: A.is_noetherian()
     474        False
     475        sage: A.is_integral_domain()
     476        False
     477        sage: A.is_field()
     478        False
     479        sage: A.is_division_algebra()
     480        False
     481        sage: A.category()
     482        Category of algebras over Finite Field of size 2
     483    """
     484   
     485
     486    def __init__(self, p=None):
     487        """
     488        INPUT:
     489            p -- positive prime integer
     490       
     491        OUTPUT:
     492            mod p Steenrod algebra
     493
     494        EXAMPLES:
     495            sage: SteenrodAlgebra()   # 2 is the default prime
     496            mod 2 Steenrod algebra
     497            sage: SteenrodAlgebra(5)
     498            mod 5 Steenrod algebra
     499        """
     500        if p is None: p = steenrod_prime
     501        if is_prime(p):
     502            self.prime = p
     503            ParentWithGens.__init__(self, GF(p))
     504        else:
     505            raise ValueError, "%s is not prime." % p
     506
     507
     508    def _repr_(self):
     509        """
     510        Printed representation of the Steenrod algebra.
     511
     512        EXAMPLES:
     513            sage: SteenrodAlgebra(3)
     514            mod 3 Steenrod algebra
     515            sage: B = SteenrodAlgebra(2003)
     516            sage: B
     517            mod 2003 Steenrod algebra
     518            sage: B._repr_()
     519            'mod 2003 Steenrod algebra'
     520        """
     521        return "mod %d Steenrod algebra" % self.prime
     522   
     523
     524    def _latex_(self):
     525        """
     526        LaTeX representation of the Steenrod algebra.
     527       
     528        EXAMPLES:
     529            sage: C = SteenrodAlgebra(3)
     530            sage: C
     531            mod 3 Steenrod algebra
     532            sage: C._latex_()
     533            '\\mathcal{A}_{3}'
     534        """
     535        return "\\mathcal{A}_{%s}" % self.prime
     536   
     537
     538    def ngens(self):
     539        """
     540        Number of generators of the Steenrod algebra.
     541
     542        This returns infinity, since the Steenrod algebra is infinitely
     543        generated.
     544
     545        EXAMPLES:
     546            sage: A = SteenrodAlgebra(3)
     547            sage: A.ngens()
     548            +Infinity
     549        """
     550        return Infinity
     551
     552
     553    def gen(self, i=0):
     554        """
     555        The ith generator of the Steenrod algebra.
     556
     557        INPUT:
     558            i -- non-negative integer
     559
     560        OUTPUT:
     561            The ith generator of the Steenrod algebra: Sq(2**i) at the prime 2,
     562            P(p**i) at odd primes
     563
     564        EXAMPLES:
     565            sage: A = SteenrodAlgebra(2)
     566            sage: A.gen(4)
     567            Sq(16)
     568        """
     569        if not isinstance(i, (Integer, int)) and i >= 0:
     570            raise ValueError, "%s is not a non-negative integer" % i
     571        return SteenrodAlgebraElement({(self.prime**i,): 1})
     572
     573
     574    def __eq__(self, right):
     575        """
     576        Two Steenrod algebras are equal <=> their associated primes are equal.
     577
     578        EXAMPLES:
     579            sage: A = SteenrodAlgebra(2)
     580            sage: B = SteenrodAlgebra(2)
     581            sage: A == B
     582            True
     583            sage: A is B
     584            False
     585            sage: C = SteenrodAlgebra(17)
     586            sage: A == C
     587            False
     588        """
     589        return type(self) == type(right) and self.prime == right.prime
     590   
     591
     592    def __call__(self, x):
     593        if isinstance(x, SteenrodAlgebraElement) and x.parent() is self:
     594            return x
     595        else:
     596            return SteenrodAlgebraElement(x,self.prime)
     597
     598
     599    def _coerce_impl(self, x):
     600        """
     601        Return the coercion of x into this Steenrod algebra.
     602
     603        INPUT:
     604            x -- a SteenrodAlgebraElement or an element of F_p
     605
     606        OUTPUT:
     607            coercion of x into the Steenrod algebra
     608       
     609        EXAMPLES:
     610            sage: A = SteenrodAlgebra(); A
     611            mod 2 Steenrod algebra
     612            sage: A(1)     # convert 1 to an element of A
     613            Sq(0)
     614            sage: A(Sq(3))
     615            Sq(3)
     616       
     617        The algebras that coerce into the mod p Steenrod algebra are:
     618       
     619           * the mod p Steenrod algebra
     620           * its base field GF(p)
     621        """
     622        return self._coerce_try(x, [self.base_ring()])
     623       
     624
     625    def __contains__(self, x):
     626        """
     627        Instances of the class SteenrodAlgebraElement with the same
     628        prime are contained in the Steenrod algebra.
     629
     630        EXAMPLES:
     631            sage: A = SteenrodAlgebra()
     632            sage: x = Sq(2) * Sq(1); x
     633            Sq(0,1) + Sq(3)
     634            sage: x in A
     635            True
     636            sage: x in SteenrodAlgebra(5)
     637            False
     638        """
     639        return isinstance(x, SteenrodAlgebraElement) and x.parent() == self
     640
     641
     642    def is_commutative(self):
     643        """
     644        The Steenrod algebra is not commutative.
     645       
     646        EXAMPLES:
     647            sage: A = SteenrodAlgebra(3)
     648            sage: A.is_commutative()
     649            False
     650        """
     651        return False
     652
     653
     654    def is_finite(self):
     655        """
     656        The Steenrod algebra is not finite.
     657       
     658        EXAMPLES:
     659            sage: A = SteenrodAlgebra(3)
     660            sage: A.is_finite()
     661            False
     662        """
     663        return False
     664
     665
     666    def order(self):
     667        """
     668        The Steenrod algebra has infinite order.
     669       
     670        EXAMPLES:
     671            sage: A = SteenrodAlgebra(3)
     672            sage: A.order()
     673            +Infinity
     674        """
     675        return Infinity
     676
     677
     678    def is_division_algebra(self):
     679        """
     680        The Steenrod algebra is not a division algebra.
     681       
     682        EXAMPLES:
     683            sage: A = SteenrodAlgebra(3)
     684            sage: A.is_division_algebra()
     685            False
     686        """
     687        return False
     688   
     689
     690    def is_field(self):
     691        """
     692        The Steenrod algebra is not a field.
     693       
     694        EXAMPLES:
     695            sage: A = SteenrodAlgebra(3)
     696            sage: A.is_field()
     697            False
     698        """
     699        return False
     700   
     701
     702    def is_integral_domain(self):
     703        """
     704        The Steenrod algebra is not an integral domain.
     705       
     706        EXAMPLES:
     707            sage: A = SteenrodAlgebra(3)
     708            sage: A.is_integral_domain()
     709            False
     710        """
     711        return False
     712   
     713
     714    def is_noetherian(self):
     715        """
     716        The Steenrod algebra is not noetherian.
     717       
     718        EXAMPLES:
     719            sage: A = SteenrodAlgebra(3)
     720            sage: A.is_noetherian()
     721            False
     722        """
     723        return False
     724       
     725
     726    def category(self):
     727        """
     728        The Steenrod algebra is an algebra over F_p.
     729       
     730        EXAMPLES:
     731            sage: A = SteenrodAlgebra(3)
     732            sage: A.category()
     733            Category of algebras over Finite Field of size 3
     734        """
     735        from sage.categories.category_types import Algebras
     736        return Algebras(GF(self.prime))
     737
     738
     739def check_and_trim(nums):
     740    """
     741    Check that list or tuple consists of non-negative integers, and
     742    strip trailing zeroes.
     743
     744    INPUT:
     745        nums -- a list or tuple
     746
     747    OUTPUT:
     748        If nums contains anything other than a non-negative integer,
     749        raise an exception.  Otherwise, return a new list or tuple, obtained
     750        from nums by omitting any zeroes from the end.
     751       
     752    EXAMPLES:
     753        sage: from sage.algebras.steenrod_algebra import check_and_trim
     754        sage: check_and_trim([3,4,1])
     755        [3, 4, 1]
     756        sage: a=[3,2,1,0,0]
     757        sage: check_and_trim(a)
     758        [3, 2, 1]
     759        sage: a    # check_and_trim doesn't affect its input
     760        [3, 2, 1, 0, 0]
     761        sage: check_and_trim([0]*127)
     762        []
     763        sage: check_and_trim((1,2,3,4,0,0,0))  # works on tuples, too
     764        (1, 2, 3, 4)
     765       
     766    If input contains anything other than non-negative integer, return
     767    an error.  The right-most problematic entry is identified.
     768    """
     769    index = len(nums)
     770    for i in range(index-1, -1, -1):
     771        if nums[i] == 0 and i == index - 1:
     772            index = i
     773        if not (isinstance(nums[i], (Integer, int)) and nums[i] >= 0):
     774            raise ValueError, "%s is not a non-negative integer" % nums[i]
     775    return nums[:index]
     776
     777
     778# The variable 'steenrod_basis' is used for determining the output
     779# format for manipulations in the Steenrod algebra.  The default value
     780# is 'milnor', and this can be changed using the function
     781# 'steenrod_set_basis'.
     782steenrod_basis = 'milnor'
     783
     784# These are the recognized basis names.
     785_steenrod_serre_cartan_basis_names = ['serre_cartan', 'serre-cartan', 'sc', \
     786                                         'adem', 'admissible']
     787_steenrod_milnor_basis_names = ['milnor', 'mil']
     788_steenrod_woodY_basis_names = ['woody', 'wood_y', 'wood-y']
     789_steenrod_woodZ_basis_names = ['woodz', 'wood_z', 'wood-z']
     790_steenrod_arnonA_basis_names = ['arnona', 'arnon_a', 'arnon-a',
     791                               'arnona_long', 'arnon_a_long', 'arnon-a-long']
     792_steenrod_wall_basis_names = ['wall', 'wall_long', 'wall-long']
     793_steenrod_arnonC_basis_names = ['arnonc', 'arnon_c', 'arnon-c']
     794_steenrod_pst_basis_names = ['pst', 'pst_', 'pst_rlex', 'pst-rlex', 'pstrlex', \
     795                                'pst_llex', 'pst-llex', 'pstllex', \
     796                                'pst_deg', 'pst-deg', 'pstdeg', \
     797                                'pst_revz', 'pst-revz', 'pstrevz']
     798_steenrod_commutator_basis_names = ['commutator', 'comm', \
     799                                       'commutator_long', 'commutator-long', \
     800                                       'comm_long', 'comm-long', \
     801                                       'comm_rlex', 'comm-rlex',
     802                                       'comm_rlex_long', 'comm-rlex-long',
     803                                       'comm_llex', 'comm-llex',
     804                                       'comm_llex_long', 'comm-llex-long',
     805                                       'comm_deg', 'comm-deg',
     806                                       'comm_deg_long', 'comm-deg-long',
     807                                       'comm_revz', 'comm-revz',
     808                                       'comm_revz_long', 'comm-revz-long']
     809
     810# These are for internal use only; they are the names used in the code
     811# to represent each basis.
     812_steenrod_basis_unique_names =  ('serre-cartan', 'milnor', 'woody', \
     813                                      'woodz', 'arnona', 'arnonc', 'wall', \
     814                                      'pst_rlex', 'pst_llex', 'pst_deg', \
     815                                      'pst_revz', 'comm_rlex', 'comm_llex', \
     816                                      'comm_deg', 'comm_revz')
     817
     818
     819def steenrod_set_basis(string=None):
     820    r"""
     821    Set the default basis for Steenrod algebra computations
     822
     823    INPUT:
     824        string (optional) -- 'milnor' or 'mil' for the Milnor basis.
     825        'serre-cartan', 'serre_cartan', 'sc', 'adem', 'admissible' for the
     826            Serre-Cartan basis.
     827        'wood_y' for Wood's Y basis.
     828        'wood_z' for Wood's Z basis.
     829        'wall' for Wall's basis.
     830        'wall_long' for Wall's basis, alternate representation
     831        'arnon_a' for Arnon's A basis.
     832        'arnon_a_long' for Arnon's A basis, alternate representation.
     833        'arnon_c' for Arnon's C basis.
     834        'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz' for various
     835            P^s_t-bases.
     836        'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz' for various
     837            commutator bases.
     838        'comm_long', 'comm_rlex_long', etc., for commutator bases, alternate
     839            representations.
     840
     841    OUTPUT:
     842        Name of basis.  If the argument 'string' is present, set the
     843        basis to be string, and return that, converted to lowercase.
     844        If it is omitted, return the name of the current basis.
     845
     846    See documentation for the function 'steenrod_algebra_basis' for
     847    descriptions of the different bases.
     848
     849    EXAMPLES:
     850        sage: c = Sq(2) * Sq(1); c
     851        Sq(0,1) + Sq(3)
     852        sage: steenrod_set_basis('serre-cartan')
     853        'serre-cartan'
     854        sage: steenrod_set_basis('SeRrE-caRTAN')
     855        'serre-cartan'
     856        sage: c
     857        Sq^{2} Sq^{1}
     858        sage: steenrod_set_basis()   # no argument: print basis
     859        'serre-cartan'
     860        sage: x = Sq(7,3,1)   # top class in A(2)
     861        sage: x
     862        Sq^{17} Sq^{5} Sq^{1}
     863        sage: steenrod_set_basis('pst')
     864        'pst'
     865        sage: x
     866        P^{0}_{1} P^{0}_{2} P^{1}_{1} P^{0}_{3} P^{1}_{2} P^{2}_{1}
     867        sage: steenrod_set_basis('Beer')
     868        Warning: Beer is not a recognized basis, and is not implemented (unless
     869        you've done it yourself).
     870        'beer'
     871
     872    The 'alternate' representations provide ways of expressing elements
     873    of the Steenrod algebra in terms of the elements $\text{Sq}^{2^n}$.
     874        sage: steenrod_set_basis('arnon_a_long')
     875        'arnon_a_long'
     876        sage: Sq(6)
     877        Sq^{1} Sq^{2} Sq^{1} Sq^{2} + Sq^{2} Sq^{4}
     878        sage: steenrod_set_basis('wall_long')
     879        'wall_long'
     880        sage: Sq(6)
     881        Sq^{2} Sq^{1} Sq^{2} Sq^{1} + Sq^{2} Sq^{4}
     882        sage: steenrod_set_basis('comm_long')
     883        'comm_long'
     884        sage: Sq(6)
     885        s_{1} s_{12} s_{2} + s_{2} s_{4}
     886        sage: steenrod_set_basis('milnor')  # reset to the default
     887        'milnor'
     888    """
     889    global steenrod_basis
     890    if string is not None:
     891        if string.lower() not in _steenrod_serre_cartan_basis_names \
     892                + _steenrod_milnor_basis_names + _steenrod_woodY_basis_names \
     893                + _steenrod_woodZ_basis_names + _steenrod_wall_basis_names \
     894                + _steenrod_arnonA_basis_names + _steenrod_arnonC_basis_names \
     895                + _steenrod_pst_basis_names + _steenrod_commutator_basis_names:
     896            print "Warning: %s is not a recognized basis, and " % string + \
     897                "is not implemented (unless you've done it yourself)."
     898        steenrod_basis = string.lower()
     899    return steenrod_basis
     900
     901
     902# This dictionary is for caching Steenrod algebras at various primes,
     903# to make sure that SteenrodAlgebraElements defined at the same prime
     904# have the same parent.
     905_steenrod_algebras = {}
     906
     907class SteenrodAlgebraElement(AlgebraElement):
     908    r"""
     909    Element of the mod p Steenrod algebra.
     910
     911    Only the mod 2 Steenrod algebra has been implemented, so far.
     912
     913    Use the function 'Sq' to define these, as in 'w=Sq(4,3,3)'
     914    or 'z=Sq(1,2)+Sq(4,1)' or 'q=Sq(8)*Sq(4) + Sq(12)'.
     915
     916    EXAMPLES:
     917        sage: w = Sq(4,3,3)
     918        sage: w
     919        Sq(4,3,3)
     920
     921    The function 'Sq', together with addition, provides an easy way to
     922    define elements:
     923        sage: b = Sq(3) + Sq(0,1)
     924        sage: b
     925        Sq(0,1) + Sq(3)
     926        sage: b.degree()
     927        3
     928        sage: (Sq(2,1) + Sq(0,1)).degree()
     929        Element is not homogeneous.
     930        sage: b.excess()
     931        1
     932
     933    Multiplication and (non-negative) exponents work as they should:
     934        sage: c = Sq(3)
     935        sage: c * c
     936        Sq(3,1)
     937        sage: c ** 2
     938        Sq(3,1)
     939        sage: c ** 0
     940        Sq(0)
     941
     942    Printed representations, different bases.  The Milnor basis is how
     943    things are written, by default:
     944        sage: b = Sq(3) + Sq(0,1)
     945        sage: b
     946        Sq(0,1) + Sq(3)
     947        sage: latex(b)
     948        \text{Sq}(0,1) + \text{Sq}(3)
     949        sage: steenrod_set_basis('adem')
     950        'adem'
     951        sage: b
     952        Sq^{2} Sq^{1}
     953        sage: steenrod_set_basis('wood_y')
     954        'wood_y'
     955        sage: c = Sq(4) ** 2; c
     956        Sq^{7} Sq^{1} + Sq^{6} Sq^{2}
     957        sage: c.basis('wall')
     958        Q^{2}_{0} Q^{0}_{0} + Q^{2}_{1} Q^{1}_{1}
     959       
     960    Iteration: elements of the Steenrod algebra can be viewed as
     961    being lists of basis elements, and one can loop over them:
     962        sage: steenrod_set_basis('milnor')
     963        'milnor'
     964        sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     965        sage: z
     966        Sq(3,0,1) + Sq(4,2) + Sq(7,1)
     967        sage: for m in z: print m
     968        Sq(3,0,1)
     969        Sq(4,2)
     970        Sq(7,1)
     971        sage: [m.excess() for m in z]
     972        [4, 6, 8]
     973        sage: for m in z: m*m
     974        0
     975        Sq(4,3,1) + Sq(7,2,1)
     976        0
     977
     978    Other operations and functions:
     979        sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     980        sage: z.is_unit()    # z is not a unit
     981        False
     982        sage: u = 1 + Sq(3,1)
     983        sage: u == Sq(0) + Sq(3,1)
     984        True
     985        sage: u.is_unit()
     986        True
     987        sage: u.additive_order()
     988        2
     989    """
     990   
     991    def __init__(self, poly, p=None):
     992        """
     993        INPUT:
     994            poly -- dictionary with entries of form (monomial: coefficient)
     995            Each coefficient is in GF(p), and each monomial is a tuple
     996            of non-negative integers (a, b, c, ...), corresponding to
     997            the Milnor basis element Sq(a, b, c, ...).
     998
     999            Alternatively, poly can be an integer n, in which case it
     1000            is viewed as being in the field GF(p): the resulting
     1001            element is n * Sq(0).
     1002           
     1003            p -- positive prime number (default steenrod_prime)
     1004
     1005        EXAMPLES:
     1006            sage: SteenrodAlgebraElement({(1,2,3): 1}, 2)
     1007            Sq(1,2,3)
     1008            sage: SteenrodAlgebraElement({(1,2,3): 4}, 2)
     1009            0
     1010
     1011        The input can also be an integer, in which case it is treated as a
     1012        multiple, mod p, of the unit element Sq(0):
     1013            sage: SteenrodAlgebraElement(3,2)
     1014            Sq(0)
     1015            sage: SteenrodAlgebraElement(6)   # p=2 is the default prime
     1016            0
     1017        """
     1018        if p is None: p = steenrod_prime
     1019        if is_prime(p):
     1020            if _steenrod_algebras.has_key(p):
     1021                alg = _steenrod_algebras[p]
     1022            else:
     1023                _steenrod_algebras[p] = SteenrodAlgebra(p)
     1024                alg = _steenrod_algebras[p]
     1025            if p == 2:
     1026                RingElement.__init__(self, alg)
     1027                F = parent(self).base_ring()
     1028                self.base_field = F
     1029                if isinstance(poly, dict):
     1030                    new_poly = {}
     1031                    for mono in poly:
     1032                        trimmed = check_and_trim(mono)
     1033                        if new_poly.has_key(trimmed):
     1034                            coeff = F(poly[mono] + new_poly[trimmed])
     1035                        else:
     1036                            coeff = F(poly[mono])
     1037                        if not coeff.is_zero():
     1038                            new_poly[trimmed] = coeff
     1039                    self._raw = {}
     1040                    for basis in _steenrod_basis_unique_names:
     1041                        self._raw[basis] = {}
     1042                    self._raw['milnor'] = new_poly
     1043                elif isinstance(poly, (Integer, int)) or poly.parent() == GF(p):
     1044                    if F(poly) != 0:
     1045                        new_poly = {(): F(poly)}
     1046                    else:
     1047                        new_poly = {}
     1048                    self._raw = {}
     1049                    for basis in _steenrod_basis_unique_names:
     1050                        self._raw[basis] = new_poly
     1051                elif isinstance(poly, SteenrodAlgebraElement):
     1052                    self._raw = poly._raw
     1053                else:
     1054                    raise ValueError, "%s is not of the correct form" % poly
     1055            else:
     1056                raise NotImplementedError, "Only the mod 2 Steerod algebra has been implemented."
     1057        else:
     1058            raise ValueError, "%s is not prime." % p
     1059   
     1060
     1061    def is_unit(self):
     1062        """
     1063        True if element has Sq(0) as a summand, False otherwise.
     1064
     1065        EXAMPLES:
     1066            sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     1067            sage: z.is_unit()
     1068            False
     1069            sage: u = 1 + Sq(3,1)
     1070            sage: u == Sq(0) + Sq(3,1)
     1071            True
     1072            sage: u.is_unit()
     1073            True
     1074        """
     1075        if self._raw['milnor'].has_key(()):
     1076            return True
     1077        else:
     1078            return False
     1079
     1080    def is_nilpotent(self):
     1081        """
     1082        True if element is not a unit, False otherwise.
     1083
     1084        EXAMPLES:
     1085            sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
     1086            sage: z.is_nilpotent()
     1087            True
     1088            sage: u = 1 + Sq(3,1)
     1089            sage: u == Sq(0) + Sq(3,1)
     1090            True
     1091            sage: u.is_nilpotent()
     1092            False
     1093        """
     1094        return not self.is_unit()
     1095
     1096
     1097    def _add_(self, other):
     1098        """
     1099        Addition for elements of the Steenrod algebra.
     1100
     1101        EXAMPLES:
     1102            sage: a = Sq(3,1) + Sq(6)
     1103            sage: b = Sq(0,2)
     1104            sage: c = Sq(6) + Sq(0,2)
     1105            sage: a + b
     1106            Sq(0,2) + Sq(3,1) + Sq(6)
     1107            sage: b + c
     1108            Sq(6)
     1109        """
     1110        F = self.base_field
     1111        poly1 = self._raw['milnor']
     1112        poly2 = other._raw['milnor']
     1113        result = poly1.copy()
     1114        for mono in poly2:
     1115            if result.has_key(mono):
     1116                coeff = F(result[mono] + poly2[mono])
     1117            else:
     1118                coeff = F(poly2[mono])
     1119            if coeff == 0:
     1120                del result[mono]
     1121            else:
     1122                result[mono] = coeff
     1123        sum = SteenrodAlgebraElement(result)
     1124        return sum
     1125
     1126
     1127    def _neg_(self):
     1128        """
     1129        Multiply every coefficient by the base field element -1.
     1130        """
     1131        p = self.parent().prime
     1132        if p == 2:
     1133            return self
     1134        else:
     1135            F = self.base_field
     1136            dict = self._raw['milnor']
     1137            for mono in dict:
     1138                dict[mono] = F(-dict[mono])
     1139            return SteenrodAlgebraElement(dict,p)
     1140
     1141
     1142    def _sub_(self, other):
     1143        """
     1144        Subtraction for elements of the Steenrod algebra.
     1145        """
     1146        return self._add_(other._neg_())
     1147
     1148
     1149    def _mul_(self, other):
     1150        """
     1151        Multiplication for elements of the Steenrod algebra.
     1152
     1153        EXAMPLES:
     1154            sage: Sq(2) * Sq(1)
     1155            Sq(0,1) + Sq(3)
     1156            sage: Sq(0) * (Sq(6,2) + Sq(9,1))
     1157            Sq(6,2) + Sq(9,1)
     1158            sage: 1 * (Sq(6,2) + Sq(9,1))
     1159            Sq(6,2) + Sq(9,1)
     1160            sage: 4 * (Sq(6,2) + Sq(9,1))
     1161            0
     1162        """
     1163        from steenrod_milnor_multiplication import milnor_multiplication
     1164       
     1165        F = self.base_field
     1166        poly1 = self._raw['milnor']
     1167        poly2 = other._raw['milnor']
     1168        result = {}
     1169        for mono1 in poly1:
     1170            for mono2 in poly2:
     1171                if len(mono1) == 0:    # multiplying by one
     1172                    if result.has_key(mono2):
     1173                        result[mono2] = F(result[mono2] + poly2[mono2])
     1174                    else:
     1175                        result[mono2] = F(poly2[mono2])
     1176                elif len(mono2) == 0:    # multiplying by one
     1177                    if result.has_key(mono1):
     1178                        result[mono1] = F(result[mono1] + poly1[mono1])
     1179                    else:
     1180                        result[mono1] = F(poly1[mono1])
     1181                else:
     1182                    new_dict = milnor_multiplication(mono1, mono2)
     1183                    for new_mono in new_dict:
     1184                        if result.has_key(new_mono):
     1185                            result[new_mono] = F(result[new_mono] + poly1[mono1]*poly2[mono2])
     1186                        else:
     1187                            result[new_mono] = F(poly1[mono1]*poly2[mono2])
     1188        return SteenrodAlgebraElement(result)
     1189
     1190
     1191    def __eq__(self,other):
     1192        """
     1193        Two elements are equal if their difference is zero.
     1194        """
     1195        difference = self - other
     1196        return len(difference._raw['milnor']) == 0
     1197
     1198    def __ne__(self,other):
     1199        return not self.__eq__(other)
     1200
     1201
     1202    def _basis_dictionary(self,basis):
     1203        r"""
     1204        Dictionary of terms of the form (mono: coeff), where mono
     1205        is a monomial in the given basis.
     1206
     1207        INPUT:
     1208            basis -- string, basis in which to work
     1209
     1210        EXAMPLES:
     1211            sage: c = Sq(2) * Sq(1)
     1212            sage: c._basis_dictionary('milnor')
     1213            {(0, 1): 1, (3,): 1}
     1214            sage: steenrod_set_basis('milnor')
     1215            'milnor'
     1216            sage: c
     1217            Sq(0,1) + Sq(3)
     1218            sage: c._basis_dictionary('serre-cartan')
     1219            {(2, 1): 1}
     1220            sage: c.basis('serre-cartan')
     1221            Sq^{2} Sq^{1}
     1222            sage: d = pst(0,3)
     1223            sage: d._basis_dictionary('arnonc')
     1224            {(7,): 1, (2, 5): 1, (4, 3): 1, (4, 2, 1): 1}
     1225            sage: d.basis('arnonc')
     1226            Sq^{2} Sq^{5} + Sq^{4} Sq^{2} Sq^{1} + Sq^{4} Sq^{3} + Sq^{7}
     1227
     1228        Implementation: to compute this, take the Milnor representation
     1229        and change bases.  Store the result in self._raw[basis], for later
     1230        use; this way, an element only needs to be converted once.
     1231        """
     1232        if basis in _steenrod_milnor_basis_names:
     1233            return self._raw['milnor']
     1234        from steenrod_algebra_bases import milnor_convert
     1235        import math
     1236        def is_power_of_two(n):
     1237            while n != 0 and n%2 == 0:
     1238                n = n >> 1
     1239            return n == 1
     1240       
     1241        if self._raw.has_key(basis) and len(self._raw[basis])>0:
     1242            return self._raw[basis]
     1243        else:
     1244            dict = {}
     1245            for mono in self._raw['milnor']:
     1246                converted = False
     1247                if dict.has_key(mono):
     1248                    old_coeff = dict[mono]
     1249                else:
     1250                    old_coeff = 0
     1251                new_coeff = old_coeff + self._raw['milnor'][mono]
     1252                if len(mono) == 0:   # length 0: no conversion
     1253                    if new_coeff != 0:
     1254                        dict[mono] = new_coeff
     1255                    else:
     1256                        del dict[mono]
     1257                    converted = True
     1258                elif basis in _steenrod_serre_cartan_basis_names:
     1259                    if len(mono) == 1:   # length 1: Sq(n) = Sq^{n}, so no conversion
     1260                        if dict.has_key(mono):
     1261                            new_coeff = dict[mono] + self._raw['milnor'][mono]
     1262                            if new_coeff != 0:
     1263                                dict[mono] = new_coeff
     1264                            else:
     1265                                del dict[mono]
     1266                        else:
     1267                            dict[mono] = self._raw['milnor'][mono]
     1268                        converted = True
     1269                elif basis in _steenrod_woodY_basis_names:
     1270                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1271                        if new_coeff != 0:
     1272                            dict[((int(math.log(mono[0],2)),0),)] = new_coeff
     1273                        else:
     1274                            del dict[((int(math.log(mono[0],2)),0),)]
     1275                        converted = True
     1276                elif basis in _steenrod_woodZ_basis_names:
     1277                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1278                        if new_coeff != 0:
     1279                            dict[((int(math.log(mono[0],2)),0),)] = new_coeff
     1280                        else:
     1281                            del dict[((int(math.log(mono[0],2)),0),)]
     1282                        converted = True
     1283                elif basis in _steenrod_wall_basis_names:
     1284                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1285                        m = int(math.log(mono[0],2))
     1286                        if new_coeff != 0:
     1287                            dict[((m,m),)] = new_coeff
     1288                        else:
     1289                            del dict[((m,m),)]
     1290                        converted = True
     1291                elif basis in _steenrod_arnonA_basis_names:
     1292                    if len(mono) == 1 and is_power_of_two(mono[0]):   # no conversion
     1293                        m = int(math.log(mono[0],2))
     1294                        if new_coeff != 0:
     1295                            dict[((m,m),)] = new_coeff
     1296                        else:
     1297                            del dict[((m,m),)]
     1298                        converted = True
     1299                elif basis in _steenrod_arnonC_basis_names:
     1300                    if len(mono) == 1:   # no conversion
     1301                        if dict.has_key(mono):
     1302                            new_coeff = dict[mono] + self._raw['milnor'][mono]
     1303                            if new_coeff != 0:
     1304                                dict[mono] = new_coeff
     1305                            else:
     1306                                del dict[mono]
     1307                        else:
     1308                            dict[mono] = self._raw['milnor'][mono]
     1309                        converted = True
     1310                if not converted:
     1311                    conversion = milnor_convert(  # conversion required
     1312                        SteenrodAlgebraElement({mono: 1}),
     1313                        basis)
     1314                    for new_mono in conversion:
     1315                        if dict.has_key(new_mono):
     1316                            new_coeff = dict[new_mono] + conversion[new_mono]
     1317                            if new_coeff != 0:
     1318                                dict[new_mono] = new_coeff
     1319                            else:
     1320                                del dict[new_mono]
     1321                        else:
     1322                            dict[new_mono] = conversion[new_mono]
     1323            self._raw[basis] = dict
     1324            return dict
     1325
     1326
     1327    def basis(self,basis):
     1328        r"""
     1329        Representation of element with respect to basis.
     1330
     1331        INPUT:
     1332            basis -- string, basis in which to work.  The choices are:
     1333            'milnor' or 'mil' for the Milnor basis.
     1334            'serre-cartan', 'serre_cartan', 'sc', 'adem', 'admissible' for
     1335                the Serre-Cartan basis.
     1336            'wood_y' for Wood's Y basis.
     1337            'wood_z' for Wood's Z basis.
     1338            'wall' for Wall's basis.
     1339            'wall_long' for Wall's basis, alternate representation
     1340            'arnon_a' for Arnon's A basis.
     1341            'arnon_a_long' for Arnon's A basis, alternate representation.
     1342            'arnon_c' for Arnon's C basis.
     1343            'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz' for various
     1344                P^s_t-bases.
     1345            'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz' for
     1346                various commutator bases.
     1347            'comm_long', 'comm_rlex_long', etc., for commutator bases, alternate
     1348                representations.
     1349
     1350        OUTPUT:
     1351            None
     1352
     1353        See documentation for the function 'steenrod_algebra_basis' for
     1354        descriptions of the different bases.
     1355
     1356        This prints the representation of element in the given basis.
     1357        Note that it only prints the representation; it does not
     1358        actually return a value.  Thus evaluating
     1359        "y = x.basis('milnor')" will set y to be None.
     1360
     1361        EXAMPLES:
     1362            sage: c = Sq(2) * Sq(1)
     1363            sage: c.basis('milnor')
     1364            Sq(0,1) + Sq(3)
     1365            sage: c.basis('serre-cartan')
     1366            Sq^{2} Sq^{1}
     1367            sage: d = pst(0,3)
     1368            sage: d.basis('arnonc')
     1369            Sq^{2} Sq^{5} + Sq^{4} Sq^{2} Sq^{1} + Sq^{4} Sq^{3} + Sq^{7}
     1370        """
     1371        try:
     1372            from sage.misc.misc import embedded
     1373            from sage.misc.latex import pretty_print, view
     1374            import sys
     1375            temp = steenrod_set_basis()
     1376            steenrod_set_basis(basis)
     1377            if embedded() and sys.displayhook == pretty_print:
     1378                view(self)
     1379            else:
     1380                print(self)
     1381        finally:
     1382            steenrod_set_basis(temp)
     1383
     1384
     1385    def degree(self):
     1386        r"""
     1387        Degree of element.
     1388       
     1389        The degree of $\text{Sq}(i_1,i_2,i_3,...)$ is
     1390        $i_1 + 3 i_2 + 7 i_3 + ... + (2^n - 1) i_n + ...$.
     1391        The degree of a sum is undefined, unless each summand has the
     1392        same degree: that is, unless the element is homogeneous.
     1393
     1394        EXAMPLES:
     1395            sage: a = Sq(1,2,1)
     1396            sage: a.degree()
     1397            14
     1398            sage: for a in Sq(3) + Sq(5,1): a.degree()
     1399            3
     1400            8
     1401            sage: (Sq(3) + Sq(5,1)).degree()
     1402            Element is not homogeneous.
     1403        """
     1404        def mono_degree(m):
     1405            i = 0
     1406            deg = 0
     1407            for n in m:
     1408                i += 1
     1409                deg += n*(2**i - 1)
     1410            return deg
     1411        degrees = [mono_degree(mono) for mono in self._raw['milnor']]
     1412        if min(degrees) == max(degrees):
     1413            return min(degrees)
     1414        else:
     1415            print "Element is not homogeneous."
     1416            return None
     1417
     1418
     1419    def excess(self):
     1420        r"""
     1421        Excess of element.
     1422
     1423        The excess of $\text{Sq}(a,b,c,...)$ is $a + b + c + ...$.
     1424        The excess of a sum of elements is the minimum of their excesses.
     1425
     1426        EXAMPLES:
     1427            sage: steenrod_set_basis('milnor')
     1428            'milnor'
     1429            sage: a = Sq(1,2,3)
     1430            sage: a.excess()
     1431            6
     1432            sage: (Sq(0,0,1) + Sq(4,1) + Sq(7)).excess()
     1433            1
     1434            sage: [m.excess() for m in (Sq(0,0,1) + Sq(4,1) + Sq(7))]
     1435            [1, 5, 7]
     1436            sage: [m for m in (Sq(0,0,1) + Sq(4,1) + Sq(7))]
     1437            [Sq(0,0,1), Sq(4,1), Sq(7)]
     1438        """
     1439        excesses = [sum(mono) for mono in self._raw['milnor']]
     1440        return min(excesses)
     1441
     1442
     1443    def may_weight(self):
     1444        r"""
     1445        May's 'weight' of element.
     1446
     1447        If we let $F_* (A)$ be the May filtration of the Steenrod
     1448        algebra, the weight of an element $x$ is the integer $k$ so
     1449        that $x$ is in $F_k(A)$ and not in $F_{k+1}(A)$.  According
     1450        to Theorem 2.6 in May's thesis [May], the weight of a Milnor
     1451        basis element $\text{Sq(r_1,r_2,...)$ is computed as follows:
     1452        write each $r_i$ in binary as $r_i = \sum_j 2^j r_{ij}$.  Then
     1453        each nonzero binary digit $r_{ij}$ contributes $i$ to the
     1454        weight: the weight is $\sum_{i,j} i r_{ij}$.  The weight of a
     1455        sum of basis elements is the minimum of the weights of the
     1456        summands.
     1457
     1458        We compute this on Milnor basis elements by adding up the
     1459        terms in their 'height' -- see the method 'wall_height' for
     1460        documentation.
     1461
     1462        EXAMPLES:
     1463            sage: Sq(0).may_weight()
     1464            0
     1465            sage: a = Sq(4)
     1466            sage: a.may_weight()
     1467            1
     1468            sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
     1469            sage: b.may_weight()
     1470            2
     1471            sage: Sq(2,1,5).wall_height()
     1472            [2, 3, 2, 1, 1]
     1473            sage: Sq(2,1,5).may_weight()
     1474            9
     1475
     1476        REFERENCES:
     1477            [May]: J. P. May, "The cohomology of restricted Lie algebras
     1478                and of Hopf algebras; application to the Steenrod
     1479                algebra." Thesis, Princeton Univ., 1964.
     1480        """
     1481        if self == 0:
     1482            return Infinity
     1483        elif self == 1:
     1484            return 0
     1485        else:
     1486            wt = Infinity
     1487            for mono in self:
     1488                wt = min(wt, sum(mono.wall_height()))
     1489            return wt
     1490
     1491
     1492    def is_decomposable(self):
     1493        r"""
     1494        return True if element is decomposable, False otherwise.
     1495
     1496        That is, if element is in the square of the augmentation
     1497        ideal, return True; otherwise, return False.
     1498
     1499        EXAMPLES:
     1500            sage: a = Sq(6)
     1501            sage: a.is_decomposable()
     1502            True
     1503            sage: for i in range(9):
     1504            ...       if not Sq(i).is_decomposable():
     1505            ...           print Sq(i)
     1506            Sq(0)
     1507            Sq(1)
     1508            Sq(2)
     1509            Sq(4)
     1510            Sq(8)
     1511        """
     1512        return self.may_weight() > 1       
     1513
     1514
     1515    def wall_height(self):
     1516        r"""
     1517        Wall's 'height' of element.
     1518
     1519        The height of an element of the Steenrod algebra is a list of
     1520        non-negative integers, defined as follows: if the element is a
     1521        monomial in the generators $\text{Sq}(2^i)$, then the $i$th
     1522        entry in the list is the number of times $\text{Sq}(2^i)$
     1523        appears.  For an arbitrary element, write it as a sum of such
     1524        monomials; then its height is the maximum, ordered
     1525        right-lexicographically, of the heights of those monomials.
     1526
     1527        According to Theorem 3 in [Wall], the height of the Milnor
     1528        basis element $\text{Sq}(r_1, r_2, ...)$ is obtained as
     1529        follows: write each $r_i$ in binary as $r_i = \sum_j 2^j r_{ij}$. 
     1530        Then each nonzero binary digit $r_{ij}$ contributes 1 to the
     1531        $k$th entry in the height, for $j \leq k \leq i+j-1$.
     1532
     1533        EXAMPLES:
     1534            sage: Sq(0).wall_height()
     1535            []
     1536            sage: a = Sq(4)
     1537            sage: a.wall_height()
     1538            [0, 0, 1]
     1539            sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
     1540            sage: b.wall_height()
     1541            [0, 0, 1, 1]
     1542            sage: Sq(0,0,3).wall_height()
     1543            [1, 2, 2, 1]
     1544
     1545        REFERENCES:
     1546            [Wall]: C. T. C. Wall, "Generators and relations for the
     1547                Steenrod algebra," Ann. of Math. (2) \textbf{72} (1960),
     1548                429--444.
     1549        """
     1550        def mono_degree(m):
     1551            i = 0
     1552            deg = 0
     1553            for n in m:
     1554                i += 1
     1555                deg += n*(2**i - 1)
     1556            return deg
     1557       
     1558        if self == 0 or self == 1:
     1559            return []
     1560        import math
     1561        result = []
     1562        for r in self._raw['milnor']:
     1563            h = [0]*(1+mono_degree(r))
     1564            i = 1
     1565            for x in r:
     1566                if x > 0:
     1567                    for j in range(1+int(math.log(x,2))):
     1568                        if (2**j & x) != 0:
     1569                            for k in range(j,i+j):
     1570                                h[k] += 1
     1571                i=i+1
     1572            h.reverse()
     1573            result = max(h, result)
     1574        result.reverse()
     1575        return check_and_trim(result)
     1576           
     1577
     1578    def antipode(self):
     1579        """
     1580        Antipode of element.
     1581
     1582        Algorithm: according to a result of Milnor's, the antipode of
     1583        Sq(n) is the sum of all of the Milnor basis elements in
     1584        dimension n.  So: convert the element to the Serre-Cartan
     1585        basis and use this formula for the antipode of Sq(n), together
     1586        with the fact that the antipode is an antihomomorphism: if we
     1587        call the antipode c, then c(ab) = c(b) c(a).
     1588
     1589        EXAMPLES:
     1590            sage: d = pst(0,3); d
     1591            Sq(0,0,1)
     1592            sage: d.antipode()
     1593            Sq(0,0,1)
     1594            sage: Sq(4).antipode()
     1595            Sq(1,1) + Sq(4)
     1596            sage: (Sq(4) * Sq(2)).antipode()
     1597            Sq(6)
     1598
     1599        Applying the antipode twice returns the original element:
     1600            sage: y = Sq(8)*Sq(4)
     1601            sage: y == (y.antipode()).antipode()
     1602            True
     1603        """
     1604        def antipode_square(n):
     1605            """
     1606            Antipode of Sq(n).
     1607
     1608            INPUT:
     1609                n -- integer
     1610           
     1611            OUTPUT:
     1612                elt -- element of the Steenrod algebra
     1613
     1614            This returns the sum of all of the elements in the Milnor
     1615            basis in dimension $n$
     1616            """
     1617            from steenrod_algebra_bases import steenrod_algebra_basis
     1618            return sum(steenrod_algebra_basis(n,'milnor'))
     1619        from steenrod_algebra_bases import milnor_convert
     1620        result = 0
     1621        for mono in self._basis_dictionary('serre_cartan'):
     1622            antipode = Sq(0)
     1623            for n in mono:
     1624                antipode = antipode_square(n) * antipode
     1625            result = result + antipode
     1626        return result
     1627
     1628
     1629    def _repr_(self):
     1630        """
     1631        String representation of element.
     1632       
     1633        Default is to use the Milnor basis, but this can be changed by
     1634        using the function steenrod_set_basis.
     1635
     1636        EXAMPLES:
     1637            sage: steenrod_set_basis('milnor')
     1638            'milnor'
     1639            sage: a = Sq(0,0,2)
     1640            sage: a
     1641            Sq(0,0,2)
     1642            sage: steenrod_set_basis('admissible')
     1643            'admissible'
     1644            sage: a
     1645            Sq^{8} Sq^{4} Sq^{2} + Sq^{9} Sq^{4} Sq^{1} + Sq^{10} Sq^{3} Sq^{1} +
     1646            Sq^{10} Sq^{4} + Sq^{11} Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{13} Sq^{1}
     1647            + Sq^{14}
     1648            sage: steenrod_set_basis('woodz')
     1649            'woodz'
     1650            sage: a
     1651            Sq^{6} Sq^{7} Sq^{1} + Sq^{14} + Sq^{4} Sq^{7} Sq^{3} + Sq^{4} Sq^{7}
     1652            Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{8} Sq^{6} + Sq^{8} Sq^{4} Sq^{2}
     1653            sage: steenrod_set_basis('arnonc')
     1654            'arnonc'
     1655            sage: a
     1656            Sq^{4} Sq^{2} Sq^{8} + Sq^{4} Sq^{4} Sq^{6} + Sq^{4} Sq^{6} Sq^{4} +
     1657            Sq^{6} Sq^{8} + Sq^{8} Sq^{4} Sq^{2} + Sq^{8} Sq^{6}
     1658            sage: steenrod_set_basis('pst_llex')
     1659            'pst_llex'
     1660            sage: a
     1661            P^{1}_{3}
     1662            sage: steenrod_set_basis('comm_revz')
     1663            'comm_revz'
     1664            sage: a
     1665            c_{0,1} c_{1,1} c_{0,3} c_{2,1} + c_{0,2} c_{0,3} c_{2,1} + c_{1,3}
     1666        """
     1667        if len(self._raw['milnor']) == 0:
     1668            return "0"
     1669        else:
     1670            return string_rep(self)
     1671
     1672
     1673    def _latex_(self):
     1674        """
     1675        LaTeX representation of element.
     1676       
     1677        Default is to use the Milnor basis, but this can be changed by
     1678        using the function steenrod_set_basis.
     1679
     1680        For any element x in the Steenrod algebra, use 'view(x)' to
     1681        see the typeset LaTeX representation.
     1682
     1683        EXAMPLES:
     1684            sage: b = Sq(0,2)
     1685            sage: steenrod_set_basis('admissible')
     1686            'admissible'
     1687            sage: b._latex_()
     1688            '\\text{Sq}^{4} \\text{Sq}^{2} + \\text{Sq}^{5} \\text{Sq}^{1} +
     1689            \\text{Sq}^{6}'
     1690            sage: steenrod_set_basis('woody')
     1691            'woody'
     1692            sage: b._latex_()
     1693            '\\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{1} + \\text{Sq}^{6} +
     1694            \\text{Sq}^{4} \\text{Sq}^{2}'
     1695            sage: steenrod_set_basis('arnona')
     1696            'arnona'
     1697            sage: b._latex_()
     1698            'X^{1}_{1} X^{2}_{2}  + X^{2}_{1}'
     1699            sage: steenrod_set_basis('pst_deg')
     1700            'pst_deg'
     1701            sage: b._latex_()
     1702            'P^{1}_{2}'
     1703            sage: steenrod_set_basis('comm_llex')
     1704            'comm_llex'
     1705            sage: b._latex_()
     1706            'c_{1,2}'
     1707            sage: steenrod_set_basis('milnor')
     1708            'milnor'
     1709            sage: b._latex_()
     1710            '\\text{Sq}(0,2)'
     1711        """
     1712        if len(self._raw['milnor']) == 0:
     1713            return "0"
     1714        else:
     1715            return string_rep(self,LaTeX=True)
     1716
     1717
     1718    def __iter__(self):
     1719        """
     1720        Iterator for looping through summands in an element of the
     1721        Steenrod algebra.
     1722
     1723        EXAMPLES:
     1724            sage: z = Sq(0,0,1) + Sq(4,1) + Sq(7)
     1725            sage: [m for m in z]
     1726            [Sq(0,0,1), Sq(4,1), Sq(7)]
     1727            sage: [m.excess() for m in z]
     1728            [1, 5, 7]
     1729            sage: for m in z: m * Sq(2)
     1730            Sq(2,0,1)
     1731            Sq(0,3) + Sq(6,1)
     1732            Sq(3,2)
     1733
     1734        This loops through the summands in the Milnor basis
     1735        representation of the element.  The element w defined here is
     1736        a single monomial in the Serre-Cartan basis, but a sum of four
     1737        monomials in the Milnor basis:
     1738            sage: steenrod_set_basis('serre_cartan')
     1739            'serre_cartan'
     1740            sage: w = Sq(4) * Sq(2) * Sq(1)
     1741            sage: w
     1742            Sq^{4} Sq^{2} Sq^{1}
     1743            sage: for m in w: m
     1744            Sq^{4} Sq^{2} Sq^{1} + Sq^{5} Sq^{2} + Sq^{6} Sq^{1} + Sq^{7}
     1745            Sq^{5} Sq^{2} + Sq^{7}
     1746            Sq^{6} Sq^{1} + Sq^{7}
     1747            Sq^{7}
     1748            sage: steenrod_set_basis('milnor')
     1749            'milnor'
     1750            sage: w
     1751            Sq(0,0,1) + Sq(1,2) + Sq(4,1) + Sq(7)
     1752            sage: for m in w: m
     1753            Sq(0,0,1)
     1754            Sq(1,2)
     1755            Sq(4,1)
     1756            Sq(7)
     1757        """
     1758        for m in sorted(self._raw['milnor'].keys()):
     1759            yield SteenrodAlgebraElement({m: self._raw['milnor'][m]})
     1760       
     1761
     1762    def additive_order(self):
     1763        """
     1764        The additive order of any element of the mod p Steenrod algebra is p.
     1765
     1766        EXAMPLES:
     1767            sage: z = Sq(4) + Sq(6) + Sq(0)
     1768            sage: z.additive_order()
     1769            2
     1770        """
     1771        return self.parent().prime
     1772
     1773
     1774def Sq(*nums):
     1775    """
     1776    Milnor element Sq(a,b,c,...).
     1777
     1778    INPUT:
     1779        nums -- list of non-negative integers
     1780       
     1781    OUTPUT:
     1782        element of the Steenrod algebra given by the single basis
     1783        element Sq(a, b, c, ...)
     1784   
     1785    EXAMPLES:
     1786        sage: Sq(5)
     1787        Sq(5)
     1788        sage: Sq(5) + Sq(2,1) + Sq(5)  # addition is mod 2:
     1789        Sq(2,1)   
     1790        sage: (Sq(4,3) + Sq(7,2)).degree()
     1791        13
     1792
     1793    Entries must be non-negative integers; otherwise, an error results.
     1794       
     1795    This function is a good way to define elements of the Steenrod algebra.
     1796    """
     1797    dict = {nums: 1}
     1798    return SteenrodAlgebraElement(dict)
     1799
     1800
     1801def pst(s,t):
     1802    """
     1803    The Margolis element P^s_t.
     1804
     1805    INPUT:
     1806        s -- non-negative integer
     1807        t -- positive integer
     1808       
     1809    OUTPUT:
     1810        The Margolis element P^s_t of the Steenrod algebra: the
     1811        element equal to Sq(0,0,...,0,2^s), where the 2^s is in
     1812        position t.
     1813
     1814    EXAMPLES:
     1815        sage: pst(3,5)
     1816        Sq(0,0,0,0,8)
     1817        sage: pst(1,2) + Sq(4)*Sq(2) + Sq(2)*Sq(4)
     1818        0
     1819    """
     1820    if not isinstance(s, (Integer, int)) and s >= 0:
     1821        raise ValueError, "%s is not a non-negative integer" % s
     1822    if not isinstance(t, (Integer, int)) and t > 0:
     1823        raise ValueError, "%s is not a positive integer" % t
     1824    nums = (0,)*(t-1) + (steenrod_prime**s,)
     1825    return SteenrodAlgebraElement({nums: 1})
     1826
     1827
     1828def degree(x):
     1829    r"""
     1830    Degree of x.
     1831   
     1832    The degree of $\text{Sq}(i_1,i_2,i_3,...)$ is $i_1 + 3 i_2 +
     1833    7 i_3 + ... + (2^n - 1) i_n + ...$.  The degree of a sum is
     1834    undefined, unless each summand has the same degree: that is,
     1835    unless the element is homogeneous.
     1836   
     1837    INPUT:
     1838        x -- element of the Steenrod algebra
     1839
     1840    OUTPUT:
     1841        degree -- non-negative integer, or None if element is not
     1842        homogeneous
     1843   
     1844    EXAMPLES:
     1845        sage: from sage.algebras.steenrod_algebra import degree
     1846        sage: a = Sq(1,2,1)
     1847        sage: degree(a)
     1848        14
     1849        sage: degree(Sq(3) + Sq(5,1))
     1850        Element is not homogeneous.
     1851    """
     1852    return x.degree()
     1853
     1854
     1855def excess(x):
     1856    r"""
     1857    Excess of x.
     1858   
     1859    The excess of $\text{Sq}(a,b,c,...)$ is $a + b + c + ...$.
     1860    The excess of a sum of elements is the minimum of their excesses.
     1861
     1862    INPUT:
     1863        x -- element of the Steenrod algebra
     1864
     1865    OUTPUT:
     1866        excess -- non-negative integer, the excess of x
     1867   
     1868    EXAMPLES:
     1869        sage: from sage.algebras.steenrod_algebra import excess
     1870        sage: a = Sq(1,2,3)
     1871        sage: excess(a)
     1872        6
     1873        sage: excess(Sq(0,0,1) + Sq(4,1) + Sq(7))
     1874        1
     1875        sage: [excess(m) for m in (Sq(0,0,1) + Sq(4,1) + Sq(7))]
     1876        [1, 5, 7]
     1877    """
     1878    return x.excess()
     1879
     1880
     1881def milnor(x):
     1882    r"""
     1883    Milnor representation of x.
     1884
     1885    INPUT:
     1886        x -- element of the Steenrod algebra
     1887
     1888    OUTPUT:
     1889        None
     1890
     1891    This prints the representation of x in the Milnor basis.  Note
     1892    that it only prints the representation; it does not actually
     1893    return a value.  Thus evaluating "y = milnor(x)" will set
     1894    y to be None.
     1895
     1896    EXAMPLES:
     1897        sage: from sage.algebras.steenrod_algebra import milnor
     1898        sage: steenrod_set_basis('adem')
     1899        'adem'
     1900        sage: x = Sq(5) * Sq(2) * Sq(1); x
     1901        Sq^{5} Sq^{2} Sq^{1}
     1902        sage: milnor(x)
     1903        Sq(1,0,1) + Sq(5,1)
     1904    """
     1905    return x.basis('milnor')
     1906
     1907
     1908def serre_cartan(x):
     1909    r"""
     1910    Serre-Cartan representation of x.
     1911
     1912    INPUT:
     1913        x -- element of the Steenrod algebra
     1914
     1915    OUTPUT:
     1916        None
     1917
     1918    This prints the representation of x in the Serre-Cartan basis.
     1919    Note that it only prints the representation; it does not actually
     1920    return a value.  Thus evaluating "y = serre_cartan(x)" will set y
     1921    to be None.
     1922
     1923    EXAMPLES:
     1924        sage: from sage.algebras.steenrod_algebra import serre_cartan
     1925        sage: steenrod_set_basis('milnor')
     1926        'milnor'
     1927        sage: x = Sq(3,2); x
     1928        Sq(3,2)
     1929        sage: serre_cartan(x)
     1930        Sq^{7} Sq^{2}
     1931    """
     1932    return x.basis('adem')
     1933
     1934adem = serre_cartan
     1935admissible = serre_cartan
     1936
     1937## string representations
     1938
     1939def string_rep(element,LaTeX=False,sort=True):
     1940    """
     1941    String representation of element.
     1942
     1943    INPUT:
     1944        element -- element of the Steenrod algebra
     1945        LaTeX (optional, default False) -- If True, output LaTeX string
     1946        sort (optional, default True) -- If True, sort output
     1947
     1948    OUTPUT:
     1949        string -- string representation of element in current basis
     1950
     1951    If LaTeX is True, output a string suitable for LaTeX; otherwise,
     1952    output a plain string.  If sort is True, sort element left
     1953    lexicographically; otherwise, no sorting is done, and so the
     1954    order in which the summands are printed may be unpredictable.
     1955   
     1956    EXAMPLES:
     1957        sage: from sage.algebras.steenrod_algebra import string_rep
     1958        sage: a = Sq(0,0,2)
     1959        sage: steenrod_set_basis('admissible')
     1960        'admissible'
     1961        sage: string_rep(a)
     1962        'Sq^{8} Sq^{4} Sq^{2} + Sq^{9} Sq^{4} Sq^{1} + Sq^{10} Sq^{3} Sq^{1} +
     1963        Sq^{10} Sq^{4} + Sq^{11} Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{13} Sq^{1}
     1964        + Sq^{14}'
     1965        sage: b = Sq(0,2)
     1966        sage: string_rep(b,LaTeX=True)
     1967        '\\text{Sq}^{4} \\text{Sq}^{2} + \\text{Sq}^{5} \\text{Sq}^{1} +
     1968        \\text{Sq}^{6}'
     1969        sage: steenrod_set_basis('woodz')
     1970        'woodz'
     1971        sage: string_rep(a)
     1972        'Sq^{6} Sq^{7} Sq^{1} + Sq^{14} + Sq^{4} Sq^{7} Sq^{3} + Sq^{4} Sq^{7}
     1973        Sq^{2} Sq^{1} + Sq^{12} Sq^{2} + Sq^{8} Sq^{6} + Sq^{8} Sq^{4} Sq^{2}'
     1974        sage: steenrod_set_basis('arnonc')
     1975        'arnonc'
     1976        sage: string_rep(a,sort=False)
     1977        'Sq^{4} Sq^{4} Sq^{6} + Sq^{6} Sq^{8} + Sq^{4} Sq^{2} Sq^{8} + Sq^{4}
     1978        Sq^{6} Sq^{4} + Sq^{8} Sq^{4} Sq^{2} + Sq^{8} Sq^{6}'
     1979        sage: string_rep(a)
     1980        'Sq^{4} Sq^{2} Sq^{8} + Sq^{4} Sq^{4} Sq^{6} + Sq^{4} Sq^{6} Sq^{4} +
     1981        Sq^{6} Sq^{8} + Sq^{8} Sq^{4} Sq^{2} + Sq^{8} Sq^{6}'
     1982        sage: steenrod_set_basis('pst_llex')
     1983        'pst_llex'
     1984        sage: string_rep(a)
     1985        'P^{1}_{3}'
     1986        sage: steenrod_set_basis('comm_revz')
     1987        'comm_revz'
     1988        sage: string_rep(a,LaTeX=True,sort=False)
     1989        'c_{0,2} c_{0,3} c_{2,1} + c_{1,3} + c_{0,1} c_{1,1} c_{0,3} c_{2,1}'
     1990        sage: string_rep(a,LaTeX=True)
     1991        'c_{0,1} c_{1,1} c_{0,3} c_{2,1} + c_{0,2} c_{0,3} c_{2,1} + c_{1,3}'
     1992        sage: steenrod_set_basis('milnor')
     1993        'milnor'
     1994        sage: string_rep(a)
     1995        'Sq(0,0,2)'
     1996        sage: string_rep(a,LaTeX=True)
     1997        '\\text{Sq}(0,0,2)'
     1998    """
     1999    if len(element._raw['milnor']) == 0:
     2000        return "0"
     2001    if steenrod_basis in _steenrod_milnor_basis_names:
     2002        dict = element._basis_dictionary('milnor')
     2003        mono_to_string = milnor_mono_to_string
     2004    elif steenrod_basis in _steenrod_serre_cartan_basis_names:
     2005        dict = element._basis_dictionary('serre-cartan')
     2006        mono_to_string = sc_mono_to_string
     2007    elif steenrod_basis in _steenrod_woodY_basis_names:
     2008        dict = element._basis_dictionary('woody')
     2009        mono_to_string = wood_mono_to_string
     2010    elif steenrod_basis in _steenrod_woodZ_basis_names:
     2011        dict = element._basis_dictionary('woodz')
     2012        mono_to_string = wood_mono_to_string
     2013    elif steenrod_basis in _steenrod_wall_basis_names:
     2014        dict = element._basis_dictionary('wall')
     2015        if steenrod_basis.find('long') >= 0:
     2016            mono_to_string = wall_long_mono_to_string
     2017        else:
     2018            mono_to_string = wall_mono_to_string
     2019    elif steenrod_basis in _steenrod_arnonA_basis_names:
     2020        dict = element._basis_dictionary('arnona')
     2021        if steenrod_basis.find('long') >= 0:
     2022            mono_to_string = arnonA_long_mono_to_string
     2023        else:
     2024            mono_to_string = arnonA_mono_to_string
     2025    elif steenrod_basis in _steenrod_arnonC_basis_names:
     2026        dict = element._basis_dictionary('arnonc')
     2027        mono_to_string = sc_mono_to_string
     2028    elif steenrod_basis in _steenrod_pst_basis_names:
     2029        mono_to_string = pst_mono_to_string
     2030        if steenrod_basis.find('rlex') >= 0:
     2031            dict = element._basis_dictionary('pst_rlex')
     2032        elif steenrod_basis.find('llex') >= 0:
     2033            dict = element._basis_dictionary('pst_llex')
     2034        elif steenrod_basis.find('deg') >= 0:
     2035            dict = element._basis_dictionary('pst_deg')
     2036        elif steenrod_basis.find('revz') >= 0:
     2037            dict = element._basis_dictionary('pst_revz')
     2038        else:
     2039            dict = element._basis_dictionary('pst_revz')
     2040    elif steenrod_basis in _steenrod_commutator_basis_names:
     2041        if steenrod_basis.find('long') >= 0:
     2042            mono_to_string = comm_long_mono_to_string
     2043        else:
     2044            mono_to_string = comm_mono_to_string
     2045        if steenrod_basis.find('rlex') >= 0:
     2046            dict = element._basis_dictionary('comm_rlex')
     2047        elif steenrod_basis.find('llex') >= 0:
     2048            dict = element._basis_dictionary('comm_llex')
     2049        elif steenrod_basis.find('deg') >= 0:
     2050            dict = element._basis_dictionary('comm_deg')
     2051        elif steenrod_basis.find('revz') >= 0:
     2052            dict = element._basis_dictionary('comm_revz')
     2053        else:
     2054            dict = element._basis_dictionary('comm_revz')
     2055    else:
     2056        raise NotImplementedError, "Don't know how to deal with basis %s." % steenrod_basis
     2057    output = ""
     2058    if sort:
     2059        sorted_list = sorted(dict.keys())
     2060    else:
     2061        sorted_list = dict
     2062    for mono in sorted_list:
     2063        if dict[mono] != 1:
     2064            coeff = str(dict[mono]) + " "
     2065        else:
     2066            coeff = ""
     2067        output = output + coeff + mono_to_string(mono,LaTeX) + " + "
     2068    return output.strip(" +")
     2069
     2070
     2071def milnor_mono_to_string(mono,LaTeX=False):
     2072    """
     2073    String representation of element of the Milnor basis.
     2074
     2075    This is used by the _repr_ and _latex_ methods.
     2076
     2077    INPUT:
     2078        mono -- tuple of non-negative integers (a,b,c,...)
     2079
     2080    OUTPUT:
     2081        string -- string Sq(a,b,c,...)
     2082       
     2083    EXAMPLES:
     2084        sage: from sage.algebras.steenrod_algebra import milnor_mono_to_string
     2085        sage: milnor_mono_to_string((1,2,3,4))
     2086        'Sq(1,2,3,4)'
     2087        sage: milnor_mono_to_string((1,2,3,4),LaTeX=True)
     2088        '\\text{Sq}(1,2,3,4)'
     2089
     2090    The empty tuple represents the unit element Sq(0):
     2091        sage: milnor_mono_to_string(())
     2092        'Sq(0)'
     2093    """
     2094    if LaTeX:
     2095        sq = "\\text{Sq}"
     2096    else:
     2097        sq = "Sq"
     2098    if len(mono) == 0:
     2099        return sq + "(0)"
     2100    else:
     2101        string = sq + "(" + str(mono[0])
     2102        for n in mono[1:]:
     2103            string = string + "," + str(n)
     2104        string = string + ")"
     2105        return string
     2106   
     2107
     2108def sc_mono_to_string(mono,LaTeX=False):
     2109    """
     2110    String representation of element of the Serre-Cartan basis.
     2111
     2112    This is used by the _repr_ and _latex_ methods.
     2113
     2114    INPUT:
     2115        mono -- tuple of positive integers (a,b,c,...)
     2116
     2117    OUTPUT:
     2118        string -- string Sq^{a} Sq^{b} Sq^{c} ...
     2119       
     2120    EXAMPLES:
     2121        sage: from sage.algebras.steenrod_algebra import sc_mono_to_string
     2122        sage: sc_mono_to_string((1,2,3,4))
     2123        'Sq^{1} Sq^{2} Sq^{3} Sq^{4}'
     2124        sage: sc_mono_to_string((1,2,3,4),LaTeX=True)
     2125        '\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{4}'
     2126
     2127    The empty tuple represents the unit element Sq(0):
     2128        sage: sc_mono_to_string(())
     2129        'Sq^{0}'
     2130    """
     2131    if LaTeX:
     2132        sq = "\\text{Sq}"
     2133    else:
     2134        sq = "Sq"
     2135    if len(mono) == 0:
     2136        return sq + "^{0}"
     2137    else:
     2138        string = ""
     2139        for n in mono:
     2140            string = string + sq + "^{" + str(n) + "} "
     2141        return string.strip(" ")
     2142
     2143
     2144def wood_mono_to_string(mono,LaTeX=False):
     2145    """
     2146    String representation of element of Wood's Y and Z bases.
     2147
     2148    This is used by the _repr_ and _latex_ methods.
     2149
     2150    INPUT:
     2151        mono -- tuple of pairs of non-negative integers (s,t)
     2152
     2153    OUTPUT:
     2154        string -- concatenation of 'Sq^{2^s (2^{t+1}-1)}' for each pair (s,t)
     2155       
     2156    EXAMPLES:
     2157        sage: from sage.algebras.steenrod_algebra import wood_mono_to_string
     2158        sage: wood_mono_to_string(((1,2),(3,0)))
     2159        'Sq^{14} Sq^{8}'
     2160        sage: wood_mono_to_string(((1,2),(3,0)),LaTeX=True)
     2161        '\\text{Sq}^{14} \\text{Sq}^{8}'
     2162
     2163    The empty tuple represents the unit element Sq(0):
     2164        sage: wood_mono_to_string(())
     2165        'Sq(0)'
     2166    """
     2167    if LaTeX:
     2168        sq = "\\text{Sq}"
     2169    else:
     2170        sq = "Sq"
     2171    if len(mono) == 0:
     2172        return sq + "(0)"
     2173    else:
     2174        string = ""
     2175        for (s,t) in mono:
     2176            string = string + sq + "^{" + \
     2177                str(2**s * (2**(t+1)-1)) + "} "
     2178        return string.strip(" ")
     2179
     2180
     2181def wall_mono_to_string(mono,LaTeX=False):
     2182    """
     2183    String representation of element of Wall's basis.
     2184
     2185    This is used by the _repr_ and _latex_ methods.
     2186
     2187    INPUT:
     2188        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     2189
     2190    OUTPUT:
     2191        string -- concatenation of 'Q^{m}_{k}' for each pair (m,k)
     2192       
     2193    EXAMPLES:
     2194        sage: from sage.algebras.steenrod_algebra import wall_mono_to_string
     2195        sage: wall_mono_to_string(((1,2),(3,0)))
     2196        'Q^{1}_{2} Q^{3}_{0}'
     2197        sage: wall_mono_to_string(((1,2),(3,0)),LaTeX=True)
     2198        'Q^{1}_{2} Q^{3}_{0}'
     2199
     2200    The empty tuple represents the unit element Sq(0):
     2201        sage: wall_mono_to_string(())
     2202        'Sq(0)'
     2203    """
     2204    if LaTeX:
     2205        sq = "\\text{Sq}"
     2206    else:
     2207        sq = "Sq"
     2208    if len(mono) == 0:
     2209        return sq + "(0)"
     2210    else:
     2211        string = ""
     2212        for (m,k) in mono:
     2213            string = string + "Q^{" + str(m) + "}_{" \
     2214                + str(k) + "} "
     2215        return string.strip(" ")
     2216
     2217
     2218def wall_long_mono_to_string(mono,LaTeX=False):
     2219    """
     2220    Alternate string representation of element of Wall's basis.
     2221
     2222    This is used by the _repr_ and _latex_ methods.
     2223
     2224    INPUT:
     2225        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     2226
     2227    OUTPUT:
     2228        string -- concatenation of terms of the form 'Sq^(2^m)'
     2229       
     2230    EXAMPLES:
     2231        sage: from sage.algebras.steenrod_algebra import wall_long_mono_to_string
     2232        sage: wall_long_mono_to_string(((1,2),(3,0)))
     2233        'Sq^{1} Sq^{2} Sq^{4} Sq^{8}'
     2234        sage: wall_long_mono_to_string(((1,2),(3,0)),LaTeX=True)
     2235        '\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{4} \\text{Sq}^{8}'
     2236
     2237    The empty tuple represents the unit element Sq(0):
     2238        sage: wall_long_mono_to_string(())
     2239        'Sq(0)'
     2240    """
     2241    if LaTeX:
     2242        sq = "\\text{Sq}"
     2243    else:
     2244        sq = "Sq"
     2245    if len(mono) == 0:
     2246        return sq + "(0)"
     2247    else:
     2248        string = ""
     2249        for (m,k) in mono:
     2250            for i in range(k,m+1):
     2251                string = string + sq + "^{" + str(2**i) + "} "
     2252        return string.strip(" ")
     2253
     2254
     2255def arnonA_mono_to_string(mono,LaTeX=False):
     2256    """
     2257    String representation of element of Arnon's A basis.
     2258
     2259    This is used by the _repr_ and _latex_ methods.
     2260
     2261    INPUT:
     2262        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     2263
     2264    OUTPUT:
     2265        string -- concatenation of 'X^{m}_{k}' for each pair (m,k)
     2266       
     2267    EXAMPLES:
     2268        sage: from sage.algebras.steenrod_algebra import arnonA_mono_to_string
     2269        sage: arnonA_mono_to_string(((1,2),(3,0)))
     2270        'X^{1}_{2} X^{3}_{0}'
     2271        sage: arnonA_mono_to_string(((1,2),(3,0)),LaTeX=True)
     2272        'X^{1}_{2} X^{3}_{0}'
     2273
     2274    The empty tuple represents the unit element Sq(0):
     2275        sage: arnonA_mono_to_string(())
     2276        'Sq(0)'
     2277    """
     2278    if LaTeX:
     2279        sq = "\\text{Sq}"
     2280    else:
     2281        sq = "Sq"
     2282    if len(mono) == 0:
     2283        return sq + "(0)"
     2284    else:
     2285        string = ""
     2286        for (m,k) in mono:
     2287            string = string + "X^{" + str(m) + "}_{" \
     2288                + str(k) + "} "
     2289        return string.strip(" ")
     2290   
     2291
     2292def arnonA_long_mono_to_string(mono,LaTeX=False):
     2293    """
     2294    Alternate string representation of element of Arnon's A basis.
     2295
     2296    This is used by the _repr_ and _latex_ methods.
     2297
     2298    INPUT:
     2299        mono -- tuple of pairs of non-negative integers (m,k) with m >= k
     2300
     2301    OUTPUT:
     2302        string -- concatenation of strings of the form 'Sq(2^m)'
     2303       
     2304    EXAMPLES:
     2305        sage: from sage.algebras.steenrod_algebra import arnonA_long_mono_to_string
     2306        sage: arnonA_long_mono_to_string(((1,2),(3,0)))
     2307        'Sq^{8} Sq^{4} Sq^{2} Sq^{1}'
     2308        sage: arnonA_long_mono_to_string(((1,2),(3,0)),LaTeX=True)
     2309        '\\text{Sq}^{8} \\text{Sq}^{4} \\text{Sq}^{2} \\text{Sq}^{1}'
     2310
     2311    The empty tuple represents the unit element Sq(0):
     2312        sage: arnonA_long_mono_to_string(())
     2313        'Sq(0)'
     2314    """
     2315    if LaTeX:
     2316        sq = "\\text{Sq}"
     2317    else:
     2318        sq = "Sq"
     2319    if len(mono) == 0:
     2320        return sq + "(0)"
     2321    else:
     2322        string = ""
     2323        for (m,k) in mono:
     2324            for i in range(m,k-1,-1):
     2325                string = string + sq + "^{" + str(2**i) + "} "
     2326        return string.strip(" ")
     2327   
     2328
     2329def pst_mono_to_string(mono,LaTeX=False):
     2330    r"""
     2331    String representation of element of a $P^s_t$-basis.
     2332
     2333    This is used by the _repr_ and _latex_ methods.
     2334
     2335    INPUT:
     2336        mono -- tuple of pairs of integers (s,t) with s >= 0, t > 0
     2337
     2338    OUTPUT:
     2339        string -- concatenation of 'P^{s}_{t}' for each pair (s,t)
     2340       
     2341    EXAMPLES:
     2342        sage: from sage.algebras.steenrod_algebra import pst_mono_to_string
     2343        sage: pst_mono_to_string(((1,2),(0,3)))
     2344        'P^{1}_{2} P^{0}_{3}'
     2345        sage: pst_mono_to_string(((1,2),(0,3)),LaTeX=True)
     2346        'P^{1}_{2} P^{0}_{3}'
     2347
     2348    The empty tuple represents the unit element Sq(0):
     2349        sage: pst_mono_to_string(())
     2350        'Sq(0)'
     2351    """
     2352    if LaTeX:
     2353        sq = "\\text{Sq}"
     2354    else:
     2355        sq = "Sq"
     2356    if len(mono) == 0:
     2357        return sq + "(0)"
     2358    else:
     2359        string = ""
     2360        for (s,t) in mono:
     2361            string = string + "P^{" + str(s) + "}_{" \
     2362                + str(t) + "} "
     2363        return string.strip(" ")
     2364
     2365
     2366def comm_mono_to_string(mono,LaTeX=False):
     2367    r"""
     2368    String representation of element of a commutator basis.
     2369
     2370    This is used by the _repr_ and _latex_ methods.
     2371
     2372    INPUT:
     2373        mono -- tuple of pairs of integers (s,t) with s >= 0, t > 0
     2374
     2375    OUTPUT:
     2376        string -- concatenation of 'c_{s,t}' for each pair (s,t)
     2377       
     2378    EXAMPLES:
     2379        sage: from sage.algebras.steenrod_algebra import comm_mono_to_string
     2380        sage: comm_mono_to_string(((1,2),(0,3)))
     2381        'c_{1,2} c_{0,3}'
     2382        sage: comm_mono_to_string(((1,2),(0,3)),LaTeX=True)
     2383        'c_{1,2} c_{0,3}'
     2384
     2385    The empty tuple represents the unit element Sq(0):
     2386        sage: comm_mono_to_string(())
     2387        'Sq(0)'
     2388    """
     2389    if LaTeX:
     2390        sq = "\\text{Sq}"
     2391    else:
     2392        sq = "Sq"
     2393    if len(mono) == 0:
     2394        return sq + "(0)"
     2395    else:
     2396        string = ""
     2397        for (s,t) in mono:
     2398            string = string + "c_{" + str(s) + "," \
     2399                + str(t) + "} "
     2400        return string.strip(" ")
     2401
     2402
     2403def comm_long_mono_to_string(mono,LaTeX=False):
     2404    r"""
     2405    Alternate string representation of element of a commutator basis.
     2406
     2407    Okay in low dimensions, but gets unwieldy as the dimension increases.
     2408
     2409    INPUT:
     2410        mono -- tuple of pairs of integers (s,t) with s >= 0, t > 0
     2411
     2412    OUTPUT:
     2413        string -- concatenation of 's_{2^s ... 2^(s+t-1)}' for each pair (s,t)
     2414       
     2415    EXAMPLES:
     2416        sage: from sage.algebras.steenrod_algebra import comm_long_mono_to_string
     2417        sage: comm_long_mono_to_string(((1,2),(0,3)))
     2418        's_{24} s_{124}'
     2419        sage: comm_long_mono_to_string(((1,2),(0,3)),LaTeX=True)
     2420        's_{24} s_{124}'
     2421
     2422    The empty tuple represents the unit element Sq(0):
     2423        sage: comm_long_mono_to_string(())
     2424        'Sq(0)'
     2425    """
     2426    if LaTeX:
     2427        sq = "\\text{Sq}"
     2428    else:
     2429        sq = "Sq"
     2430    if len(mono) == 0:
     2431        return sq + "(0)"
     2432    else:
     2433        string = ""
     2434        for (s,t) in mono:
     2435            if s + t > 4:
     2436                comma = ","
     2437            else:
     2438                comma = ""
     2439            string = string + "s_{"
     2440            for i in range(t):
     2441                string = string + str(2**(s+i)) + comma
     2442            string = string.strip(",") + "} "
     2443        return string.strip(" ")
  • new file sage/algebras/steenrod_algebra_bases.py

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

    diff -r 2615becf7bdb -r b175ce22e869 sage/algebras/steenrod_milnor_multiplication.py
    - +  
     1r"""
     2Milnor multiplication for elements of the Steenrod algebra.
     3
     4AUTHORS:
     5    - John H. Palmieri (2008-05-28: version 0.1.1)
     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