Ticket #6670: trac-6670-group_algebra.patch

File trac-6670-group_algebra.patch, 19.8 KB (added by Martin Raum, 13 years ago)
  • sage/algebras/group_algebra.py

    diff -r ca1f31d6f6bf 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)) == 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(KleinFourGroup())
     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
     163            [3 0 0]
     164            [0 1 0]
     165            [0 0 1]
     166        """
     167        return self._element_constructor(self._group.gen(i), as_group_element = True)
     168
    63169    def group(self):
    64170        r""" Return the group of this group algebra.
     171
    65172        EXAMPLES:
    66173            sage: GroupAlgebra(GL(3, GF(11))).group()
    67174            General Linear Group of degree 3 over Finite Field of size 11
     
    70177        """
    71178        return self._group
    72179
     180    ###########################################################################
     181    ## GroupAlgebra_class :: mathmatical properties
     182    ###########################################################################
     183
    73184    def is_commutative(self):
    74185        r""" Return True if self is a commutative ring. True if and only if
    75186        self.group() is abelian.
     
    170281    # I don't know if that means "is canonically isomorphic to a prime field"
    171282    # or "is identical to a prime field".
    172283
    173     def _coerce_impl(self, x):
    174         return self(self.base_ring().coerce(x))
     284    ###########################################################################
     285    ## GroupAlgebra_class :: elements
     286    ###########################################################################
    175287
    176     def _an_element_impl(self):
     288    def _an_element_(self):
     289        r""" Return an element of self.
     290        EXAMPLES :
     291            sage: A = GroupAlgebra(GL(3, GF(7)))
     292            sage: A.an_element()
     293
     294            [3 0 0]
     295            [0 1 0]
     296            [0 0 1]
    177297        """
    178         Return an element of self.
    179        
     298        return self(self._formal_sum_module([
     299             (self.base_ring().an_element(), self.group().an_element())
     300             ]))
     301
     302    def random_element(self) :
     303        r""" Return a random element of self.
    180304        EXAMPLE:
    181305            sage: GroupAlgebra(SU(2, 13), QQ).an_element() # random; hideous formatting!
    182306            -1/95*[       9 2*a + 12]
    183307            [       0        3] - 4*[      9 9*a + 2]
    184308            [3*a + 5       1]
    185309        """
    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()) ]))
     310        return self(self._formal_sum_module([
     311            (self.base_ring().random_element(), self.group().random_element()),
     312            (self.base_ring().random_element(), self.group().random_element()),
     313            ]))
    193314
    194     def __call__(self, x, check=True):
     315    def construction(self) :
     316        r"""
     317        EXAMPLES :
     318        sage: A = GroupAlgebra(KleinFourGroup(), QQ)
     319        sage: A.construction()                                       
     320        (GroupAlgebraFunctor, Rational Field)
     321        """
     322        return GroupAlgebraFunctor(self._group), self.base_ring()
     323
     324    def _element_constructor_(self, x, as_group_element = False) :
    195325        r"""
    196326        Create an element of this group algebra.
    197327       
     
    199329            -- x: either a FormalSum element consisting of elements of
    200330            self.group(), an element of self.base_ring(), or an element
    201331            of self.group().
    202             -- check (boolean): whether or not to check that the given elements
    203             really do lie in self.group(). Chiefly provided to speed up
    204             arithmetic operations with elements that have already been checked
    205             to lie in the group.
    206 
     332            -- as_group_element : if true and x may be considered as a basis
     333            element and a group element, consider it a group element
    207334        OUTPUT:
    208335            -- a GroupAlgebraElement instance whose parent is self.
    209336
     
    233360        Ordering of elements in output unpredictable as sort order of such wildly
    234361        dissimilar elements is subject to change between platforms and versions
    235362        (see trac ticket \#4373).
    236             sage: OG(FormalSum([ (1, G(2)), (2, RR(0.77)) ]), check=False) # random
    237             [2 0]
    238             [0 2] + 2*0.770000000000000
    239363            sage: OG(OG.base_ring().gens()[1])
    240364            sqrt5*[1 0]
    241365            [0 1]
    242             """
    243         return GroupAlgebraElement(self, x, check)
     366        """
     367        if isinstance(x, Element) :
     368            P = x.parent()
     369            if P is self.base_ring() and not as_group_element:
     370                return GroupAlgebraElement_class(self,
     371                 self._formal_sum_module( [(x, self.group()(1))] ) )
     372            elif P is self.group() :
     373                return GroupAlgebraElement_class(self,
     374                 self._formal_sum_module( [(self.base_ring().one_element(), x)] ) )
     375            elif P is self._formal_sum_module :
     376                return GroupAlgebraElement_class(self, x)
    244377
    245     def __eq__(self, other):
    246         r""" Test for equality.
     378        raise TypeError, "Don't know how to create an element of %s from %s" % \
     379                         (self, x)
     380
     381    def _cmp_(self, other) :
     382        r"""
     383        Compare two algebras self and other. They are considered equal if and only
     384        if their base rings and their groups coincide.
     385
    247386        EXAMPLES:
    248387            sage: GroupAlgebra(AbelianGroup(1)) == GroupAlgebra(AbelianGroup(1))
    249388            True
     
    251390            False
    252391            sage: GroupAlgebra(AbelianGroup(2)) == GroupAlgebra(AbelianGroup(1))
    253392            False
    254             """
    255         if not isinstance(other, GroupAlgebra):
    256             return False
    257         else:
    258             return self.base_ring() == other.base_ring() and self.group() == other.group()
     393            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     394            sage: B = GroupAlgebra_class(KleinFourGroup(), QQ)
     395            sage: A == B
     396            False
     397            sage: A == A
     398            True
     399        """
     400        c = cmp(type(self), type(other))
     401
     402        if c == 0 :
     403            c = cmp(self._group, other._group)
     404        if c == 0 :
     405            c = cmp(self.base_ring(), other.base_ring())
     406
     407        return c
    259408
    260409    def _repr_(self):
    261410        r""" String representation of self. See GroupAlgebra.__init__ for a
    262         doctest."""
    263         return "Group algebra of group \"%s\" over base ring %s" % (self.group(), self.base_ring())
     411        doctest.
     412
     413        EXAMPLES :
     414            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     415            sage: A
     416            Group algebra of group "The Klein 4 group of order 4, as a permutation group" over base ring Integer Ring
     417        """
     418        return "Group algebra of group \"%s\" over base ring %s" % \
     419               (self.group(), self.base_ring())
     420
     421    def _latex_(self):
     422        r"""Latex string of self.
     423       
     424        EXAMPLES :
     425            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     426            sage: latex(A)
     427            Group algebra of group \langle (3,4), (1,2) \rangle over base ring \Bold{Z}
     428        """
     429        return "Group algebra of group %s over base ring %s" % \
     430               (latex(self.group()), latex(self.base_ring()))
    264431
    265432    def element_class(self):
    266433        r"""
     
    268435
    269436        EXAMPLES:
    270437            sage: GroupAlgebra(SU(2, GF(4,'a'))).element_class()
    271             <class 'sage.algebras.group_algebra.GroupAlgebraElement'>
     438            <class 'sage.algebras.group_algebra.GroupAlgebraElement_class'>
    272439        """
    273         return GroupAlgebraElement
    274 
     440        return GroupAlgebraElement_class
    275441
    276442    def category(self):
    277443        r"""
     
    284450        from sage.categories.category_types import GroupAlgebras
    285451        return GroupAlgebras(self.base_ring())
    286452
     453def GroupAlgebraElement(parent, x, check = True) :
     454    r"""
     455    Create an element of the group algebra parent.
     456    x       -- an element of the base ring, the group or a formal sum with
     457               summand (a, g), where a is in the base ring and g is in the group
     458    check   -- determines whether the summand of a formal sum will be checked
     459               for correctness
     460   
     461    EXAMPLES :
     462        sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)   
     463        sage: GroupAlgebraElement(A, KleinFourGroup().gen(1))
     464        (1,2)
     465        sage: GroupAlgebraElement(A, 1)                     
     466        ()
     467        sage: GroupAlgebraElement(A, 10)
     468        10*()
     469    """
     470    ## Provide this for backward compatibility to the old class layout
    287471
     472    assert isinstance(parent, GroupAlgebra_class), "%s must be group algebra"
    288473
    289 class GroupAlgebraElement(AlgebraElement):
     474    if not isinstance(x, Element) :
     475        x = IntegerRing()(x)
    290476   
    291     def __init__(self, parent, x, check):
     477    P = x.parent()
     478    if parent.base_ring().has_coerce_map_from(P) :
     479        x = parent.base_ring()(x)
     480    elif parent.group().has_coerce_map_from(P) :
     481        x = parent.group()(x)
     482    elif P is parent._formal_sum_module :
     483        if check :
     484            for c,g in x :
     485                if not c in parent.base_ring() or not g in parent.group() :
     486                    raise ValueError, "summands of %s must be elements of base " + \
     487                                      "ring and group respectively"
     488    elif parent._formal_sum_module.has_coerce_map_from(P) :
     489        x = self._formal_sum_module(
     490             [(self.base_ring()(c), self.group(g)) for c,g in x] )
     491
     492        x = parent._formal_sum_module(x)
     493    else :
     494        raise TypeError, "Can't construct an element of %s from %s" % (parent, x)
     495
     496    return parent._element_constructor(x)
     497
     498###########################################################################
     499## GroupAlgebraElement_class
     500###########################################################################
     501
     502class GroupAlgebraElement_class ( AlgebraElement ) :
     503   
     504    def __init__(self, parent, x) :
    292505        r""" Create an element of the parent group algebra. Not intended to be
    293506        called by the user; see GroupAlgebra.__call__ for examples and
    294         doctests."""
     507        doctests.
     508       
     509        EXAMPLES :
     510            sage: A = GroupAlgebra_class(KleinFourGroup(), ZZ)
     511            sage: GroupAlgebraElement_class(A, A._formal_sum_module([(1, KleinFourGroup().gen(0))]))
     512            (3,4)
     513        """
    295514        AlgebraElement.__init__(self, parent)
    296515       
    297         if not hasattr(x, 'parent'):
    298             x = IntegerRing()(x) # occasionally coercion framework tries to pass a Python int
     516        self._fs = x
    299517
    300         if isinstance(x, FormalSum):
    301             if check:
    302                 for c,d in x._data:
    303                     if d.parent() != self.parent().group():
    304                         raise TypeError, "%s is not an element of group %s" % (d, self.parent().group())
    305                 self._fs = x
    306             else:
    307                 self._fs = x
     518    ###########################################################################
     519    ## GroupAlgebraElement_class :: Arithmetic
     520    ###########################################################################
    308521
    309         elif self.base_ring().has_coerce_map_from(x.parent()):
    310             self._fs = self.parent()._formal_sum_module([ (x, self.parent().group()(1)) ])
    311         elif self.parent().group().has_coerce_map_from(x.parent()):
    312             self._fs = self.parent()._formal_sum_module([ (1, self.parent().group()(x)) ])
    313         else:
    314             raise TypeError, "Don't know how to create an element of %s from %s" % (self.parent(), x)
    315 
    316     def _repr_(self):
    317         return self._fs._repr_()
    318 
    319     def _add_(self, other):
     522    def _add_(left, right):
    320523        r"""
    321         Add self to other.
     524        Add left to other.
    322525       
    323526        EXAMPLE:
    324527            sage: G = GL(3, GF(7))
     
    329532            2*[0  0  2]
    330533            [2  5  0]
    331534            [6  6  2]
    332 """
    333         fs_sum = self._fs + other._fs
    334         return self.parent()(fs_sum, check=False)
     535        """
     536        return left.parent()(left._fs + right._fs)
    335537
    336     def _mul_(self, right):
    337         r""" Calculate self*right, where both self and right are GroupAlgebraElements.
     538    def _mul_(left, right):
     539        r""" Calculate left*right, where both left and right are GroupAlgebraElements_class.
    338540       
    339541        EXAMPLE:
    340542            sage: G = GL(3, GF(7))
     
    352554            sage: za*za == za^2
    353555            True
    354556        """
    355         d1 = self._fs._data
    356         d2 = right._fs._data
    357         new = []
    358         for (a1, g1) in d1:
    359             for a2,g2 in d2:
    360                 if self.parent().group().is_multiplicative():
    361                     new.append( (a1*a2, g1*g2) )
    362                 else:
    363                     new.append( (a1*a2, g1 + g2) )
    364         return self.parent()( self.parent()._formal_sum_module(new), check=False)
     557        if left.parent().group().is_multiplicative() :
     558            product = [ (a1 * a2, g1 * g2)
     559                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
     560        else :
     561            product = [ (a1 * a2, g1 + g2)
     562                        for (a1,g1) in left._fs for (a2,g2) in right._fs ]
    365563
    366     def __eq__(self, other):
    367         r""" Test if self is equal to other.
     564        return left.parent()( left.parent()._formal_sum_module(product) )
     565
     566    ###########################################################################
     567    ## GroupAlgebraElement_class :: Comparision
     568    ###########################################################################
     569
     570    def __cmp__(self, other) :
     571        r""" Compare self and other.
    368572
    369573        EXAMPLES:
    370574            sage: G = AbelianGroup(1,[4])
     
    377581            sage: a == GroupAlgebra(AbelianGroup(1, [5]))(1)
    378582            False
    379583        """
    380         if isinstance(other, GroupAlgebraElement) and self.parent() == other.parent():
    381             return self._fs == other._fs
    382         else:
    383             return False
     584        c = cmp(type(self), type(other))
     585
     586        if c == 0 :
     587            c = cmp(self._fs, other._fs)
     588
     589        return c
     590
     591    ###########################################################################
     592    ## GroupAlgebraElement_class :: Representations
     593    ###########################################################################
     594
     595    def _repr_(self) :
     596        r"""
     597        EXAMPLES :
     598            sage: G = KleinFourGroup()
     599            sage: A = group_algebra_ng.GroupAlgebra_class(G, ZZ)
     600            sage: latex(A(1) + A(G.gen(0)))
     601            () + (3,4)
     602        """
     603        return self._fs._repr_()
     604
     605    def _latex_(self) :
     606        r"""
     607        EXAMPLES :
     608            sage: G = KleinFourGroup()
     609            sage: A = group_algebra_ng.GroupAlgebra_class(G, ZZ)
     610            sage: latex(A(1) + A(G.gen(0)))
     611            () + (3,4)
     612        """
     613        return latex(self._fs)
     614