Skip to content

Introduction

Introduction to groups, representations, and steerable convolutions using the SteerableConvolutions.jl package.

julia
using SteerableConvolutions

Groups

A group G=(E,) is a set of elements E equipped with a group action . Consider the cyclic group G=C8 of order N=8. This group contains 8 elements E={0,1,2,3,4,5,6,7}, and the group action represents rotations in the plane of angle 2πn/N for nE.

julia
G = CyclicGroup(8)
CyclicGroup(8)

We can access or create elements of the group. An element g is represented by an integer n between 0 and 7, representing a rotation by angle 2πn/N.

julia
g = G(3)
CyclicGroup(8)(3)

A group element g has some properties:

julia
typeof(g), g.group, g.n
(Element{CyclicGroup, Int64}, CyclicGroup(8), 3)

Since the group is finite, all the group elements can be accessed with the elements function:

julia
elements(G)
8-element Vector{Element{CyclicGroup, Int64}}:
 CyclicGroup(8)(0)
 CyclicGroup(8)(1)
 CyclicGroup(8)(2)
 CyclicGroup(8)(3)
 CyclicGroup(8)(4)
 CyclicGroup(8)(5)
 CyclicGroup(8)(6)
 CyclicGroup(8)(7)

Group elements can be multiplied. This group action represents consecutive rotations, which creates a new group element. Note how the angles start over after 8 rotations.

julia
G(1) * G(2), G(3) * G(7)
(CyclicGroup(8)(3), CyclicGroup(8)(2))

The unit element e=0 represents a rotation by zero degrees:

julia
one(G), one(g), G(0), G(2) * G(-2)
(CyclicGroup(8)(0), CyclicGroup(8)(0), CyclicGroup(8)(0), CyclicGroup(8)(0))

The unit elements does not modify the angle:

julia
one(G) * G(3)
CyclicGroup(8)(3)

Since the group action is analogous to multiplication, we can compute inverses and powers:

julia
inv(g), g^2
(CyclicGroup(8)(5), CyclicGroup(8)(6))

Group representations

A linear Representation of a group G is a matrix-valued function over the group:

ρ:GGL(Rd),

where d is the size of the representation and GL(Rd) is the space of invertible matrices of size d×d.

Regular representation

One such representation is the regular representation, which encodes the group action using a permutation matrix of size N:

julia
ρ = regular_representation(G)
round.(Int, ρ(g))
8×8 Matrix{Int64}:
 0  0  0  0  0  1  0  0
 0  0  0  0  0  0  1  0
 0  0  0  0  0  0  0  1
 1  0  0  0  0  0  0  0
 0  1  0  0  0  0  0  0
 0  0  1  0  0  0  0  0
 0  0  0  1  0  0  0  0
 0  0  0  0  1  0  0  0

Internally, all Representations are stored in a different basis, leading to some round-off errors:

julia
ρ(g)
8×8 Matrix{Float64}:
  2.08322e-16   2.52189e-17  -2.25256e-16  …   4.77749e-16  -4.14108e-16
 -1.25056e-16   3.02922e-17  -6.61772e-17      1.0           2.7533e-16
  9.73001e-17   1.63997e-16  -1.14234e-16     -1.32874e-16   1.0
  1.0           2.53663e-18  -3.84216e-17     -1.16926e-16  -2.9981e-17
  1.52811e-16   1.0           2.32711e-16      5.90395e-18  -1.64308e-16
 -1.52811e-16   1.41315e-16   1.0          …  -2.00193e-16   1.36552e-16
  9.73001e-17  -1.41315e-16   9.39328e-17     -1.18996e-16   4.38588e-17
 -4.17889e-17  -1.36241e-16   1.83623e-16     -2.27949e-16   1.08797e-16

One property of group representations is that group actions are represented as matrix multiplications:

julia
g, h = G(3), G(-1)
g * h
CyclicGroup(8)(2)

The corresponding matrix is

julia
matrix = ρ(g * h)
round.(Int, matrix)
8×8 Matrix{Int64}:
 0  0  0  0  0  0  1  0
 0  0  0  0  0  0  0  1
 1  0  0  0  0  0  0  0
 0  1  0  0  0  0  0  0
 0  0  1  0  0  0  0  0
 0  0  0  1  0  0  0  0
 0  0  0  0  1  0  0  0
 0  0  0  0  0  1  0  0

Compare with

julia
matrix = ρ(g) * ρ(h)
round.(Int, matrix)
8×8 Matrix{Int64}:
 0  0  0  0  0  0  1  0
 0  0  0  0  0  0  0  1
 1  0  0  0  0  0  0  0
 0  1  0  0  0  0  0  0
 0  0  1  0  0  0  0  0
 0  0  0  1  0  0  0  0
 0  0  0  0  1  0  0  0
 0  0  0  0  0  1  0  0

