Documentation contents

atlas Library · Script File

W_classes.at

This file serves to compute with Weyl group conjugacy classes and characters.

A large initial part is dedicated to deciding conjugacy in the Weyl group, and
finding an explicit witness of conjugacy from a class representative.

A first major task is to list the $W$ conjugacy classes.

Every Weyl group element $w$ has an associated Levi subgroup (not necessarily
standard), whose roots are those whose reflections fix all weights fixed by
$w$ (its eigenspace for $1$ in the reflection representation). The function
|Levi_info@WeylElt| defined in Levi_subgroups.at computes the |Levi_info| for
this Levi subgroup. Then $w$ is in the Weyl group of this Levi subgroup, and
by construction it is a relatively elliptic element there.

The Weyl subgroup of any Levi subgroup is conjugate in $W$ to that of a
standard Levi subgroup, so for the purpose of finding the conjugacy classes of
$W$ it suffices to consider only standard Levi subgroups. These have been
classified (under conjugacy by $W$) in Levi_subgroups.at. The function
|standard_Levi_conjugacy_representatives| defined there lists standard Levi
conjugacy class representatives, and the function |classify_standard_Levis|
provides for a root datum more complete information in the form of a
|StdLeviTable|, which also lists Levi conjugacy orbits for easy looking up.

A subsidiary task is to enumerate elliptic conjugacy classes for each standard
Levi subsystem. The function |elliptics_for_standard_Levi@(RootDatum,[int])|
defined in elliptic.at accomplishes this, partly by explicit listing.
Source
atlas-scripts/W_classes.at (781 lines)
Definitions
63
Loads
Loaded by
W_reps.at all_finite_order.at good_W_representatives.at finite_unipotents.at projectors_using_character_tables.at nilpotent_orbits.at subgroups.at isomorphism_W.at class_tables.at character_table_E6.at character_table_E7.at character_table_E8.at classical_W_classes_and_reps.at

Definitions in source order

conjugacy_class_reps

L43conjugacy_class_reps (RootDatum rd) = [WeylElt]
list of conjugacy class representatives of W(rd)

Levi_of

L48Levi_of (WeylElt w) = [int]
posroot indices for simples of |w| system
avoiding construction of a |RootDatum|

StdLeviEltImage type

L52
set_type StdLeviEltImage =
   (WeylElt actor { conjugator from |image| back to original |w| }
  , [int]   Levi  { simples for a standard Levi }
  , WeylElt image { an element for Levi, conjugate in |W| to original |w| }
  )

Fields: actor, Levi, image

StdLeviReducer type

L57
set_type StdLeviReducer = (WeylElt->StdLeviEltImage)

conjugate_from_some_standard_Levi

L60conjugate_from_some_standard_Levi = StdLeviReducer
it is easy (but not very useful) to find some "standard" conjugate of |w|
The usefulness of a |StdLeviReducer| is limited if it can choose different
standard Levis for different elements, even though they are conjugate. To be
more useful, we must force finding a Levi from a fixed set of representatives.
Both |levi_lookup| methods from Levi_subgroups.at will force choosing a Levi
from a fixed set of representatives of classes of standard Levi subgroups.
L67

conjugate_from_elected_Levi

L74conjugate_from_elected_Levi (StdLeviFinder lookup) = StdLeviReducer

Levi_reducer declared

L78Levi_reducer : (RootDatum->StdLeviReducer)
make this a variable; implements a map to standard Levi
L79

Levi_reducer_rho

L81Levi_reducer_rho (RootDatum rd) = StdLeviReducer

Levi_reducer_classify

L83Levi_reducer_classify (RootDatum rd) = StdLeviReducer
this appears to be faster
L86

ConjugacyWitnesser type

L105
set_type ConjugacyWitnesser     = (WeylElt->(WeylElt->Maybe<WeylElt>))
Conjugacy tests will always be curried (take one |WeylElt| first, then
possibly after some preparation produce a function that takes a second one)
and come in two forms: a strong one that can produce a withness of conjugacy
in case it holds, and a weak one that just tells whether conjugacy holds.

Our approach always begins with reducing to the relatively elliptic case:
each $w$ is relatively elliptic in the (generally not standard) Levi subgroup
|Levi_of(w)| and if $w,w'$ have |Levi_of(w)=Levi_of(w')| and are conjugate in
$W$ they are already conjugate in |Levi_of(w)|; therefore to test an arbitrary
pair for conjugacy we can first test their Levi subgroups for conjugacy, and
if so conjugate the elements to a common Levi subgroup and test conjugacy
there. (For practical reasons that common Levi will be taken to be standard.)
To avoid unnecessarily creation of (sub-) root data, the reduced test will be
performed inside the original Weyl group, but with a specified list of
generators of the Levi subgroup passed as argument (being a stardard Levi,
this will be a subset of the simple roots, not necessarily listed increasing).

