Ticket #3959: group_algebras_v1.patch

File group_algebras_v1.patch, 14.8 kB (added by davidloeffler, 4 months ago)
  • a/sage/algebras/all.py

    old new  
    3535from steenrod_algebra_element import Sq 
    3636from steenrod_algebra_bases import steenrod_algebra_basis 
    3737 
     38from group_algebra import GroupAlgebra, GroupAlgebraElement 
     39 
    3840     
    3941def is_R_algebra(Q, R): 
    4042    # TODO: do something nontrivial when morphisms are defined.  
  • /dev/null

    old new  
     1r""" 
     2Class for group algebras of arbitrary groups (over a general commutative base 
     3ring). 
     4 
     5NOTE: 
     6    -- It seems to be impossible to make this fit nicely with Sage's coercion 
     7    model. The problem is that (for example) if G is the additive group (ZZ,+), 
     8    and R = ZZ[G] is its group ring, then the integer 2 can be coerced into R 
     9    in two ways -- via G, or via the base ring -- and *the answers are 
     10    different*. In practice we get around this by preventing elements of G 
     11    coercing automatically into ZZ[G], which is a shame, but makes more sense 
     12    than preventing elements of the base ring doing so. 
     13 
     14AUTHOR: 
     15    -- David Loeffler (2008-08-24): initial version 
     16""" 
     17 
     18#***************************************************************************** 
     19#       Copyright (C) 2008 William Stein <wstein@gmail.com> 
     20#                     2008 David Loeffler <d.loeffler.01@cantab.net> 
     21# 
     22#  Distributed under the terms of the GNU General Public License (GPL) 
     23#                  http://www.gnu.org/licenses/ 
     24#***************************************************************************** 
     25 
     26from sage.algebras.algebra import Algebra 
     27from sage.algebras.algebra_element import AlgebraElement 
     28from sage.rings.all import IntegerRing 
     29from sage.groups.group import Group 
     30from sage.structure.formal_sum import FormalSums_generic, FormalSums, FormalSum 
     31from sage.sets.set import Set 
     32 
     33 
     34class GroupAlgebra(Algebra): 
     35 
     36    def __init__(self, group, base_ring = IntegerRing()): 
     37        r""" Create the given group algebra. 
     38        INPUT: 
     39            -- (Group) group: a generic group. 
     40            -- (Ring) base_ring: a commutative ring. 
     41        OUTPUT: 
     42            -- a GroupAlgebra instance. 
     43 
     44        EXAMPLES: 
     45            sage: GroupAlgebra(GL(3, GF(7))) 
     46            Group algebra of group "General Linear Group of degree 3 over Finite 
     47            Field of size 7" over base ring Integer Ring 
     48            sage: GroupAlgebra(1) 
     49            Traceback (most recent call last): 
     50            ... 
     51            TypeError: "1" is not a group 
     52        """ 
     53        if not base_ring.is_commutative(): 
     54            raise NotImplementedError, "Base ring must be commutative" 
     55         
     56        if not isinstance(group, Group): 
     57            raise TypeError, '"%s" is not a group' % group 
     58 
     59        Algebra.__init__(self, base_ring) 
     60        self._formal_sum_module = FormalSums(base_ring) 
     61        self._group = group 
     62 
     63    def group(self): 
     64        r""" Return the group of this group algebra. 
     65        EXAMPLES: 
     66            sage: GroupAlgebra(GL(3, GF(11))).group() 
     67            General Linear Group of degree 3 over Finite Field of size 11 
     68            sage: GroupAlgebra(SymmetricGroup(10)).group() 
     69            Symmetric group of order 10! as a permutation group 
     70        """ 
     71        return self._group 
     72 
     73    def is_commutative(self): 
     74        r""" Return True if self is a commutative ring. True if and only if 
     75        self.group() is abelian. 
     76 
     77        EXAMPLES: 
     78            sage: GroupAlgebra(SymmetricGroup(2)).is_commutative() 
     79            True 
     80            sage: GroupAlgebra(SymmetricGroup(3)).is_commutative() 
     81            False 
     82        """ 
     83        return self.group().is_abelian() 
     84 
     85    def is_field(self): 
     86        r""" Return True if self is a field. This is always false unless 
     87        self.group() is trivial and self.base_ring() is a field. 
     88        EXAMPLES: 
     89            sage: GroupAlgebra(SymmetricGroup(2)).is_field() 
     90            False 
     91            sage: GroupAlgebra(SymmetricGroup(1)).is_field() 
     92            False 
     93            sage: GroupAlgebra(SymmetricGroup(1), QQ).is_field() 
     94            True 
     95        """ 
     96        if not self.base_ring().is_field(): 
     97            return False 
     98        return (self.group().order() == 1) 
     99 
     100    def is_finite(self): 
     101        r""" Return True if self is finite, which is true if and only if 
     102        self.group() and self.base_ring() are both finite. 
     103         
     104        EXAMPLES: 
     105            sage: GroupAlgebra(SymmetricGroup(2), IntegerModRing(10)).is_finite() 
     106            True 
     107            sage: GroupAlgebra(SymmetricGroup(2)).is_finite() 
     108            False 
     109            sage: GroupAlgebra(AbelianGroup(1), IntegerModRing(10)).is_finite() 
     110            False 
     111        """ 
     112        return (self.base_ring().is_finite() and self.group().is_finite()) 
     113 
     114    def is_exact(self): 
     115        r""" Return True if elements of self have exact representations, 
     116        which is true of self if and only if it is true of self.group() 
     117        and self.base_ring(). 
     118 
     119        EXAMPLES: 
     120            sage: GroupAlgebra(GL(3, GF(7))).is_exact() 
     121            True 
     122            sage: GroupAlgebra(GL(3, GF(7)), RR).is_exact() 
     123            False 
     124            sage: GroupAlgebra(GL(3, pAdicRing(7))).is_exact() # not implemented correctly (not my fault)! 
     125            False 
     126        """ 
     127        return self.group().is_exact() and self.base_ring().is_exact() 
     128 
     129    def is_integral_domain(self): 
     130        r""" Return True if self is an integral domain.  
     131         
     132        This is false unless 
     133        self.base_ring() is an integral domain, and even then it is false unless 
     134        self.group() has no nontrivial elements of finite order. I don't know if  
     135        this condition suffices, but it obviously does if the group is abelian and 
     136        finitely generated. 
     137 
     138        EXAMPLES: 
     139            sage: GroupAlgebra(SymmetricGroup(2)).is_integral_domain() 
     140            False 
     141            sage: GroupAlgebra(SymmetricGroup(1)).is_integral_domain() 
     142            True 
     143            sage: GroupAlgebra(SymmetricGroup(1), IntegerModRing(4)).is_integral_domain() 
     144            False 
     145            sage: GroupAlgebra(AbelianGroup(1)).is_integral_domain() 
     146            True 
     147            sage: GroupAlgebra(AbelianGroup(2, [0,2])).is_integral_domain() 
     148            False 
     149            sage: GroupAlgebra(GL(2, ZZ)).is_integral_domain() # not implemented 
     150            False 
     151        """ 
     152        if not self.base_ring().is_integral_domain(): 
     153            return False 
     154        if self.group().is_finite(): 
     155            if self.group().order() > 1: 
     156                return False 
     157            else: 
     158                return True 
     159        if self.group().is_abelian(): 
     160            invs = self.group().invariants() 
     161            if Set(invs) != Set([0]): 
     162                return False 
     163            else: 
     164                return True 
     165        if not self.group().is_abelian(): 
     166            raise NotImplementedError 
     167 
     168    # I haven't written is_noetherian(), because I don't know when group 
     169    # algebras are noetherian, and I haven't written is_prime_field(), because 
     170    # I don't know if that means "is canonically isomorphic to a prime field" 
     171    # or "is identical to a prime field". 
     172 
     173    def _coerce_impl(self, x): 
     174        return self(self.base_ring().coerce(x)) 
     175 
     176    def _an_element_impl(self): 
     177        """ 
     178        Return an element of self.  
     179         
     180        EXAMPLE: 
     181            sage: GroupAlgebra(SU(2, 13), QQ).an_element() # random; hideous formatting! 
     182            -1/95*[       9 2*a + 12] 
     183            [       0        3] - 4*[      9 9*a + 2] 
     184            [3*a + 5       1] 
     185        """ 
     186        try: 
     187            return self(self._formal_sum_module([ 
     188                (self.base_ring().random_element(), self.group().random_element()), 
     189                (self.base_ring().random_element(), self.group().random_element()), 
     190                ])) 
     191        except: # base ring or group might not implement .random_element() 
     192            return self(self._formal_sum_module([ (self.base_ring().an_element(), self.group().an_element()) ])) 
     193 
     194    def __call__(self, x, check=True): 
     195        r""" 
     196        Create an element of this group algebra. 
     197         
     198        INPUT: 
     199            -- x: either a FormalSum element consisting of elements of 
     200            self.group(), an element of self.base_ring(), or an element  
     201            of self.group(). 
     202            -- check (boolean): whether or not to check that the given elements 
     203            really do lie in self.group(). 
     204 
     205        OUTPUT: 
     206            -- a GroupAlgebraElement instance whose parent is self. 
     207 
     208        EXAMPLES: 
     209            sage: G = AbelianGroup(1) 
     210            sage: f = G.gen() 
     211            sage: ZG = GroupAlgebra(G) 
     212            sage: ZG(f) 
     213            f 
     214            sage: ZG(1) == ZG(G(1)) 
     215            True 
     216            sage: ZG(FormalSum([(1,f), (2, f**2)])) 
     217            2*f^2 + f 
     218            sage: G = GL(2,7) 
     219            sage: OG = GroupAlgebra(G, ZZ[sqrt(5)]) 
     220            sage: OG(2) 
     221            2*[1 0] 
     222            [0 1] 
     223            sage: OG(G(2)) # conversion is not the obvious one 
     224            [2 0] 
     225            [0 2] 
     226            sage: OG(FormalSum([ (1, G(2)), (2, RR(0.77)) ]) ) 
     227            Traceback (most recent call last): 
     228            ... 
     229            TypeError: 0.770000000000000 is not an element of group General Linear Group of degree 2 over Finite Field of size 7 
     230            sage: OG(FormalSum([ (1, G(2)), (2, RR(0.77)) ]), check=False) 
     231            [2 0] 
     232            [0 2] + 2*0.770000000000000 
     233            sage: OG(OG.base_ring().gens()[1]) 
     234            sqrt5*[1 0] 
     235            [0 1] 
     236            """ 
     237        return GroupAlgebraElement(self, x, check) 
     238 
     239    def __eq__(self, other): 
     240        r""" Test for equality.  
     241        EXAMPLES: 
     242            sage: GroupAlgebra(AbelianGroup(1)) == GroupAlgebra(AbelianGroup(1)) 
     243            True 
     244            sage: GroupAlgebra(AbelianGroup(1), QQ) == GroupAlgebra(AbelianGroup(1), ZZ) 
     245            False 
     246            sage: GroupAlgebra(AbelianGroup(2)) == GroupAlgebra(AbelianGroup(1)) 
     247            False 
     248            """ 
     249        if not isinstance(other, GroupAlgebra): 
     250            return False 
     251        else: 
     252            return self.base_ring() == other.base_ring() and self.group() == other.group() 
     253 
     254    def _repr_(self): 
     255        r""" String representation of self. See GroupAlgebra.__init__ for a 
     256        doctest.""" 
     257        return "Group algebra of group \"%s\" over base ring %s" % (self.group(), self.base_ring()) 
     258 
     259    def element_class(self): 
     260        r""" 
     261        The class of elements of self, which is GroupAlgebraElement. 
     262 
     263        EXAMPLES: 
     264            sage: GroupAlgebra(SU(2, GF(4,'a'))).element_class() 
     265            <class 'sage.algebras.group_algebra.GroupAlgebraElement'> 
     266        """ 
     267        return GroupAlgebraElement 
     268 
     269 
     270    def category(self): 
     271        r""" 
     272        The category to which self belongs, which is the category of group algebras over self.base_ring(). 
     273 
     274        EXAMPLES: 
     275            sage: GroupAlgebra(SU(2, GF(4, 'a')), IntegerModRing(12)).category() 
     276            Category of group algebras over Ring of integers modulo 12 
     277        """ 
     278        from sage.categories.category_types import GroupAlgebras 
     279        return GroupAlgebras(self.base_ring()) 
     280 
     281 
     282 
     283class GroupAlgebraElement(AlgebraElement): 
     284     
     285    def __init__(self, parent, x, check): 
     286        r""" Create an element of the parent group algebra. Not intended to be 
     287        called by the user; see GroupAlgebra.__call__ for examples and 
     288        doctests.""" 
     289        AlgebraElement.__init__(self, parent) 
     290         
     291        if not hasattr(x, 'parent'): 
     292            x = IntegerRing()(x) # occasionally coercion framework tries to pass a Python int 
     293 
     294        if isinstance(x, FormalSum): 
     295            if check: 
     296                for c,d in x._data: 
     297                    if d.parent() != self.parent().group(): 
     298                        raise TypeError, "%s is not an element of group %s" % (d, self.parent().group()) 
     299                self._fs = x 
     300            else: 
     301                self._fs = x 
     302 
     303        elif self.base_ring().has_coerce_map_from(x.parent()): 
     304            self._fs = self.parent()._formal_sum_module([ (x, self.parent().group()(1)) ]) 
     305        elif self.parent().group().has_coerce_map_from(x.parent()): 
     306            self._fs = self.parent()._formal_sum_module([ (1, self.parent().group()(x)) ]) 
     307        else: 
     308            raise TypeError, "Don't know how to create an element of %s from %s" % (self.parent(), x) 
     309 
     310    def _repr_(self): 
     311        return self._fs._repr_() 
     312 
     313    def _add_(self, other): 
     314        r""" 
     315        Add self to other. 
     316         
     317        EXAMPLE: 
     318            sage: G = GL(3, GF(7)) 
     319            sage: ZG = GroupAlgebra(G) 
     320            sage: g1 = G([0,0,2,2,5,0,6,6,2]) 
     321            sage: s = ZG(g1) 
     322            sage: s + s 
     323            2*[0  0  2] 
     324            [2  5  0] 
     325            [6  6  2] 
     326""" 
     327        fs_sum = self._fs + other._fs 
     328        return self.parent()(fs_sum, check=False) 
     329 
     330    def _mul_(self, right): 
     331        r""" Calculate self*right, where both self and right are GroupAlgebraElements. 
     332         
     333        EXAMPLE: 
     334            sage: G = GL(3, GF(7)) 
     335            sage: ZG = GroupAlgebra(G) 
     336            sage: a, b = G.random_element(), G.random_element() 
     337            sage: za, zb = ZG(a), ZG(b) 
     338            sage: za*ZG(2) # random 
     339            2*[4,5,0] 
     340            [0,5,1] 
     341            [2,5,1] 
     342            sage: za*2 == za*ZG(2) 
     343            True 
     344            sage: (ZG(1) + za)*(ZG(2) + zb) == ZG(FormalSum([ (2,G(1)), (2,a), (1, b), (1, a*b)])) 
     345            True 
     346            sage: za*za == za^2 
     347            True 
     348        """ 
     349        d1 = self._fs._data 
     350        d2 = right._fs._data 
     351        new = [] 
     352        for (a1, g1) in d1: 
     353            for a2,g2 in d2: 
     354                if self.parent().group().is_multiplicative(): 
     355                    new.append( (a1*a2, g1*g2) ) 
     356                else: 
     357                    new.append( (a1*a2, g1 + g2) ) 
     358        return self.parent()( self.parent()._formal_sum_module(new), check=False) 
     359 
     360    def __eq__(self, other): 
     361        r""" Test if self is equal to other. 
     362 
     363        EXAMPLES: 
     364            sage: G = AbelianGroup(1,[4]) 
     365            sage: a = GroupAlgebra(G)(1) 
     366            sage: b = GroupAlgebra(G)(2) 
     367            sage: a + a == b 
     368            True 
     369            sage: a == b 
     370            False 
     371            sage: a == GroupAlgebra(AbelianGroup(1, [5]))(1) 
     372            False 
     373        """ 
     374        if isinstance(other, GroupAlgebraElement) and self.parent() == other.parent(): 
     375            return self._fs == other._fs 
     376        else: 
     377            return False