Documentation contents

atlas Library · Script File

Levi_subgroups.at

This file groups function concerning classification of and computation with
Levi subgroups.

It regroups things that used to be in W_classes.at and conjugate.at

We try as much as possible to work with Levi subgroups without building a
complete |RootDatum| for them all the time, since that is somewhat costly.

Some possible presentations of a Levi system

A Levi system, not necessarily standard, can be defined either by the roots
forming a simple system for it (represented by their indices, usually within
|posroots(rd)|, though the code handles negative indices of negative roots
too), or by a predicate selecting the indices of positive roots in the system.

The function |Levi_info| deduces the predicate from the simple system, or from
a Weyl group element $w$ (selecting coroots vanishing on $w$-fixed weights),
and |Levi_datum| builds the root datum for the subsystem, given the predicate.
Source
atlas-scripts/Levi_subgroups.at (488 lines)
Definitions
37
Loads
Loaded by
parabolics.at W_classes.at conjugate.at

Definitions in source order

LeviInfo type

L28
set_type LeviInfo = (RootDatum rd,(int->bool) select)

Fields: rd, select

Levi_info 2 overloads

L31Levi_info (RootDatum rd, [int] simples) = LeviInfo
select posroots indices for (non standard) Levi, given by its simple system
L36Levi_info (WeylElt w) = LeviInfo
the |select| predicate for the above functions to use for a given |w|

posroot_indices

L40posroot_indices (LeviInfo(rd,member)) = [int]

simples

L42simples (LeviInfo(rd,):LI) = [int]
alternatively, with (rd,select):LI
let rho2_L = two_rho(Levi_info)
in list(rd.nr_of_posroots,(int i): select(i) and coroot(rd,i)*rho2_L=2)
L50

is_Levi

L55is_Levi ((RootDatum,[int]) (rd,simples):args) = bool

also defined in subgroups.at

Levi_datum 3 overloads

L65Levi_datum = sub_datum@LeviInfo
a root datum can be formed from |Levi_info|, or simple (co)root index list
defined in basic.at
L66Levi_datum ((RootDatum,[int])pair) = RootDatum
convert to |LeviInfo| before calling |sub_datum
L69Levi_datum (WeylElt w) = RootDatum

from_no_Cminus

L72from_no_Cminus (KGBElt x,[int] Levi_gens) = (WeylElt,KGBElt)
restrict some operations from Weylgroup.at to only use Levi reflections

also in this file at line 102; also defined in Weylgroup.at

from_no_Cplus

L86from_no_Cplus (KGBElt x,[int] Levi_gens) = (WeylElt,KGBElt)

also in this file at line 106; also defined in Weylgroup.at

from_no_Cminus

L102from_no_Cminus (Param p,[int] Levi_gens) = (WeylElt, Param)
the same for parameters

also in this file at line 72; also defined in Weylgroup.at

from_no_Cplus

L106from_no_Cplus (Param p,[int] Levi_gens) = (WeylElt, Param)

also in this file at line 86; also defined in Weylgroup.at

It turns out that Levi subsystems (whether or not standard) are conjugate in
$W$ if and only if their |two_rho| weights are in the same $W$-orbit.
L111

standard_Levi_conjugacy_representatives

L116standard_Levi_conjugacy_representatives (RootDatum rd) = [ [int] ]
select from subsets of diagrams representatives of $2\rho$-value classes
The following functions, up to |classify_standard_Levis|, aim to classify
standard Levis under conjugation _and_ find conjugators for each one from the
first of their class. The Levi orbit table produced is used in some functions
in W_classes.at; the ultimate goal of efficiently classifying Weyl group
elements up to conjugation, with witnesses, is also achieved there.

For each standard Levi system |standard_Levi| (a list of simple root indices)
we determine the dominant orbit representative |rho2_dom| of its $2\rho$, a
Weyl group element |w0| that witnesses this (|w0*rho2_dom=two_rho(rd,Levi)|),
and the (non standard) image $L$ under |inverse(w0)| of |standard_Levi|, which
has |two_rho(Levi_info(L))=rho2_dom| (this holds because the Levi system
remains positive throughout the action by letters of |inverse(w0)|). A
conjugate standard Levi system will give the same |rho2_dom|, but will not
necessarily transform to the same system $L$; therefore we generate the orbit
of $L$ under the stabiliser subgroup of the |rho2_dom|, which is also a Levi
subgroup (of unrelated type) and therefore generated by the reflections that
stabilise |rho2_dom|. The generation also finds witnesses of the conjugation.
L123
Next task: given a standard Levi, list the non-standard Levis conjugate to it
whose $2\rho$-value is dominant
L143

orbit_entry type

