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

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

This is a rebase to 4.1.2

  • sage/algebras/all.py

    diff -r 5bf36a37cd0c sage/algebras/all.py
    a b  
    3333from steenrod_algebra_element import Sq
    3434from steenrod_algebra_bases import steenrod_algebra_basis
    3535
    36 from group_algebra import GroupAlgebra, GroupAlgebraElement
     36from group_algebra import GroupAlgebra, GroupAlgebraElement, GroupAlgebraFunctor, GroupAlgebra_class, GroupAlgebraElement_class
    3737
    3838   
    3939def is_R_algebra(Q, R):
  • sage/algebras/group_algebra.py

    diff -r 5bf36a37cd0c 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.category_types 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: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     411            sage: B = GroupAlgebra_class(KleinFourGroup(), QQ)
     412            sage: A == B
     413            False
     414            sage: A == A
     415            True
     416        """
     417        c = cmp(type(self), type(other))
     418
     419        if c == 0 :
     420            c = cmp(self._group, other._group)
     421        if c == 0 :
     422            c = cmp(self.base_ring(), other.base_ring())
     423
     424        return c
    271425
    272426    def _repr_(self):
    273427        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())
     428        doctest.
     429
     430        EXAMPLES :
     431            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     432            sage: A
     433            Group algebra of group "The Klein 4 group of order 4, as a permutation group" over base ring Integer Ring
     434        """
     435        return "Group algebra of group \"%s\" over base ring %s" % \
     436               (self.group(), self.base_ring())
     437
     438    def _latex_(self):
     439        r"""Latex string of self.
     440       
     441        EXAMPLES :
     442            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     443            sage: latex(A)
     444            Group algebra of group \langle (3,4), (1,2) \rangle over base ring \Bold{Z}
     445        """
     446        return "Group algebra of group %s over base ring %s" % \
     447               (latex(self.group()), latex(self.base_ring()))
    276448
    277449    def element_class(self):
    278450        r"""
     
    280452
    281453        EXAMPLES:
    282454            sage: GroupAlgebra(SU(2, GF(4,'a'))).element_class()
    283             <class 'sage.algebras.group_algebra.GroupAlgebraElement'>
     455            <class 'sage.algebras.group_algebra.GroupAlgebraElement_class'>
    284456        """
    285         return GroupAlgebraElement
    286 
     457        return GroupAlgebraElement_class
    287458
    288459    def category(self):
    289460        r"""
     
    296467        from sage.categories.category_types import GroupAlgebras
    297468        return GroupAlgebras(self.base_ring())
    298469
     470def GroupAlgebraElement(parent, x, check = True) :
     471    r"""
     472    Create an element of the group algebra parent.
     473    x       -- an element of the base ring, the group or a formal sum with
     474               summand (a, g), where a is in the base ring and g is in the group
     475    check   -- determines whether the summand of a formal sum will be checked
     476               for correctness
     477   
     478    EXAMPLES :
     479        sage: G = KleinFourGroup()
     480        sage: A = GroupAlgebra_class(G, ZZ)   
     481        sage: GroupAlgebraElement(A, G.gen(1))
     482        (1,2)
     483        sage: GroupAlgebraElement(A, 1)                     
     484        ()
     485        sage: GroupAlgebraElement(A, 10)
     486        10*()
     487    """
     488    ## Provide this for backward compatibility to the old class layout
    299489
     490    assert isinstance(parent, GroupAlgebra_class), "%s must be group algebra"
    300491
    301 class GroupAlgebraElement(AlgebraElement):
     492    if not isinstance(x, Element) :
     493        x = IntegerRing()(x)
    302494   
    303     def __init__(self, parent, x, check):
     495    if isinstance(x, FormalSum) and check :
     496        for c,g in x :
     497            if not c in parent.base_ring() or not g in parent.group() :
     498                raise ValueError, "summands of %s must be elements of base " + \
     499                                  "ring and group respectively"
     500
     501    return parent._element_constructor(x)
     502
     503###########################################################################
     504## GroupAlgebraElement_class
     505###########################################################################
     506
     507class GroupAlgebraElement_class ( AlgebraElement ) :
     508   
     509    def __init__(self, parent, x) :
    304510        r""" Create an element of the parent group algebra. Not intended to be
    305511        called by the user; see GroupAlgebra.__call__ for examples and
    306         doctests."""
     512        doctests.
     513       
     514        EXAMPLES :
     515            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     516            sage: GroupAlgebraElement_class(A, A._formal_sum_module([(1, KleinFourGroup().gen(0))]))
     517            (3,4)
     518        """
    307519        AlgebraElement.__init__(self, parent)
    308520       
    309         if not hasattr(x, 'parent'):
    310             x = IntegerRing()(x) # occasionally coercion framework tries to pass a Python int
     521        self._fs = x
    311522
    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
     523    ###########################################################################
     524    ## GroupAlgebraElement_class :: Arithmetic
     525    ###########################################################################
    320526
    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):
     527    def _add_(left, right):
    332528        r"""
    333         Add self to other.
     529        Add left to right.
    334530       
    335531        EXAMPLE:
    336532            sage: G = GL(3, GF(7))
    337533            sage: ZG = GroupAlgebra(G)
    338             sage: g1 = G([0,0,2,2,5,0,6,6,2])
     534            sage: g1 = ZG.group()([0,0,2,2,5,0,6,6,2])
    339535            sage: s = ZG(g1)
    340536            sage: s + s
    341537            2*[0  0  2]
    342538            [2  5  0]
    343539            [6  6  2]
    344 """
    345         fs_sum = self._fs + other._fs
    346         return self.parent()(fs_sum, check=False)
     540        """
     541        return left.parent()(left._fs + right._fs)
    347542
    348     def _mul_(self, right):
    349         r""" Calculate self*right, where both self and right are GroupAlgebraElements.
     543    def _mul_(left, right):
     544        r""" Calculate left*right, where both left and right are GroupAlgebraElements_class.
    350545       
    351546        EXAMPLE:
    352547            sage: G = GL(3, GF(7))
    353548            sage: ZG = GroupAlgebra(G)
    354             sage: a, b = G.random_element(), G.random_element()
     549            sage: a, b = ZG.group().random_element(), ZG.group().random_element()
    355550            sage: za, zb = ZG(a), ZG(b)
    356551            sage: za*ZG(2) # random
    357552            2*[4,5,0]
     
    364559            sage: za*za == za^2
    365560            True
    366561        """
    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)
     562        if left.parent().group().is_multiplicative() :
     563            product = [ (a1 * a2, g1 * g2)
     564                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
     565        else :
     566            product = [ (a1 * a2, g1 + g2)
     567                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
    377568
    378     def __eq__(self, other):
    379         r""" Test if self is equal to other.
     569        return left.parent()( left.parent()._formal_sum_module(product) )
     570
     571    ###########################################################################
     572    ## GroupAlgebraElement_class :: Comparision
     573    ###########################################################################
     574
     575    def __cmp__(self, other) :
     576        r""" Compare self and other.
    380577
    381578        EXAMPLES:
    382579            sage: G = AbelianGroup(1,[4])
    383             sage: a = GroupAlgebra(G)(1)
    384             sage: b = GroupAlgebra(G)(2)
     580            sage: ZG = GroupAlgebra(G)
     581            sage: a = ZG(1)
     582            sage: b = ZG(2)
    385583            sage: a + a == b
    386584            True
    387585            sage: a == b
     
    389587            sage: a == GroupAlgebra(AbelianGroup(1, [5]))(1)
    390588            False
    391589        """
    392         if isinstance(other, GroupAlgebraElement) and self.parent() == other.parent():
    393             return self._fs == other._fs
    394         else:
    395             return False
     590        c = cmp(type(self), type(other))
     591
     592        if c == 0 :
     593            c = cmp(self._fs, other._fs)
     594
     595        return c
     596
     597    ###########################################################################
     598    ## GroupAlgebraElement_class :: Representations
     599    ###########################################################################
     600
     601    def _repr_(self) :
     602        r"""
     603        EXAMPLES :
     604            sage: G = KleinFourGroup()
     605            sage: A = GroupAlgebra_class(G, ZZ)
     606            sage: latex(A(1) + A(G.gen(0)))
     607            () + (3,4)
     608        """
     609        return self._fs._repr_()
     610
     611    def _latex_(self) :
     612        r"""
     613        EXAMPLES :
     614            sage: G = KleinFourGroup()
     615            sage: A = GroupAlgebra_class(G, ZZ)
     616            sage: latex(A(1) + A(G.gen(0)))
     617            () + (3,4)
     618        """
     619        return latex(self._fs)
     620