# Ticket #10052: trac_10052-steenrod.delta2to3.patch

File trac_10052-steenrod.delta2to3.patch, 36.9 KB (added by jhpalmieri, 11 years ago)

Diff between v2 and v3 (for reference only)

• ## sage/algebras/steenrod/steenrod_algebra.py

# HG changeset patch
# User J. H. Palmieri <palmieri@math.washington.edu>
# Date 1292438212 28800
# Parent  23d55536e72d68862f27758cf9f3abaf714ecd96
#10052: diff between v2 and v3

diff -r 23d55536e72d -r 2dc0757a042f sage/algebras/steenrod/steenrod_algebra.py
 a The list of exponents (e_1, e_2, ...) function* for the sub-Hopf algebra.  The profile function must satisfy the condition - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 \leq i < r. - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 < i < r. At odd primes, the situation is similar: the dual is isomorphic to the tensor product of a polynomial algebra and an exterior algebra, Here the profile function has two pieces k, which maps the non-negative integers to the set \{1, 2\}. These must satisfy the following conditions: - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 \leq i < r. - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 < i < r. - if k(i+j) = 1, then either e(i) \leq j or k(j) = 1 for all i \geq 1, j \geq 0. class SteenrodAlgebra_generic(Combinator and profile[0][0] < Infinity) or (truncation_type < Infinity)): if basis != 'milnor' and basis.find('pst') == -1: raise NotImplementedError, "For sub-Hopf algebras of the Steenrod algebra, only the Milnor basis and the pst bases (when p=2) are implemented." raise NotImplementedError, "For sub-Hopf algebras of the Steenrod algebra, only the Milnor basis and the pst bases are implemented." self._basis_name = basis self._basis_fcn = partial(steenrod_algebra_basis, p=p, class SteenrodAlgebra_generic(Combinator AttributeError: 'CombinatorialFreeModule_with_category.element_class' object has no attribute 'antipode' sage: A(a).antipode() # convert to elt of A, then compute antipode Sq(2,1) + Sq(5) sage: G = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]], basis='pst') TESTS: The following sort of thing is also tested by the function :func:steenrod_basis_error_check :: sage: H = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]]) sage: G = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]], basis='pst') sage: max([H[n].dimension() - G[n].dimension() for n in range(100)]) 0 """ from sage.rings.all import GF basis = self._basis_fcn(n) class SteenrodAlgebra_generic(Combinator return result def coproduct(self, x, algorithm='milnor'): """ r""" Return the coproduct of an element x of this algebra. INPUT: class SteenrodAlgebra_generic(Combinator sage: SteenrodAlgebra().Sq(3).coproduct() 1 # Sq(3) + Sq(1) # Sq(2) + Sq(2) # Sq(1) + Sq(3) # 1 The element Sq(0,1) is primitive:: The element \text{Sq}(0,1) is primitive:: sage: SteenrodAlgebra(basis='adem').Sq(0,1).coproduct() 1 # Sq^2 Sq^1 + 1 # Sq^3 + Sq^2 Sq^1 # 1 + Sq^3 # 1 class SteenrodAlgebra_generic(Combinator 1 # P(4) + P(1) # P(3) + P(2) # P(2) + P(3) # P(1) + P(4) # 1 sage: SteenrodAlgebra(p=3, basis='serre-cartan').P(4).coproduct() 1 # P^4 + P^1 # P^3 + P^2 # P^2 + P^3 # P^1 + P^4 # 1 sage: SteenrodAlgebra(p=11).Q(0,2).coproduct() sage: SteenrodAlgebra(p=11, profile=((), (2,1,2))).Q(0,2).coproduct() 1 # Q_0 Q_2 + Q_0 # Q_2 + Q_0 Q_2 # 1 - Q_2 # Q_0 """ # taken from categories.coalgebras_with_basis, then modified class SteenrodAlgebra_generic(Combinator sage: A5 = SteenrodAlgebra(p=5, basis='adem') sage: all([x.antipode().antipode() == x for x in A5.basis(25)]) True sage: H = SteenrodAlgebra(profile=[2,2,1]) sage: H.Sq(1,2).antipode() in H True """ p = self.prime() if self.basis_name() == 'serre-cartan': class SteenrodAlgebra_generic(Combinator return True if (isinstance(x, self.Element) and x.prime() == p): A = SteenrodAlgebra(p=p, basis=self.basis_name()) if self._has_nontrivial_profile(): return all([self._check_profile_on_basis(mono) for mono in x.support()]) for mono in A(x).support()]) return True  # trivial profile, so True return False class SteenrodAlgebra_generic(Combinator -  a, b, c, ... - non-negative integers OUTPUT: element of the Steenrod algebra given by the Milnor single basis element P(a, b, c, ...) single basis element P(a, b, c, ...) Note that at the prime 2, this is the same element as \text{Sq}(a, b, c, ...). class SteenrodAlgebra_generic(Combinator Q_1 Q_4 sage: A5.Q(1,4) == A5.Q_exp(0,1,0,0,1) True sage: H = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]]) sage: H.Q(2) Q_2 sage: H.Q(4) Traceback (most recent call last): ... ValueError: Element not in this algebra """ if len(nums) != len(set(nums)): return self(0) class SteenrodAlgebra_generic(Combinator answer = self.one() for i in nums: answer = answer * self.monomial(((i,), ())) return answer t = answer.leading_support() if self._check_profile_on_basis(t): return answer raise ValueError, "Element not in this algebra" def an_element(self): """ An element of this Steenrod algebra. The element depends on the basis.  (This is used by the automatic test suite, so having different elements in different bases may help in discovering bugs.) the basis and whether there is a nontrivial profile function. (This is used by the automatic test suite, so having different elements in different bases may help in discovering bugs.) EXAMPLES:: class SteenrodAlgebra_generic(Combinator sage: SteenrodAlgebra(p=5).an_element() 4 Q_1 Q_3 P(2,1) sage: SteenrodAlgebra(basis='pst').an_element() P^3_1 P^3_1 sage: SteenrodAlgebra(basis='pst', profile=[3,2,1]).an_element() P^0_1 """ from sage.rings.all import GF basis = self.basis_name() p = self.prime() if self._has_nontrivial_profile(): if self.ngens() > 0: return self.gen(0) else: return self.one() if basis == 'milnor' and p == 2: return self.monomial((2,1)) if basis == 'milnor' and p > 2: class SteenrodAlgebra_generic(Combinator +Infinity sage: SteenrodAlgebra(profile=[3,2,1]).ngens() # A(2) 3 sage: SteenrodAlgebra(profile=[3,2,1], basis='pst').ngens() 3 sage: SteenrodAlgebra(p=3, profile=[[3,2,1], [2,2,2,2]]).ngens() # A(3) at p=3 4 sage: SteenrodAlgebra(profile=[1,2,1,1]).ngens() class SteenrodAlgebra_generic(Combinator return Infinity n = self.profile(1) p = self.prime() if p == 2 and self == AA(n-1, p=p): if p == 2 and self._profile == AA(n-1, p=p)._profile: return n if p > 2 and self == AA(n, p=p): if p > 2 and self._profile == AA(n, p=p)._profile: return n+1 if p == 2: return sum(self._profile) class SteenrodAlgebra_generic(Combinator algebra is A(n), return the appropriate list of generators. For other sub-Hopf algebras: return a non-minimal generating set: the family of P^s_t's contained in the algebra. set: the family of P^s_t's and Q_n's contained in the algebra. EXAMPLES:: class SteenrodAlgebra_generic(Combinator OUTPUT: the ith generator of this algebra For the full Steenrod algebra, the i^{th} generator is Sq(2^i) at the prime 2; when p is odd, the 0th generator \text{Sq}(2^i) at the prime 2; when p is odd, the 0th generator is \beta = Q(0), and for i>0, the i^{th} generator is P(p^{i-1}). class SteenrodAlgebra_generic(Combinator Sq(16) sage: A.gen(200) Sq(1606938044258990275541962092341162602522202993782792835301376) sage: SteenrodAlgebra(2, basis='adem').gen(2) Sq^4 sage: SteenrodAlgebra(2, basis='pst').gen(2) P^2_1 sage: B = SteenrodAlgebra(5) sage: B.gen(0) Q_0 class SteenrodAlgebra_generic(Combinator sage: D3 = SteenrodAlgebra(p=3, profile=(lambda n: n, lambda n: 1 if n<1 else 2)) sage: [D3.gen(n) for n in range(9)] [P(1), Q_1, P(0,1), Q_2, P(0,3), P(0,0,1), Q_3, P(0,0,3), P(0,0,0,1)] sage: SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]], basis='pst').gen(2) P^1_1 """ from sage.rings.infinity import Infinity from sage.rings.all import Integer class SteenrodAlgebra_generic(Combinator raise ValueError, "This algebra only has %s generators, so call gen(i) with 0 <= i < %s" % (num, num) # check to see if equal to A(n) for some n. n = self.profile(1) if p == 2 and self == AA(n-1, p=p): if p == 2 and self._profile == AA(n-1, p=p)._profile: return self.pst(i,1) if p > 2 and self == AA(n, p=p): if p > 2 and self._profile == AA(n, p=p)._profile: if i == 0: return self.Q(0) return self.pst(i-1, 1) class SteenrodAlgebra_generic(Combinator Note that if the profile function is specified by a function, then by default it has infinite truncation type: the profile function is assumed to grow without bound.  :: function is assumed to be infinite after the 100th term.  :: sage: SteenrodAlgebra(profile=lambda n: 1).is_commutative() False class SteenrodAlgebra_generic(Combinator .. warning:: Deprecated (July 2010). Use :meth:change_basis instead. Deprecated (December 2010). Use :meth:change_basis instead. EXAMPLES:: sage: c = Sq(2) * Sq(1) sage: c.basis('milnor') doctest:...: DeprecationWarning: The .basis() method is deprecated.  Use .change_basis() instead. doctest:...: DeprecationWarning: (Since Sage 4.6.2) The .basis() method is deprecated.  Use .change_basis() instead. Sq(0,1) + Sq(3) """ from sage.misc.misc import deprecation deprecation('The .basis() method is deprecated. Use .change_basis() instead.') deprecation('The .basis() method is deprecated. Use .change_basis() instead.', version='Sage 4.6.2') return self.change_basis(basis) def coproduct(self, algorithm='milnor'): class SteenrodAlgebra_generic(Combinator The additive order of any nonzero element of the mod p Steenrod algebra is p. OUTPUT: 0 or p OUTPUT: 1 (for the zero element) or p (for anything else) EXAMPLES:: def SteenrodAlgebra(p=2, basis='milnor', there are also several other, less well-known, bases. See the documentation for this module (type sage.algebras.steenrod.steenrod_algebra?) and the function :func:sage.algebras.steenrod.steenrod_algebra_bases.steenrod_algebra_basis :func:steenrod_algebra_basis  for full descriptions of each of the implemented bases. This module implements the following bases at all primes: def SteenrodAlgebra(p=2, basis='milnor', - 'arnon_c': Arnon's C basis. When defining a Steenrod algebra, you can specify a basis. Then elements of that Steenrod algebra are printed in that basis :: elements of that Steenrod algebra are printed in that basis:: sage: adem = SteenrodAlgebra(2, 'adem') sage: x = adem.Sq(2,1)  # Sq(-) always means a Milnor basis element def SteenrodAlgebra(p=2, basis='milnor', The profile function e must satisfy the condition - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 \leq i < r. - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 < i < r. This is specified via profile, and optionally precision and truncation_type.  First, profile must have one of the def SteenrodAlgebra(p=2, basis='milnor', False sage: D2.is_finite() False sage: E2 = SteenrodAlgebra(profile=lambda n: max(4-n, 0), truncation_type=Infinity) sage: D2 == E2 True The argument precision only needs to be specified if the profile function is defined by a function and you want to control def SteenrodAlgebra(p=2, basis='milnor', Together, the functions e and k must satisfy the conditions - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 \leq i < r, - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 < i < r, - if k(i+j) = 1, then either e(i) \leq j or k(j) = 1 for all i \geq 1, j \geq 0. def SteenrodAlgebra(p=2, basis='milnor', sage: SteenrodAlgebra(profile=[1,2,1,1], basis='adem') Traceback (most recent call last): ... NotImplementedError: For sub-Hopf algebras of the Steenrod algebra, only the Milnor basis and the pst bases (when p=2) are implemented. NotImplementedError: For sub-Hopf algebras of the Steenrod algebra, only the Milnor basis and the pst bases are implemented. TESTS:
• ## sage/algebras/steenrod/steenrod_algebra_bases.py

diff -r 23d55536e72d -r 2dc0757a042f sage/algebras/steenrod/steenrod_algebra_bases.py
 a def convert_to_milnor_matrix_(n, basis, OUTPUT: matrix - change-of-basis matrix, a square matrix over GF(p) (This is not really intended for casual users, so no error checking is made on the integer n, the basis name, or the prime.) .. note:: This is called internally.  It is not intended for casual users, so no error checking is made on the integer n, the basis name, or the prime.  Also, users should call :func:convert_to_milnor_matrix instead of this function (which has a trailing underscore in its name), because the former is the cached version of the latter. EXAMPLES:: def convert_from_milnor_matrix(n, basis, OUTPUT: matrix - change-of-basis matrix, a square matrix over GF(p) (This is not really intended for casual users, so no error checking is made on the integer n, the basis name, or the prime.) .. note:: This is called internally.  It is not intended for casual users, so no error checking is made on the integer n, the basis name, or the prime. EXAMPLES:: def steenrod_algebra_basis_(n, basis='mi - p - positive prime number (optional, default = 2) - profile - profile function (optional, default None).  This is just passed on to the function :func:milnor_basis. is just passed on to the functions :func:milnor_basis and :func:pst_basis. - truncation_type - truncation type, either 0 or Infinity (optional Infinity).  This is just passed on to the function (optional, default Infinity if no profile function is specified, 0 otherwise).  This is just passed on to the function :func:milnor_basis. OUTPUT: tuple of objects representing basis elements for the Steenrod algebra in dimension n .. note:: Users should use :func:steenrod_algebra_basis instead of this function (which has a trailing underscore in its name): :func:steenrod_algebra_basis is the cached version of this one, and so will be faster. The choices for the string basis are as follows; see the documentation for :mod:sage.algebras.steenrod.steenrod_algebra for details on each basis: def steenrod_algebra_basis_(n, basis='mi sage: steenrod_algebra_basis(5)   # milnor basis is the default ((2, 1), (5,)) Bases in negative dimension are empty:: Bases in negative dimensions are empty:: sage: steenrod_algebra_basis(-2, 'wall') () def milnor_basis(n, p=2, **kwds): to be used; None means the profile function for the entire Steenrod algebra.  See :mod:sage.algebras.steenrod.steenrod_algebra and :func:SteenrodAlgebra for information on profile functions. :func:SteenrodAlgebra  for information on profile functions. - truncation_type - truncation type, either 0 or Infinity (optional Infinity). (optional, default Infinity if no profile function is specified, 0 otherwise) OUTPUT: tuple of mod p Milnor basis elements in dimension n def milnor_basis(n, p=2, **kwds): from sage.rings.infinity import Infinity from sage.combinat.integer_vector_weighted import WeightedIntegerVectors profile = kwds.get("profile", None) trunc = kwds.get("truncation_type", Infinity) trunc = kwds.get("truncation_type", None) if profile is not None and trunc is None: trunc = 0 result = [] if p == 2: def milnor_basis(n, p=2, **kwds): index += 1 # check profile: okay = True if profile is not None and len(profile[0]) > 0: if profile is not None and (len(profile[0]) > 0 or len(profile[1]) > 0): # check profile function for q_mono for i in q_mono: if ((len(profile[1]) > i and profile[1][i] == 1) def serre_cartan_basis(n, p=2, bound=1): \geq 2m_{i+1} for each i. At odd primes, it consists of monomials \beta^{e_0} P^{s_1} \beta^{e_1} P^{s_2} ...  P^{s_k} \beta^{e_k} with each e_i either 0 or 1, s_i \geq p s_{i+1} + e_i, and s_k \geq 1. e_i for all i, and s_k \geq 1. EXAMPLES:: def serre_cartan_basis(n, p=2, bound=1): sage: serre_cartan_basis(50,5) ((1, 5, 0, 1, 1), (1, 6, 1)) If optional argument bound is present, include only those monomials whose last term is at least bound (when p=2), or those for which s_k - epsilon_k >= bound (when p is odd). :: If optional argument bound is present, include only those monomials whose last term is at least bound (when p=2), or those for which s_k - e_k \geq bound (when p is odd). :: sage: serre_cartan_basis(7, bound=2) ((7,), (5, 2)) def atomic_basis(n, basis, **kwds): - n - non-negative integer - basis - string, the name of the basis - profile - profile function (optional, default None). Together with truncation_type, specify the profile function to be used; None means the profile function for the entire Steenrod algebra.  See :mod:sage.algebras.steenrod.steenrod_algebra and :func:SteenrodAlgebra for information on profile functions. - truncation_type - truncation type, either 0 or Infinity (optional, default Infinity if no profile function is specified, 0 otherwise). OUTPUT: tuple of basis elements in dimension n The atomic bases include Wood's Y and Z bases, Wall's basis, def atomic_basis(n, basis, **kwds): bases. (All of these bases are constructed similarly, hence their constructions have been consolidated into a single function. Also, see the documentation for 'steenrod_algebra_basis' for descriptions of them.) descriptions of them.)  For P^s_t-bases, you may also specify a profile function and truncation type; profile functions are ignored for the other bases. EXAMPLES:: def atomic_basis(n, basis, **kwds): from sage.rings.infinity import Infinity profile = kwds.get("profile", None) trunc = kwds.get("truncation_type", None) if profile is not None and trunc is None: trunc = 0 if n == 0: return ((),) def arnonC_basis(n,bound=1): sage: arnonC_basis(7) ((7,), (2, 5), (4, 3), (4, 2, 1)) If optional argument bound is present, include only those monomials whose first term is at least as large as bound:: If optional argument bound is present, include only those monomials whose first term is at least as large as bound:: sage: arnonC_basis(7,3) ((7,), (4, 3), (4, 2, 1)) def atomic_basis_odd(n, basis, p, **kwds :func:SteenrodAlgebra for information on profile functions. - truncation_type - truncation type, either 0 or Infinity (optional Infinity). (optional, default Infinity if no profile function is specified, 0 otherwise). OUTPUT: tuple of basis elements in dimension n The only possible difference in the implementations for P^s_t bases and commutator bases is that the former make sense, and require filtering, if there is a nontrivial profile function. However, this function should not be called for commutator bases if there is a profile function, so we treat the two bases exactly the same. This function is called by :func:steenrod_algebra_basis, and it will not be called for commutator bases if there is a profile function, so we treat the two bases exactly the same. EXAMPLES:: sage: from sage.algebras.steenrod.steenrod_algebra_bases import atomic_basis_odd sage: atomic_basis_odd(8, 'pst_rlex', 3) (((), (((0, 1), 2),)),) sage: atomic_basis_odd(18, 'pst_rlex', 3) (((0, 2), ()), ((0, 1), (((1, 1), 1),))) sage: atomic_basis_odd(18, 'pst_rlex', 3, profile=((), (2,2,2))) (((0, 2), ()),) """ def sorting_pair(s,t,basis):   # pair used for sorting the basis if basis.find('rlex') >= 0: def atomic_basis_odd(n, basis, p, **kwds from sage.rings.infinity import Infinity from sage.combinat.integer_vector_weighted import WeightedIntegerVectors profile = kwds.get("profile", None) trunc = kwds.get("truncation_type", None) trunc = kwds.get("truncation_type", 0) result = [] for dim in range(n/(2*p-2) + 1): def atomic_basis_odd(n, basis, p, **kwds index += 1 # check profile: okay = True if profile is not None and profile != ((), ()) > 0: if profile is not None and profile != ((), ()): # check profile function for q_mono for i in q_mono: if ((len(profile[1]) > i and profile[1][i] == 1) def atomic_basis_odd(n, basis, p, **kwds okay = False break for ((s,t), n) in p_mono: if ((len(profile) > t-1 and profile[t-1] <= s) or (len(profile) <= t-1 and trunc < Infinity)): for ((s,t), exp) in p_mono: if ((len(profile[0]) > t-1 and profile[0][t-1] <= s) or (len(profile[0]) <= t-1 and trunc < Infinity)): okay = False break def atomic_basis_odd(n, basis, p, **kwds return tuple(result) ############################################################################# def steenrod_basis_error_check(dim, p, verbose=False): def steenrod_basis_error_check(dim, p): """ This performs crude error checking. def steenrod_basis_error_check(dim, p, v - dim - non-negative integer - p - positive prime number - verbose - bool, optional (default False) OUTPUT: None def steenrod_basis_error_check(dim, p, v This function checks at the prime p as the dimension goes up from 0 to dim. If verbose is True, then print some messages along the way. If verbose is False and all tests pass, then there should be no output. If you set the Sage verbosity level to a positive integer (using set_verbose(n)), then some extra messages will be printed. EXAMPLES:: sage: sage.algebras.steenrod.steenrod_algebra_bases.steenrod_basis_error_check(12,2) sage: sage.algebras.steenrod.steenrod_algebra_bases.steenrod_basis_error_check(30,3) sage: from sage.algebras.steenrod.steenrod_algebra_bases import steenrod_basis_error_check sage: steenrod_basis_error_check(15,2) # long time sage: steenrod_basis_error_check(40,3) # long time sage: steenrod_basis_error_check(80,5) # long time """ import sage.misc.misc as misc if p == 2: bases = ('adem','woody', 'woodz', 'wall', 'arnona', 'arnonc', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz') else: bases = ('adem', 'milnor', bases = ('adem', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz') if verbose: print "p=%s, checking up to dimension %s" % (p, dim) for i in range(dim): if verbose and i % 5 == 0: print "up to dimension ", i if i % 5 == 0: misc.verbose("up to dimension %s"%i) milnor_dim = len(steenrod_algebra_basis_(i,'milnor',p=p)) for B in bases: # use steenrod_algebra_basis_, the uncached version def steenrod_basis_error_check(dim, p, v if mat.nrows() != 0 and not mat.is_invertible(): print "%s invertibility problem in dim %s at p=%s" % (B, i, p) if verbose: print "done checking" misc.verbose("done checking, no profiles") bases = ('pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz') if p == 2: profiles = [(4,3,2,1), (2,2,3,1,1), (0,0,0,2)] else: profiles = [((3,2,1), ()), ((), (2,1,2)), ((3,2,1), (2,2,2,2))] for i in range(dim): if i % 5 == 0: misc.verbose("up to dimension %s"%i) for pro in profiles: milnor_dim = len(steenrod_algebra_basis_(i,'milnor',p=p,profile=pro)) for B in bases: if milnor_dim != len(steenrod_algebra_basis_(i,B,p,profile=pro)): print "problem with milnor/%s in dimension %s with profile %s"%(B, i, pro) misc.verbose("done checking with profiles")
• ## sage/algebras/steenrod/steenrod_algebra_misc.py

diff -r 23d55536e72d -r 2dc0757a042f sage/algebras/steenrod/steenrod_algebra_misc.py
 a The main functions here are - :func:normalize_profile.  This function returns the canonical (and hashable) description of any profile function.  See :mod:sage.algebras.steenrod.steenrod_algebra and :func:SteenrodAlgebra for information on profile functions. :mod:sage.algebras.steenrod.steenrod_algebra and :func:SteenrodAlgebra  for information on profile functions. - functions named *_mono_to_string where * is a basis name (:func:milnor_mono_to_string, etc.).  These convert tuples def is_valid_profile(profile, truncation sub-Hopf algebras of the Steenrod algebra.  Briefly: at the prime 2, a profile function e is valid if it satisfies the condition - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 \leq i < r. - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 < i < r. At odd primes, a pair of profile functions e and k are valid if they satisfy - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 \leq i < r. - e(r) \geq \min( e(r-i) - i, e(i)) for all 0 < i < r. - if k(i+j) = 1, then either e(i) \leq j or k(j) = 1 for all i \geq 1, j \geq 0. def is_valid_profile(profile, truncation False sage: is_valid_profile([6,2,0], Infinity) False sage: is_valid_profile([0,3], 0) False sage: is_valid_profile([0,0,4], 0) False sage: is_valid_profile([0,0,0,4,0], 0) True Odd primes:: def is_valid_profile(profile, truncation True """ if p == 2: pro = list(profile) + [truncation_type] pro = list(profile) + [truncation_type]*len(profile) r = 0 for pro_r in pro: r += 1 # index of pro_r def is_valid_profile(profile, truncation return False else: # p odd: e = list(profile[0]) + [truncation_type] e = list(profile[0]) + [truncation_type]*len(profile[0]) k = list(profile[1]) if truncation_type > 0: k = k + [2] def normalize_profile(profile, precision terms (say, terms after the 100th), then they are given by truncation_type if that is 0 or \infty.  If truncation_type is 'auto', then in the case of a tuple, it gets set to 0, while for the other cases it gets set to '\infty'. gets set to 0, while for the other cases it gets set to \infty. See the examples below. def comm_mono_to_string(mono, latex=Fals - latex - boolean (optional, default False), if true, output LaTeX string - p - positive prime number (optional, default 2).  Unused. - p - positive prime number (optional, default 2) OUTPUT: string - concatenation of strings of the form c_{s,t} for each pair (s,t) def convert_perm(m): sage: sage.algebras.steenrod.steenrod_algebra_misc.convert_perm((3,7,4)) [1, 3, 2] sage: sage.algebras.steenrod.steenrod_algebra_misc.convert_perm((5,0,6,3)) [2, 4, 1, 3] [3, 1, 4, 2] """ m2 = list(m) m2.sort() return [list(m).index(x)+1 for x in m2] return [list(m2).index(x)+1 for x in m]
• ## sage/algebras/steenrod/steenrod_algebra_mult.py

diff -r 23d55536e72d -r 2dc0757a042f sage/algebras/steenrod/steenrod_algebra_mult.py
 a elements $Q_{f_1} Q_{f_2} ... \mathcal{P Second, use the fact that the$Q_k$'s form an exterior algebra:$Q_k^2 = 0$for all$k$, and if$i \neq j$, then$Q_i$and$Q_j$anticommute:$Q_i Q_j = -Q_j Q_i$. After these two steps, the product is of the form$Q_i Q_j = -Q_j Q_i$. After these two steps, the product is a linear combination of terms of the form .. math:: \sum Q_{e_1} Q_{e_2} ... \mathcal{P}(r_1, r_2, ...) \mathcal{P}(s_1, s_2, ...). Q_{e_1} Q_{e_2} ... \mathcal{P}(r_1, r_2, ...) \mathcal{P}(s_1, s_2, ...). Finally, use Milnor matrices to multiply the pairs of$\mathcal{P}(...)\$ terms, as at the prime 2: form all possible representing a sum of admissible monomia REFERENCES: - [Mil] J. W. Milnor, "The Steenrod algebra and its dual, Ann. of Math. (2) \textbf{67} (1958), 150--171. - [Mil] J. W. Milnor, "The Steenrod algebra and its dual", Ann. of Math. (2) 67 (1958), 150--171. - [SE] N. E. Steenrod, "Cohomology operations (Lectures by N. E. STeenrod written and revised by D. B. A.  Epstein). Annals of N. E. Steenrod written and revised by D. B. A.  Epstein)". Annals of Mathematics Studies, No. 50, 1962, Princeton University Press. """ def milnor_multiplication(r,s): \text{Sq}(2,4) \text{Sq}(0,1) = \text{Sq}(2, 5) + \text{Sq}(2, 0, 0, 1) This uses the same algorithm Monks does in his Maple package. This uses the same algorithm Monks does in his Maple package: see http://mathweb.scranton.edu/monks/software/Steenrod/steen.html. """ result = {} rows = len(r) + 1 def milnor_multiplication_odd(m1,m2,p): 2 P(13,21,83) + P(14,24,82) + P(17,20,83) + P(25,18,83) + P(26,21,82) + P(36,15,80,1) + P(49,12,83) + 2 P(50,15,82) + 2 P(53,11,83) + 2 P(63,15,81) This uses the same algorithm Monks does in his Maple package to iterate through the possible matrices. iterate through the possible matrices: see http://mathweb.scranton.edu/monks/software/Steenrod/steen.html. """ from sage.rings.all import GF F = GF(p) def adem_(a, b, c=0, p=2): OUTPUT: a dictionary representing the mod p Adem relations applied to P^a P^b or (if c present) to P^a \beta^b P^c. .. note:: Users should use :func:adem instead of this function (which has a trailing underscore in its name): :func:adem is the cached version of this one, and so will be faster. The mod p Adem relations for the mod p Steenrod algebra are as follows: if p=2, then if a < 2b, def adem_(a, b, c=0, p=2): If p is given and is odd, then with two inputs a and b, the Adem relation for P^a P^b is computed.  With three inputs a, b, c, the Adem relation for P^a \beta^b P^c is computed. In either case, the keys in output are all tuples of odd length, In either case, the keys in the output are all tuples of odd length, with (i_1, i_2, ..., i_m) representing .. math:: def make_mono_admissible_(mono, p=2): to the first pair (or triple when p is odd) where the sequence is inadmissible, and then apply this function recursively to each of the resulting tuples (i_1, ..., i_{j-1}, NEW, i_{j+2}, ...), keeping track of the coefficients keeping track of the coefficients. .. note:: Users should use :func:make_mono_admissible instead of this function (which has a trailing underscore in its name): :func:make_mono_admissible is the cached version of this one, and so will be faster. EXAMPLES::
• ## sage/categories/coalgebras_with_basis.py

diff -r 23d55536e72d -r 2dc0757a042f sage/categories/coalgebras_with_basis.py
 a class CoalgebrasWithBasis(Category_over_ @lazy_attribute def coproduct(self): """ If :meth:.coproduct_on_basis is available, construct the If :meth:coproduct_on_basis is available, construct the coproduct morphism from self to self \otimes self by extending it by linearity class CoalgebrasWithBasis(Category_over_ @lazy_attribute def counit(self): """ If :meth:.counit_on_basis is available, construct the If :meth:counit_on_basis is available, construct the counit morphism from self to self \otimes self by extending it by linearity