L147
set_type orbit_entry =
  ( int L_int  { Levi subgroup, as |[int]| encoded by |combination_encode| }
  , WeylElt w  { conjugator from standard Levi for which orbit was generated }
  )

Fields: L_int, w

orbit_data type

L151
set_type orbit_data = [orbit_entry]

act_up

L155act_up (WeylElt w,[int] Levi) = [int]
Transform root set by Weyl group action. Is used only for making the $2\rho$
value of |Levi| dominant, so all positive roots remain so; whence the name
The following function facilitates identifying all Levi subgroups conjugate to
|standard_Levi|, by providing a full list of those (non standard) Levi
subgroups whose $2\rho$-value is dominant, with witnesses of the action from
|standard_Levi| to them; in other words it returns a list of |(L,w)| where
|two_rho(L)=dominant(two_rho(standard_Levi)) and |L=w*standard_Levi| (but with
|L| encoded as an integer, so these are not actually valid expressions).

The orbit is generated for the stabiliser in the Weyl group of the mentioned
dominant weight, called |rho2_dom| below. The values acted upon are
fixed-sized sets of posroots (each set generating a subsystem whose sum of
posroots equals |rho2_dom|) which are represented by a single integer for
faster comparison. The encoding is done using |combination_encode| which
generally produces smaller values than |to_bitset| (one could make the values
even smaller by expointing the fact that only root numbers whose coroots are
at level |2| for |rho@_dom| are involved, but no gain would be obtained).

The acting stabiliser is a Levi subgroup (of unrelated type) so generated by
involutions (root reflections for |simples| below). Orbit elements are
generated while keeping track of the (first found) acting Weyl group element
to each point. Since orbits can be very large (notably for E8), it pays to try
to reduce equality testing by proceeding by shells defined by the distance (in
the Cayley graph) from the initial point: each newly generated element needs
to be tested for presence in the previous shell (a backwards move) or in the
current shell (a move that does not change the distance). All new elements not
thus filtered out are gathered, and passed through |sort_u| to remove
duplicates before being integrated as a new shell. Each shell being sorted,
looking up in each shell can be done using binary search.
L159

rho_stabiliser_orbit

L188rho_stabiliser_orbit (RootDatum rd, [int] standard_Levi) = orbit_data

other_entry type

L232
set_type other_entry = (int L, WeylElt w)

Fields: L, w

in a |Std_Levi_orbit|, |Levi_repr| is an encoded standard Levi, as are first
members |L| of |others|; for |(L,w) in others| one has |L=w*Levi_repr|

StdLeviOrbit type

L233
set_type StdLeviOrbit = (vec rho2, int Levi_repr, [other_entry] others)

Fields: rho2, Levi_repr, others

StdLeviTable type

L234
set_type StdLeviTable = [[StdLeviOrbit]] { list of lists, grouped by |k| }

show

L236show(StdLeviTable t) = [vec,[int],[[int],WeylElt]]

also defined in modules.at, K_Nilpotent.at, good_W_representatives.at, arthur_parameters.at, sub_cells.at, associated_variety_annihilator.at, geck_generic.at, L_packet.at, ratmat.at, nilpotent_orbits.at, subgroups.at, poset.at, cyclotomic.at, polynomial.at, character_tables.at, springer_tables.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, weak_packets.at, cyclotomic_Lie_algebra.at, cyclotomicMat.at, bracket.at, exceptional.at, nilpotent_posets.at, lazy_lists.at

Levi subgroups are conjugate if and only if they have |two_rho| values in the
same W-orbit; however if two (standard) Levi subgroups are transformed so as
to have the same (dominant) value of |two_rho|, they have not necessarily
become equal. However one Levi subgroup is necessarily found in the
|rho_stabiliser_orbit| of the other, with a witnessing Weyl group element, and
this allows finding a conjugator from one Levi to the other. The
classification of standard Levi subgroups then proceeds by transforming each
to a situation with dominant |two_rho|, grouping together those with the same
value pf |two_rho|; then in each group the first one is chosen to represent
the orbit, |rho_stabiliser_orbit| is applied to it, and all other elements in
the group are looked up in this orbit.
L244

classify_standard_Levis

L258classify_standard_Levis (RootDatum rd) = StdLeviTable
group together conjugate standard Levis, with witness conjugating from first

StdLeviImage type

L285
set_type StdLeviImage =
   (WeylElt actor { conjugator from |image| back to original |w| }
  , [int]   std_Levi  { simples for a standard Levi }
  )

Fields: actor, std_Levi

StdLeviFinder type

