Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

map_word and parabolic_subgroup for Weyl groups #4519

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions experimental/LieAlgebras/src/LieAlgebras.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import ..Oscar:
isomorphism,
kernel,
lower_central_series,
map_word,
matrix,
normalizer,
number_of_generators,
Expand Down
156 changes: 156 additions & 0 deletions experimental/LieAlgebras/src/WeylGroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,159 @@

return MapFromFunc(W, G, iso, isoinv)
end

@doc raw"""
map_word(w::WeylGroupElem, genimgs::Vector; genimgs_inv::Vector = genimgs, init = nothing)

If `init` is `nothing` and `word(w) = [`$i_1$`, ..., `$i_n$`]`,
then return the product $R_1 R_2 \cdots R_n$ with $R_j =$ `genimgs[`$i_j$`]`.
Otherwise return the product $xR_1 R_2 \cdots R_n$ where $x =$ `init`.

The length of `genimgs` must be equal to the rank of the parent of `w`.
If `w` is the trivial element, then `init` is returned if it is different
from `nothing`, and otherwise `one(genimgs[1])` is returned if `genimgs` is non-empty.
If `w` is trivial, `init` is nothing and `genimgs` is empty, an error occurs.

See also: [`map_word(::Union{FPGroupElem, SubFPGroupElem}, ::Vector)`](@ref),
[`map_word(::Union{PcGroupElem, SubPcGroupElem}, ::Vector)`](@ref).
Note that `map_word(::WeylGroupElem)` accepts but ignores the `genimgs_inv` keyword argument
because the generators of a Weyl group are always self-inverse.
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved

# Examples
```jldoctest
julia> W = weyl_group(:B, 3); imgs = [2, 3, 5];

julia> map_word(one(W), imgs)
1

julia> map_word(W([1]), imgs)
2

julia> map_word(W([1]), imgs; init=7)
14

julia> map_word(W([1,2,1]), imgs)
12

julia> map_word(W([2,1,2]), imgs) # W([2,1,2]) == W([1,2,1])
12

julia> map_word(W([3, 2, 1, 3, 2, 3]), imgs)
2250
```
"""
function map_word(
w::WeylGroupElem, genimgs::Vector; genimgs_inv::Vector=genimgs, init=nothing
)
@req length(genimgs) == number_of_generators(parent(w)) begin
"Length of vector of images does not equal rank of Weyl group"

Check warning on line 305 in experimental/LieAlgebras/src/WeylGroup.jl

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/WeylGroup.jl#L305

Added line #L305 was not covered by tests
end
return map_word(Int.(word(w)), genimgs; init=init)
end

@doc raw"""
parabolic_subgroup(W::WeylGroup, vec::Vector{<:Integer}, w::WeylGroupElem=one(W)) -> WeylGroup, Map{WeylGroup, WeylGroup}

Return a Weyl group `P` and an embedding $f:P\to W$ such that $f(P)$ is
the subgroup `U` of `W` generated by `[inv(w)*u*w for u in gens(W)[vec]]`.
Further, `f` maps `gen(P, i)` to `inv(w)*gen(W, vec[i])*w`.
The elements of `vec` must be pairwise distinct integers in
`1:number_of_generators(W)` and `vec` must be non-empty.

# Examples
```jldoctest
julia> W = weyl_group(:B, 3)
Weyl group
of root system of rank 3
of type B3

julia> P1, f1 = parabolic_subgroup(W, [1, 2])
(Weyl group of root system of type A2, Map: P1 -> W)

julia> f1(P1[1] * P1[2]) == W[1] * W[2]
true

julia> P2, f2 = parabolic_subgroup(W, [1, 2], W[1])
(Weyl group of root system of type A2, Map: P2 -> W)

julia> f2(P2[1]) == W[1] && f2(P2[2]) == W[1] * W[2] * W[1]
true

julia> P3, f3 = parabolic_subgroup(W, [1,3,2])
(Weyl group of root system of type B3 (non-canonical ordering), Map: P3 -> W)

julia> f3(P3[2]) == W[3]
true
```
"""
function parabolic_subgroup(W::WeylGroup, vec::Vector{<:Integer}, w::WeylGroupElem=one(W))
@req allunique(vec) "Elements of vector are not pairwise distinct"
@req all(i -> 1 <= i <= number_of_generators(W), vec) "Invalid indices"
cm = cartan_matrix(root_system(W))[vec, vec]
para = weyl_group(cm)
genimgs = map(x -> inv(w) * x * w, gens(W)[vec])
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved
emb = function (u::WeylGroupElem)
return map_word(u, genimgs)
end
return para, MapFromFunc(para, W, emb)
end

