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