Maximal Subgroups and Branching Rules#
Branching rules#
If \(G\) is a Lie group and \(H\) is a subgroup, one often needs to know how representations of \(G\) restrict to \(H\). Irreducibles usually do not restrict to irreducibles. In some cases the restriction is regular and predictable, in other cases it is chaotic. In some cases it follows a rule that can be described combinatorially, but the combinatorial description is subtle. The description of how irreducibles decompose into irreducibles is called a branching rule.
References for this topic:
Sage can compute how a character of \(G\) restricts to \(H\). It does so not by memorizing a combinatorial rule, but by computing the character and restricting the character to a maximal torus of \(H\). What Sage has memorized (in a series of built-in encoded rules) are the various embeddings of maximal tori of maximal subgroups of \(G\). The maximal subgroups of Lie groups were determined in [Dynkin1952]. This approach to computing branching rules has a limitation: the character must fit into memory and be computable by Sage’s internal code in real time.
It is sufficient to consider the case where \(H\) is a maximal subgroup of \(G\), since if this is known then one may branch down successively through a series of subgroups, each maximal in its predecessors. A problem is therefore to understand the maximal subgroups in a Lie group, and to give branching rules for each, and a goal of this tutorial is to explain the embeddings of maximal subgroups.
Sage has a class BranchingRule
for branching rules. The function
branching_rule
returns elements of this class. For example,
the natural embedding of \(Sp(4)\) into \(SL(4)\) corresponds to
the branching rule that we may create as follows:
sage: b = branching_rule("A3","C2",rule="symmetric"); b
symmetric branching rule A3 => C2
>>> from sage.all import *
>>> b = branching_rule("A3","C2",rule="symmetric"); b
symmetric branching rule A3 => C2
The name “symmetric” of this branching rule will be
explained further later, but it means that \(Sp(4)\) is
the fixed subgroup of an involution of \(Sl(4)\).
Here A3
and C2
are the Cartan types of the groups
\(G=SL(4)\) and \(H=Sp(4)\).
Now we may see how representations of \(SL(4)\) decompose into irreducibles when they are restricted to \(Sp(4)\):
sage: A3 = WeylCharacterRing("A3",style="coroots")
sage: chi = A3(1,0,1); chi.degree()
15
sage: C2 = WeylCharacterRing("C2",style="coroots")
sage: chi.branch(C2,rule=b)
C2(0,1) + C2(2,0)
>>> from sage.all import *
>>> A3 = WeylCharacterRing("A3",style="coroots")
>>> chi = A3(Integer(1),Integer(0),Integer(1)); chi.degree()
15
>>> C2 = WeylCharacterRing("C2",style="coroots")
>>> chi.branch(C2,rule=b)
C2(0,1) + C2(2,0)
Alternatively, we may pass chi
to b
as an
argument of its branch method, which gives the same
result:
sage: b.branch(chi)
C2(0,1) + C2(2,0)
>>> from sage.all import *
>>> b.branch(chi)
C2(0,1) + C2(2,0)
It is believed that the built-in branching rules of Sage are sufficient to handle all maximal subgroups and this is certainly the case when the rank if less than or equal to 8.
However, if you want to branch to a subgroup that
is not maximal you may not find a built-in
branching rule. We may compose branching rules to build
up embeddings. For example, here are two different
embeddings of \(Sp(4)\) with Cartan type C2
in
\(Sp(8)\), with Cartan type C4
. One embedding
factors through \(Sp(4)\times Sp(4)\), while the
other factors through \(SL(4)\). To check that the embeddings
are not conjugate, we branch a (randomly chosen) representation.
Observe that we do not have to build the intermediate
Weyl character rings
.
sage: C4 = WeylCharacterRing("C4",style="coroots")
sage: b1 = branching_rule("C4","A3","levi")*branching_rule("A3","C2","symmetric"); b1
composite branching rule C4 => (levi) A3 => (symmetric) C2
sage: b2 = branching_rule("C4","C2xC2","orthogonal_sum")*branching_rule("C2xC2","C2","proj1"); b2
composite branching rule C4 => (orthogonal_sum) C2xC2 => (proj1) C2
sage: C2 = WeylCharacterRing("C2",style="coroots")
sage: C4 = WeylCharacterRing("C4",style="coroots")
sage: [C4(2,0,0,1).branch(C2, rule=br) for br in [b1,b2]]
[4*C2(0,0) + 7*C2(0,1) + 15*C2(2,0) + 7*C2(0,2) + 11*C2(2,1) + C2(0,3) + 6*C2(4,0) + 3*C2(2,2),
10*C2(0,0) + 40*C2(1,0) + 50*C2(0,1) + 16*C2(2,0) + 20*C2(1,1) + 4*C2(3,0) + 5*C2(2,1)]
>>> from sage.all import *
>>> C4 = WeylCharacterRing("C4",style="coroots")
>>> b1 = branching_rule("C4","A3","levi")*branching_rule("A3","C2","symmetric"); b1
composite branching rule C4 => (levi) A3 => (symmetric) C2
>>> b2 = branching_rule("C4","C2xC2","orthogonal_sum")*branching_rule("C2xC2","C2","proj1"); b2
composite branching rule C4 => (orthogonal_sum) C2xC2 => (proj1) C2
>>> C2 = WeylCharacterRing("C2",style="coroots")
>>> C4 = WeylCharacterRing("C4",style="coroots")
>>> [C4(Integer(2),Integer(0),Integer(0),Integer(1)).branch(C2, rule=br) for br in [b1,b2]]
[4*C2(0,0) + 7*C2(0,1) + 15*C2(2,0) + 7*C2(0,2) + 11*C2(2,1) + C2(0,3) + 6*C2(4,0) + 3*C2(2,2),
10*C2(0,0) + 40*C2(1,0) + 50*C2(0,1) + 16*C2(2,0) + 20*C2(1,1) + 4*C2(3,0) + 5*C2(2,1)]
What’s in a branching rule?#
The essence of the branching rule is a function from the weight lattice of \(G\) to the weight lattice of the subgroup \(H\), usually implemented as a function on the ambient vector spaces. Indeed, we may conjugate the embedding so that a Cartan subalgebra \(U\) of \(H\) is contained in a Cartan subalgebra \(T\) of \(G\). Since the ambient vector space of the weight lattice of \(G\) is \(\hbox{Lie}(T)^*\), we get map \(\hbox{Lie}(T)^*\to\hbox{Lie}(U)^*\), and this must be implemented as a function. For speed, the function usually just returns a list, which can be coerced into \(\hbox{Lie}(U)^*\).
sage: b = branching_rule("A3","C2","symmetric")
sage: for r in RootSystem("A3").ambient_space().simple_roots():
....: print("{} {}".format(r, b(r)))
(1, -1, 0, 0) [1, -1]
(0, 1, -1, 0) [0, 2]
(0, 0, 1, -1) [1, -1]
>>> from sage.all import *
>>> b = branching_rule("A3","C2","symmetric")
>>> for r in RootSystem("A3").ambient_space().simple_roots():
... print("{} {}".format(r, b(r)))
(1, -1, 0, 0) [1, -1]
(0, 1, -1, 0) [0, 2]
(0, 0, 1, -1) [1, -1]
We could conjugate this map by an element of the Weyl group of \(G\), and the resulting map would give the same decomposition of representations of \(G\) into irreducibles of \(H\). However it is a good idea to choose the map so that it takes dominant weights to dominant weights, and, insofar as possible, simple roots of \(G\) into simple roots of \(H\). This includes sometimes the affine root \(\alpha_0\) of \(G\), which we recall is the negative of the highest root.
The branching rule has a describe()
method that shows how
the roots (including the affine root) restrict. This is a
useful way of understanding the embedding. You might
want to try it with various branching rules of different
kinds, "extended"
, "symmetric"
, "levi"
etc.
sage: b.describe()
0
O-------+
| |
| |
O---O---O
1 2 3
A3~
root restrictions A3 => C2:
O=<=O
1 2
C2
1 => 1
2 => 2
3 => 1
For more detailed information use verbose=True
>>> from sage.all import *
>>> b.describe()
<BLANKLINE>
0
O-------+
| |
| |
O---O---O
1 2 3
A3~
<BLANKLINE>
root restrictions A3 => C2:
<BLANKLINE>
O=<=O
1 2
C2
<BLANKLINE>
1 => 1
2 => 2
3 => 1
<BLANKLINE>
For more detailed information use verbose=True
The extended Dynkin diagram of \(G\) and the ordinary
Dynkin diagram of \(H\) are shown for reference, and
3 => 1
means that the third simple root \(\alpha_3\)
of \(G\) restricts to the first simple root of \(H\).
In this example, the affine root does not restrict to
a simple roots, so it is omitted from the list of
restrictions. If you add the parameter verbose=true
you will
be shown the restriction of all simple roots and the
affine root, and also the restrictions of the fundamental weights
(in coroot notation).
Maximal subgroups#
Sage has a database of maximal subgroups for every simple Cartan
type of rank \(\le 8\). You may access this with the
maximal_subgroups
method of the Weyl character ring:
sage: E7 = WeylCharacterRing("E7",style="coroots")
sage: E7.maximal_subgroups()
A7:branching_rule("E7","A7","extended")
E6:branching_rule("E7","E6","levi")
A2:branching_rule("E7","A2","miscellaneous")
A1:branching_rule("E7","A1","iii")
A1:branching_rule("E7","A1","iv")
A1xF4:branching_rule("E7","A1xF4","miscellaneous")
G2xC3:branching_rule("E7","G2xC3","miscellaneous")
A1xG2:branching_rule("E7","A1xG2","miscellaneous")
A1xA1:branching_rule("E7","A1xA1","miscellaneous")
A1xD6:branching_rule("E7","A1xD6","extended")
A5xA2:branching_rule("E7","A5xA2","extended")
>>> from sage.all import *
>>> E7 = WeylCharacterRing("E7",style="coroots")
>>> E7.maximal_subgroups()
A7:branching_rule("E7","A7","extended")
E6:branching_rule("E7","E6","levi")
A2:branching_rule("E7","A2","miscellaneous")
A1:branching_rule("E7","A1","iii")
A1:branching_rule("E7","A1","iv")
A1xF4:branching_rule("E7","A1xF4","miscellaneous")
G2xC3:branching_rule("E7","G2xC3","miscellaneous")
A1xG2:branching_rule("E7","A1xG2","miscellaneous")
A1xA1:branching_rule("E7","A1xA1","miscellaneous")
A1xD6:branching_rule("E7","A1xD6","extended")
A5xA2:branching_rule("E7","A5xA2","extended")
It should be understood that there are other ways of embedding \(A_2=\hbox{SL}(3)\) into the Lie group \(E_7\), but only one way as a maximal subgroup. On the other hand, there are but only one way to embed it as a maximal subgroup. The embedding will be explained below. You may obtain the branching rule as follows, and use it to determine the decomposition of irreducible representations of \(E_7\) as follows:
sage: b = E7.maximal_subgroup("A2"); b
miscellaneous branching rule E7 => A2
sage: E7, A2 = [WeylCharacterRing(x,style="coroots") for x in ["E7","A2"]]
sage: E7(1,0,0,0,0,0,0).branch(A2,rule=b)
A2(1,1) + A2(4,4)
>>> from sage.all import *
>>> b = E7.maximal_subgroup("A2"); b
miscellaneous branching rule E7 => A2
>>> E7, A2 = [WeylCharacterRing(x,style="coroots") for x in ["E7","A2"]]
>>> E7(Integer(1),Integer(0),Integer(0),Integer(0),Integer(0),Integer(0),Integer(0)).branch(A2,rule=b)
A2(1,1) + A2(4,4)
This gives the same branching rule as just pasting line beginning to the right of the colon onto the command line:
sage:branching_rule("E7","A2","miscellaneous")
miscellaneous branching rule E7 => A2
>>> from sage.all import *
sage:branching_rule("E7","A2","miscellaneous")
miscellaneous branching rule E7 => A2
There are two distinct embeddings of \(A_1=\hbox{SL}(2)\) into
\(E_7\) as maximal subgroups, so the maximal_subgroup
method will return a list of rules:
sage: WeylCharacterRing("E7").maximal_subgroup("A1")
[iii branching rule E7 => A1, iv branching rule E7 => A1]
>>> from sage.all import *
>>> WeylCharacterRing("E7").maximal_subgroup("A1")
[iii branching rule E7 => A1, iv branching rule E7 => A1]
The list of maximal subgroups returned by the maximal_subgroups
method for irreducible Cartan types of rank up to 8 is believed to
be complete up to outer automorphisms. You may want a list that is
complete up to inner automorphisms. For example, \(E_6\) has a
nontrivial Dynkin diagram automorphism so it has an outer
automorphism that is not inner:
sage: E6, A2xG2 = [WeylCharacterRing(x,style="coroots") for x in ["E6","A2xG2"]]
sage: b = E6.maximal_subgroup("A2xG2"); b
miscellaneous branching rule E6 => A2xG2
sage: E6(1,0,0,0,0,0).branch(A2xG2,rule=b)
A2xG2(0,1,1,0) + A2xG2(2,0,0,0)
sage: E6(0,0,0,0,0,1).branch(A2xG2,rule=b)
A2xG2(1,0,1,0) + A2xG2(0,2,0,0)
>>> from sage.all import *
>>> E6, A2xG2 = [WeylCharacterRing(x,style="coroots") for x in ["E6","A2xG2"]]
>>> b = E6.maximal_subgroup("A2xG2"); b
miscellaneous branching rule E6 => A2xG2
>>> E6(Integer(1),Integer(0),Integer(0),Integer(0),Integer(0),Integer(0)).branch(A2xG2,rule=b)
A2xG2(0,1,1,0) + A2xG2(2,0,0,0)
>>> E6(Integer(0),Integer(0),Integer(0),Integer(0),Integer(0),Integer(1)).branch(A2xG2,rule=b)
A2xG2(1,0,1,0) + A2xG2(0,2,0,0)
Since as we see the two 27 dimensional irreducibles (which are interchanged by the outer automorphism) have different branching, the \(A_2\times G_2\) subgroup is changed to a different one by the outer automorphism. To obtain the second branching rule, we compose the given one with this automorphism:
sage: b1 = branching_rule("E6","E6","automorphic")*b; b1
composite branching rule E6 => (automorphic) E6 => (miscellaneous) A2xG2
>>> from sage.all import *
>>> b1 = branching_rule("E6","E6","automorphic")*b; b1
composite branching rule E6 => (automorphic) E6 => (miscellaneous) A2xG2
Levi subgroups#
A Levi subgroup may or may not be maximal. They are easily classified. If one starts with a Dynkin diagram for \(G\) and removes a single node, one obtains a smaller Dynkin diagram, which is the Dynkin diagram of a smaller subgroup \(H\).
For example, here is the A3 Dynkin diagram:
sage: A3 = WeylCharacterRing("A3")
sage: A3.dynkin_diagram()
O---O---O
1 2 3
A3
>>> from sage.all import *
>>> A3 = WeylCharacterRing("A3")
>>> A3.dynkin_diagram()
O---O---O
1 2 3
A3
We see that we may remove the node 3 and obtain \(A_2\), or the node 2 and obtain \(A_1 \times A_1\). These correspond to the Levi subgroups \(GL(3)\) and \(GL(2) \times GL(2)\) of \(GL(4)\).
Let us construct the irreducible representations of \(GL(4)\) and branch them down to these down to \(GL(3)\) and \(GL(2) \times GL(2)\):
sage: reps = [A3(v) for v in A3.fundamental_weights()]; reps
[A3(1,0,0,0), A3(1,1,0,0), A3(1,1,1,0)]
sage: A2 = WeylCharacterRing("A2")
sage: A1xA1 = WeylCharacterRing("A1xA1")
sage: [pi.branch(A2, rule="levi") for pi in reps]
[A2(0,0,0) + A2(1,0,0), A2(1,0,0) + A2(1,1,0), A2(1,1,0) + A2(1,1,1)]
sage: [pi.branch(A1xA1, rule="levi") for pi in reps]
[A1xA1(1,0,0,0) + A1xA1(0,0,1,0),
A1xA1(1,1,0,0) + A1xA1(1,0,1,0) + A1xA1(0,0,1,1),
A1xA1(1,1,1,0) + A1xA1(1,0,1,1)]
>>> from sage.all import *
>>> reps = [A3(v) for v in A3.fundamental_weights()]; reps
[A3(1,0,0,0), A3(1,1,0,0), A3(1,1,1,0)]
>>> A2 = WeylCharacterRing("A2")
>>> A1xA1 = WeylCharacterRing("A1xA1")
>>> [pi.branch(A2, rule="levi") for pi in reps]
[A2(0,0,0) + A2(1,0,0), A2(1,0,0) + A2(1,1,0), A2(1,1,0) + A2(1,1,1)]
>>> [pi.branch(A1xA1, rule="levi") for pi in reps]
[A1xA1(1,0,0,0) + A1xA1(0,0,1,0),
A1xA1(1,1,0,0) + A1xA1(1,0,1,0) + A1xA1(0,0,1,1),
A1xA1(1,1,1,0) + A1xA1(1,0,1,1)]
Let us redo this calculation in coroot notation. As we have explained, coroot notation does not distinguish between representations of \(GL(4)\) that have the same restriction to \(SL(4)\), so in effect we are now working with the groups \(SL(4)\) and its Levi subgroups \(SL(3)\) and \(SL(2) \times SL(2)\), which is the derived group of its Levi subgroup:
sage: A3 = WeylCharacterRing("A3", style="coroots")
sage: reps = [A3(v) for v in A3.fundamental_weights()]; reps
[A3(1,0,0), A3(0,1,0), A3(0,0,1)]
sage: A2 = WeylCharacterRing("A2", style="coroots")
sage: A1xA1 = WeylCharacterRing("A1xA1", style="coroots")
sage: [pi.branch(A2, rule="levi") for pi in reps]
[A2(0,0) + A2(1,0), A2(0,1) + A2(1,0), A2(0,0) + A2(0,1)]
sage: [pi.branch(A1xA1, rule="levi") for pi in reps]
[A1xA1(1,0) + A1xA1(0,1), 2*A1xA1(0,0) + A1xA1(1,1), A1xA1(1,0) + A1xA1(0,1)]
>>> from sage.all import *
>>> A3 = WeylCharacterRing("A3", style="coroots")
>>> reps = [A3(v) for v in A3.fundamental_weights()]; reps
[A3(1,0,0), A3(0,1,0), A3(0,0,1)]
>>> A2 = WeylCharacterRing("A2", style="coroots")
>>> A1xA1 = WeylCharacterRing("A1xA1", style="coroots")
>>> [pi.branch(A2, rule="levi") for pi in reps]
[A2(0,0) + A2(1,0), A2(0,1) + A2(1,0), A2(0,0) + A2(0,1)]
>>> [pi.branch(A1xA1, rule="levi") for pi in reps]
[A1xA1(1,0) + A1xA1(0,1), 2*A1xA1(0,0) + A1xA1(1,1), A1xA1(1,0) + A1xA1(0,1)]
Now we may observe a distinction difference in branching from
versus
Consider the representation A3(0,1,0)
, which is the six dimensional
exterior square. In the coroot notation, the restriction contained two
copies of the trivial representation, 2*A1xA1(0,0)
. The other way,
we had instead three distinct representations in the restriction, namely
A1xA1(1,1,0,0)
and A1xA1(0,0,1,1)
, that is,
\(\det \otimes 1\) and \(1 \otimes \det\).
The Levi subgroup A1xA1
is actually not maximal. Indeed, we may
factor the embedding:
Therefore there are branching rules A3 -> C2
and C2 -> A2
, and
we could accomplish the branching in two steps, thus:
sage: A3 = WeylCharacterRing("A3", style="coroots")
sage: C2 = WeylCharacterRing("C2", style="coroots")
sage: B2 = WeylCharacterRing("B2", style="coroots")
sage: D2 = WeylCharacterRing("D2", style="coroots")
sage: A1xA1 = WeylCharacterRing("A1xA1", style="coroots")
sage: reps = [A3(fw) for fw in A3.fundamental_weights()]
sage: [pi.branch(C2, rule="symmetric").branch(B2, rule="isomorphic"). \
branch(D2, rule="extended").branch(A1xA1, rule="isomorphic") for pi in reps]
[A1xA1(1,0) + A1xA1(0,1), 2*A1xA1(0,0) + A1xA1(1,1), A1xA1(1,0) + A1xA1(0,1)]
>>> from sage.all import *
>>> A3 = WeylCharacterRing("A3", style="coroots")
>>> C2 = WeylCharacterRing("C2", style="coroots")
>>> B2 = WeylCharacterRing("B2", style="coroots")
>>> D2 = WeylCharacterRing("D2", style="coroots")
>>> A1xA1 = WeylCharacterRing("A1xA1", style="coroots")
>>> reps = [A3(fw) for fw in A3.fundamental_weights()]
>>> [pi.branch(C2, rule="symmetric").branch(B2, rule="isomorphic"). \
branch(D2, rule="extended").branch(A1xA1, rule="isomorphic") for pi in reps]
[A1xA1(1,0) + A1xA1(0,1), 2*A1xA1(0,0) + A1xA1(1,1), A1xA1(1,0) + A1xA1(0,1)]
As you can see, we’ve redone the branching rather circuitously this
way, making use of the branching rules A3 -> C2
and B2 -> D2
, and
two accidental isomorphisms C2 = B2
and D2 = A1xA1
. It is much
easier to go in one step using rule="levi"
, but reassuring that we
get the same answer!
Subgroups classified by the extended Dynkin diagram#
It is also true that if we remove one node from the extended Dynkin diagram that we obtain the Dynkin diagram of a subgroup. For example:
sage: G2 = WeylCharacterRing("G2", style="coroots")
sage: G2.extended_dynkin_diagram()
3
O=<=O---O
1 2 0
G2~
>>> from sage.all import *
>>> G2 = WeylCharacterRing("G2", style="coroots")
>>> G2.extended_dynkin_diagram()
3
O=<=O---O
1 2 0
G2~
Observe that by removing the 1 node that we obtain an \(A_2\) Dynkin diagram. Therefore the exceptional group \(G_2\) contains a copy of \(SL(3)\). We branch the two representations of \(G_2\) corresponding to the fundamental weights to this copy of \(A_2\):
sage: G2 = WeylCharacterRing("G2", style="coroots")
sage: A2 = WeylCharacterRing("A2", style="coroots")
sage: [G2(f).degree() for f in G2.fundamental_weights()]
[7, 14]
sage: [G2(f).branch(A2, rule="extended") for f in G2.fundamental_weights()]
[A2(0,0) + A2(0,1) + A2(1,0), A2(0,1) + A2(1,0) + A2(1,1)]
>>> from sage.all import *
>>> G2 = WeylCharacterRing("G2", style="coroots")
>>> A2 = WeylCharacterRing("A2", style="coroots")
>>> [G2(f).degree() for f in G2.fundamental_weights()]
[7, 14]
>>> [G2(f).branch(A2, rule="extended") for f in G2.fundamental_weights()]
[A2(0,0) + A2(0,1) + A2(1,0), A2(0,1) + A2(1,0) + A2(1,1)]
The two representations of \(G_2\), of degrees 7 and 14 respectively, are the action on the octonions of trace zero and the adjoint representation.
For embeddings of this type, the rank of the subgroup \(H\) is the same as the rank of \(G\). This is in contrast with embeddings of Levi type, where \(H\) has rank one less than \(G\).
Levi subgroups of \(G_2\)#
The exceptional group \(G_2\) has two Levi subgroups of type
\(A_1\). Neither is maximal, as we can see from the extended
Dynkin diagram: the subgroups \(A_1\times A_1\) and \(A_2\)
are maximal and each contains a Levi subgroup. (Actually
\(A_1\times A_1\) contains a conjugate of both.) Only
the Levi subgroup containing the short root is implemented
as an instance of rule="levi"
. To obtain the other,
use the rule:
sage: branching_rule("G2","A2","extended")*branching_rule("A2","A1","levi")
composite branching rule G2 => (extended) A2 => (levi) A1
>>> from sage.all import *
>>> branching_rule("G2","A2","extended")*branching_rule("A2","A1","levi")
composite branching rule G2 => (extended) A2 => (levi) A1
which branches to the \(A_1\) Levi subgroup containing a long root.
Orthogonal and symplectic subgroups of orthogonal and symplectic groups#
If \(G = \hbox{SO}(n)\) then \(G\) has a subgroup \(\hbox{SO}(n-1)\). Depending on
whether \(n\) is even or odd, we thus have branching rules
['D',r]
to ['B',r-1]
or ['B',r]
to ['D',r]
. These are
handled as follows:
sage: branching_rule("B4","D4",rule="extended")
extended branching rule B4 => D4
sage: branching_rule("D4","B3",rule="symmetric")
symmetric branching rule D4 => B3
>>> from sage.all import *
>>> branching_rule("B4","D4",rule="extended")
extended branching rule B4 => D4
>>> branching_rule("D4","B3",rule="symmetric")
symmetric branching rule D4 => B3
If \(G = \hbox{SO}(r+s)\) then \(G\) has a subgroup \(\hbox{SO}(r) \times \hbox{SO}(s)\). This lifts to an embedding of the universal covering groups
Sometimes this embedding is of extended type, and sometimes it is
not. It is of extended type unless \(r\) and \(s\) are both odd. If it is
of extended type then you may use rule="extended"
. In any case you
may use rule="orthogonal_sum"
. The name refer to the origin of the
embedding \(SO(r) \times SO(s) \to SO(r+s)\) from the decomposition of
the underlying quadratic space as a direct sum of two orthogonal
subspaces.
There are four cases depending on the parity of \(r\) and \(s\). For example, if \(r = 2k\) and \(s = 2l\) we have an embedding:
['D',k] x ['D',l] --> ['D',k+l]
This is of extended type. Thus consider the embedding
D4xD3 -> D7
. Here is the extended Dynkin diagram:
0 O O 7
| |
| |
O---O---O---O---O---O
1 2 3 4 5 6
Removing the 4 vertex results in a disconnected Dynkin diagram:
0 O O 7
| |
| |
O---O---O O---O
1 2 3 5 6
This is D4xD3
. Therefore use the “extended” branching rule:
sage: D7 = WeylCharacterRing("D7", style="coroots")
sage: D4xD3 = WeylCharacterRing("D4xD3", style="coroots")
sage: spin = D7(D7.fundamental_weights()[7]); spin
D7(0,0,0,0,0,0,1)
sage: spin.branch(D4xD3, rule="extended")
D4xD3(0,0,1,0,0,1,0) + D4xD3(0,0,0,1,0,0,1)
>>> from sage.all import *
>>> D7 = WeylCharacterRing("D7", style="coroots")
>>> D4xD3 = WeylCharacterRing("D4xD3", style="coroots")
>>> spin = D7(D7.fundamental_weights()[Integer(7)]); spin
D7(0,0,0,0,0,0,1)
>>> spin.branch(D4xD3, rule="extended")
D4xD3(0,0,1,0,0,1,0) + D4xD3(0,0,0,1,0,0,1)
But we could equally well use the “orthogonal_sum” rule:
sage: spin.branch(D4xD3, rule="orthogonal_sum")
D4xD3(0,0,1,0,0,1,0) + D4xD3(0,0,0,1,0,0,1)
>>> from sage.all import *
>>> spin.branch(D4xD3, rule="orthogonal_sum")
D4xD3(0,0,1,0,0,1,0) + D4xD3(0,0,0,1,0,0,1)
Similarly we have embeddings:
['D',k] x ['B',l] --> ['B',k+l]
These are also of extended type. For example consider the embedding of
D3xB2 -> B5
. Here is the B5
extended Dynkin diagram:
O 0
|
|
O---O---O---O=>=O
1 2 3 4 5
Removing the 3 node gives:
O 0
|
O---O O=>=O
1 2 4 5
and this is the Dynkin diagram or D3xB2
. For such branchings we
again use either rule="extended"
or rule="orthogonal_sum"
.
Finally, there is an embedding
['B',k] x ['B',l] --> ['D',k+l+1]
This is not of extended type, so you may not use rule="extended"
.
You must use rule="orthogonal_sum"
:
sage: D5 = WeylCharacterRing("D5",style="coroots")
sage: B2xB2 = WeylCharacterRing("B2xB2",style="coroots")
sage: [D5(v).branch(B2xB2,rule="orthogonal_sum") for v in D5.fundamental_weights()]
[B2xB2(1,0,0,0) + B2xB2(0,0,1,0),
B2xB2(0,2,0,0) + B2xB2(1,0,1,0) + B2xB2(0,0,0,2),
B2xB2(0,2,0,0) + B2xB2(0,2,1,0) + B2xB2(1,0,0,2) + B2xB2(0,0,0,2),
B2xB2(0,1,0,1), B2xB2(0,1,0,1)]
>>> from sage.all import *
>>> D5 = WeylCharacterRing("D5",style="coroots")
>>> B2xB2 = WeylCharacterRing("B2xB2",style="coroots")
>>> [D5(v).branch(B2xB2,rule="orthogonal_sum") for v in D5.fundamental_weights()]
[B2xB2(1,0,0,0) + B2xB2(0,0,1,0),
B2xB2(0,2,0,0) + B2xB2(1,0,1,0) + B2xB2(0,0,0,2),
B2xB2(0,2,0,0) + B2xB2(0,2,1,0) + B2xB2(1,0,0,2) + B2xB2(0,0,0,2),
B2xB2(0,1,0,1), B2xB2(0,1,0,1)]
Non-maximal Levi subgroups and Projection from Reducible Types#
Not all Levi subgroups are maximal. Recall that the Dynkin-diagram of a Levi subgroup \(H\) of \(G\) is obtained by removing a node from the Dynkin diagram of \(G\). Removing the same node from the extended Dynkin diagram of \(G\) results in the Dynkin diagram of a subgroup of \(G\) that is strictly larger than \(H\). However this subgroup may or may not be proper, so the Levi subgroup may or may not be maximal.
If the Levi subgroup is not maximal, the branching rule may or may not be implemented in Sage. However if it is not implemented, it may be constructed as a composition of two branching rules.
For example, prior to Sage-6.1 branching_rule("E6","A5","levi")
returned a not-implemented error and the advice to branch to
A5xA1
. And we can see from the extended Dynkin diagram of \(E_6\)
that indeed \(A_5\) is not a maximal subgroup, since removing node 2
from the extended Dynkin diagram (see below) gives A5xA1
. To
construct the branching rule to \(A_5\) we may proceed as follows:
sage: b = branching_rule("E6","A5xA1","extended")*branching_rule("A5xA1","A5","proj1"); b
composite branching rule E6 => (extended) A5xA1 => (proj1) A5
sage: E6 = WeylCharacterRing("E6",style="coroots")
sage: A5 = WeylCharacterRing("A5",style="coroots")
sage: E6(0,1,0,0,0,0).branch(A5,rule=b)
3*A5(0,0,0,0,0) + 2*A5(0,0,1,0,0) + A5(1,0,0,0,1)
sage: b.describe()
O 0
|
|
O 2
|
|
O---O---O---O---O
1 3 4 5 6
E6~
root restrictions E6 => A5:
O---O---O---O---O
1 2 3 4 5
A5
0 => (zero)
1 => 1
3 => 2
4 => 3
5 => 4
6 => 5
For more detailed information use verbose=True
>>> from sage.all import *
>>> b = branching_rule("E6","A5xA1","extended")*branching_rule("A5xA1","A5","proj1"); b
composite branching rule E6 => (extended) A5xA1 => (proj1) A5
>>> E6 = WeylCharacterRing("E6",style="coroots")
>>> A5 = WeylCharacterRing("A5",style="coroots")
>>> E6(Integer(0),Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)).branch(A5,rule=b)
3*A5(0,0,0,0,0) + 2*A5(0,0,1,0,0) + A5(1,0,0,0,1)
>>> b.describe()
<BLANKLINE>
O 0
|
|
O 2
|
|
O---O---O---O---O
1 3 4 5 6
E6~
root restrictions E6 => A5:
<BLANKLINE>
O---O---O---O---O
1 2 3 4 5
A5
<BLANKLINE>
0 => (zero)
1 => 1
3 => 2
4 => 3
5 => 4
6 => 5
<BLANKLINE>
For more detailed information use verbose=True
Note that it is not necessary to construct the Weyl character ring
for the intermediate group A5xA1
.
This last example illustrates another common problem:
how to extract one component from a reducible root system.
We used the rule "proj1"
to extract the first component.
We could similarly use "proj2"
to get the second, or
more generally any combination of components:
sage: branching_rule("A2xB2xG2","A2xG2","proj13")
proj13 branching rule A2xB2xG2 => A2xG2
>>> from sage.all import *
>>> branching_rule("A2xB2xG2","A2xG2","proj13")
proj13 branching rule A2xB2xG2 => A2xG2
Symmetric subgroups#
If \(G\) admits an outer automorphism (usually of order two) then we may try to find the branching rule to the fixed subgroup \(H\). It can be arranged that this automorphism maps the maximal torus \(T\) to itself and that a maximal torus \(U\) of \(H\) is contained in \(T\).
Suppose that the Dynkin diagram of \(G\) admits an automorphism. Then \(G\) itself admits an outer automorphism. The Dynkin diagram of the group \(H\) of invariants may be obtained by “folding” the Dynkin diagram of \(G\) along the automorphism. The exception is the branching rule \(GL(2r) \to SO(2r)\).
Here are the branching rules that can be obtained using
rule="symmetric"
.
\(G\) |
\(H\) |
Cartan Types |
---|---|---|
\(GL(2r)\) |
\(Sp(2r)\) |
|
\(GL(2r+1)\) |
\(SO(2r+1)\) |
|
\(GL(2r)\) |
\(SO(2r)\) |
|
\(SO(2r)\) |
\(SO(2r-1)\) |
|
\(E_6\) |
\(F_4\) |
|
Tensor products#
If \(G_1\) and \(G_2\) are Lie groups, and we have representations \(\pi_1: G_1 \to GL(n)\) and \(\pi_2: G_2 \to GL(m)\) then the tensor product is a representation of \(G_1 \times G_2\). It has its image in \(GL(nm)\) but sometimes this is conjugate to a subgroup of \(SO(nm)\) or \(Sp(nm)\). In particular we have the following cases.
Group |
Subgroup |
Cartan Types |
---|---|---|
\(GL(rs)\) |
\(GL(r)\times GL(s)\) |
|
\(SO(4rs+2r+2s+1)\) |
\(SO(2r+1)\times SO(2s+1)\) |
|
\(SO(4rs+2s)\) |
\(SO(2r+1)\times SO(2s)\) |
|
\(SO(4rs)\) |
\(SO(2r)\times SO(2s)\) |
|
\(SO(4rs)\) |
\(Sp(2r)\times Sp(2s)\) |
|
\(Sp(4rs+2s)\) |
\(SO(2r+1)\times Sp(2s)\) |
|
\(Sp(4rs)\) |
\(Sp(2r)\times SO(2s)\) |
|
These branching rules are obtained using rule="tensor"
.
Symmetric powers#
The \(k\)-th symmetric and exterior power homomorphisms map \(GL(n) \to GL \left(\binom{n+k-1}{k} \right)\) and \(GL \left(\binom{n}{k} \right)\). The corresponding branching rules are not implemented but a special case is. The \(k\)-th symmetric power homomorphism \(SL(2) \to GL(k+1)\) has its image inside of \(SO(2r+1)\) if \(k = 2r\) and inside of \(Sp(2r)\) if \(k = 2r-1\). Hence there are branching rules:
['B',r] => A1
['C',r] => A1
and these may be obtained using rule="symmetric_power"
.
Plethysms#
The above branching rules are sufficient for most cases, but a few fall between the cracks. Mostly these involve maximal subgroups of fairly small rank.
The rule rule="plethysm"
is a powerful rule that includes any
branching rule from types \(A\), \(B\), \(C\) or \(D\) as a special case. Thus it
could be used in place of the above rules and would give the same
results. However, it is most useful when branching from \(G\) to a
maximal subgroup \(H\) such that \(rank(H) < rank(G)-1\).
We consider a homomorphism \(H \to G\) where \(G\) is one of \(SL(r+1)\),
\(SO(2r+1)\), \(Sp(2r)\) or \(SO(2r)\). The function
branching_rule_from_plethysm
produces the corresponding branching
rule. The main ingredient is the character \(\chi\) of the
representation of \(H\) that is the homomorphism to \(GL(r+1)\),
\(GL(2r+1)\) or \(GL(2r)\).
Let us consider the symmetric fifth power representation of
\(SL(2)\). This is implemented above by rule="symmetric_power"
, but
suppose we want to use rule="plethysm"
. First we construct the
homomorphism by invoking its character, to be called chi
:
sage: A1 = WeylCharacterRing("A1", style="coroots")
sage: chi = A1([5])
sage: chi.degree()
6
sage: chi.frobenius_schur_indicator()
-1
>>> from sage.all import *
>>> A1 = WeylCharacterRing("A1", style="coroots")
>>> chi = A1([Integer(5)])
>>> chi.degree()
6
>>> chi.frobenius_schur_indicator()
-1
This confirms that the character has degree 6 and is symplectic, so it
corresponds to a homomorphism \(SL(2) \to Sp(6)\), and there is a
corresponding branching rule C3 -> A1
:
sage: A1 = WeylCharacterRing("A1", style="coroots")
sage: C3 = WeylCharacterRing("C3", style="coroots")
sage: chi = A1([5])
sage: sym5rule = branching_rule_from_plethysm(chi, "C3")
sage: [C3(hwv).branch(A1, rule=sym5rule) for hwv in C3.fundamental_weights()]
[A1(5), A1(4) + A1(8), A1(3) + A1(9)]
>>> from sage.all import *
>>> A1 = WeylCharacterRing("A1", style="coroots")
>>> C3 = WeylCharacterRing("C3", style="coroots")
>>> chi = A1([Integer(5)])
>>> sym5rule = branching_rule_from_plethysm(chi, "C3")
>>> [C3(hwv).branch(A1, rule=sym5rule) for hwv in C3.fundamental_weights()]
[A1(5), A1(4) + A1(8), A1(3) + A1(9)]
This is identical to the results we would obtain using
rule="symmetric_power"
:
sage: A1 = WeylCharacterRing("A1", style="coroots")
sage: C3 = WeylCharacterRing("C3", style="coroots")
sage: [C3(v).branch(A1, rule="symmetric_power") for v in C3.fundamental_weights()]
[A1(5), A1(4) + A1(8), A1(3) + A1(9)]
>>> from sage.all import *
>>> A1 = WeylCharacterRing("A1", style="coroots")
>>> C3 = WeylCharacterRing("C3", style="coroots")
>>> [C3(v).branch(A1, rule="symmetric_power") for v in C3.fundamental_weights()]
[A1(5), A1(4) + A1(8), A1(3) + A1(9)]
But the next example of plethysm gives a branching rule not available by other methods:
sage: G2 = WeylCharacterRing("G2", style="coroots")
sage: D7 = WeylCharacterRing("D7", style="coroots")
sage: ad = G2.adjoint_representation(); ad.degree()
14
sage: ad.frobenius_schur_indicator()
1
sage: for r in D7.fundamental_weights(): # long time (1.29s)
....: print(D7(r).branch(G2, rule=branching_rule_from_plethysm(ad, "D7")))
G2(0,1)
G2(0,1) + G2(3,0)
G2(0,0) + G2(2,0) + G2(3,0) + G2(0,2) + G2(4,0)
G2(0,1) + G2(2,0) + G2(1,1) + G2(0,2) + G2(2,1) + G2(4,0) + G2(3,1)
G2(1,0) + G2(0,1) + G2(1,1) + 2*G2(3,0) + 2*G2(2,1) + G2(1,2) + G2(3,1) + G2(5,0) + G2(0,3)
G2(1,1)
G2(1,1)
>>> from sage.all import *
>>> G2 = WeylCharacterRing("G2", style="coroots")
>>> D7 = WeylCharacterRing("D7", style="coroots")
>>> ad = G2.adjoint_representation(); ad.degree()
14
>>> ad.frobenius_schur_indicator()
1
>>> for r in D7.fundamental_weights(): # long time (1.29s)
... print(D7(r).branch(G2, rule=branching_rule_from_plethysm(ad, "D7")))
G2(0,1)
G2(0,1) + G2(3,0)
G2(0,0) + G2(2,0) + G2(3,0) + G2(0,2) + G2(4,0)
G2(0,1) + G2(2,0) + G2(1,1) + G2(0,2) + G2(2,1) + G2(4,0) + G2(3,1)
G2(1,0) + G2(0,1) + G2(1,1) + 2*G2(3,0) + 2*G2(2,1) + G2(1,2) + G2(3,1) + G2(5,0) + G2(0,3)
G2(1,1)
G2(1,1)
In this example, \(ad\) is the 14-dimensional adjoint representation of the exceptional group \(G_2\). Since the Frobenius-Schur indicator is 1, the representation is orthogonal, and factors through \(SO(14)\), that is, \(D7\).
We do not actually have to create the character (or for that matter its ambient WeylCharacterRing) in order to create the branching rule:
sage: branching_rule("D4","A2.adjoint_representation()","plethysm")
plethysm (along A2(1,1)) branching rule D4 => A2
>>> from sage.all import *
>>> branching_rule("D4","A2.adjoint_representation()","plethysm")
plethysm (along A2(1,1)) branching rule D4 => A2
The adjoint representation of any semisimple Lie group is orthogonal, so we do not need to compute the Frobenius-Schur indicator.
Miscellaneous other subgroups#
Use rule="miscellaneous"
for the following rules. Every maximal
subgroup \(H\) of an exceptional group \(G\) are either among these,
or the five \(A_1\) subgroups described in the next section,
or (if \(G\) and \(H\) have the same rank) is available using
rule="extended"
.
\[\begin{split}\begin{aligned} B_3 & \to G_2, \\ E_6 & \to A_2, \\ E_6 & \to G_2, \\ F_4 & \to G_2 \times A_1, \\ E_6 & \to G_2 \times A_2, \\ E_7 & \to G_2 \times C_3, \\ E_7 & \to F_4 \times A_1, \\ E_7 & \to A_1 \times A_1, \\ E_7 & \to G_2 \times A_1, \\ E_7 & \to A_2 \\ E_8 & \to G_2 \times F_4. \\ E_8 & \to A_2 \times A_1. \\ E_8 & \to B_2 \end{aligned}\end{split}\]
The first rule corresponds to the embedding of \(G_2\) in \(\hbox{SO}(7)\) in its action on the trace zero octonions. The two branching rules from \(E_6\) to \(G_2\) or \(A_2\) are described in [Testerman1989]. We caution the reader that Theorem G.2 of that paper, proved there in positive characteristic is false over the complex numbers. On the other hand, the assumption of characteristic \(p\) is not important for Theorems G.1 and A.1, which describe the torus embeddings, hence contain enough information to compute the branching rule. There are other ways of embedding \(G_2\) or \(A_2\) into \(E_6\). These may embeddings be characterized by the condition that the two 27-dimensional representations of \(E_6\) restrict irreducibly to \(G_2\) or \(A_2\). Their images are maximal subgroups.
The remaining rules come about as follows. Let \(G\) be \(F_4\), \(E_6\), \(E_7\) or \(E_8\), and let \(H\) be \(G_2\), or else (if \(G=E_7\)) \(F_4\). We embed \(H\) into \(G\) in the most obvious way; that is, in the chain of subgroups
\[G_2\subset F_4\subset E_6 \subset E_7 \subset E_8\]
Then the centralizer of \(H\) is \(A_1\), \(A_2\), \(C_3\), \(F_4\) (if \(H=G_2\)) or \(A_1\) (if \(G=E_7\) and \(H=F_4\)). This gives us five of the cases. Regarding the branching rule \(E_6 \to G_2 \times A_2\), Rubenthaler [Rubenthaler2008] describes the embedding and applies it in an interesting way.
The embedding of \(A_1\times A_1\) into \(E_7\) is as follows. Deleting the 5 node of the \(E_7\) Dynkin diagram gives the Dynkin diagram of \(A_4\times A_2\), so this is a Levi subgroup. We embed \(\hbox{SL}(2)\) into this Levi subgroup via the representation \([4]\otimes[2]\). This embeds the first copy of \(A_1\). The other \(A_1\) is the connected centralizer. See [Seitz1991], particularly the proof of (3.12).
The embedding if \(G_2\times A_1\) into \(E_7\) is as follows. Deleting the 2 node of the \(E_7\) Dynkin diagram gives the \(A_6\) Dynkin diagram, which is the Levi subgroup \(\hbox{SL}(7)\). We embed \(G_2\) into \(\hbox{SL}(7)\) via the irreducible seven-dimensional representation of \(G_2\). The \(A_1\) is the centralizer.
The embedding if \(A_2\times A_1\) into \(E_8\) is as follows. Deleting the 2 node of the \(E_8\) Dynkin diagram gives the \(A_7\) Dynkin diagram, which is the Levi subgroup \(\hbox{SL}(8)\). We embed \(A_2\) into \(\hbox{SL}(8)\) via the irreducible eight-dimensional adjoint representation of \(\hbox{SL}(2)\). The \(A_1\) is the centralizer.
The embedding \(A_2\) into \(E_7\) is proved in [Seitz1991] (5.8). In particular, he computes the embedding of the \(\hbox{SL}(3)\) torus in the \(E_7\) torus, which is what is needed to implement the branching rule. The embedding of \(B_2\) into \(E_8\) is also constructed in [Seitz1991] (6.7). The embedding of the \(B_2\) Cartan subalgebra, needed to implement the branching rule, is easily deduced from (10) on page 111.
Maximal A1 subgroups of Exceptional Groups#
There are seven embeddings of \(SL(2)\) into an exceptional group as a maximal subgroup: one each for \(G_2\) and \(F_4\), two nonconjugate embeddings for \(E_7\) and three for \(E_8\) These are constructed in [Testerman1992]. Create the corresponding branching rules as follows. The names of the rules are roman numerals referring to the seven cases of Testerman’s Theorem 1:
sage: branching_rule("G2","A1","i")
i branching rule G2 => A1
sage: branching_rule("F4","A1","ii")
ii branching rule F4 => A1
sage: branching_rule("E7","A1","iii")
iii branching rule E7 => A1
sage: branching_rule("E7","A1","iv")
iv branching rule E7 => A1
sage: branching_rule("E8","A1","v")
v branching rule E8 => A1
sage: branching_rule("E8","A1","vi")
vi branching rule E8 => A1
sage: branching_rule("E8","A1","vii")
vii branching rule E8 => A1
>>> from sage.all import *
>>> branching_rule("G2","A1","i")
i branching rule G2 => A1
>>> branching_rule("F4","A1","ii")
ii branching rule F4 => A1
>>> branching_rule("E7","A1","iii")
iii branching rule E7 => A1
>>> branching_rule("E7","A1","iv")
iv branching rule E7 => A1
>>> branching_rule("E8","A1","v")
v branching rule E8 => A1
>>> branching_rule("E8","A1","vi")
vi branching rule E8 => A1
>>> branching_rule("E8","A1","vii")
vii branching rule E8 => A1
The embeddings are characterized by the root
restrictions in their branching rules: usually
a simple root of the ambient group \(G\) restricts
to the unique simple root of \(A_1\), except for
root \(\alpha_4\) for rules iv, vi and vii,
and the root \(\alpha_6\) for root vii; this is
essentially the way Testerman characterizes
the embeddings, and this information may
be obtained from Sage by employing the
describe()
method of the branching rule.
Thus:
sage: branching_rule("E8","A1","vii").describe()
O 2
|
|
O---O---O---O---O---O---O---O
1 3 4 5 6 7 8 0
E8~
root restrictions E8 => A1:
O
1
A1
1 => 1
2 => 1
3 => 1
4 => (zero)
5 => 1
6 => (zero)
7 => 1
8 => 1
For more detailed information use verbose=True
>>> from sage.all import *
>>> branching_rule("E8","A1","vii").describe()
<BLANKLINE>
O 2
|
|
O---O---O---O---O---O---O---O
1 3 4 5 6 7 8 0
E8~
root restrictions E8 => A1:
<BLANKLINE>
O
1
A1
<BLANKLINE>
1 => 1
2 => 1
3 => 1
4 => (zero)
5 => 1
6 => (zero)
7 => 1
8 => 1
<BLANKLINE>
For more detailed information use verbose=True
Writing your own branching rules#
Sage has many built-in branching rules. Indeed, at least
up to rank eight (including all the exceptional groups)
branching rules to all maximal subgroups are implemented
as built in rules, except for a few obtainable using
branching_rule_from_plethysm
. This means that
all the rules in [McKayPatera1981] are available in Sage.
Still in this section we are including instructions for coding a rule by
hand. As we have already explained, the branching rule is a function from the
weight lattice of G
to the weight lattice of H
, and if you supply this
you can write your own branching rules.
As an example, let us consider how to implement the branching rule
A3 -> C2
. Here H = C2 = Sp(4)
embedded as a subgroup in
A3 = GL(4)
. The Cartan subalgebra \(\hbox{Lie}(U)\) consists of
diagonal matrices with eigenvalues u1, u2, -u2, -u1
. Then
C2.space()
is the two dimensional vector spaces consisting of the
linear functionals u1
and u2
on U
. On the other hand
\(Lie(T) = \mathbf{R}^4\). A convenient way to see the restriction is to
think of it as the adjoint of the map [u1,u2] -> [u1,u2,-u2,-u1]
,
that is, [x0,x1,x2,x3] -> [x0-x3,x1-x2]
. Hence we may encode the
rule:
def brule(x):
return [x[0]-x[3], x[1]-x[2]]
or simply:
brule = lambda x: [x[0]-x[3], x[1]-x[2]]
Let us check that this agrees with the built-in rule:
sage: A3 = WeylCharacterRing(['A', 3])
sage: C2 = WeylCharacterRing(['C', 2])
sage: brule = lambda x: [x[0]-x[3], x[1]-x[2]]
sage: A3(1,1,0,0).branch(C2, rule=brule)
C2(0,0) + C2(1,1)
sage: A3(1,1,0,0).branch(C2, rule="symmetric")
C2(0,0) + C2(1,1)
>>> from sage.all import *
>>> A3 = WeylCharacterRing(['A', Integer(3)])
>>> C2 = WeylCharacterRing(['C', Integer(2)])
>>> brule = lambda x: [x[Integer(0)]-x[Integer(3)], x[Integer(1)]-x[Integer(2)]]
>>> A3(Integer(1),Integer(1),Integer(0),Integer(0)).branch(C2, rule=brule)
C2(0,0) + C2(1,1)
>>> A3(Integer(1),Integer(1),Integer(0),Integer(0)).branch(C2, rule="symmetric")
C2(0,0) + C2(1,1)
Although this works, it is better to make the rule
into an element of the BranchingRule
class, as follows.
sage: brule = BranchingRule("A3","C2",lambda x : [x[0]-x[3], x[1]-x[2]],"custom")
sage: A3(1,1,0,0).branch(C2, rule=brule)
C2(0,0) + C2(1,1)
>>> from sage.all import *
>>> brule = BranchingRule("A3","C2",lambda x : [x[Integer(0)]-x[Integer(3)], x[Integer(1)]-x[Integer(2)]],"custom")
>>> A3(Integer(1),Integer(1),Integer(0),Integer(0)).branch(C2, rule=brule)
C2(0,0) + C2(1,1)
Automorphisms and triality#
The case where \(G=H\) can be treated as a special case of a branching rule. In most cases if \(G\) has a nontrivial outer automorphism, it has order two, corresponding to the symmetry of the Dynkin diagram. Such an involution exists in the cases \(A_r\), \(D_r\), \(E_6\).
So the automorphism acts on the representations of \(G\), and its effect may be computed using the branching rule code:
sage: A4 = WeylCharacterRing("A4",style="coroots")
sage: A4(1,0,1,0).degree()
45
sage: A4(0,1,0,1).degree()
45
sage: A4(1,0,1,0).branch(A4,rule="automorphic")
A4(0,1,0,1)
>>> from sage.all import *
>>> A4 = WeylCharacterRing("A4",style="coroots")
>>> A4(Integer(1),Integer(0),Integer(1),Integer(0)).degree()
45
>>> A4(Integer(0),Integer(1),Integer(0),Integer(1)).degree()
45
>>> A4(Integer(1),Integer(0),Integer(1),Integer(0)).branch(A4,rule="automorphic")
A4(0,1,0,1)
In the special case where G=D4
, the Dynkin diagram has
extra symmetries, and these correspond to outer automorphisms
of the group. These are implemented as the "triality"
branching rule:
sage: branching_rule("D4","D4","triality").describe()
O 4
|
|
O---O---O
1 |2 3
|
O 0
D4~
root restrictions D4 => D4:
O 4
|
|
O---O---O
1 2 3
D4
1 => 3
2 => 2
3 => 4
4 => 1
For more detailed information use verbose=True
>>> from sage.all import *
>>> branching_rule("D4","D4","triality").describe()
<BLANKLINE>
O 4
|
|
O---O---O
1 |2 3
|
O 0
D4~
root restrictions D4 => D4:
<BLANKLINE>
O 4
|
|
O---O---O
1 2 3
D4
<BLANKLINE>
1 => 3
2 => 2
3 => 4
4 => 1
<BLANKLINE>
For more detailed information use verbose=True
Triality his is not an automorphisms of \(SO(8)\), but of its double cover \(spin(8)\). Note that \(spin(8)\) has three representations of degree 8, namely the standard representation of \(SO(8)\) and the two eight-dimensional spin representations. These are permuted by triality:
sage: D4 = WeylCharacterRing("D4",style="coroots")
sage: D4(0,0,0,1).branch(D4,rule="triality")
D4(1,0,0,0)
sage: D4(0,0,0,1).branch(D4,rule="triality").branch(D4,rule="triality")
D4(0,0,1,0)
sage: D4(0,0,0,1).branch(D4,rule="triality").branch(D4,rule="triality").branch(D4,rule="triality")
D4(0,0,0,1)
>>> from sage.all import *
>>> D4 = WeylCharacterRing("D4",style="coroots")
>>> D4(Integer(0),Integer(0),Integer(0),Integer(1)).branch(D4,rule="triality")
D4(1,0,0,0)
>>> D4(Integer(0),Integer(0),Integer(0),Integer(1)).branch(D4,rule="triality").branch(D4,rule="triality")
D4(0,0,1,0)
>>> D4(Integer(0),Integer(0),Integer(0),Integer(1)).branch(D4,rule="triality").branch(D4,rule="triality").branch(D4,rule="triality")
D4(0,0,0,1)
By contrast, rule="automorphic"
simply interchanges the two
spin representations, as it always does in type \(D\):
sage: D4(0,0,0,1).branch(D4,rule="automorphic")
D4(0,0,1,0)
sage: D4(0,0,1,0).branch(D4,rule="automorphic")
D4(0,0,0,1)
>>> from sage.all import *
>>> D4(Integer(0),Integer(0),Integer(0),Integer(1)).branch(D4,rule="automorphic")
D4(0,0,1,0)
>>> D4(Integer(0),Integer(0),Integer(1),Integer(0)).branch(D4,rule="automorphic")
D4(0,0,0,1)