Ticket #6670: trac-6670-group_algebra-3.patch

File trac-6670-group_algebra-3.patch, 21.3 KB (added by Martin Raum, 13 years ago)

This is a rebase to 4.3alpha0 .

  • sage/algebras/group_algebra.py

    diff -r 44f70d431d43 sage/algebras/group_algebra.py
    a b  
    2828from sage.rings.all import IntegerRing
    2929from sage.groups.group import Group
    3030from sage.structure.formal_sum import FormalSums_generic, FormalSums, FormalSum
     31from sage.structure.element import Element
    3132from sage.sets.set import Set
     33from sage.misc.latex import latex
    3234
     35from sage.categories.morphism import Morphism
     36from sage.categories.pushout import ConstructionFunctor
     37from sage.categories.rings import Rings
    3338
    34 class GroupAlgebra(Algebra):
     39_cache = dict()
    3540
    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.
     41class GroupAlgebraFunctor ( ConstructionFunctor ) :
     42    r"""
     43    A functor assigning a group algebra to its base ring.
     44    """
     45    def __init__(self, group) :
     46        r"""
     47        INPUT :
     48        group       -- a group that will be the module basis for the
     49                       group algebras in the range.
    4350
    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
     51        EXAMPLES :
     52            sage: F = GroupAlgebraFunctor(KleinFourGroup())
     53            sage: loads(dumps(F)) == F
     54            True
    5255        """
    53         if not base_ring.is_commutative():
    54             raise NotImplementedError, "Base ring must be commutative"
     56        self.__group = group
     57
     58        ConstructionFunctor.__init__(self, Rings(), Rings())
     59
     60    def group(self) :
     61        r"""
     62        Return the group which is associtated to this functor.
     63
     64        EXAMPLES :
     65            sage: GroupAlgebraFunctor(CyclicPermutationGroup(17)).group() == CyclicPermutationGroup(17)
     66            True
     67        """
     68        return self.__group
     69
     70    def __call__(self, base_ring) :
     71        r""" Create the group algeba with given base ring over self.group().
     72        INPUT :
     73        base_ring       -- the base ring of the group algebra.
     74        OUTPUT :
     75        A group algebra.
     76
     77        EXAMPLES :
     78            sage: F = GroupAlgebraFunctor(CyclicPermutationGroup(17))
     79            sage: F(QQ)
     80            Group algebra of group "Cyclic group of order 17 as a permutation group" over base ring Rational Field
     81        """
     82        return GroupAlgebra(self.__group, base_ring)
     83
     84def GroupAlgebra(group, base_ring = IntegerRing()) :
     85    r""" Create the given group algebra.
     86    INPUT:
     87        -- (Group) group: a generic group.
     88        -- (Ring) base_ring: a commutative ring.
     89    OUTPUT:
     90        -- a GroupAlgebra instance.
     91
     92    EXAMPLES:
     93        sage: GroupAlgebra(GL(3, GF(7)))
     94        Group algebra of group "General Linear Group of degree 3 over Finite
     95        Field of size 7" over base ring Integer Ring
     96        sage: GroupAlgebra(1)
     97        Traceback (most recent call last):
     98        ...
     99        TypeError: "1" is not a group
     100        sage: GroupAlgebra(KleinFourGroup()) is GroupAlgebra(KleinFourGroup())
     101        True
     102    """
     103    global _cache
     104
     105    if not base_ring.is_commutative():
     106        raise NotImplementedError, "Base ring must be commutative"
    55107       
    56         if not isinstance(group, Group):
    57             raise TypeError, '"%s" is not a group' % group
     108    if not isinstance(group, Group):
     109        raise TypeError, '"%s" is not a group' % group
    58110
     111
     112    key = (group, base_ring)
     113
     114    try :
     115        return _cache[key]
     116    except KeyError :
     117        A = GroupAlgebra_class(group, base_ring)
     118        _cache[key] = A
     119   
     120        return A
     121
     122class GroupAlgebra_class ( Algebra ) :
     123
     124    def __init__(self, group, base_ring):
     125        r"""
     126        EXAMPLES :
     127            sage: A = GroupAlgebra(GL(3, GF(7)))
     128            sage: A.has_coerce_map_from(GL(3, GF(7)))
     129            True
     130        """
    59131        Algebra.__init__(self, base_ring)
     132       
    60133        self._formal_sum_module = FormalSums(base_ring)
    61134        self._group = group
    62135
     136        if not base_ring.has_coerce_map_from(group) :
     137            ## some matrix groups assume that coercion is only valid to
     138            ## other matrix groups. This is a workaround
     139            ## call _element_constructor_ to coerce group elements
     140            #try :
     141            self._populate_coercion_lists_( coerce_list = [base_ring, group] )
     142            #except TypeError :
     143            #    self._populate_coercion_lists_( coerce_list = [base_ring] )
     144        else :
     145            self._populate_coercion_lists_( coerce_list = [base_ring] )
     146
     147    def ngens(self) :
     148        r""" Return the number of generators.
     149
     150        EXAMPLES :
     151            sage: A = GroupAlgebra(SL2Z)
     152            sage: A.ngens()
     153            2
     154        """
     155        return self._group.ngens()
     156
     157    def gen(self, i = 0) :
     158        r"""
     159        EXAMPLES :
     160            sage: A = GroupAlgebra(GL(3, GF(7)))
     161            sage: A.gen(0)
     162            [3 0 0]
     163            [0 1 0]
     164            [0 0 1]
     165        """
     166        return self._element_constructor(self._group.gen(i), as_group_element = True)
     167
    63168    def group(self):
    64169        r""" Return the group of this group algebra.
     170
    65171        EXAMPLES:
    66172            sage: GroupAlgebra(GL(3, GF(11))).group()
    67173            General Linear Group of degree 3 over Finite Field of size 11
     
    70176        """
    71177        return self._group
    72178
     179    ###########################################################################
     180    ## GroupAlgebra_class :: mathmatical properties
     181    ###########################################################################
     182
    73183    def is_commutative(self):
    74184        r""" Return True if self is a commutative ring. True if and only if
    75185        self.group() is abelian.
     
    182292    # I don't know if that means "is canonically isomorphic to a prime field"
    183293    # or "is identical to a prime field".
    184294
    185     def _coerce_impl(self, x):
    186         return self(self.base_ring().coerce(x))
     295    ###########################################################################
     296    ## GroupAlgebra_class :: elements
     297    ###########################################################################
    187298
    188     def _an_element_impl(self):
     299    def _an_element_(self):
     300        r""" Return an element of self.
     301        EXAMPLES :
     302            sage: A = GroupAlgebra(GL(3, GF(7)))
     303            sage: A.an_element()
     304            [3 0 0]
     305            [0 1 0]
     306            [0 0 1]
    189307        """
    190         Return an element of self.
    191        
     308        return self(self._formal_sum_module([
     309             (self.base_ring().an_element(), self.group().an_element())
     310             ]))
     311
     312    def random_element(self) :
     313        r""" Return a random element of self.
    192314        EXAMPLE:
    193315            sage: GroupAlgebra(SU(2, 13), QQ).an_element() # random; hideous formatting!
    194316            -1/95*[       9 2*a + 12]
    195317            [       0        3] - 4*[      9 9*a + 2]
    196318            [3*a + 5       1]
    197319        """
    198         try:
    199             return self(self._formal_sum_module([
    200                 (self.base_ring().random_element(), self.group().random_element()),
    201                 (self.base_ring().random_element(), self.group().random_element()),
    202                 ]))
    203         except: # base ring or group might not implement .random_element()
    204             return self(self._formal_sum_module([ (self.base_ring().an_element(), self.group().an_element()) ]))
     320        return self(self._formal_sum_module([
     321            (self.base_ring().random_element(), self.group().random_element()),
     322            (self.base_ring().random_element(), self.group().random_element()),
     323            ]))
    205324
    206     def __call__(self, x, check=True):
     325    def construction(self) :
     326        r"""
     327        EXAMPLES :
     328        sage: A = GroupAlgebra(KleinFourGroup(), QQ)
     329        sage: A.construction()                                       
     330        (GroupAlgebraFunctor, Rational Field)
     331        """
     332        return GroupAlgebraFunctor(self._group), self.base_ring()
     333
     334    def _element_constructor_(self, x, as_group_element = False) :
    207335        r"""
    208336        Create an element of this group algebra.
    209337       
     
    211339            -- x: either a FormalSum element consisting of elements of
    212340            self.group(), an element of self.base_ring(), or an element
    213341            of self.group().
    214             -- check (boolean): whether or not to check that the given elements
    215             really do lie in self.group(). Chiefly provided to speed up
    216             arithmetic operations with elements that have already been checked
    217             to lie in the group.
    218 
     342            -- as_group_element : if true and x may be considered as a basis
     343            element and a group element, consider it a group element
    219344        OUTPUT:
    220345            -- a GroupAlgebraElement instance whose parent is self.
    221346
    222347        EXAMPLES:
    223             sage: G = AbelianGroup(1)
    224             sage: f = G.gen()
     348            sage: G = KleinFourGroup()
     349            sage: f = G.gen(0)
    225350            sage: ZG = GroupAlgebra(G)
    226351            sage: ZG(f)
    227             f
     352            (3,4)
    228353            sage: ZG(1) == ZG(G(1))
    229354            True
     355            sage: G = AbelianGroup(1)
     356            sage: ZG = GroupAlgebra(G)
     357            sage: f = ZG.group().gen()
    230358            sage: ZG(FormalSum([(1,f), (2, f**2)]))
    231             2*f^2 + f
     359            f + 2*f^2
    232360            sage: G = GL(2,7)
    233361            sage: OG = GroupAlgebra(G, ZZ[sqrt(5)])
    234362            sage: OG(2)
     
    240368            sage: OG(FormalSum([ (1, G(2)), (2, RR(0.77)) ]) )
    241369            Traceback (most recent call last):
    242370            ...
    243             TypeError: 0.770000000000000 is not an element of group General Linear Group of degree 2 over Finite Field of size 7
     371            TypeError: Cannot coerce 0.770000000000000 to a 2-by-2 matrix over Finite Field of size 7
    244372
    245373        Ordering of elements in output unpredictable as sort order of such wildly
    246374        dissimilar elements is subject to change between platforms and versions
    247375        (see trac ticket \#4373).
    248             sage: OG(FormalSum([ (1, G(2)), (2, RR(0.77)) ]), check=False) # random
    249             [2 0]
    250             [0 2] + 2*0.770000000000000
    251376            sage: OG(OG.base_ring().gens()[1])
    252377            sqrt5*[1 0]
    253378            [0 1]
    254             """
    255         return GroupAlgebraElement(self, x, check)
     379        """
     380        if isinstance(x, Element) :
     381            P = x.parent()
     382            if P is self.base_ring() and not as_group_element:
     383                return GroupAlgebraElement_class(self,
     384                 self._formal_sum_module( [(x, self.group()(1))] ) )
     385            elif P is self.group() :
     386                return GroupAlgebraElement_class(self,
     387                 self._formal_sum_module( [(self.base_ring().one_element(), x)] ) )
     388            elif P is self._formal_sum_module :
     389                return GroupAlgebraElement_class(self, x)
     390            elif isinstance(x, FormalSum) and self._formal_sum_module.has_coerce_map_from(P) :
     391                 return GroupAlgebraElement_class(self,
     392                          self._formal_sum_module(
     393                           [(self.base_ring()(c), self.group()(g)) for c,g in x] ) )
    256394
    257     def __eq__(self, other):
    258         r""" Test for equality.
     395        raise TypeError, "Don't know how to create an element of %s from %s" % \
     396                             (self, x)
     397
     398    def __cmp__(self, other) :
     399        r"""
     400        Compare two algebras self and other. They are considered equal if and only
     401        if their base rings and their groups coincide.
     402
    259403        EXAMPLES:
    260404            sage: GroupAlgebra(AbelianGroup(1)) == GroupAlgebra(AbelianGroup(1))
    261405            True
     
    263407            False
    264408            sage: GroupAlgebra(AbelianGroup(2)) == GroupAlgebra(AbelianGroup(1))
    265409            False
    266             """
    267         if not isinstance(other, GroupAlgebra):
    268             return False
    269         else:
    270             return self.base_ring() == other.base_ring() and self.group() == other.group()
     410            sage: from sage.algebras.group_algebra import GroupAlgebra_class
     411            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     412            sage: B = GroupAlgebra_class(KleinFourGroup(), QQ)
     413            sage: A == B
     414            False
     415            sage: A == A
     416            True
     417        """
     418        c = cmp(type(self), type(other))
     419
     420        if c == 0 :
     421            c = cmp(self._group, other._group)
     422        if c == 0 :
     423            c = cmp(self.base_ring(), other.base_ring())
     424
     425        return c
    271426
    272427    def _repr_(self):
    273428        r""" String representation of self. See GroupAlgebra.__init__ for a
    274         doctest."""
    275         return "Group algebra of group \"%s\" over base ring %s" % (self.group(), self.base_ring())
     429        doctest.
     430
     431        EXAMPLES :
     432            sage: A = GroupAlgebra(KleinFourGroup(), ZZ)
     433            sage: A
     434            Group algebra of group "The Klein 4 group of order 4, as a permutation group" over base ring Integer Ring
     435        """
     436        return "Group algebra of group \"%s\" over base ring %s" % \
     437               (self.group(), self.base_ring())
     438
     439    def _latex_(self):
     440        r"""Latex string of self.
     441       
     442        EXAMPLES :
     443            sage: A = GroupAlgebra(KleinFourGroup(), ZZ)
     444            sage: latex(A)
     445            Group algebra of group \langle (3,4), (1,2) \rangle over base ring \Bold{Z}
     446        """
     447        return "Group algebra of group %s over base ring %s" % \
     448               (latex(self.group()), latex(self.base_ring()))
    276449
    277450    def element_class(self):
    278451        r"""
     
    280453
    281454        EXAMPLES:
    282455            sage: GroupAlgebra(SU(2, GF(4,'a'))).element_class()
    283             <class 'sage.algebras.group_algebra.GroupAlgebraElement'>
     456            <class 'sage.algebras.group_algebra.GroupAlgebraElement_class'>
    284457        """
    285         return GroupAlgebraElement
    286 
     458        return GroupAlgebraElement_class
    287459
    288460    def category(self):
    289461        r"""
     
    296468        from sage.categories.all import GroupAlgebras
    297469        return GroupAlgebras(self.base_ring())
    298470
     471def GroupAlgebraElement(parent, x, check = True) :
     472    r"""
     473    Create an element of the group algebra parent.
     474    x       -- an element of the base ring, the group or a formal sum with
     475               summand (a, g), where a is in the base ring and g is in the group
     476    check   -- determines whether the summand of a formal sum will be checked
     477               for correctness
     478   
     479    EXAMPLES :
     480        sage: G = KleinFourGroup()
     481        sage: A = GroupAlgebra(G)   
     482        sage: GroupAlgebraElement(A, A.group().gen(1))
     483        (1,2)
     484        sage: GroupAlgebraElement(A, 1)               
     485        ()
     486        sage: GroupAlgebraElement(A, 10)
     487        10*()
     488    """
     489    ## Provide this for backward compatibility to the old class layout
    299490
     491    assert isinstance(parent, GroupAlgebra_class), "%s must be group algebra"
    300492
    301 class GroupAlgebraElement(AlgebraElement):
     493    if not isinstance(x, Element) :
     494        x = IntegerRing()(x)
    302495   
    303     def __init__(self, parent, x, check):
     496    if isinstance(x, FormalSum) and check :
     497        for c,g in x :
     498            if not c in parent.base_ring() or not g in parent.group() :
     499                raise ValueError, "summands of %s must be elements of base " + \
     500                                  "ring and group respectively"
     501
     502    return parent._element_constructor(x)
     503
     504###########################################################################
     505## GroupAlgebraElement_class
     506###########################################################################
     507
     508class GroupAlgebraElement_class ( AlgebraElement ) :
     509   
     510    def __init__(self, parent, x) :
    304511        r""" Create an element of the parent group algebra. Not intended to be
    305512        called by the user; see GroupAlgebra.__call__ for examples and
    306         doctests."""
     513        doctests.
     514       
     515        EXAMPLES :
     516            sage: A = GroupAlgebra(KleinFourGroup(), ZZ)
     517            sage: GroupAlgebraElement(A, A._formal_sum_module([(1, KleinFourGroup().gen(0))]))
     518            (3,4)
     519        """
    307520        AlgebraElement.__init__(self, parent)
    308521       
    309         if not hasattr(x, 'parent'):
    310             x = IntegerRing()(x) # occasionally coercion framework tries to pass a Python int
     522        self._fs = x
    311523
    312         if isinstance(x, FormalSum):
    313             if check:
    314                 for c,d in x._data:
    315                     if d.parent() != self.parent().group():
    316                         raise TypeError, "%s is not an element of group %s" % (d, self.parent().group())
    317                 self._fs = x
    318             else:
    319                 self._fs = x
     524    ###########################################################################
     525    ## GroupAlgebraElement_class :: Arithmetic
     526    ###########################################################################
    320527
    321         elif self.base_ring().has_coerce_map_from(x.parent()):
    322             self._fs = self.parent()._formal_sum_module([ (x, self.parent().group()(1)) ])
    323         elif self.parent().group().has_coerce_map_from(x.parent()):
    324             self._fs = self.parent()._formal_sum_module([ (1, self.parent().group()(x)) ])
    325         else:
    326             raise TypeError, "Don't know how to create an element of %s from %s" % (self.parent(), x)
    327 
    328     def _repr_(self):
    329         return self._fs._repr_()
    330 
    331     def _add_(self, other):
     528    def _add_(left, right):
    332529        r"""
    333         Add self to other.
     530        Add left to right.
    334531       
    335532        EXAMPLE:
    336533            sage: G = GL(3, GF(7))
    337534            sage: ZG = GroupAlgebra(G)
    338             sage: g1 = G([0,0,2,2,5,0,6,6,2])
     535            sage: g1 = ZG.group()([0,0,2,2,5,0,6,6,2])
    339536            sage: s = ZG(g1)
    340537            sage: s + s
    341538            2*[0  0  2]
    342539            [2  5  0]
    343540            [6  6  2]
    344 """
    345         fs_sum = self._fs + other._fs
    346         return self.parent()(fs_sum, check=False)
     541        """
     542        return left.parent()(left._fs + right._fs)
    347543
    348     def _mul_(self, right):
    349         r""" Calculate self*right, where both self and right are GroupAlgebraElements.
     544    def _mul_(left, right):
     545        r""" Calculate left*right, where both left and right are GroupAlgebraElements_class.
    350546       
    351547        EXAMPLE:
    352548            sage: G = GL(3, GF(7))
    353549            sage: ZG = GroupAlgebra(G)
    354             sage: a, b = G.random_element(), G.random_element()
     550            sage: a, b = ZG.group().random_element(), ZG.group().random_element()
    355551            sage: za, zb = ZG(a), ZG(b)
    356552            sage: za*ZG(2) # random
    357553            2*[4,5,0]
     
    364560            sage: za*za == za^2
    365561            True
    366562        """
    367         d1 = self._fs._data
    368         d2 = right._fs._data
    369         new = []
    370         for (a1, g1) in d1:
    371             for a2,g2 in d2:
    372                 if self.parent().group().is_multiplicative():
    373                     new.append( (a1*a2, g1*g2) )
    374                 else:
    375                     new.append( (a1*a2, g1 + g2) )
    376         return self.parent()( self.parent()._formal_sum_module(new), check=False)
     563        if left.parent().group().is_multiplicative() :
     564            product = [ (a1 * a2, g1 * g2)
     565                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
     566        else :
     567            product = [ (a1 * a2, g1 + g2)
     568                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
    377569
    378     def __eq__(self, other):
    379         r""" Test if self is equal to other.
     570        return left.parent()( left.parent()._formal_sum_module(product) )
     571
     572    ###########################################################################
     573    ## GroupAlgebraElement_class :: Comparision
     574    ###########################################################################
     575
     576    def __cmp__(self, other) :
     577        r""" Compare self and other.
    380578
    381579        EXAMPLES:
    382580            sage: G = AbelianGroup(1,[4])
    383             sage: a = GroupAlgebra(G)(1)
    384             sage: b = GroupAlgebra(G)(2)
     581            sage: ZG = GroupAlgebra(G)
     582            sage: a = ZG(1)
     583            sage: b = ZG(2)
    385584            sage: a + a == b
    386585            True
    387586            sage: a == b
     
    389588            sage: a == GroupAlgebra(AbelianGroup(1, [5]))(1)
    390589            False
    391590        """
    392         if isinstance(other, GroupAlgebraElement) and self.parent() == other.parent():
    393             return self._fs == other._fs
    394         else:
    395             return False
     591        c = cmp(type(self), type(other))
     592
     593        if c == 0 :
     594            c = cmp(self._fs, other._fs)
     595
     596        return c
     597
     598    ###########################################################################
     599    ## GroupAlgebraElement_class :: Representations
     600    ###########################################################################
     601
     602    def _repr_(self) :
     603        r"""
     604        EXAMPLES :
     605            sage: G = KleinFourGroup()
     606            sage: A = GroupAlgebra(G, ZZ)
     607            sage: latex(A(1) + A(A.group().gen(0)))
     608            () + (3,4)
     609        """
     610        return self._fs._repr_()
     611
     612    def _latex_(self) :
     613        r"""
     614        EXAMPLES :
     615            sage: G = KleinFourGroup()
     616            sage: A = GroupAlgebra(G, ZZ)
     617            sage: latex(A(1) + A(A.group().gen(0)))
     618            () + (3,4)
     619        """
     620        return latex(self._fs)
     621