5.4 Subrepresentations

Let \(V = \mathbb{K}^D\) be the space on which a representation \(\rho: G \to \operatorname{GL}(V)\) acts, with \(\mathbb{K} = \mathbb{R}\) or \(\mathbb{C}\). A subspace \(W\) of \(V\) is invariant under \(\rho\) if and only if: for all \(\vec{w} \in W\) and \(g \in G\), we have \(\rho_g \vec{w} \in W\).

In MATLAB/Octave it is customary to work with matrices and vectors. With \(d\) the dimension of \(W\), we identify \(W \sim \mathbb{K}^d\). It remains to define the relationship between \(V\) and \(W\). For that purpose, we define two linear maps: the injection map \(I: W \to V\) and the projection map \(P: V \to W\). The injection map is identified with a \(D \times d\) matrix such that:

\[ \vec{w} \to \vec{v} = I \cdot \vec{w} \]

injects a vector from the subspace in the larger parent space. The projection map is identified with a \(d \times D\) matrix such that

\[ \vec{v} \to \vec{w} = P \cdot \vec{v}, \]

a vector of the parent space is projected into the subspace. The projector on the subspace is given by \(\Pi = I \cdot P\).

In RepLAB, subrepresentations, of type SubRep can be constructed in several ways:

  • by providing the parent representation and the injection map,

  • by computing the complement subrepresentation of a subrepresentation,

  • by splitting a representation,

  • by computing the irreducible decomposition of a representation.

Note that similar representations are a special case of subrepresentations where \(D=d\) and the projection and injection maps are bijective.

In the examples below, we will work with the three-dimensional natural representation of \(S_3\).

S3 = replab.S(3);
rep = S3.naturalRep
rep =

Orthogonal reducible representation
   dimension: 3
       field: 'R'
       group: Symmetric group acting on 3 elements
   isUnitary: true
preimages{1}: [2, 3, 1]
   images{1}: [0, 0, 1; 1, 0, 0; 0, 1, 0]
preimages{2}: [2, 1, 3]
   images{2}: [0, 1, 0; 1, 0, 0; 0, 0, 1]

Explicit subrepresentations

A subrepresentation can be explicitly constructed using the subRep method. Given the natural representation of \(S_3\), one can compute the trivial subrepresentation corresponding to the subspace spanned by the vector \(I = (1,1,1)^\top\).

I = [1;1;1];
trivialSubRep = rep.subRep(I)
trivialSubRep =

Real subrepresentation
       dimension: 1
           field: 'R'
           group: Symmetric group acting on 3 elements
       isUnitary: false
          parent: Orthogonal reducible representation
basis(1,'exact'): [1; 1; 1]

The injection and projection maps are available through the injection and projection methods.

In the example above, we see that the projection map was automatically computed:

trivialSubRep.projection
ans =

   0.3333   0.3333   0.3333

When the injection map is given in exact arithmetic as well, the projection map is computed in exact arithmetic as well. This can slow down the computations considerably, however.

I = replab.cyclotomic([1;1;1]);
trivialSubRep = rep.subRep(I)
trivialSubRep.projection('exact')
trivialSubRep =

Real subrepresentation
       dimension: 1
           field: 'R'
           group: Symmetric group acting on 3 elements
       isUnitary: false
          parent: Orthogonal reducible representation
basis(1,'exact'): [1; 1; 1]

ans =
  1/3  1/3  1/3  

If known, one can provide the projection map, either in exact or approximate form:

P = replab.cyclotomic('[1/3, 1/3, 1/3]');
trivialSubRep = rep.subRep(I, 'projection', P);

Complement subrepresentation

Given a subrepresentation, one can compute the complement. Here, the trivial subrepresentation has dimension \(d=1\), the parent representation has dimension \(D=3\), so the complement has dimension \(D-d = 2\).

The method name is maschke as it uses Maschke’s theorem as a theoretical basis.

standardRep = rep.maschke(trivialSubRep)
standardRep =

Real subrepresentation
        dimension: 2
            field: 'R'
            group: Symmetric group acting on 3 elements
        isUnitary: false
           parent: Orthogonal reducible representation
basis(1,'double'): [0.8165; -0.40825; -0.40825]
basis(2,'double'): [1.4073e-16; 0.70711; -0.70711]

Splitting a representation

The split method enumerate all irreducible subrepresentations, without doing further processing.

rep.split
ans =
{
  [1,1] =

    replab.SubRep object with properties:

                  dimension: [1x1 double]
        divisionAlgebraName: 
                      field: R
                      group: [1x1 replab.SymmetricGroup]
         injection_internal: [3x1 double]
               isSimilarRep: 0
                  isUnitary: 1
             mapsAreAdjoint: 1
                     parent: [1x1 replab.rep.RepByImages_monomial]
        projection_internal: [1x3 double]

  [1,2] =

    replab.SubRep object with properties:

                  dimension: [1x1 double]
        divisionAlgebraName: 
                      field: R
                      group: [1x1 replab.SymmetricGroup]
         injection_internal: [3x2 double]
               isSimilarRep: 0
                  isUnitary: 1
             mapsAreAdjoint: 1
                     parent: [1x1 replab.rep.RepByImages_monomial]
        projection_internal: [2x3 double]

}