@doc raw"""
parabolic_subgroup_with_projection(W::WeylGroup, vec::Vector{<:Integer}) -> WeylGroup, Map{WeylGroup, WeylGroup}, Map{WeylGroup, WeylGroup}
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved

Return a triple `(P, emb, proj)` that describes a factor of `W`, that is,
a product of irreducible factors.
Here `P, emb = `[`parabolic_subgroup`](@ref)`(W, vec)`
and `proj` is the projection map from `W` onto `P`,
which is a left-inverse of `emb`.
If `P` is not a factor of `W`, an error occurs.
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved

# Examples
```jldoctest
julia> W = weyl_group([(:A, 3), (:B, 3)])
Weyl group
of root system of rank 6
of type A3 x B3

julia> P1, f1, p1 = parabolic_subgroup_with_projection(W, [1,2,3])
(Weyl group of root system of type A3, Map: P1 -> W, Map: W -> P1)

julia> p1(W[1]*W[4]*W[2]*W[6]) == P1[1] * P1[2]
true

julia> P2, f2, p2 = parabolic_subgroup_with_projection(W, [4,6,5])
(Weyl group of root system of type B3 (non-canonical ordering), Map: P2 -> W, Map: W -> P2)

julia> p2(W[5]) == P2[3]
true
```
"""
function parabolic_subgroup_with_projection(
W::WeylGroup, vec::Vector{<:Integer}; check_factor::Bool=true
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved
)
if check_factor
# Check that every generator in gens(W)[vec] commutes with every other generator.
# In other words, vec describes a union of irreducible components of the Coxeter diagram.
cm = cartan_matrix(root_system(W))
for i in vec
for j in setdiff(1:number_of_generators(W), vec)
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved
@req is_zero_entry(cm, i, j) begin
"Input vector does not describe a factor of the Weyl group, \

Check warning on line 397 in experimental/LieAlgebras/src/WeylGroup.jl

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/WeylGroup.jl#L397

Added line #L397 was not covered by tests
so there is no projection homomorphism"
fingolfin marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
end

factor, emb = parabolic_subgroup(W, vec)
# Generators of W are mapped to the corresponding generators of factor,
# or to 1 if there is no corresponding generator
proj_gen_imgs = [one(factor) for _ in 1:number_of_generators(W)]
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved
for i in 1:length(vec)
proj_gen_imgs[vec[i]] = gen(factor, i)
end
proj = function (w::WeylGroupElem)
return map_word(w, proj_gen_imgs)
end
return factor, emb, MapFromFunc(W, factor, proj)
end
2 changes: 2 additions & 0 deletions experimental/LieAlgebras/src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export killing_matrix
export lie_algebra
export lower_central_series
export matrix_repr_basis
export parabolic_subgroup
export parabolic_subgroup_with_projection
export show_dynkin_diagram
export simple_module
export special_linear_lie_algebra
Expand Down
95 changes: 95 additions & 0 deletions experimental/LieAlgebras/test/WeylGroup-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,99 @@
end
end
end

@testset "WeylGroup parabolic subgroup test for $(Wname)" for (
Wname, W, vec, check_proj
) in [
("A1", weyl_group(:A, 1), [1], true),
("A5", weyl_group(:A, 5), [1, 5, 3], false),
("B2", weyl_group(:B, 2), [2, 1], false),
("F4", weyl_group(:F, 4), [2, 3], false),
("A5+E8+D4", weyl_group((:A, 5), (:E, 8), (:D, 4)), [6:13; 1:5], true),
(
"A3 with non-canonical ordering of simple roots",
weyl_group(root_system([2 -1 -1; -1 2 0; -1 0 2])),
[2, 3], false,
),
(
"B4 with non-canonical ordering of simple roots",
weyl_group(root_system([2 -1 -1 0; -1 2 0 -1; -2 0 2 0; 0 -1 0 2])),
[2, 4], false,
),
(
"complicated case 1",
begin
cm = cartan_matrix((:A, 3), (:C, 3), (:E, 6), (:G, 2))
for _ in 1:50
i, j = rand(1:nrows(cm), 2)
if i != j
swap_rows!(cm, i, j)
swap_cols!(cm, i, j)
end
end
weyl_group(cm)
end,
unique(rand(1:14, 5)), false,
),
(
"complicated case 2",
begin
cm = cartan_matrix((:F, 4), (:B, 2), (:E, 7), (:G, 2))
for _ in 1:50
i, j = rand(1:nrows(cm), 2)
if i != j
swap_rows!(cm, i, j)
swap_cols!(cm, i, j)
end
end
weyl_group(root_system(cm))
end,
unique(rand(1:15, 6)), false,
),
]
for k in 1:4
if k == 1
# On the first run, test the standard parabolics and projections
if check_proj
para, emb, proj = parabolic_subgroup_with_projection(W, vec)
else
para, emb = parabolic_subgroup(W, vec)
end
genimgs = [gen(W, i) for i in vec] # Desired images of gens(para) in W
else
# On subsequent runs, conjugate by random elements
conj = rand(W)
para, emb = parabolic_subgroup(W, vec, conj)
genimgs = [inv(conj) * gen(W, vec[i]) * conj for i in 1:length(vec)]
TWiedemann marked this conversation as resolved.
Show resolved Hide resolved
end
# Test that emb maps gens(para) to genimgs
for i in 1:length(vec)
@test emb(gen(para, i)) == genimgs[i]
end
# Test that emb is a homomorphism
for _ in 1:5
p1 = rand(para)
p2 = rand(para)
@test emb(p1) * emb(p2) == emb(p1 * p2)
end
# Test proj
if k == 1 && check_proj
# Test that proj maps gens(para) to gens(W)[vec]
for i in 1:length(vec)
@test proj(gen(W, vec[i])) == gen(para, i)
end
# Test that proj is a homomorphism
for _ in 1:5
w1 = rand(W)
w2 = rand(W)
@test proj(w1) * proj(w2) == proj(w1 * w2)
end
# Test that proj is the left-inverse of emb
for _ in 1:5
p = rand(para)
@test proj(emb(p)) == p
end
end
end
end
end
Loading