# Haskell for Maths

## Friday, 10 February 2012

### Introducing the Group Algebra

Here's an interesting example of an algebra.

Given a group, form the free vector space on the elements of the group. For example, if g and h are elements of the group, then the following are some elements of the free vector space:
- g + h
- 1 + 2*g
- 2 + g*h + h/3

It's pretty obvious how to define an algebra structure on this vector space:
- the unit is 1, the identity element of the group
- the multiplication is the multiplication in the group, lifted to the vector space by linearity.

So for example:
(1 + 2g)(g + h/3) = g + 2g^2 + h/3 + 2gh/3

This is called the group algebra. (It's a special case of the monoid algebra construction that we looked at previously.) Given some particular field k and group G, it is usually written as kG.

How can we represent this in Haskell? Well in HaskellForMaths, we already have code for working in permutation groups, and code for forming free vector spaces. So it's fairly straightforward:

```
module Math.Algebras.GroupAlgebra where

-- ... imports ...

instance (Eq k, Num k) => Algebra k (Permutation Int) where

unit x = x *> return 1

mult = nf . fmap (\(g,h) -> g*h)

type GroupAlgebra k = Vect k (Permutation Int)

p :: [[Int]] -> GroupAlgebra Q

p = return . fromCycles

```

Then for example we can do the following:

`\$ cabal update`
`\$ cabal install HaskellForMaths`
`\$ ghci`
`> :m Math.Core.Utils Math.Algebras.GroupAlgebra`
`> (1 + p[[1,2,3],[4,5]])^2`
`1+2[[1,2,3],[4,5]]+[[1,3,2]]`

(Actually, in HaskellForMaths <= 0.4.3, the first term will be shown as [] instead of 1. That's just a "bug" in the Show instance, which I have a fix for in the next release.)

For reference, in a maths book, the same result would be written:
( 1 + (1 2 3)(4 5) )^2 = 1 + 2(1 2 3)(4 5) + (1 3 2)

So I guess one thing to point out is that in effect this code defines the group algebra for the group of all permutations of the integers. In practice however, we can always think of ourselves as working in some finite subgroup of this group. For example, if we want to work in the group of symmetries of a square, generated by a rotation (1 2 3 4) and a reflection (1 2)(3 4), then we just need to consider only sums of the eight elements in the generated group.

Another thing to point out is that this code could easily be modified to allow permutations over an arbitrary type, since that is supported by the underlying permutation code.

So what is this group algebra then? What sort of thing is it, and how should one think about it?

Well, first, as an algebra, it has zero divisors. For example:

`> (1+p[[1,2]])*(1-p[[1,2]])`
`0`

However, a lot of the elements aren't zero divisors, and whenever they're not, they have inverses. The group elements themselves have inverses of course, but so do many sums of group elements. For example:

`> (1+p[[1,2,3]])^-1`
`1/2-1/2[[1,2,3]]+1/2[[1,3,2]]`
`> (1+2*p[[1,2,3]])^-1`
`1/9-2/9[[1,2,3]]+4/9[[1,3,2]]`

Just to check:

`> (1+p[[1,2,3]]) * (1-p[[1,2,3]]+p[[1,3,2]])`
`2`
`> (1+2*p[[1,2,3]]) * (1-2*p[[1,2,3]]+4*p[[1,3,2]])`
`9`

How do we calculate the inverses? Well it's quite clever actually. Let's work through an example. Suppose we want to find an inverse for
x = 1+2*p[[1,2]]+3*p[[1,2,3]]
The inverse, if it exists, will be a linear combination of elements of the group generated by 1, p[[1,2]] and p[[1,2,3]]. So it will be a sum
y = a*1 + b*p[[1,2]] + c*p[[1,3]] + d*p[[2,3]] + e*p[[1,2,3]] + f*p[[1,3,2]]
By supposition x*y = 1, so
(1+2*p[[1,2]]+3*p[[1,2,3]]) * (a*1+b*p[[1,2]]+c*p[[1,3]]+d*p[[2,3]]+e*p[[1,2,3]]+f*p[[1,3,2]]) =
1 + 0*p[[1,2]] + 0*p[[1,3]] + 0*p[[2,3]] + 0*p[[1,2,3]] + 0*p[[1,3,2]]

If we multiply out and equate coefficients, we will get a linear system in a,b,c,d,e,f. Something like:

```
a+2b      +3e    = 1 (coefficients of 1)

2a+ b+3c          = 0 (coefficients of p[[1,2]])

c+3d+2e    = 0 (coefficients of p[[1,3]])

3b   + d   +2f = 0 (coefficients of p[[2,3]])

```

etc

So we just solve the linear system to find a,b,c,d,e,f.

Here's the code:

```
`newtype X a = X a deriving (Eq,Ord,Show)`

```
```

`instance HasInverses (GroupAlgebra Q) where`

`    inverse x@(V ts) =`

`        let gs = elts \$ map fst ts -- all elements in the group generated by the terms`

`            n = length gs`

`            y = V \$ zip gs \$ map (glexvar . X) [1..n] -- x1*1+x2*g2+...+xn*gn`

`            x' = V \$ map (\(g,c) -> (g, unit c)) ts -- lift the coefficients in x into the polynomial algebra`

`            one = x' * y`

`            m = [ [coeff (mvar (X j)) c | j <- [1..n]] | i <- gs, let c = coeff i one] -- matrix of the linear system`

`            b = 1 : replicate (n-1) 0`

`        in case solveLinearSystem m b of -- find v such that m v == b`

`            Just v -> nf \$ V \$ zip gs v`

`            Nothing -> error "GroupAlgebra.inverse: not invertible"`

```

I won't explain it in detail. I'll just remark that this is one of the places where HaskellForMaths shows its power. We happen to have a type for polynomials lying around. They're a Num instance, so we can use them as the coefficients in GroupAlgebra k. We can create new variables x1, x2, ... (using glexvar . X), lift field elements into the polynomial algebra (using unit), multiply x and y in the group algebra, extract the coefficients into a matrix, and solve the linear system.

I should point out that unfortunately, since this method involves solving a linear system in |G| variables, it's only going to be efficient for small groups.

So what is the group algebra useful for? Well actually quite a lot. It's fundamental to the study of representation theory - representing groups as matrices. It's also used for "Fourier analysis of groups" - though I don't know much about that. But those will have to wait for another time.

#### 3 comments:

1. When calculating the inverse of
x = 1+2*p[[1,2]]+3*p[[1,2,3]]
you look for the inverse in the subalgebra generated by 1, p[[1,2]]] and 3[[1,2,3]]. More generally, the subalgebra generated by all group elements occuring in the sum presentation of x with non-zero coefficient.
Then you solve a system of equations.
Is there any (idea for an) algorithm that computes an inverse or at least checks if x is invertible in the case of a group algebra for non-finite groups?

1. Good question.
Note that the definition of group algebra that I'm using allows only *finite* sums of group elements. (Definitions allowing infinite sums are possible, but I don't see straight away how we would represent them in a computer program.)
It is possible to work over an infinite group. Indeed, the code above is really doing so. It is working over the infinite group of finite permutations of the natural numbers. Given any finite sum of finite permutations, the group generated by the permutations is finite.
If we allow elements of infinite order, then I suspect that their inverses would typically involve infinite sums, and therefore be disallowed by the above definition. For example, if x has infinite order, then (1+x)^-1 = 1-x+x^2-x^3+... (assuming some kind of convergence of the right hand side).

2. This comment has been removed by the author.