ConjugacyTester type

L106
set_type ConjugacyTester        = (WeylElt->(WeylElt->bool))

LeviConjugacyWitnesser type

L107
set_type LeviConjugacyWitnesser = ([int],WeylElt->(WeylElt->Maybe<WeylElt>))

LeviConjugacyTester type

L108
set_type LeviConjugacyTester    = ([int],WeylElt->(WeylElt->bool))
conjugacy test, using a provided |classify| method and an elliptic case test
L110

conjugacy_witness

L112conjugacy_witness (StdLeviReducer classify, LeviConjugacyWitnesser Lcw) = ConjugacyWitnesser

also in this file at line 278

conjugacy_test

L140conjugacy_test (StdLeviReducer classify, LeviConjugacyTester Levi_test) = ConjugacyTester
Using an elliptic case test that does not provide a witness in case of a
positive result, we can use the same approach but omit all the conjugacy
computations (other than conjugating the given elements |w| to the elected
standard Levi in the orbit of of |Levi_of(w)|, which happens inside |classify|.
Our next task is giving a conjugacy test for the elliptic case. For that we
shall use an explicit enumeration of the set of minimal length representatives
of an elliptic element; once this is done for one element, we can test the
other element by finding a minimal length conjugate and looking it up.
L155
The following greedy algorithm is guaranteed to give at least one minimal
length conjugate of any eleent |w| it may be applied to, and moreover to give
*all* such conjugates if |w| is elliptic; these facts are due to He. This
essentially says that one can conjugate |w| to a minimal length conjugate
doing one simple, weakly length decreasing conjugation at a time; moreover,
for a given minimal length elliptic element, all its conjugates of the same
length can be obtained by a sequence of length-preserving simple conjugations.

NOTE: in A2 the two simple generators are conjugate, but (obviously) not by
either one of them, which shows that the elliptic hypothesis in the second
part of the above claim cannot be dropped.

So: given a Weyl group element |w|, generate simple conjugates of it that are
not longer than it, replacing |w| whenever a shorter conjugate is found, while
restarting the generation; as long as that does not happen, make a collection
of all equal length conjugates generated, which is also used for producing
furtehr simple conjugates (and cleared at a restart). For every conjugate
generated, also record a conjugating element towards it from the original |w|.

The function |minima_He| implements this. For generating equal length
conjugates we use an orbit generation by shells of distance from the starting
point at the current length.
L161

hash_code

L185hash_code (WeylElt w,int mod) = int

also defined in hash.at

minima_He

L187minima_He ([int] Levi,WeylElt w) = [WeylElt,WeylElt]
$(w', g)$ with $g*w*/g = w'$

minimal_representative_with_witness

L225minimal_representative_with_witness (WeylElt w) = (WeylElt,WeylElt)
one selected minimal length class representative, witness conjugating to it;
this works whether or not |w| is (relatively) elliptic

also in this file at line 232

minimal_representative

L228minimal_representative (WeylElt w) = WeylElt
often one does not need a witness, so the following can be used instead

also in this file at line 235

minimal_representative_with_witness

L232minimal_representative_with_witness (([int],WeylElt) a) = (WeylElt,WeylElt)
Even though finding a minimum can be done without, we can restrict to a Levi

also in this file at line 225

minimal_representative

L235minimal_representative (([int],WeylElt) a) = WeylElt
often one does not need a witness, so the following can be used instead

also in this file at line 228

is_elliptic_for_Levi

L238is_elliptic_for_Levi ([int] Levi,WeylElt w) = bool

minimal_representatives_with_witness

L241minimal_representatives_with_witness (([int],WeylElt)args) = [WeylElt,WeylElt]

minimal_representatives

L245minimal_representatives (([int],WeylElt)args) = [WeylElt]

He_witnesser

L248He_witnesser = LeviConjugacyWitnesser

He_tester

L257He_tester = LeviConjugacyTester
Conjugacy test, using reduction to elliptic

We use the fact that x,y are conjugate iff L_x=x.Levi_datum is
conjugate to L_y=y.Levi_datum, and, after conjugating L_y to L_x,
x_ell is L_x conjugate to y_ell, where x_ell, y_ell are the elliptic
classes in L_x, L_y corresponding to x,y
Note that there is a choice of how to conjugate L_y to L_x, however the
result is independent of that choice, essentially because the only elliptic
class in type A is the Coxeter element, and the elliptic classes in a
simple group are fixed by all outer automorphisms.
L262

is_conjugate_in

L274is_conjugate_in (RootDatum rd) = ConjugacyTester

conjugacy_witness

L278conjugacy_witness (StdLeviReducer classify) = ConjugacyWitnesser
similarly default to |He_witnesser| for |conjugacy_witness|

also in this file at line 112

conjugacy_witness_in

L281conjugacy_witness_in (RootDatum rd) = ConjugacyWitnesser

untabled_tester

L300untabled_tester (LeviConjugacyTester Levi_test) = ConjugacyTester
We can test for conjugacy without doing a classificatin of the standard Levis.
The function |untabled_tester| conjugates |Levi_of(x)| for the first candidate
|x| to some standard Levi |sLevi|, and generates the |rho_stabiliser_orbit|
(which tabulates all Levis conjugate to it that have a dominant |two_rho|
value). For the other candidate |y|, it first does some quick checks that will
rule out many non-conjugate elements, and if this is not decisive, finds a
Levi |L| conjugate to |Levi_of(y))| that has dominant |two_rho|; if this
matches, |L| must be tabulated and we can find a conjugate from |Levi_of(y)|
via |L| to |sLevi|; after conjugating both |x| and |y| into |sLevi|, the
provided |LeviConjugacyTester| is applied to compare the images of |x| and |y|.

Note that although we are not interested in getting a witness for conjugacy in
case it should hold, we still must keep track of elemeent that conjugate the
Levi subgroups in question to each other.
the following inefficient function is unused, but motivates the one after it
L340

Levi_orbit

L343Levi_orbit (RootDatum rd, [int] Levi ) = [[int]]
$W$-orbit of (non standard) Levi subsystem, represented by simple systems
posroot indices
Computing just the size of this Levi orbit can be done a bit more efficiently
than generating it, though it requires a some preliminary computation. The e
idea is to use the stabiliser subgroup $M$ in $W$ of $\rho_L$; although it
does not contain the normaliser $N_L$ of the parabolic subgroup $L$ ow $W$
(since elements of $N_L$ can send |simples(L)| to a different set that also
generates $L$), the intersection $M\cap N_L$ has known index in $N_L$, namely
the size of $W_L$ (every coset by $W_L$ meets the intersection uniquely: there
is a unique element of $W_L$ that sends the image of |simples(L)| by an
element of $N_L$ back to |simples(L)| as a set). So we generate the (hopefully
small) orbit under $M$ of images of the Levi system |simples(L)|, then by
dividing the size of $M$ by that of the orbit find the size of $M\cap N_L$,
which multiplied by the size of $W_L$ gives the size of $N_L$; finally
dividing the size of $W$ by that gives our Levi orbit size.

The orbit generation here is tailored to the specific situation, whence we do
it using local code (the |begin|-|end| block below) rather than writing or
using a more general orbit generation. The special circumstance is that we
know that all elements of the acting subgroup fix $\rho_L$, so the only way
they can map all simple generators of $L$ to roots of $L$ is by permuting them
among each other. We can then ignore the distinction between a root and its
opposite (working only with positive root indices) and not worry about
choosing the simple generators for the positive part of each Levi system
(which is why we had to single out the "do nothing" case above): the Levi
system implied by a set of indices is the one additively generated by those
roots and their opposites, and this results in the same system only if the
indices are the same up to permutation. So again we can use an equality test
for orbit membership, provided we sort our lists of indices to be increasing.
L372

Levi_normalizer_index

L401Levi_normalizer_index ((RootDatum,(int->bool))(rd,select):Levi_info) = int
index of $W_L$ in $N_L$
L439

Levi_orbit_size

L441Levi_orbit_size ((RootDatum,(int->bool))(rd,):Levi_info) = int

elliptic_simple_decomposition

L453elliptic_simple_decomposition (WeylElt w) = [WeylElt,(string,int)]
Now onward to the task of getting the size of the conjugacy class of |w| for
|Levi_datum(w)|, where, ignoring the central torus, it is elliptic. This root
datum can have multiple simple factors, and we can decompose |w| as commuting
product of elements of the Weyl groups of the simple factors, and its
conjugacy class will be the Cartesian product of the conjugacy classes of the
factors (the same goes for the centraliser). The following function determines
this decomposition, where each |WeylElt| in the result is associated to a
different root datum, which is simple up to a central torus.
word in simple factor root datum, and latter type

centralizer_order

L473centralizer_order = (WeylElt->int)

also defined in combinatorics.at, character_tables.at

size_of_conjugacy_class

L490size_of_conjugacy_class (WeylElt w) = int
number of elements of a conjugacy class

sizes_of_conjugacy_classes

L492sizes_of_conjugacy_classes (RootDatum rd) = [int]

WeylClassTable type

L501
set_type
[ WeylClassTable =
  ( int order_W
  , [WeylElt] class_representatives
  , (WeylElt->int) class_of
  , [int] class_sizes
  , (int,int->int) class_power
  , [int] trivial
  , [int] sign
  , [int] reflection
  , ([int]->int) dimension
  , ([int]->int) norm2
  , ([int],[int]->int) inner
  , ([int],[int]->[int]) direct_sum
  , ([int],int->[int]) Cartesian_power
  , ([int],[int]->[int]) tensor
  , ([int],int->[int]) tensor_power
  , (int->[int]) sym_power_refl
  )
]

Fields: order_W, class_representatives, class_of, class_sizes, class_power, trivial, sign, reflection, dimension, norm2, inner, direct_sum, Cartesian_power, tensor, tensor_power, sym_power_refl

A final production is a type for storing data relevant to W-characters,
notably information about conjugacy classes. This will be a (mildly) "stateful
value" in that some data, notably for the symmetric powers of the reflection
representation, are computed and stored on demand only. In order to achieve
this access is often via function components that can access the hidden state.

W_class_table 2 overloads

L529W_class_table ( RootDatum rd , [WeylElt] !reps , (int->int) class_size , (WeylElt->int) class_nr_of , (int,int->int) power_map ) = WeylClassTable
From the above functions, the generic table constructor will only use
|conjugacy_class_reps|, |size_of_conjugacy_class|, and |is_conjugate| to get
its information (and choices) concerning conjugacy. Since these general
purpose functions may be much slower than type specific ones, our main
constructor takes additional arguments in their place, and then the generic
constructor will provide mentioned functions in thir place.
conjugacy class representatives
size of class, by class numer
conjugacy classification
for conjugacy classes
L591W_class_table ( RootDatum rd , [WeylElt] reps , (WeylElt->int) class_size , ConjugacyTester is_conjugate_to ) = WeylClassTable

W_class_table_generic

L606W_class_table_generic (RootDatum rd) = WeylClassTable
a version with no help to find conjugacy classes, potentially much slower

W_class_table_untabled

L612W_class_table_untabled (RootDatum rd) = WeylClassTable

trivial_class_table

L619!trivial_class_table = W_class_table_generic(adjoint(""))
A valid class table that can be used to initialise local variables

n_classes

L621n_classes (WeylClassTable tab) = int

also defined in character_tables.at

root_datum

L623root_datum (WeylClassTable tab) = RootDatum
at least one class exists

also defined in basic.at, W_reps.at, K_Nilpotent.at, sommers.at, parabolics.at, K.at, nilpotent_orbits.at, extended_misc.at, character_tables.at, springer_tables.at, disconnected.at, cyclotomic_Lie_algebra.at, bracket.at, exceptional.at

reorder

L627reorder (WeylClassTable tab, [WeylElt] reps) = WeylClassTable
adapt an existing table to an externally imposed order of the classes

class_representative

L662class_representative (WeylClassTable tab) = (int i) WeylElt

also defined in character_tables.at

class_size

L664class_size (WeylClassTable tab) = (int i) int

also defined in combinatorics.at, character_tables.at

conjugacy_class_number

L667conjugacy_class_number (WeylClassTable ct,WeylElt w) = int
index i for which w is conjugate to classes[i], in given WeylClassTable

character_value

L670character_value (WeylClassTable ct,[int] char, WeylElt w) = int
value of character char at w\in W

Adams

L674Adams (WeylClassTable tab) = ([int]char, int n) [int]
Adams's operation (not Jeff's): evaluate character at class of $w^n$

sym_power

L678sym_power (WeylClassTable tab) = ([int]char, int n) [int]
symmetric power of a character

also defined in character_tables.at

last symmetric power is the one we want
L690

ext_power

L693ext_power (WeylClassTable tab) = ([int]char, int n) [int]
exterior power of a character

also defined in character_tables.at

last symmetric power is the one we want
L705
Convenience functions
L707

test_size_of_conjugacy_classes 2 overloads

L723test_size_of_conjugacy_classes (RootDatum rd,[WeylElt] c) = (int,int)
test: sum of sizes of conjugacy class = |W|
L726test_size_of_conjugacy_classes (RootDatum rd) = bool

print_conjugacy_classes

L764print_conjugacy_classes (RootDatum rd) = void

also in this file at line 730

print_conjugacy_classes_long

L767print_conjugacy_classes_long (RootDatum rd) = void

also in this file at line 752

Generated from atlas-scripts at commit 648506c (2026-10-13).