L289
set_type StdLeviFinder = ([int]->StdLeviImage)
From $w$ we find the associated non-standard Levi subsystem, the minimal one
in whose Weyl group $w$ occurs. Our next task, surprisingly difficult, is to
find a standard Levi system conjugate to it, and a conjugating element of $W$.

The difficulty that the set of generators for our system may contain negative
roots, so that the sum of positive roots of the system is not a positive sum
of the given generators, but of a different set |Levi_datum(rd,Levi).simples|
(defining the same subsystem). That set is in the orbit of the former (even
under the Weyl group of just the Levi itself), but using it woudtl be quite
cumbersome. However the function |two_rho@(rd,[int])| from basic/at is defined
in a positivity-agnostic way, so we can use that and proceed very similarly to
how we looked up standard Levis (but using already computed |StdLeviTable|).
L291
For looking up arbitrary Levi subgroups, we need a slightly different table
than |StdLeviTable|: a list of one |orbit_data| for each |rho2_dom| value
L306

rho_data type

L310
set_type rho_data = ([int] Levi, vec rho2_dom, orbit_data orbit)

Fields: Levi, rho2_dom, orbit

orbits_table

L312orbits_table (RootDatum rd) = [[ rho_data ]]
given |StdLeviTable|: tabled representative of any Levi, and conjugator
L325

Levi_lookup

L327Levi_lookup (RootDatum rd, [[ rho_data ]] table) = StdLeviFinder

also in this file at line 470

Here is another approach that we previously used instead of using |two_rho|;
we keep it because the implemented functionality might have other uses. For
one, the function |from_standard_Levi| below is a fast way to find some
conjugate standrad Levi of an arbitrary one, without doing classification.

For the case where we are given a non standard list of simple generators (not
all positive, and in arbitrary order) for the _full_ root system, there is an
easy algorithm to find $w$ (called |chamber| below) that maps the set of
simple roots of |rd| to those generators, and the permutation of them (map
from positions to simple root index being mapped to it) so obtained. It goes:
as long as the system contains a negative root, select one (recording its
position) and apply the corresponding (non simple) root reflection to all
roots; ultimately all roots become positive, and as a set we have obtained the
simple roots. The list of their indices is our permutation; as letters of $w$,
from right to left, take for each reflection applied the simple generator that
ended up at the recorded position. This is done in |chamber_max_system| below.

Our approach is then to extend the Levi system one root at a time to a maximal
system, and then apply this algorithm; once this is, done we get a standard
Levi conjugate to our original by truncating the above permutation to as many
initial entries as the rank of our original Levi was, and a Weyl group element
conjugating that standard Levi to the original (|from_standard_Levi | below).
The classification of the standard Levi subgroups finally allows us to replace
the standard Levi by the elected representative of its class.

Extending to a maximal rank Levi is done by repeatedly finding a root by which
we can extend the Levi system to a larger one; to this end we first locate
using |minimal_extenders| a set of candidates (root indices, not necessarily
positive ones), whose roots are minimally positive for some some linear form
vanishing on |Levi|. From these, |extend_Levi| will then select a minimal one
that extends |Levi| by adding a single root.
L341

minimal_extenders

L375minimal_extenders (RootDatum rd,[int] Levi) = [int]
list of posroot indices, minimal>0 for some linear form vanishing on |Levi|

extend_Levi

L405extend_Levi (RootDatum rd,[int] Levi) = [int]

maximize_Levi

L419maximize_Levi (RootDatum rd,[int] !Levi) = [int]
return maximal Levi containing |Levi|, ordered in the way they were found

chamber_max_system

L424chamber_max_system (RootDatum rd, [int] sys) = (WeylElt,[int])
find chamber defined by a maximal system, and its simple root permutation

from_standard_Levi

L439from_standard_Levi ((RootDatum,[int]) (rd,Levi):arg) = StdLeviImage
for non-standard Levi: some conjugate standard Levi, and conjugator from it

standard_Levi_lookup

L446standard_Levi_lookup (RootDatum rd,StdLeviTable full_table) = StdLeviFinder
given |StdLeviTable|: tabled representative of a standard Levi, conjugator
does linear search for |rho2| in the table, then again in its orbit

Levi_lookup

L470Levi_lookup (RootDatum rd,StdLeviTable table) = StdLeviFinder
given |StdLeviTable|: tabled representative of any Levi, and conjugator

also in this file at line 327

keep the tabulated Levi found, adapt the conjugator
L475
facilitate reverting to |(RootDatum,[int])| encoding of Levi subgroups
L481

uproot

L484uproot (RootDatum rd, mat root_vectors) = [int]
convert root encoding of set of roots to list of root indices

un_datum

L488un_datum (RootDatum rd, RootDatum sub) = [int]
convert |RootDatum| encoding of |sub| back to list of root indices

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