Script File
combinatorics.at
The purpose of this module is to collect basic combinatorial functions, like factorials, binomial coefficients, generators of partitions and so on
Definitions in source order
|factorial@int| is now defined in basic.at, and it can be written as |n!|L9
binom 2 overloads
binom (int n, int k) = intbinom (rat n, int k) = ratmultinom
multinom ([int] a) = intmultinomial coefficient, upper index implicit
multi_choose
multi_choose (int n,int k) = intfalling_power
falling_power (int n, int k) = intrising_power
rising_power (int n, int k) = intCombinatorial number system ${\N\choose k}\to\N$ encoding and decodingL35combination_encode
combination_encode([int] list) = intRepresent any $k$-combination on $\N$ as a single natural number For fixed $k$ this is bijective, and a decoding follows.
|list| strictly increasing
combination_decode
combination_decode(int k) = (int->[int])next assert(@:N=0)L50
even_places
even_places ([int] v)extract components at even or odd positions
odd_places
odd_places ([int] v)PermutationsL57
Permutation type
set_type Permutation = vec { second line of 2-line form of a permutation }is_permutation
is_permutation (vec v) = boolpermutation_matrix
permutation_matrix (Permutation pi) = matMatrix whose left-multiplication to a column vector permutes it by |pi|. It has nonzero entries at each (pi(j),j), it could have been defined (using |matrix| from basic.at) as |matrix((#pi,#pi),(int i,int j): #(i=pi[j]) )|.
permutation
permutation (mat P) = Permutationassumed a permutation matrix
right-act on row [0,1,...,n-1] for one-line form
compose_permutations
compose_permutations (Permutation sigma, Permutation pi) = Permutationinverse
inverse (Permutation pi) = Permutationhope the name causes no conflict
also defined in basic.at
permutation_inverse
permutation_inverse (Permutation pi) = Permutationlonger name for non-checking (so faster) version of the above
permutation_product
permutation_product (mat M) = Permutationa product of many permutations, arranged as columns of a matrix
cyclic_permutation
cyclic_permutation (int n) = ([int] cycle) Permutationget transpositions as |cyclic_permutation(n)([i,j])|, and cycles similarly
cycle_product
cycle_product (int n) = ([[int]]->Permutation)similarly make a permutation from a product of cycles (disjoint or not)
permute 2 overloads
permute (Permutation pi,vec v) = vecpermutation action on |vec| values
permutation_act
permutation_act (Permutation sigma, mat M) = matleft-multiply by permutation matrix (permute rows by permutation)
permutation_right_act
permutation_right_act (mat M,Permutation sigma) = matright-multiply by permutation matrix (permute columns by inverse permutation)
permute_rows
permute_rows = permutation_act@(Permutation,mat)permute_columns
permute_columns (Permutation sigma,mat M) = matpermutation_conjugation
permutation_conjugation (Permutation sigma, mat M) = matpermutation_cycles
permutation_cycles (Permutation pi) = [[int]]permutation_encode
permutation_encode (Permutation sigma) = intrepresent a permutation as a single number: its lexicographic position
permutation_decode
permutation_decode(int code, int n) = Permutationpermutation number |code| in lexicographic order among permutations of |n|
permutation_iterator
permutation_iterator (vec pi) = Iterator<vec>The following generates partitions starting from #n, without large storage
let (get,incr)= permutation_iterator(#n) in
while
case get() | none(): false | some(perm): process(perm); true esac
do incr()
od
Instead of |#n| one can supply any vector |pi| as starting value, which will
generate all permutations only if |pi| is weakly increasing. In case of
equality among entries of |pi|, permuting these among each other is avoided.
generate |(#xs)!| permutations of |xs|, not avoiding permutation of equalsL205
permutations
root_orbits
root_orbits (WeylElt w) = [[int]]group root indices by orbits under action of cyclic group generated by |w|
multiset_permutations
multiset_permutations ([int] multiplicities) = [[int]]PartitionsL242
Partition type
set_type Partition = [int] { list of decreasing parts, no trailing zeros }strip_to_partition
strip_to_partition (Partition lambda) = [int]alternatively: |for x in list do if =x then break fi od|L248
is_partition
is_partition ([int] seq) = boolfrequencies
frequencies (Partition lambda) = vecfrequency vector, position 0 unused
repeat_parts
repeat_parts (vec frequencies) = Partitionthe following is a right-inverse to |frequencies|; assuming |frequencies[0]=0| to avoid getting trailing 0's, the image is precisely the set of partitions
sort_to_partition
sort_to_partition ([int] parts) = Partitioncycle_type
cycle_type ([int] pi) = Partitioncycle sizes in decreasing order
transpose
transpose ([int] parts) = Partitiontranspose of a composition, after implicitly sorting it to a partition
also defined in basic.at
or more "manually", when |parts| assumed already in decreasing order
if #lambda=0 then []
else let l=#lambda in
for i:lambda[0] { since |i<lambda[0]|, we can never set |l:=0| below }
do while lambda[l-1]<=i do l-:=1 od; l
od
fiL274Levi_A
Levi_A ([int] parts) = (int,LieType,[int])basic data for Levi factor of $A_{n-1}$ given by composition |parts| of $n$
|(n,Levi_type,simples)|
compressed_string
compressed_string(Partition P) = stringalso in this file at line 1138
rlex_leq_partitions
rlex_leq_partitions (Partition lambda, Partition mu) = boollexicographic comparison restricted to partitions of same |n| (0-extended)
rlex_cmp_partitions
rlex_cmp_partitions (Partition lambda, Partition mu) = intsame, but three-way result in $\{-1,0,1\}$ for less/equal/greater; no 0-ext
if |lambda| exhausted then so is |mu|, and we have equalityL318
slex_leq_partitions
slex_leq_partitions ((Partition,Partition) (lambda,mu):pair) = boolcomparing partitions by sum then lexicographically; implicitly 0-extend
slex_cmp_partitions
slex_cmp_partitions ((Partition,Partition) (lambda,mu):pair) = intindex_partition
index_partition([Partition] sorted_list) = (Partition->int)look up partition in sorted list of partitions, all assumed of same sum
dominance_leq_compositions
dominance_leq_compositions (Partition v,Partition w) = booldominance order on compositions, assumed to be so of the same number
dominance_leq_partitions
dominance_leq_partitions (Partition v,Partition w) = boolsame as previous, but assuming |v|,|w| are equal sum partitions (so sorted)
functions related to representations of S_nL365
hook_lengths
hook_lengths (Partition lambda) = [int]also in this file at line 376
not viewed as partition, but sorting is the sameL371
Sn_representation_dimension
Sn_representation_dimension (Partition lambda) = inthook_lengths
hook_lengths ([bool] edges) = [int]also in this file at line 367
edge_sequence
edge_sequence (Partition lambda) = ([bool],int)edge sequence from first horizontal (false) to last horizontal, and shift
cycle_type_order
cycle_type_order = lcm@[int]cycle_centralizer_order
cycle_centralizer_order ([int] cycles) = intalso in this file at line 850
cycle_class_size
cycle_class_size ([int] cycles) = intalso in this file at line 856
cycle_power
cycle_power ([int] cycles, int k) = [int]compute cycle type of power of a permutation, given its cycle type
Murnaghan_Nakayama
Murnaghan_Nakayama (Partition lambda, [int] cycle_type) = intcharacter of irreducible Sn representation lambda at give cycle type
generating all partitions; for counting, see |n_partitions| in lazy_lists.atL430
partitions
partitions = (int n) [Partition]generating partitions, all of whose parts must lie in a given setL452
part_restricted_partitions
part_restricted_partitions ((int->bool)pred) = (int n) [Partition]odd_part_partitions
odd_part_partitions = part_restricted_partitions(is_odd@int)strict_partitions
strict_partitions = (int n) [Partition]partitions with distinct parts: all multiplicities are 0 or 1
Jordan types of nilpotent elements (or orbits)L503
is_valid 2 overloads
is_valid (string type,Partition P) = booltest if partition is valid (nilpotent orbit) Jordan type in type ABCD
is_valid (LieType t) = (Partition->bool)also defined in L_packet.at
Combinatorics specifically for (Weyl groups of) types B,C,DL530
parity_restricted_partitions
parity_restricted_partitions (bool restrict_odd_parts) = (int->[Partition])partitions with even multiplicity of parts of one parity (odd or even)
Signed_cycles type
set_type Signed_cycles = [int,bool] { bool |b| encodes product |minus_1^#b| }for conjugagy classes: cycles with product of signs, for simple types B,C,D
BiPartition type
set_type BiPartition = (Partition,Partition)
for $W(C_n)$ irreducible representations: partition pairs of total size $n$
no specific interpretation imposed here, but ordering should always have: positive/even/0/false/trivial repn BEFORE negative/odd/1/true/sign repn one parametrises irreps of the hyperoctahedral group $W(C_n)=W(B_n)$ also in bijection with |Signed_cycles| as (unflipped lengths,flipped lengths)L569
Symbol type
set_type Symbol = [[int]] { must have 2 lists, first longer than second by 1 }Sometimes (Springer correspondence) a transformation of |BiPartition| is used The type to represent them is delibetately distinct from |BiPartition|
both lists strictly INcreasing with non-negative entries equivalence [a_1,...a_k]->[0,a_1+1,s_2+1,...a_k+1] can be used to adapt length every symbol can be written with length difference 1 and at most one term 0L578
rank 2 overloads
rank (Signed_cycles cycles) = intrank (BiPartition(lambda,mu)) = intalso in this file at line 942, line 948; also defined in basic.at, sommers.at
=
= (Signed_cycles cyc0,Signed_cycles cyc1) = boolequality is strict (don't want to force interpretation onto |[int,bool|])
also in this file at line 639, line 1016, line 1087; also defined in basic.at, modules.at
!=
!= (Signed_cycles cyc0,Signed_cycles cyc1) = boolalso in this file at line 1017, line 1088; also defined in basic.at
same_as
same_as (Signed_cycles cyc) = (Signed_cycles->bool)for equivalence up to permutation of cycles, use |c0.same_as(c1)|
The hyperoctahedral group $H_n$ can be represented by sigend permutation
matrices (where every row and column has a unique nonzero entry, which lies in
$\{-1,1\}$. There is a surjective group morphism to $S_n$ forgetting the signs.
This is the symmetry group of en $n$-dimensional hyperoctahedron (also of the
hypercube), centered at the origin, with 2 vertices on each coordinate axis.
Conjugacy classes of $H_n$ are given by signed cycle types: projection to
$S_n$ gives a cycle type (for the permutation of the axes), and to each cycle
is attached the product of the signs for the coordinate axes in the cycle.L605to_cycles
to_cycles (BiPartition(lambda,mu)) = Signed_cyclesconverting partition pairs to signed cycle types, second has flipped cycles
to_partition_pair
to_partition_pair(Signed_cycles cy) = BiPartitionthe inverse of |to_cycles@BiPartition|
pairs_of_total_sum
pairs_of_total_sum (int n,(int->[Partition]) lister) = [BiPartition]generate pairs of partitions of total size |n| with size |k| components produced in the order in which |lister| lists them, starting all on left
partition_pairs
partition_pairs (int n) = [BiPartition]generate all bi-partitions of |n| by size distribution, starting all left
=
= (BiPartition (P,Q), BiPartition (R,S)) = boolalso in this file at line 588, line 1016, line 1087; also defined in basic.at, modules.at
<=
<=(BiPartition (P,Q), BiPartition (R,S)) = boolcompare |BiPartition| values of same sum, in ordering of |partition_pairs|
index_bipartition
index_bipartition ([BiPartition] sorted_list) = (BiPartition->int)look up pair in sorted list of partition pairs, all assumed of same sum
counterpart of the Murnaghan-Nakayama rule for hyperocthedral groupsL655
Characters of the hyperoctahedral group $H_n$ are parametrised as follows by bi-partitions |(lambda,mu)| of $n$. Call "axis-sign" the 1-dimensional representation of any hyperoctahedral group that takes value $+1$ on all simple reflection except the last (for the off-length simple root) where it takes the value $-1$: on a general signed permutation it is the product of the nonzero entries in its matrix (it is also the product of the cycle-signs in its signed cycle type). Given a bi-partition |(lambda,mu)|, let |l=sum(lambda),m=sum(mu)|, let $K$ be the $H_l\times H_m$ subgroup of $H_n$, restrict (back up the surjective group morphisms $H_i\to S_i$) the irreducible representations for |lambda| and |mu| of $S_l$ respectively $S_m$ to ones of $H_l$ respectively $H_m$, tensor the latter with the axis-sign representation of $H_m$, then induce the resulting (outer tensor product) representation of $K=H_l\times H_l$ from $K$ to $H_n$.L657
hyperoctahedral_character
hyperoctahedral_character ( BiPartition (lambda,mu):pair ,Signed_cycles signed_cycle_type ) = intirreducible repn, sign applies to |mu|
describes a conjugacy class
core_length
core_length (int n) = intcore_number
core_number (int k) = intcore_quotient_2
core_quotient_2 (Partition lambda) = (int,BiPartition)Core number and quotient partition pair. In the latter, as per |BiPartition| convention, the partition coming from the EVEN edge positions comes first
from_core_quotient_2
from_core_quotient_2 (int d,BiPartition(lambda,mu)) = PartitionSplicing BiPartitions |(lambda,mu)|, with 2-core with (unbalance) number |d|
classic_permutation
classic_permutation (WeylElt w) = PermutationFind classical (permutation or signed permutation) description of Weyl group elements in classical types. The associated root datum must have one simple factor of type A-D, but need not have standard (Bourbaki) diagram numbering. The output is a (signed) permutation in one-line format. For type $A_n$ this is just a permutation of $n+1$ (hence 0-based), for types $B_n$, $C_n$, $D_n$ this is a permutation of the $2n$ elements $-n, ,..., -2 -1, 1, 2, ..., n$, commuting with $x \mapsto -x$, and the one-line format consists of a list of the images of $1, 2, ..., n$ (1-based); it determines the signed permutation.
signed_permutation
signed_permutation(WeylElt w) = [int]a simpler version when |w| is known to be for some Sp(2n) or SO(m)
signed_cycle_type_code
signed_cycle_type_code ([int] sigma) = vecfor a signed permutation |sigma| of $\{1,...,n\}$, represented by the images
of $1,...,n$, compute the cycle type as list of pairs (cycle length, sign);
return weakly decreasing vector of sign*cycle_length, e.g., |[4,2,-1,-1,-3]|
cycle_code
cycle_code(WeylElt w) = vecassuming |w| is for |Sp(2n)| or |SO(m)|
as_signed_cycles
as_signed_cycles (vec v) = Signed_cyclesconvert code as above to |Signed_cycles|, ordering as |to_cycles| does
as_bipartition
as_bipartition (vec v) = BiPartitionsigned_cycle_type
signed_cycle_type ([int] sigma) = Signed_cyclescycle_type_order
cycle_type_order (Signed_cycles cycles) = intcycle_centralizer_order
cycle_centralizer_order (Signed_cycles cycles) = intalso in this file at line 394
cycle_class_size
cycle_class_size (Signed_cycles cycles) = intalso in this file at line 396
cycle_power
cycle_power (Signed_cycles cycles, int k) = Signed_cyclescompute cycle type of power of a signed permutation, given its cycle type
a |Symbol| is a transformed |BiPartition|: reversed, strict, length diff. 1L873
normalize
normalize (Symbol S) = Symbolnormalize symbol: |f|=|g|+1 and at most 1 zero
all other functions taking |Symbol| assume that argument is normalizedL883
symbol
symbol (BiPartition(lambda,mu)) = Symbolnormalized
symbol_to_bipartition
symbol_to_bipartition (Symbol S) = BiPartitionis_special
is_special (Symbol S) = boolmake_special 2 overloads
make_special (Symbol S) = Symbolmake_special (BiPartition bip) = BiPartitionalso in this file at line 1090
adaptation to the above to deal with Weyl groups of type DnL923
is_very_even
is_very_even (Partition P) = boola condition relevant to which cycle types give split classes in $W(D_n)$
whether all parts are even
is_doubly_even
is_doubly_even (Partition P) = boola condition relevant to which $D_n$ nilpotent orbits are split from $O(2n)$
even parts even multiplicities only
D_class type
set_type D_class = { cycle types restricted to Dn subgroup }
( Signed_cycles unsplit_class { the XOR of all |bool| values is |false| }
| (Partition,bool) split_class { "all false" even cycles, and a single sign }
)Fields: unsplit_class, split_class
D_irrep type
set_type D_irrep = { from folding pairs of partitions under swapping }
( (Partition,Partition) unsplit_irr { unequal partitions, larger first }
| (Partition,bool) split_irr { for pair of equal partitions, with sign }
)Fields: unsplit_irr, split_irr
rank 2 overloads
rank (D_class c) = intrecover the value of |n|
rank (D_irrep chi) = intalso in this file at line 584, line 585; also defined in basic.at, sommers.at
cycle_type_order
cycle_type_order (D_class c) = intcentralizer_order
centralizer_order (D_class c) = intclass_size
class_size (D_class c) = intcycle_power
cycle_power (D_class c, int k) = D_classcompute cycle type of power of a signed permutation, given its cycle type
to_D_class
to_D_class ([int] sigma) = D_classrather than |signed_cycle_type_code|, $D_n$ classes need a finer analysis
as from |classic_permutation
same_as
same_as (D_class c0) = (D_class->bool)=
= (D_class c0, D_class c1) = boolalso in this file at line 588, line 639, line 1087; also defined in basic.at, modules.at
!=
!= (D_class c0,D_class c1) = boolalso in this file at line 595, line 1088; also defined in basic.at
D_classes
D_classes (int n) = [D_class]D_irreducibles
D_irreducibles (int n) = [D_irrep]less_eq
less_eq (D_class elt) = (D_class->bool)predicate of coming before a given element in the ordering of |D_classes|
<=
<= (D_class a,D_class b) = booli.e., |less_eq(b)(a)|
index_D_classes
index_D_classes ([D_class] sorted_list) = (D_class->int)look up pair in sorted list of |D_class|es, all assumed for the same size
same_as
same_as (D_irrep chi) = (D_irrep->bool)=
= (D_irrep c0, D_irrep c1) = boolalso in this file at line 588, line 639, line 1016; also defined in basic.at, modules.at
!=
!= (D_irrep c0,D_irrep c1) = boolalso in this file at line 595, line 1017; also defined in basic.at
make_special
make_special (D_irrep chi) = D_irrepcharacter
character (D_irrep chi, D_class c) = intalso defined in modules.at, W_reps.at
compressed_string
compressed_string(BiPartition(P,Q)) = stringfor printing |BiPartition| values compactly
also in this file at line 290
Generated from atlas-scripts at commit 7e1b958 (2026-09-17).
Commented-out code, lines 736–756 (19 lines)
Core and quotient operations can be defined in terms of associating to any partition $\lambda$ the subset $\{ lambda[i]-i-1 | i\in\N \}$ of $\Z$. This set represents the set of vertical edges terminating the rows of the Young diagram, recorded by their diagonal positions (the main diagonal separating positions in $\N$ from its complement, i.e., its splits between -1 and 0). This set is bounded above while its complement is bounded below; more specifically the set meets $\N$, and its complement the complement of $\N$, in equal size finite sets. An ordered pair of partitions can be "spliced together" as follows: take there associated sets, transform the former by $i\mapsto 2i$ and the latter by $i\mapsto 2i+1$, merge the results and find the partition corresponding to the set. If the Young diagrams original partitions together have $n$, the spliced partition can be covered by $n$ dominos. More generally we could add a fixed integer $d$ in the first transformation and subtract it in the second; then $d$ will be the unbalance of black and white squares in the diagram of the resulting partition, and after removing $n$ dominos from it we are left with a "2-core" still having the same unbalance. It is a staircase diagram with |core_length(d)| parts. The pair of original partitions is the "2-quotient" of the spliced partition.