Ticket #9123: trac_9123-schur-algebra-and-gln-characters-ht.patch

File trac_9123-schur-algebra-and-gln-characters-ht.patch, 18.7 KB (added by hthomas, 10 years ago)
  • doc/en/reference/combinat/algebra.rst

    diff -r 54dc5fef7983 doc/en/reference/combinat/algebra.rst
    a b  
    1212   ../sage/algebras/iwahori_hecke_algebra
    1313   ../sage/algebras/nil_coxeter_algebra
    1414   ../sage/algebras/affine_nil_temperley_lieb
     15   ../sage/algebras/schur_algebra
  • sage/algebras/all.py

    diff -r 54dc5fef7983 sage/algebras/all.py
    a b  
    3838from iwahori_hecke_algebra import IwahoriHeckeAlgebraT
    3939from affine_nil_temperley_lieb import AffineNilTemperleyLiebTypeA
    4040from nil_coxeter_algebra import NilCoxeterAlgebra
     41from schur_algebra import SchurAlgebra, TensorSpace
  • new file sage/algebras/schur_algebra.py

    diff -r 54dc5fef7983 sage/algebras/schur_algebra.py
    - +  
     1
     2r"""
     3Schur algebras for `GL_n`
     4
     5This file implements:
     6
     7- Schur algebras for `GL_n` over an arbitrary field,
     8
     9- The canonical action of the Schur algebra on a tensor power of the standard representation,
     10
     11- Using the above to calculate the characters of irreducible `GL_n` modules.
     12
     13AUTHORS:
     14
     15- Eric Webster (2010-07-01): implement Schur algebra
     16
     17- Hugh Thomas (2011-05-08): implement action of Schur algebra and characters of irreducible modules
     18
     19REFERENCES:
     20
     21J. Green, Polynomial representations of `GL_n`, Springer Verlag. 
     22
     23"""
     24
     25#*****************************************************************************
     26#  Copyright (C) 2010 Eric Webster
     27#  Copyright (C) 2011 Hugh Thomas (hugh.ross.thomas@gmail.com)
     28#
     29#  Distributed under the terms of the GNU General Public License (GPL)
     30#                  http://www.gnu.org/licenses/
     31#*****************************************************************************
     32
     33
     34from sage.categories.all import AlgebrasWithBasis
     35from sage.combinat.free_module import CombinatorialFreeModule
     36from sage.combinat.permutation import Permutations
     37from copy import copy
     38from sage.rings.ring import CommutativeRing
     39from sage.rings.integer import Integer
     40from sage.misc.cachefunc import cached_method
     41from sage.combinat.sf.sfa import SymmetricFunctionAlgebra
     42from sage.rings.rational_field import QQ
     43from sage.combinat.words.word import Word
     44from sage.combinat.words.words import Words
     45from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
     46from sage.groups.perm_gps.permgroup_named import SymmetricGroup
     47from sage.combinat.tableau import SemistandardTableaux
     48from sage.misc.flatten import flatten
     49from sage.combinat.partition import Partitions, Partition
     50from sage.matrix.constructor import Matrix
     51
     52def SchurAlgebra(n,r,R):
     53
     54    """
     55    The Schur algebra for `GL_n` with rank `r` over the
     56    ring `R`.
     57    """
     58
     59    if not isinstance(n,(int,Integer)) or n <= 0:
     60        raise ValueError, "n must be a positive integer (n=%s)"%(n)
     61    if not isinstance(r,(int,Integer)) or r < 0:
     62        raise ValueError, "r must be a non-negative integer (r=%s)"%(r)
     63    if not isinstance(R,CommutativeRing):
     64        raise ValueError, "R must be a commutative Ring (R=%s)"%(R)
     65
     66    return SchurAlgebra_nrR(n,r,R)
     67
     68def _schur_I_nr_representatives(n, r, element, index):
     69
     70    """
     71    This is an internal function called by schur_representation_indices below.
     72    """
     73
     74    if r == 0:
     75        return index
     76
     77    if len(element) == r:
     78        index.append(copy(element))
     79        return
     80
     81    if len(element) == 0:
     82        for i in range(1,n+1):
     83            element.append(i)
     84            _schur_I_nr_representatives(n,r,element,index)
     85            element.pop()
     86    else:
     87        for i in range(element[-1],n+1):
     88            element.append(i)
     89            _schur_I_nr_representatives(n,r,element,index)
     90            element.pop()
     91
     92    return index
     93
     94
     95
     96def schur_representative_indices(n, r):
     97
     98    r"""
     99    This function returns a set which functions as a basis of `S_K(n,r)`.
     100   
     101    More specifically, the basis for `S_K(n,r)` consists of equivalence classes of pairs words of length ``r`` on the alphabet `1\dots n`,
     102    where the equivalence relation is simultaneous permutation of the two words.
     103    We can therefore fix a representative for each equivalence class
     104    in which the entries of the first word
     105    weakly increase, and the entries of the second word
     106    whose corresponding values
     107    in the first word are equal, also weakly increase. 
     108
     109    EXAMPLES::
     110
     111        sage: sage.algebras.schur_algebra.schur_representative_indices(2,2)
     112        [(word: 11, word: 11), (word: 11, word: 12), (word: 11, word: 22), (word: 12, word: 11), (word: 12, word: 12), (word: 12, word: 21), (word: 12, word: 22), (word: 22, word: 11), (word: 22, word: 12), (word: 22, word: 22)]
     113 
     114
     115    """
     116   
     117    basis = []
     118    I_nr_repr = _schur_I_nr_representatives(n, r, [], [])
     119    for e in I_nr_repr:
     120        j = 0
     121        k = 0
     122        I1 = []
     123        l = len(e)
     124        while k < l:
     125            if e[k] != e[j]:
     126                I2 = []
     127                if j == 0:
     128                    I1 = _schur_I_nr_representatives(n,k-j,[],[])
     129                else:
     130                    I2 = _schur_I_nr_representatives(n,k-j,[],[])
     131                    I = []
     132                    for m1 in range(0,len(I1)):
     133                        for m2 in range(0,len(I2)):
     134                            I.append(I1[m1]+I2[m2])
     135                    I1 = I
     136                j = k
     137            elif k == l-1:
     138                I2 = []
     139                k += 1
     140                if j == 0:
     141                    I1 = _schur_I_nr_representatives(n,k-j,[],[])
     142                else:
     143                    I2 = _schur_I_nr_representatives(n,k-j,[],[])
     144                    I = []
     145                    for m1 in range(0,len(I1)):
     146                        for m2 in range(0,len(I2)):
     147                            I.append(I1[m1]+I2[m2])
     148                    I1 = I
     149            else:
     150                k += 1
     151
     152        for v in I1:
     153            basis.append((Word(e),Word(v)))
     154
     155    return basis
     156
     157def schur_representative_from_index(index):
     158    """
     159    This function simultaneously reorders a pair of words to obtain the
     160    equivalent element
     161    of the distinguished basis of the Schur algebra. 
     162    seealso:: :func:`schur_representative_indices`
     163
     164    INPUT:
     165
     166    - A 2-ple of words from `Words (range(1,n+1),r)`
     167
     168    OUTPUT:
     169
     170    - The corresponding pair of words ordered correctly.
     171
     172    EXAMPLES::
     173
     174        sage: sage.algebras.schur_algebra.schur_representative_from_index((Word([2,1,2,2]),Word([1,3,0,0])))
     175        (word: 1222, word: 3001)
     176
     177
     178    """
     179   
     180    w = []
     181    for i in range(0,len(index[0])):
     182        w.append((index[0][i], index[1][i]))
     183    w.sort()
     184    index = [[], []]
     185    for i in range(0, len(w)):
     186        index[0].append(w[i][0])
     187        index[1].append(w[i][1])
     188    return tuple(map(Word, index))
     189
     190
     191class SchurAlgebra_nrR(CombinatorialFreeModule):
     192
     193    """
     194    This is the class that implements Schur algebras.
     195
     196    EXAMPLES::
     197
     198        sage: S = sage.algebras.schur_algebra.SchurAlgebra_nrR(2, 2, ZZ); S
     199        Schur Algebra (2,2) over Integer Ring
     200
     201    """
     202
     203    def __init__(self, n, r, R):
     204
     205        self._n = n
     206        self._r = r
     207
     208        CombinatorialFreeModule.__init__(self, R, schur_representative_indices(n,r), category = AlgebrasWithBasis(R))
     209
     210    def _repr_(self):
     211        """
     212        EXAMPLES::
     213
     214            sage: S = sage.algebras.schur_algebra.SchurAlgebra_nrR(4, 4, ZZ)
     215            sage: repr(S)
     216            'Schur Algebra (4,4) over Integer Ring'
     217        """
     218        return "Schur Algebra (%s,%s) over %s"%(self._n, self._r, self.base_ring())
     219
     220    @cached_method   
     221    def one_basis(self):
     222        return None
     223
     224    def product_on_basis(self, e_ij, e_kl):
     225        r"""
     226        Product of basis elements, as per :meth:`AlgebrasWithBasis.ParentMethods.product_on_basis`.
     227
     228        EXAMPLES::
     229
     230            sage: S=sage.algebras.schur_algebra.SchurAlgebra(2, 3, QQ)
     231            sage: B=S.basis()       
     232
     233        If we multiply two basis elements `x` and `y`, such that `x[1]` and `y[0]` are not
     234        permutations of each other, the result is zero
     235
     236        .. link::
     237
     238        ::
     239
     240            sage: B[(Word((1, 1, 1)), Word((1, 1, 2)))]*B[(Word((1, 2, 2)),Word((1, 1, 2)))]
     241            0
     242         
     243        If we multiply a basis element `x` by a basis element which consists of the same tuple repeated twice (on either side),
     244        the result
     245        is either zero (if the previous case applies) or `x`     
     246
     247        .. link::
     248
     249        ::
     250
     251            sage: B[(Word((1, 2, 2)), Word((1, 2, 2)))]*B[(Word((1, 2, 2)), Word((1, 1, 2)))]
     252            B[(word: 122, word: 112)]
     253
     254
     255        An arbitrary product, on the other hand, may have multiplicities
     256
     257        .. link::
     258
     259        ::
     260
     261            sage: B[(Word((1, 1, 1)), Word((1, 1, 2)))]*B[(Word((1, 1, 2)), Word((1, 2, 2)))]
     262            2*B[(word: 111, word: 122)]
     263
     264        """
     265
     266        k = e_kl[0]
     267        j = e_ij[1]
     268
     269        i = e_ij[0]
     270        l = e_kl[1]
     271
     272        l = sorted(l)
     273
     274        # Find basis elements (p,q) such that p ~ i and q ~ l
     275        e_pq = []
     276        for v in self.basis().keys():
     277            if v[0] == i and sorted(v[1]) == l:
     278                e_pq.append(v)
     279
     280        b = self.basis()
     281        product = self.zero()
     282
     283        # Find s in I(n,r) such that (p,s) ~ (i,j) and (s,q) ~ (k,l)
     284        for e in e_pq:
     285            Z_ijklpq = self.base_ring()(0)
     286            for s in Permutations([xx for xx in j]):
     287                if schur_representative_from_index((e[0],s)) == e_ij and schur_representative_from_index((s,e[1])) == e_kl:
     288                    Z_ijklpq += self.base_ring()(1)
     289            product += Z_ijklpq*b[e]
     290
     291        return product
     292
     293class TensorSpace(CombinatorialFreeModule):
     294    """
     295    This is the ``r``-fold tensor product of an ``n``-dimensional free module over ``R``,
     296    equipped with an action of the Schur algebra `S(n,r)` and the
     297    symmetric group `S_r`.
     298        """
     299
     300    def __init__(self, n, r, R):
     301
     302        self._n = n
     303        self._r = r
     304        self._R = R
     305        CombinatorialFreeModule.__init__(self, R, Words(range(1,n+1), r))
     306
     307    def _repr_(self):
     308        return "The %s-fold tensor product of a free module of dimension %s over %s"%(self._r, self._n, self.base_ring())
     309
     310    def _basis_elt_from_permuted_word(self, v, perm):
     311        """
     312        return the basis element of self corresponding to applying the permutation perm to a word v
     313        """
     314        return self.basis()[Word(v).apply_permutation_to_positions(perm)]
     315
     316    def action_by_perm(self, t, perm):
     317        """
     318        Apply a permutation to an element of self
     319
     320        INPUT:
     321
     322        - ``perm`` is an element of Permutations(self._r)
     323        - ``t`` is an element of self
     324
     325        OUTPUT:
     326
     327        - the output is the result of acting by ``perm`` on ``t``
     328        """
     329        h=self.module_morphism(self._basis_elt_from_permuted_word, codomain=self)
     330        return h(t, perm)
     331
     332    def action_by_symmetric_group_algebra(self, t, z):
     333        """
     334        INPUT:
     335
     336        - ``t`` -- an element of ``self``
     337        - ``z`` -- an element of ``SymmetricGroupAlgebra(self._R,self._r)``
     338
     339        OUTPUT:
     340
     341        result of action of ``z`` on ``t``. 
     342        """
     343        S=SymmetricGroupAlgebra(self._R,self._r)
     344        assert z in S
     345        sym_action=S.module_morphism(self.action_by_perm, codomain=self,position=1)   
     346        return sym_action(t, z)
     347
     348    def _monomial_product(self,xi,v):
     349        """
     350        Result of acting by the basis element ``xi`` of ``S`` on the basis element ``v`` of self.
     351        """
     352        x=self.zero()
     353        for i in Words(range(1,self._n+1),self._r):
     354            if schur_representative_from_index((i,v))==xi:
     355                x=x+self.basis()[i]
     356        return x
     357
     358    def action_by_Schur_alg(self,nu,v):
     359       
     360        r"""
     361        returns action of ``nu`` in Schur algebra on ``v`` in ``self``.
     362        """
     363
     364        A=SchurAlgebra(self._n,self._r,self._R)
     365        assert nu in A
     366        g=A.module_morphism(self._monomial_product, codomain=self)
     367        action= self.module_morphism(g,codomain=self,position=1)
     368        return action(nu,v)
     369
     370def bracket(r,X,S):
     371    r"""
     372    Given ``X`` a set of permutations of ``r`` in cycle notation,
     373    return the sum in the symmetric group algebra
     374    of those permutations, times their sign.
     375
     376    This implements the notation `\{X\}` from just before (5.3a) of Green.
     377
     378    EXAMPLES::
     379
     380        sage: sage.algebras.schur_algebra.bracket(2,[PermutationGroupElement(()),PermutationGroupElement((1,2))],SymmetricGroupAlgebra(QQ,2))
     381        () - (1,2)
     382
     383    """
     384    t=S.zero()
     385    SG=SymmetricGroup(r)
     386    return sum([x.sign()*S.basis()[SG(x)] for x in X])
     387
     388
     389def GL_n_irred_character(n,mu,KK):
     390    r"""
     391    This function calculates the character of the irreducible character indexed by ``mu`` of `GL(n)` over the field ``KK``.
     392   
     393    INPUT:
     394
     395     - ``n`` is a positive integer.
     396     - ``mu`` is a partition of at most ``n`` parts.
     397     - ``KK`` is a field .
     398   
     399    OUTPUT:
     400
     401    a symmetric function which should be interpreted in ``n`` variables to be meaningful as a character
     402
     403    EXAMPLES:
     404
     405        Over `\QQ`, the irreducible character for ``mu`` is the Schur function associated to ``mu``,
     406        plus garbage terms (Schur functions associated to partitions with more than `n` parts)
     407
     408        ::
     409
     410            sage: from sage.algebras.schur_algebra import GL_n_irred_character
     411            sage: z = GL_n_irred_character(2, [2], QQ)
     412            sage: sbasis = SymmetricFunctionAlgebra(QQ, 'schur')
     413            sage: sbasis(z)
     414            s[2]
     415
     416   
     417            sage: from sage.algebras.schur_algebra import GL_n_irred_character
     418            sage: z = GL_n_irred_character(4, [3, 2], QQ) # long time
     419            sage: sbasis = SymmetricFunctionAlgebra(QQ, 'schur') # long time
     420            sage: sbasis(z) #long time
     421            -5*s[1, 1, 1, 1, 1] + s[3, 2]
     422
     423        Over a Galois field, the irreducible character for `\mu` will in general
     424        be smaller. 
     425   
     426        In characteristic `p`, for a one-part partition `(r)`, where
     427        `r= a_0 + p a_1 + p^2 a_2 + \dots`, the result is [Green, after 5.5d]
     428        the product of `h[a_0], h[a_1]( pbasis[p]), h[a_2] ( pbasis[p^2]),\dots,`
     429        which is consistent with the following
     430
     431        ::
     432
     433            sage: from sage.algebras.schur_algebra import GL_n_irred_character
     434            sage: GL_n_irred_character(2, [7], GF(3)) # long time
     435            m[4, 3] + m[6, 1] + m[7]
     436
     437   
     438    """
     439    mbasis = SymmetricFunctionAlgebra(QQ,basis='monomial')
     440    r=sum(mu)
     441    A=SchurAlgebra(n,r,KK)
     442    M=TensorSpace(n,r,KK)
     443    S=SymmetricGroupAlgebra(KK,r)
     444
     445    #make ST the superstandard tableau of shape mu
     446    from sage.combinat.tableau import from_shape_and_word
     447    ST=from_shape_and_word(mu, range(1,r+1), order='English')
     448
     449    #make ell the reading word of the highest weight tableau of shape mu
     450    ell=[]
     451    for i in range(0,len(mu)):
     452        for j in range(0,mu[i]):
     453            ell.append(i+1)
     454
     455    e=M.basis()[Word(ell)]; #the element e_l
     456    BracC=bracket(r,ST.column_stabilizer(),S)
     457    f=M.action_by_symmetric_group_algebra(e,BracC)
     458
     459    #[Green, Theorem 5.3b] says that a basis of the Carter-Lusztig module V_\mu is given by taking
     460    #this f, and multiplying by
     461    #all xi_{i,ell} with ell as above and i semistandard. 
     462   
     463    carter_lusztig=[]
     464    for i in [Word(flatten(T)) for T in SemistandardTableaux(mu,max_entry=n)]:
     465        y=M.action_by_Schur_alg(A.basis()[schur_representative_from_index((i,Word(ell)))],e)
     466        carter_lusztig.append(y.to_vector())
     467
     468    #Therefore, we now have carter_lusztig as a list giving the basis of `V_\mu`
     469
     470    #We want to think of expressing this character as a sum of monomial
     471    #symmetric functions. 
     472
     473    #We will determine a basis element for each m_\lambda in the
     474    #character, and we want to keep track of them by \lambda.
     475
     476    #That means that we only want to pick out the basis elements above for 
     477    #those semistandard words whose content is a partition. 
     478
     479    contents=Partitions(r,max_length=n).list() #all partitions of r, length at most n
     480
     481    # JJ will consist of a list for each element of `contents`,
     482    # recording the list
     483    # of semistandard tableaux words with that content
     484
     485    # graded_basis will consist of the a corresponding basis element
     486
     487
     488    graded_basis=[]
     489    JJ=[]
     490    for i in range(0,len(contents)):
     491        graded_basis.append([])
     492        JJ.append([])
     493    for i in [Word(flatten(T),range(1,n+1))for T in SemistandardTableaux(mu,max_entry=n)]:
     494        con=i.evaluation()
     495        if all([ con[j+1] <= con[j] for j in range(0,len(con)-1)]):
     496                #don't test whether con is in Partitions, because con could
     497                #have trailing zeros
     498            JJ[contents.index(Partition(con))].append(i)
     499            x=M.action_by_Schur_alg(A.basis()[schur_representative_from_index((i,Word(ell)))],f)
     500            graded_basis[contents.index(Partition(con))].append(x.to_vector())
     501
     502    #There is an inner product on the Carter-Lusztig module V_\mu; its
     503    #maximal submodule is exactly the kernel of the inner product. 
     504
     505    #Now, for each possible partition content, we look at the graded piece of
     506    #that degree, and we record how these elements pair with each of the
     507    #elements of carter_lusztig. 
     508   
     509    #The kernel of this pairing is the part of this graded piece which is
     510    #not in the irreducible module for \mu. 
     511
     512    length=len(carter_lusztig)
     513
     514    Phi=mbasis.zero()
     515    for aa in range(0,len(contents)):
     516        Mat=[]
     517        for kk in range(0,len(JJ[aa])): 
     518            temp=[]
     519            for j in range(0,length):
     520                temp.append(graded_basis[aa][kk].inner_product(carter_lusztig[j]))
     521            Mat.append(temp)
     522        Angle=Matrix(Mat)
     523        Phi=Phi+(len(JJ[aa])-Angle.kernel().rank())*mbasis(contents[aa])
     524    return Phi
     525
  • sage/groups/matrix_gps/general_linear.py

    diff -r 54dc5fef7983 sage/groups/matrix_gps/general_linear.py
    a b  
    197197        except TypeError:
    198198            return False
    199199        return True
     200   
     201    def irreducible_character (self, mu):
     202        """
     203        returns the character of the irreducible module with highest weight mu
     204        """
     205
     206        from algebras.schur_algebra import GL_n_irred_character
     207        return GL_n_irred_character (self.degree(), mu, self.base_ring())
    200208
    201209class GeneralLinearGroup_finite_field(GeneralLinearGroup_generic, MatrixGroup_gap_finite_field):
    202210    pass