Decomposing a representation (approximate)

More powerful than the split method, the decomposition method computes a decomposition of a representation into isotypic components, identifying equivalent irreducible representations present. The corresponding theory is discussed in Section 2.7 of [Ser77].

dec = rep.decomposition
dec =

Orthogonal reducible representation
        dimension: 3
            field: 'R'
            group: Symmetric group acting on 3 elements
        isUnitary: true
           parent: Orthogonal reducible representation
basis(1,'double'): [0.57735; 0.57735; 0.57735]
basis(2,'double'): [0.8165; -0.40825; -0.40825]
basis(3,'double'): [1.4073e-16; 0.70711; -0.70711]
     component(1): Isotypic component R(1) (trivial)
     component(2): Isotypic component R(2) (nontrivial)

The returned object is of type Irreducible, and it contains isotypic components of type Isotypic. However, all these objects are subrepresentations in themselves, so the projection/injection methods can be called.

c1 = dec.component(1);
c2 = dec.component(2);
inj1 = c1.injection
inj2 = c2.injection
inj1 =

   0.5774
   0.5774
   0.5774

inj2 =

   8.1650e-01   1.4073e-16
  -4.0825e-01   7.0711e-01
  -4.0825e-01  -7.0711e-01

Isotypic components themselves can contain multiple copies of irreducible representations (for this example, a single copy!).

c1.irreps
ans =
{
  [1,1] =

    replab.SubRep object with properties:

                  dimension: [1x1 double]
        divisionAlgebraName: 
                      field: R
                      group: [1x1 replab.SymmetricGroup]
         injection_internal: [3x1 double]
               isSimilarRep: 0
                  isUnitary: 1
             mapsAreAdjoint: 1
                     parent: [1x1 replab.rep.RepByImages_monomial]
        projection_internal: [1x3 double]

}

Refine subrepresentations

Given an inexact subrepresentation, one can ask RepLAB to refine the approximate injection and projection maps.

errBefore = c1.errorBound
refined = c1.refine;
errAfter = refined.errorBound
errBefore = 4.1514e-16
error: scalar cannot be indexed with .
error: called from
    harmonize_unitary_largeScale at line 30 column 5
    refine at line 433 column 25
error: 'refined' undefined near line 1, column 1

Decomposing a representation (exact)

RepLAB was developed originally to work with approximate decompositions. Later on, support was added for exact real and complex character tables. However, RepLAB is unable to compute those character tables by itself, and relies either on precomputed data or known construction for families of groups.

To decompose a representation exactly, one first needs to verify that the corresponding character table (real or complex), is available.

rep.group.realCharacterTable
ans =

  Class  1a   3a   2a  
   Size   1    2    3  
                       
    X.1  1    1    1   
    X.2  1    1   -1   
    X.3  2   -1    0   

Note that for some groups, only the complex character table is known; in those case, one can complexify a real representation before decomposing it.

The method call is decomposition with an extra parameter:

dec = rep.decomposition('exact')
dec =

Orthogonal reducible representation
       dimension: 3
           field: 'R'
           group: Symmetric group acting on 3 elements
       isUnitary: true
          parent: Orthogonal reducible representation
basis(1,'exact'): [1/3; 1/3; 1/3]
basis(2,'exact'): [1/6; -1/3; 1/6]
basis(3,'exact'): [-sqrt(3)/6; 0; sqrt(3)/6]
    component(1): Isotypic component R(1) (trivial)
    component(2): Isotypic component 0 x R(1) (nontrivial)
    component(3): Isotypic component R(2) (nontrivial)

And then, the injection/projection maps can be recovered in exact arithmetic.

I = dec.injection('exact')
P = dec.projection('exact')
ans =
  1/3   1/6  -sqrt(3)/6  
  1/3  -1/3       0      
  1/3   1/6   sqrt(3)/6  
ans =
      1      1     1     
      1     -2     1     
  -sqrt(3)   0  sqrt(3)  

Adding a group to the Atlas

If a group is not known in RepLAB, it is possible to add it to the Atlas, using a JSON interoperability format. This format includes character tables and allows RepLAB to recognize the group.

Group data can be exported from GAP System. First, one needs to install GAP System and set the gapBinaryPath variable. Then, one runs the computeAndAdd method.

G = replab.PermutationGroup.of([2 3 1 4 5], [2 1 3 4 5], [1 2 3 5 4]);
replab.Atlas.computeAndAdd(G);

Before asking for the character table of that group, one needs to restart RepLAB, as of January 2022. This limitation may be lifted in the future.