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

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

This applies cleanly to a fresh 4.3.1

  • sage/algebras/group_algebra.py

    diff -r 33c04bb5aea0 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: from sage.algebras.group_algebra import GroupAlgebraFunctor
     53            sage: F = GroupAlgebraFunctor(KleinFourGroup())
     54            sage: loads(dumps(F)) == F
     55            True
    5256        """
    53         if not base_ring.is_commutative():
    54             raise NotImplementedError, "Base ring must be commutative"
     57        self.__group = group
     58
     59        ConstructionFunctor.__init__(self, Rings(), Rings())
     60
     61    def group(self) :
     62        r"""
     63        Return the group which is associtated to this functor.
     64
     65        EXAMPLES :
     66            sage: from sage.algebras.group_algebra import GroupAlgebraFunctor
     67            sage: GroupAlgebraFunctor(CyclicPermutationGroup(17)).group() == CyclicPermutationGroup(17)
     68            True
     69        """
     70        return self.__group
     71
     72    def __call__(self, base_ring) :
     73        r""" Create the group algeba with given base ring over self.group().
     74        INPUT :
     75        base_ring       -- the base ring of the group algebra.
     76        OUTPUT :
     77        A group algebra.
     78
     79        EXAMPLES :
     80            sage: from sage.algebras.group_algebra import GroupAlgebraFunctor
     81            sage: F = GroupAlgebraFunctor(CyclicPermutationGroup(17))
     82            sage: F(QQ)
     83            Group algebra of group "Cyclic group of order 17 as a permutation group" over base ring Rational Field
     84        """
     85        return GroupAlgebra(self.__group, base_ring)
     86
     87def GroupAlgebra(group, base_ring = IntegerRing()) :
     88    r""" Create the given group algebra.
     89    INPUT:
     90        -- (Group) group: a generic group.
     91        -- (Ring) base_ring: a commutative ring.
     92    OUTPUT:
     93        -- a GroupAlgebra instance.
     94
     95    EXAMPLES:
     96        sage: GroupAlgebra(GL(3, GF(7)))
     97        Group algebra of group "General Linear Group of degree 3 over Finite
     98        Field of size 7" over base ring Integer Ring
     99        sage: GroupAlgebra(1)
     100        Traceback (most recent call last):
     101        ...
     102        TypeError: "1" is not a group
     103        sage: GroupAlgebra(KleinFourGroup()) is GroupAlgebra(KleinFourGroup())
     104        True
     105    """
     106    global _cache
     107
     108    if not base_ring.is_commutative():
     109        raise NotImplementedError, "Base ring must be commutative"
    55110       
    56         if not isinstance(group, Group):
    57             raise TypeError, '"%s" is not a group' % group
     111    if not isinstance(group, Group):
     112        raise TypeError, '"%s" is not a group' % group
    58113
     114
     115    key = (group, base_ring)
     116
     117    try :
     118        return _cache[key]
     119    except KeyError :
     120        A = GroupAlgebra_class(group, base_ring)
     121        _cache[key] = A
     122   
     123        return A
     124
     125class GroupAlgebra_class ( Algebra ) :
     126
     127    def __init__(self, group, base_ring):
     128        r"""
     129        EXAMPLES :
     130            sage: A = GroupAlgebra(GL(3, GF(7)))
     131            sage: A.has_coerce_map_from(GL(3, GF(7)))
     132            True
     133        """
    59134        Algebra.__init__(self, base_ring)
     135       
    60136        self._formal_sum_module = FormalSums(base_ring)
    61137        self._group = group
    62138
     139        if not base_ring.has_coerce_map_from(group) :
     140            ## some matrix groups assume that coercion is only valid to
     141            ## other matrix groups. This is a workaround
     142            ## call _element_constructor_ to coerce group elements
     143            #try :
     144            self._populate_coercion_lists_( coerce_list = [base_ring, group] )
     145            #except TypeError :
     146            #    self._populate_coercion_lists_( coerce_list = [base_ring] )
     147        else :
     148            self._populate_coercion_lists_( coerce_list = [base_ring] )
     149
     150    def ngens(self) :
     151        r""" Return the number of generators.
     152
     153        EXAMPLES :
     154            sage: A = GroupAlgebra(SL2Z)
     155            sage: A.ngens()
     156            2
     157        """
     158        return self._group.ngens()
     159
     160    def gen(self, i = 0) :
     161        r"""
     162        EXAMPLES :
     163            sage: A = GroupAlgebra(GL(3, GF(7)))
     164            sage: A.gen(0)
     165            [3 0 0]
     166            [0 1 0]
     167            [0 0 1]
     168        """
     169        return self._element_constructor(self._group.gen(i), as_group_element = True)
     170
    63171    def group(self):
    64172        r""" Return the group of this group algebra.
     173
    65174        EXAMPLES:
    66175            sage: GroupAlgebra(GL(3, GF(11))).group()
    67176            General Linear Group of degree 3 over Finite Field of size 11
     
    70179        """
    71180        return self._group
    72181
     182    ###########################################################################
     183    ## GroupAlgebra_class :: mathmatical properties
     184    ###########################################################################
     185
    73186    def is_commutative(self):
    74187        r""" Return True if self is a commutative ring. True if and only if
    75188        self.group() is abelian.
     
    182295    # I don't know if that means "is canonically isomorphic to a prime field"
    183296    # or "is identical to a prime field".
    184297
    185     def _coerce_impl(self, x):
    186         return self(self.base_ring().coerce(x))
     298    ###########################################################################
     299    ## GroupAlgebra_class :: elements
     300    ###########################################################################
    187301
    188     def _an_element_impl(self):
     302    def _an_element_(self):
     303        r""" Return an element of self.
     304        EXAMPLES :
     305            sage: A = GroupAlgebra(GL(3, GF(7)))
     306            sage: A.an_element()
     307            [3 0 0]
     308            [0 1 0]
     309            [0 0 1]
    189310        """
    190         Return an element of self.
    191        
     311        return self(self._formal_sum_module([
     312             (self.base_ring().an_element(), self.group().an_element())
     313             ]))
     314
     315    def random_element(self) :
     316        r""" Return a random element of self.
    192317        EXAMPLE:
    193318            sage: GroupAlgebra(SU(2, 13), QQ).an_element() # random; hideous formatting!
    194319            -1/95*[       9 2*a + 12]
    195320            [       0        3] - 4*[      9 9*a + 2]
    196321            [3*a + 5       1]
    197322        """
    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()) ]))
     323        return self(self._formal_sum_module([
     324            (self.base_ring().random_element(), self.group().random_element()),
     325            (self.base_ring().random_element(), self.group().random_element()),
     326            ]))
    205327
    206     def __call__(self, x, check=True):
     328    def construction(self) :
     329        r"""
     330        EXAMPLES :
     331        sage: A = GroupAlgebra(KleinFourGroup(), QQ)
     332        sage: A.construction()                                       
     333        (GroupAlgebraFunctor, Rational Field)
     334        """
     335        return GroupAlgebraFunctor(self._group), self.base_ring()
     336
     337    def _element_constructor_(self, x, as_group_element = False) :
    207338        r"""
    208339        Create an element of this group algebra.
    209340       
     
    211342            -- x: either a FormalSum element consisting of elements of
    212343            self.group(), an element of self.base_ring(), or an element
    213344            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 
     345            -- as_group_element : if true and x may be considered as a basis
     346            element and a group element, consider it a group element
    219347        OUTPUT:
    220348            -- a GroupAlgebraElement instance whose parent is self.
    221349
    222350        EXAMPLES:
    223             sage: G = AbelianGroup(1)
    224             sage: f = G.gen()
     351            sage: G = KleinFourGroup()
     352            sage: f = G.gen(0)
    225353            sage: ZG = GroupAlgebra(G)
    226354            sage: ZG(f)
    227             f
     355            (3,4)
    228356            sage: ZG(1) == ZG(G(1))
    229357            True
     358            sage: G = AbelianGroup(1)
     359            sage: ZG = GroupAlgebra(G)
     360            sage: f = ZG.group().gen()
    230361            sage: ZG(FormalSum([(1,f), (2, f**2)]))
    231             2*f^2 + f
     362            f + 2*f^2
    232363            sage: G = GL(2,7)
    233364            sage: OG = GroupAlgebra(G, ZZ[sqrt(5)])
    234365            sage: OG(2)
     
    240371            sage: OG(FormalSum([ (1, G(2)), (2, RR(0.77)) ]) )
    241372            Traceback (most recent call last):
    242373            ...
    243             TypeError: 0.770000000000000 is not an element of group General Linear Group of degree 2 over Finite Field of size 7
     374            TypeError: Cannot coerce 0.770000000000000 to a 2-by-2 matrix over Finite Field of size 7
    244375
    245376        Ordering of elements in output unpredictable as sort order of such wildly
    246377        dissimilar elements is subject to change between platforms and versions
    247378        (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
    251379            sage: OG(OG.base_ring().gens()[1])
    252380            sqrt5*[1 0]
    253381            [0 1]
    254             """
    255         return GroupAlgebraElement(self, x, check)
     382        """
     383        if isinstance(x, Element) :
     384            P = x.parent()
     385            if P is self.base_ring() and not as_group_element:
     386                return GroupAlgebraElement_class(self,
     387                 self._formal_sum_module( [(x, self.group()(1))] ) )
     388            elif P is self.group() :
     389                return GroupAlgebraElement_class(self,
     390                 self._formal_sum_module( [(self.base_ring().one_element(), x)] ) )
     391            elif P is self._formal_sum_module :
     392                return GroupAlgebraElement_class(self, x)
     393            elif isinstance(x, FormalSum) and self._formal_sum_module.has_coerce_map_from(P) :
     394                 return GroupAlgebraElement_class(self,
     395                          self._formal_sum_module(
     396                           [(self.base_ring()(c), self.group()(g)) for c,g in x] ) )
    256397
    257     def __eq__(self, other):
    258         r""" Test for equality.
     398        raise TypeError, "Don't know how to create an element of %s from %s" % \
     399                             (self, x)
     400
     401    def __cmp__(self, other) :
     402        r"""
     403        Compare two algebras self and other. They are considered equal if and only
     404        if their base rings and their groups coincide.
     405
    259406        EXAMPLES:
    260407            sage: GroupAlgebra(AbelianGroup(1)) == GroupAlgebra(AbelianGroup(1))
    261408            True
     
    263410            False
    264411            sage: GroupAlgebra(AbelianGroup(2)) == GroupAlgebra(AbelianGroup(1))
    265412            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()
     413            sage: from sage.algebras.group_algebra import GroupAlgebra_class
     414            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     415            sage: B = GroupAlgebra_class(KleinFourGroup(), QQ)
     416            sage: A == B
     417            False
     418            sage: A == A
     419            True
     420        """
     421        c = cmp(type(self), type(other))
     422
     423        if c == 0 :
     424            c = cmp(self._group, other._group)
     425        if c == 0 :
     426            c = cmp(self.base_ring(), other.base_ring())
     427
     428        return c
    271429
    272430    def _repr_(self):
    273431        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())
     432        doctest.
     433
     434        EXAMPLES :
     435            sage: A = GroupAlgebra(KleinFourGroup(), ZZ)
     436            sage: A
     437            Group algebra of group "The Klein 4 group of order 4, as a permutation group" over base ring Integer Ring
     438        """
     439        return "Group algebra of group \"%s\" over base ring %s" % \
     440               (self.group(), self.base_ring())
     441
     442    def _latex_(self):
     443        r"""Latex string of self.
     444       
     445        EXAMPLES :
     446            sage: A = GroupAlgebra(KleinFourGroup(), ZZ)
     447            sage: latex(A)
     448            Group algebra of group \langle (3,4), (1,2) \rangle over base ring \Bold{Z}
     449        """
     450        return "Group algebra of group %s over base ring %s" % \
     451               (latex(self.group()), latex(self.base_ring()))
    276452
    277453    def element_class(self):
    278454        r"""
     
    280456
    281457        EXAMPLES:
    282458            sage: GroupAlgebra(SU(2, GF(4,'a'))).element_class()
    283             <class 'sage.algebras.group_algebra.GroupAlgebraElement'>
     459            <class 'sage.algebras.group_algebra.GroupAlgebraElement_class'>
    284460        """
    285         return GroupAlgebraElement
    286 
     461        return GroupAlgebraElement_class
    287462
    288463    def category(self):
    289464        r"""
     
    296471        from sage.categories.all import GroupAlgebras
    297472        return GroupAlgebras(self.base_ring())
    298473
     474def GroupAlgebraElement(parent, x, check = True) :
     475    r"""
     476    Create an element of the group algebra parent.
     477    x       -- an element of the base ring, the group or a formal sum with
     478               summand (a, g), where a is in the base ring and g is in the group
     479    check   -- determines whether the summand of a formal sum will be checked
     480               for correctness
     481   
     482    EXAMPLES :
     483        sage: G = KleinFourGroup()
     484        sage: A = GroupAlgebra(G)   
     485        sage: GroupAlgebraElement(A, A.group().gen(1))
     486        (1,2)
     487        sage: GroupAlgebraElement(A, 1)               
     488        ()
     489        sage: GroupAlgebraElement(A, 10)
     490        10*()
     491    """
     492    ## Provide this for backward compatibility to the old class layout
    299493
     494    assert isinstance(parent, GroupAlgebra_class), "%s must be group algebra"
    300495
    301 class GroupAlgebraElement(AlgebraElement):
     496    if not isinstance(x, Element) :
     497        x = IntegerRing()(x)
    302498   
    303     def __init__(self, parent, x, check):
     499    if isinstance(x, FormalSum) and check :
     500        for c,g in x :
     501            if not c in parent.base_ring() or not g in parent.group() :
     502                raise ValueError, "summands of %s must be elements of base " + \
     503                                  "ring and group respectively"
     504
     505    return parent._element_constructor(x)
     506
     507###########################################################################
     508## GroupAlgebraElement_class
     509###########################################################################
     510
     511class GroupAlgebraElement_class ( AlgebraElement ) :
     512   
     513    def __init__(self, parent, x) :
    304514        r""" Create an element of the parent group algebra. Not intended to be
    305515        called by the user; see GroupAlgebra.__call__ for examples and
    306         doctests."""
     516        doctests.
     517       
     518        EXAMPLES :
     519            sage: A = GroupAlgebra(KleinFourGroup(), ZZ)
     520            sage: GroupAlgebraElement(A, A._formal_sum_module([(1, KleinFourGroup().gen(0))]))
     521            (3,4)
     522        """
    307523        AlgebraElement.__init__(self, parent)
    308524       
    309         if not hasattr(x, 'parent'):
    310             x = IntegerRing()(x) # occasionally coercion framework tries to pass a Python int
     525        self._fs = x
    311526
    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
     527    ###########################################################################
     528    ## GroupAlgebraElement_class :: Arithmetic
     529    ###########################################################################
    320530
    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):
     531    def _add_(left, right):
    332532        r"""
    333         Add self to other.
     533        Add left to right.
    334534       
    335535        EXAMPLE:
    336536            sage: G = GL(3, GF(7))
    337537            sage: ZG = GroupAlgebra(G)
    338             sage: g1 = G([0,0,2,2,5,0,6,6,2])
     538            sage: g1 = ZG.group()([0,0,2,2,5,0,6,6,2])
    339539            sage: s = ZG(g1)
    340540            sage: s + s
    341541            2*[0  0  2]
    342542            [2  5  0]
    343543            [6  6  2]
    344 """
    345         fs_sum = self._fs + other._fs
    346         return self.parent()(fs_sum, check=False)
     544        """
     545        return left.parent()(left._fs + right._fs)
    347546
    348     def _mul_(self, right):
    349         r""" Calculate self*right, where both self and right are GroupAlgebraElements.
     547    def _mul_(left, right):
     548        r""" Calculate left*right, where both left and right are GroupAlgebraElements_class.
    350549       
    351550        EXAMPLE:
    352551            sage: G = GL(3, GF(7))
    353552            sage: ZG = GroupAlgebra(G)
    354             sage: a, b = G.random_element(), G.random_element()
     553            sage: a, b = ZG.group().random_element(), ZG.group().random_element()
    355554            sage: za, zb = ZG(a), ZG(b)
    356555            sage: za*ZG(2) # random
    357556            2*[4,5,0]
     
    364563            sage: za*za == za^2
    365564            True
    366565        """
    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)
     566        if left.parent().group().is_multiplicative() :
     567            product = [ (a1 * a2, g1 * g2)
     568                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
     569        else :
     570            product = [ (a1 * a2, g1 + g2)
     571                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
    377572
    378     def __eq__(self, other):
    379         r""" Test if self is equal to other.
     573        return left.parent()( left.parent()._formal_sum_module(product) )
     574
     575    ###########################################################################
     576    ## GroupAlgebraElement_class :: Comparision
     577    ###########################################################################
     578
     579    def __cmp__(self, other) :
     580        r""" Compare self and other.
    380581
    381582        EXAMPLES:
    382583            sage: G = AbelianGroup(1,[4])
    383             sage: a = GroupAlgebra(G)(1)
    384             sage: b = GroupAlgebra(G)(2)
     584            sage: ZG = GroupAlgebra(G)
     585            sage: a = ZG(1)
     586            sage: b = ZG(2)
    385587            sage: a + a == b
    386588            True
    387589            sage: a == b
     
    389591            sage: a == GroupAlgebra(AbelianGroup(1, [5]))(1)
    390592            False
    391593        """
    392         if isinstance(other, GroupAlgebraElement) and self.parent() == other.parent():
    393             return self._fs == other._fs
    394         else:
    395             return False
     594        c = cmp(type(self), type(other))
     595
     596        if c == 0 :
     597            c = cmp(self._fs, other._fs)
     598
     599        return c
     600
     601    ###########################################################################
     602    ## GroupAlgebraElement_class :: Representations
     603    ###########################################################################
     604
     605    def _repr_(self) :
     606        r"""
     607        EXAMPLES :
     608            sage: G = KleinFourGroup()
     609            sage: A = GroupAlgebra(G, ZZ)
     610            sage: latex(A(1) + A(A.group().gen(0)))
     611            () + (3,4)
     612        """
     613        return self._fs._repr_()
     614
     615    def _latex_(self) :
     616        r"""
     617        EXAMPLES :
     618            sage: G = KleinFourGroup()
     619            sage: A = GroupAlgebra(G, ZZ)
     620            sage: latex(A(1) + A(A.group().gen(0)))
     621            () + (3,4)
     622        """
     623        return latex(self._fs)
     624