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.
Definitions in source order
LeviInfo type
set_type LeviInfo = (RootDatum rd,(int->bool) select)
Fields: rd, select
Levi_info 2 overloads
Levi_info (RootDatum rd, [int] simples) = LeviInfoselect posroots indices for (non standard) Levi, given by its simple system
Levi_info (WeylElt w) = LeviInfothe |select| predicate for the above functions to use for a given |w|
posroot_indices
posroot_indices (LeviInfo(rd,member)) = [int]simples
simples (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
is_Levi ((RootDatum,[int]) (rd,simples):args) = boolalso defined in subgroups.at
Levi_datum 3 overloads
Levi_datum = sub_datum@LeviInfoa root datum can be formed from |Levi_info|, or simple (co)root index list
defined in basic.at
Levi_datum ((RootDatum,[int])pair) = RootDatumconvert to |LeviInfo| before calling |sub_datum
Levi_datum (WeylElt w) = RootDatumfrom_no_Cminus
from_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
from_no_Cplus (KGBElt x,[int] Levi_gens) = (WeylElt,KGBElt)also in this file at line 106; also defined in Weylgroup.at
from_no_Cminus
from_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
from_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
standard_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 dominantL143
orbit_entry type
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
set_type orbit_data = [orbit_entry]
act_up
act_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
rho_stabiliser_orbit (RootDatum rd, [int] standard_Levi) = orbit_dataother_entry type
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
set_type StdLeviOrbit = (vec rho2, int Levi_repr, [other_entry] others)
Fields: rho2, Levi_repr, others
StdLeviTable type
set_type StdLeviTable = [[StdLeviOrbit]] { list of lists, grouped by |k| }show
show(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
classify_standard_Levis (RootDatum rd) = StdLeviTablegroup together conjugate standard Levis, with witness conjugating from first
StdLeviImage type
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
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| valueL306
rho_data type
set_type rho_data = ([int] Levi, vec rho2_dom, orbit_data orbit)
Fields: Levi, rho2_dom, orbit
orbits_table
orbits_table (RootDatum rd) = [[ rho_data ]]given |StdLeviTable|: tabled representative of any Levi, and conjugatorL325
Levi_lookup
Levi_lookup (RootDatum rd, [[ rho_data ]] table) = StdLeviFinderalso 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
minimal_extenders (RootDatum rd,[int] Levi) = [int]list of posroot indices, minimal>0 for some linear form vanishing on |Levi|
extend_Levi
extend_Levi (RootDatum rd,[int] Levi) = [int]maximize_Levi
maximize_Levi (RootDatum rd,[int] !Levi) = [int]return maximal Levi containing |Levi|, ordered in the way they were found
chamber_max_system
chamber_max_system (RootDatum rd, [int] sys) = (WeylElt,[int])find chamber defined by a maximal system, and its simple root permutation
from_standard_Levi
from_standard_Levi ((RootDatum,[int]) (rd,Levi):arg) = StdLeviImagefor non-standard Levi: some conjugate standard Levi, and conjugator from it
standard_Levi_lookup
standard_Levi_lookup (RootDatum rd,StdLeviTable full_table) = StdLeviFindergiven |StdLeviTable|: tabled representative of a standard Levi, conjugator
does linear search for |rho2| in the table, then again in its orbit
Levi_lookup
Levi_lookup (RootDatum rd,StdLeviTable table) = StdLeviFindergiven |StdLeviTable|: tabled representative of any Levi, and conjugator
also in this file at line 327
keep the tabulated Levi found, adapt the conjugatorL475
facilitate reverting to |(RootDatum,[int])| encoding of Levi subgroupsL481
uproot
uproot (RootDatum rd, mat root_vectors) = [int]convert root encoding of set of roots to list of root indices
un_datum
un_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).