As a result, the matrix of the unit element is always the identity matrix:

julia
round.(Int, ρ(one(G)))
8×8 Matrix{Int64}:
 1  0  0  0  0  0  0  0
 0  1  0  0  0  0  0  0
 0  0  1  0  0  0  0  0
 0  0  0  1  0  0  0  0
 0  0  0  0  1  0  0  0
 0  0  0  0  0  1  0  0
 0  0  0  0  0  0  1  0
 0  0  0  0  0  0  0  1

Irreducible representations

The regular representation is composed of irreducible represenations (Irreps). For the circular group, there are N/2 irreps of different frequencies. With frequency 0, we get the trivial (constant) representation ψ0, which is a 1×1 identity matrix for all group elements:

julia
ψ₀ = Irrep(G, 0)
ψ₀(G(0)), ψ₀(G(1)), ψ₀(G(2))
([1.0;;], [1.0;;], [1.0;;])

The next irrep ψ1 has frequency 1 and takes the value of a 2×2 rotation matrix ψ1(g)=R(2πg/N), with

R(θ)=[cos(θ)sin(θ)sin(θ)cos(θ)].
julia
ψ₁ = Irrep(G, 1)
ψ₁(g)
2×2 Matrix{Float64}:
 -0.707107  -0.707107
  0.707107  -0.707107

All the valid irrep frequencies are accessible through the frequencies function:

julia
frequencies(G)
0:4

Direct sums

The direct sum of two represenations is a new representation that gives the block diagonal concatenation of the original matrices. It can be called using the directsum function or the operator (type \oplus<tab>):

julia
ρ_sum = ψ₀  ψ₀  ψ₀  ψ₁
ρ_sum(G(1))
5×5 Matrix{Float64}:
 1.0  0.0  0.0  0.0        0.0
 0.0  1.0  0.0  0.0        0.0
 0.0  0.0  1.0  0.0        0.0
 0.0  0.0  0.0  0.707107  -0.707107
 0.0  0.0  0.0  0.707107   0.707107
julia
ρ_sum(G(2))
5×5 Matrix{Float64}:
 1.0  0.0  0.0  0.0           0.0
 0.0  1.0  0.0  0.0           0.0
 0.0  0.0  1.0  0.0           0.0
 0.0  0.0  0.0  6.12323e-17  -1.0
 0.0  0.0  0.0  1.0           6.12323e-17
julia
ρ_sum(G(3))
5×5 Matrix{Float64}:
 1.0  0.0  0.0   0.0        0.0
 0.0  1.0  0.0   0.0        0.0
 0.0  0.0  1.0   0.0        0.0
 0.0  0.0  0.0  -0.707107  -0.707107
 0.0  0.0  0.0   0.707107  -0.707107

Any representation ρ can be represented as a direct sum of irreps through a change of basis:

ρ(g)=B(iIψi(g))B1gG,

where B is the basis matrix and (ψi)i are the irreps of frequencies i. The list of indices I can contain repetitions. Let's check for the regular representation ρ:

julia
B = basis(ρ)
8×8 Matrix{Float64}:
 0.353553   0.5           0.0          …   0.0           0.353553
 0.353553   0.353553      0.353553         0.353553     -0.353553
 0.353553   3.06162e-17   0.5             -0.5           0.353553
 0.353553  -0.353553      0.353553         0.353553     -0.353553
 0.353553  -0.5           6.12323e-17      1.83697e-16   0.353553
 0.353553  -0.353553     -0.353553     …  -0.353553     -0.353553
 0.353553  -9.18485e-17  -0.5              0.5           0.353553
 0.353553   0.353553     -0.353553        -0.353553     -0.353553

The irreps of ρ are stored as a list of frequencies I:

julia
I = frequencies(ρ)
5-element Vector{Int64}:
 0
 1
 2
 3
 4

We can assemble the direct sum:

julia
ρ_block =(map(i -> Irrep(G, i), I)...)
ρ_block(g)
8×8 Matrix{Float64}:
 1.0   0.0        0.0        0.0          …  0.0        0.0        0.0
 0.0  -0.707107  -0.707107   0.0             0.0        0.0        0.0
 0.0   0.707107  -0.707107   0.0             0.0        0.0        0.0
 0.0   0.0        0.0       -1.83697e-16     0.0        0.0        0.0
 0.0   0.0        0.0       -1.0             0.0        0.0        0.0
 0.0   0.0        0.0        0.0          …  0.707107  -0.707107   0.0
 0.0   0.0        0.0        0.0             0.707107   0.707107   0.0
 0.0   0.0        0.0        0.0             0.0        0.0       -1.0

We can verify that the direct sum is equal to the regular representation when applying the change of basis:

julia
B * ρ_block(g) * inv(B)  ρ(g)
true

This page was generated using Literate.jl.