From 23ac963840d9f9192a89d764932f31e4a80da7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Thu, 8 Feb 2024 17:52:35 +0100 Subject: [PATCH 01/12] Remove unused internal function --- experimental/LieAlgebras/src/RootSystem.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index 21277ffde10b..7b499e30b26a 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -340,10 +340,6 @@ function simple_roots(R::RootSystem) return positive_roots(R)[1:rank(R)] end -function type(R::RootSystem) - return R.type -end - @doc raw""" simple_coroot(R::RootSystem, i::Int) -> RootSpaceElem From 148c80ab1c4baae8fbdef90feba0c0e27898e63d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 9 Feb 2024 17:54:36 +0100 Subject: [PATCH 02/12] Replace `cartan_type_with_ordering` tests --- .../LieAlgebras/test/CartanMatrix-test.jl | 245 +++++++++++------- 1 file changed, 158 insertions(+), 87 deletions(-) diff --git a/experimental/LieAlgebras/test/CartanMatrix-test.jl b/experimental/LieAlgebras/test/CartanMatrix-test.jl index 8d53a14c0159..f94f8929082a 100644 --- a/experimental/LieAlgebras/test/CartanMatrix-test.jl +++ b/experimental/LieAlgebras/test/CartanMatrix-test.jl @@ -121,100 +121,171 @@ @test cartan_bilinear_form(ZZ[2 -4; -1 2]) == ZZ[2 -4; -4 8] end - @testset "cartan_type(gcm::ZZMatrix; check::Bool)" begin - # test if we follow our own conventions - @test cartan_type(cartan_matrix(:A, 3); check=false) == [(:A, 3)] - @test cartan_type(cartan_matrix(:B, 2); check=false) == [(:B, 2)] - @test cartan_type(cartan_matrix(:C, 2); check=false) == [(:C, 2)] - - # tests for irreducibles - @test cartan_type(cartan_matrix(:A, 1); check=false) == [(:A, 1)] - @test cartan_type(cartan_matrix(:A, 2); check=false) == [(:A, 2)] - - @test cartan_type(cartan_matrix(:B, 3); check=false) == [(:B, 3)] - @test cartan_type(ZZ[2 -2 0; -1 2 -1; 0 -1 2]; check=false) == [(:B, 3)] - - # Cn - @test cartan_type(cartan_matrix(:C, 3); check=false) == [(:C, 3)] - @test cartan_type(ZZ[2 -1 0; -2 2 -1; 0 -1 2]; check=false) == [(:C, 3)] - - # Dn - @test cartan_type(cartan_matrix(:D, 4); check=false) == [(:D, 4)] - @test cartan_type(ZZ[2 -1 -1 -1; -1 2 0 0; -1 0 2 0; -1 0 0 2]) == [(:D, 4)] - @test cartan_type(cartan_matrix(:D, 6); check=false) == [(:D, 6)] - - @test cartan_type(cartan_matrix(:E, 6); check=false) == [(:E, 6)] - @test cartan_type(cartan_matrix(:E, 7); check=false) == [(:E, 7)] - @test cartan_type(cartan_matrix(:E, 8); check=false) == [(:E, 8)] - @test cartan_type(cartan_matrix(:F, 4); check=false) == [(:F, 4)] - @test cartan_type(cartan_matrix(:G, 2); check=false) == [(:G, 2)] - - # for F4 and G2 we also allow the transposed Cartan matrix - @test cartan_type(transpose(cartan_matrix(:F, 4))) == [(:F, 4)] - @test cartan_type(transpose(cartan_matrix(:G, 2))) == [(:G, 2)] - - # test decomposable Cartan matrices - @test cartan_type(cartan_matrix((:A, 1), (:A, 2)); check=false) == [(:A, 1), (:A, 2)] - @test cartan_type(cartan_matrix((:A, 1), (:B, 2)); check=false) == [(:A, 1), (:B, 2)] - @test cartan_type(cartan_matrix((:C, 2), (:B, 2)); check=false) == [(:C, 2), (:B, 2)] - @test cartan_type(ZZ[2 0 -1 0; 0 2 0 -2; -2 0 2 0; 0 -1 0 2]; check=false) == - [(:B, 2), (:C, 2)] - end - - @testset "cartan_type_with_ordering(gcm::ZZMatrix; check::Bool)" begin - # we only test the ordering here the type detection is tested in "cartan_type(gcm::ZZMatrix; check::Bool)" - - # An - _, ord = cartan_type_with_ordering(cartan_matrix(:A, 1)) - @test ord == [1] - - _, ord = cartan_type_with_ordering(cartan_matrix(:A, 2)) - @test ord == [1, 2] - - # Bn - _, ord = cartan_type_with_ordering(cartan_matrix(:B, 2)) - @test ord == [1, 2] - - _, ord = cartan_type_with_ordering(cartan_matrix(:B, 3)) - @test ord == [1, 2, 3] - - # Cn - _, ord = cartan_type_with_ordering(cartan_matrix(:C, 2)) - @test ord == [1, 2] - - _, ord = cartan_type_with_ordering(cartan_matrix(:C, 3)) - @test ord == [1, 2, 3] - - # Dn - _, ord = cartan_type_with_ordering(cartan_matrix(:D, 4)) - @test ord == [1, 2, 3, 4] - - _, ord = cartan_type_with_ordering(ZZ[2 -1 -1 -1; -1 2 0 0; -1 0 2 0; -1 0 0 2]) - @test ord == [2, 1, 3, 4] + @testset "cartan_type_with_ordering" begin + @testset "A_n" begin + @testset "A_$n" for n in 1:8 + cm = cartan_matrix(:A, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); + check=false, + ) + @test type == [(:A, n)] + # automorphism group of Dynkin diagram is S_2 + @test ord in [Vector{Int}(perm), reverse(Vector{Int}(perm))] + @test !is_one(perm) || ord == 1:n + end + end + end - # En - _, ord = cartan_type_with_ordering(cartan_matrix(:E, 6)) - @test ord == [1, 3, 4, 2, 5, 6] + @testset "B_n" begin + @testset "B_$n" for n in 2:8 + cm = cartan_matrix(:B, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); + check=false, + ) + if n == 2 + # B_2 is isomorphic to C_2; we decide based on the ordering + if is_one(perm) + @test type == [(:B, n)] + @test ord == [1, 2] + else + @test type == [(:C, 2)] + @test ord == [1, 2] + end + else + @test type == [(:B, n)] + # no automorphisms of Dynkin diagram + @test ord == Vector{Int}(perm) + end + @test !is_one(perm) || ord == 1:n + end + end + end - _, ord = cartan_type_with_ordering(cartan_matrix(:E, 7)) - @test ord == [1, 3, 4, 2, 5, 6, 7] + @testset "C_n" begin + @testset "C_$n" for n in 2:8 + cm = cartan_matrix(:C, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); + check=false, + ) + if n == 2 + # C_2 is isomorphic to B_2; we decide based on the ordering + if is_one(perm) + @test type == [(:C, n)] + @test ord == [1, 2] + else + @test type == [(:B, 2)] + @test ord == [1, 2] + end + else + @test type == [(:C, n)] + # no automorphisms of Dynkin diagram + @test ord == Vector{Int}(perm) + end + end + end + end - _, ord = cartan_type_with_ordering(cartan_matrix(:E, 8)) - @test ord == [1, 3, 4, 2, 5, 6, 7, 8] + @testset "D_n" begin + @testset "D_$n" for n in 4:8 + cm = cartan_matrix(:D, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); + check=false, + ) + @test type == [(:D, n)] + if n == 4 + # automorphism group of Dynkin diagram is S_3, only one fixpoint + @test ord[2] == perm(2) + else + # automorphism group of Dynkin diagram is S_2 + aut = @perm (n - 1, n) + @test ord in [Vector{Int}(perm), Vector{Int}(aut * perm)] + end + @test !is_one(perm) || ord == 1:n + end + end + end - # F4 - _, ord = cartan_type_with_ordering(cartan_matrix(:F, 4)) - @test ord == [1, 2, 3, 4] + @testset "E_n" begin + @testset "E_$n" for n in 6:8 + cm = cartan_matrix(:E, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); + check=false, + ) + @test type == [(:E, n)] + if n == 6 + # automorphism group of Dynkin diagram is S_2 + aut = @perm (1, 6)(3, 5) + @test ord in [Vector{Int}(perm), Vector{Int}(aut * perm)] + else + # no automorphisms of Dynkin diagram + @test ord == Vector{Int}(perm) + end + @test !is_one(perm) || ord == 1:n + end + end + end - _, ord = cartan_type_with_ordering(ZZ[2 -1 0 0; -1 2 -2 0; 0 -1 2 -1; 0 0 -1 2]) - @test ord == [4, 3, 2, 1] + @testset "F_$n" for n in 4:4 + cm = cartan_matrix(:F, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); check=false + ) + @test type == [(:F, n)] + # no automorphisms of Dynkin diagram + @test ord == Vector{Int}(perm) + @test !is_one(perm) || ord == 1:n + end + end - # G2 - _, ord = cartan_type_with_ordering(cartan_matrix(:G, 2)) - @test ord == [1, 2] + @testset "G_$n" for n in 2:2 + cm = cartan_matrix(:G, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); check=false + ) + @test type == [(:G, n)] + # no automorphisms of Dynkin diagram + @test ord == Vector{Int}(perm) + @test !is_one(perm) || ord == 1:n + end + end - _, ord = cartan_type_with_ordering(transpose(cartan_matrix(:G, 2))) - @test ord == [2, 1] + @testset "non-simple cases" begin + type, ord = cartan_type_with_ordering(cartan_matrix((:A, 1), (:A, 2)); check=false) + @test type == [(:A, 1), (:A, 2)] + @test ord == 1:3 + + type, ord = cartan_type_with_ordering(cartan_matrix((:A, 1), (:B, 2)); check=false) + @test type == [(:A, 1), (:B, 2)] + @test ord == 1:3 + + type, ord = cartan_type_with_ordering(cartan_matrix((:C, 2), (:B, 2)); check=false) + @test type == [(:C, 2), (:B, 2)] + @test ord == 1:4 + + type, ord = cartan_type_with_ordering( + cartan_matrix((:E, 8), (:A, 5), (:D, 4), (:F, 4), (:B, 8)); check=false + ) + @test type == [(:E, 8), (:A, 5), (:D, 4), (:F, 4), (:B, 8)] + @test ord == 1:(8 + 5 + 4 + 4 + 8) + + type, ord = cartan_type_with_ordering( + ZZ[2 0 -1 0; 0 2 0 -2; -2 0 2 0; 0 -1 0 2]; check=false + ) + @test type == [(:B, 2), (:C, 2)] + @test ord == [1, 3, 2, 4] + end end @testset "is_cartan_type" begin From ca7ab3855ac7cc0cd09cd9a9554071ba3d098498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 9 Feb 2024 14:34:07 +0100 Subject: [PATCH 03/12] Some minor fixes --- experimental/LieAlgebras/src/CartanMatrix.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/experimental/LieAlgebras/src/CartanMatrix.jl b/experimental/LieAlgebras/src/CartanMatrix.jl index 0858454b9611..2133322080b8 100644 --- a/experimental/LieAlgebras/src/CartanMatrix.jl +++ b/experimental/LieAlgebras/src/CartanMatrix.jl @@ -312,7 +312,7 @@ function cartan_type_with_ordering(gcm::ZZMatrix; check::Bool=true) # used for traversal undone = trues(rk) - plan = zeros(Int, 3) # a root is connected to up to 3 others + plan = zeros(Int, 4) # a root is connected to up to 3 others head = 0 # index up to which we planned (cyclic) tail = 0 # index of plan which will be done next @@ -328,7 +328,7 @@ function cartan_type_with_ordering(gcm::ZZMatrix; check::Bool=true) if tail != head tail += 1 - if tail == 4 + if tail == 5 tail = 1 end i = plan[tail] @@ -361,7 +361,7 @@ function cartan_type_with_ordering(gcm::ZZMatrix; check::Bool=true) for i in roots j = adj[i][1] if length(adj[i]) == 1 && gcm[i, j] * gcm[j, i] == 1 - if length(adj[j]) == 1 || (length(adj[j]) == 2 && gcm[j, adj[j][2]] == -1) + if length(adj[j]) == 2 && all(k -> gcm[j, k] == -1, adj[j]) v = i break elseif v == 0 @@ -425,7 +425,7 @@ function cartan_type_with_ordering(gcm::ZZMatrix; check::Bool=true) # plan to visit j if undone if undone[j] head += 1 - if head == 4 + if head == 5 head = 1 end plan[head] = j From 4197f50c771daadcf1b5380353cc282e7fd67aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 9 Feb 2024 18:10:42 +0100 Subject: [PATCH 04/12] Add dispatch with `Vector{Tuple{Symbol,Int}}` to all constructors --- experimental/LieAlgebras/src/CartanMatrix.jl | 25 ++++++++++++++++--- experimental/LieAlgebras/src/RootSystem.jl | 10 +++++--- experimental/LieAlgebras/src/WeylGroup.jl | 17 ++++++++++--- .../LieAlgebras/test/WeylGroup-test.jl | 1 + 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/experimental/LieAlgebras/src/CartanMatrix.jl b/experimental/LieAlgebras/src/CartanMatrix.jl index 2133322080b8..ff479da1be56 100644 --- a/experimental/LieAlgebras/src/CartanMatrix.jl +++ b/experimental/LieAlgebras/src/CartanMatrix.jl @@ -80,27 +80,46 @@ function cartan_matrix(fam::Symbol, rk::Int) end @doc raw""" - cartan_matrix(type::Tuple{Symbol,Int}...) -> ZZMatrix + cartan_matrix(type::Vector{Tuple{Symbol,Int}}) -> ZZMatrix Returns a block diagonal matrix of indecomposable Cartan matrices as defined by type. For allowed values see `cartan_matrix(fam::Symbol, rk::Int)`. # Example ```jldoctest -julia> cartan_matrix((:A, 2), (:B, 2)) +julia> cartan_matrix([(:A, 2), (:B, 2)]) [ 2 -1 0 0] [-1 2 0 0] [ 0 0 2 -1] [ 0 0 -2 2] ``` """ -function cartan_matrix(type::Tuple{Symbol,Int}...) +function cartan_matrix(type::Vector{Tuple{Symbol,Int}}) @req length(type) > 0 "At least one type is required" blocks = [cartan_matrix(t...) for t in type] return block_diagonal_matrix(blocks) end +@doc raw""" + cartan_matrix(type::Tuple{Symbol,Int}...) -> ZZMatrix + +Returns a block diagonal matrix of indecomposable Cartan matrices as defined by type. +For allowed values see `cartan_matrix(fam::Symbol, rk::Int)`. + +# Example +```jldoctest +julia> cartan_matrix((:A, 2), (:B, 2)) +[ 2 -1 0 0] +[-1 2 0 0] +[ 0 0 2 -1] +[ 0 0 -2 2] +``` +""" +function cartan_matrix(type::Tuple{Symbol,Int}...) + return cartan_matrix(collect(type)) +end + @doc raw""" is_cartan_matrix(mat::ZZMatrix; generalized::Bool=true) -> Bool diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index 7b499e30b26a..5c7377aafba8 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -55,13 +55,17 @@ function root_system(fam::Symbol, rk::Int) return R end -function root_system(types::Tuple{Symbol,Int}...) - cartan = cartan_matrix(types...) +function root_system(type::Vector{Tuple{Symbol,Int}}) + cartan = cartan_matrix(type) R = root_system(cartan; check=false) - R.type = collect(types) + R.type = type return R end +function root_system(type::Tuple{Symbol,Int}...) + return root_system(collect(type)) +end + function Base.show(io::IO, ::MIME"text/plain", R::RootSystem) io = pretty(io) println(io, "Root system defined by Cartan matrix") diff --git a/experimental/LieAlgebras/src/WeylGroup.jl b/experimental/LieAlgebras/src/WeylGroup.jl index 2b0188d5aa7b..a6699f4dab15 100644 --- a/experimental/LieAlgebras/src/WeylGroup.jl +++ b/experimental/LieAlgebras/src/WeylGroup.jl @@ -54,19 +54,28 @@ end @doc raw""" weyl_group(fam::Symbol, rk::Int) -> WeylGroup -Returns the Weyl group defined by . +Returns the Weyl group of the given type. See `cartan_matrix(fam::Symbol, rk::Int)` for allowed combinations. """ function weyl_group(fam::Symbol, rk::Int) return weyl_group(root_system(fam, rk)) end @doc raw""" - weyl_group(type::Tuple{Symbol, Int}...) -> WeylGroup + weyl_group(type::Vector{Tuple{Symbol,Int}}) -> WeylGroup -Returns the Weyl group defined by . +Returns the Weyl group of the given type. See `cartan_matrix(fam::Symbol, rk::Int)` for allowed combinations. +""" +function weyl_group(type::Vector{Tuple{Symbol,Int}}) + return weyl_group(root_system(type)) +end + +@doc raw""" + weyl_group(type::Tuple{Symbol,Int}...) -> WeylGroup + +Returns the Weyl group of the given type. See `cartan_matrix(fam::Symbol, rk::Int)` for allowed combinations. """ function weyl_group(type::Tuple{Symbol,Int}...) - return weyl_group(root_system(type...)) + return weyl_group(root_system(collect(type))) end @doc raw""" diff --git a/experimental/LieAlgebras/test/WeylGroup-test.jl b/experimental/LieAlgebras/test/WeylGroup-test.jl index de2a23738ec5..e4ea8fbab3e6 100644 --- a/experimental/LieAlgebras/test/WeylGroup-test.jl +++ b/experimental/LieAlgebras/test/WeylGroup-test.jl @@ -55,6 +55,7 @@ include( ("B4", weyl_group(root_system(:B, 4))), ("D5", weyl_group(cartan_matrix(:D, 5))), ("F4+G2", weyl_group((:F, 4), (:G, 2))), + ("E6+C3", weyl_group([(:E, 4), (:C, 2)])), ("A_1^(1)", weyl_group(ZZ[2 -2; -2 2])), # TODO: replace with cartan_matrix(A_1^(1)), once functionality for affine type is added ( "complicated case 1", From 3c87d16f804535ae7e197fcff4a4e938b3f0f2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 9 Feb 2024 18:35:27 +0100 Subject: [PATCH 05/12] Rewrite `cartan_type_with_ordering` --- experimental/LieAlgebras/src/CartanMatrix.jl | 245 +++++++++---------- 1 file changed, 118 insertions(+), 127 deletions(-) diff --git a/experimental/LieAlgebras/src/CartanMatrix.jl b/experimental/LieAlgebras/src/CartanMatrix.jl index ff479da1be56..e1c669a038aa 100644 --- a/experimental/LieAlgebras/src/CartanMatrix.jl +++ b/experimental/LieAlgebras/src/CartanMatrix.jl @@ -298,18 +298,11 @@ end Returns the Cartan type of a Cartan matrix `gcm` together with a vector indicating a canonical ordering of the roots in the Dynkin diagram (currently only Cartan matrices of finite type are supported). The keyword argument `check` can be set to `false` to skip verification whether `gcm` is indeed a Cartan matrix of finite type. + # Example ```jldoctest -julia> cartan_matrix(:E, 6) -[ 2 0 -1 0 0 0] -[ 0 2 0 -1 0 0] -[-1 0 2 -1 0 0] -[ 0 -1 -1 2 -1 0] -[ 0 0 0 -1 2 -1] -[ 0 0 0 0 -1 2] - julia> cartan_type_with_ordering(cartan_matrix(:E, 6)) -([(:E, 6)], [1, 3, 4, 2, 5, 6]) +([(:E, 6)], [1, 2, 3, 4, 5, 6]) julia> cartan_type_with_ordering(ZZ[2 0 -1 0; 0 2 0 -2; -2 0 2 0; 0 -1 0 2]) ([(:B, 2), (:C, 2)], [1, 3, 2, 4]) @@ -323,135 +316,133 @@ function cartan_type_with_ordering(gcm::ZZMatrix; check::Bool=true) # global information ord = sizehint!(Int[], rk) # ordering of the roots - adj = [sizehint!(Int[], 3) for _ in 1:rk] # store adjacent roots, adj[i] is ordered asc + adj = [[j for j in 1:rk if i != j && !is_zero_entry(gcm, i, j)] for i in 1:rk] # adjacency list + done = falses(rk) # whether a root is already in a component - # information about current type - num = 0 # number of roots - roots = sizehint!(Int[], rk) + for v0 in 1:rk + done[v0] && continue - # used for traversal - undone = trues(rk) - plan = zeros(Int, 4) # a root is connected to up to 3 others - head = 0 # index up to which we planned (cyclic) - tail = 0 # index of plan which will be done next - - i, j = 1, 2 - while true - while i == j || (j <= rk && is_zero_entry(gcm, i, j)) - j += 1 + # rank 1 + if length(adj[v0]) == 0 + push!(type, (:A, 1)) + push!(ord, v0) + done[v0] = true + continue end - if j == rk + 1 - num += 1 - undone[i] = false - push!(roots, i) - if tail != head - tail += 1 - if tail == 5 - tail = 1 - end - i = plan[tail] - else # nothing further is planned - offset = length(ord) + 1 - if num == 1 # rank 1 - push!(type, (:A, 1)) - push!(ord, i) - elseif num == 2 # rank 2 - i, j = roots[1], roots[2] - if gcm[i, j] * gcm[j, i] == 1 - push!(type, (:A, 2)) - push!(ord, i, j) - elseif gcm[i, j] == -2 - push!(type, (:C, 2)) - push!(ord, i, j) - elseif gcm[j, i] == -2 - push!(type, (:B, 2)) - push!(ord, i, j) - elseif gcm[i, j] == -3 - push!(type, (:G, 2)) - push!(ord, i, j) - else - push!(type, (:G, 2)) - push!(ord, j, i) - end - else # rank > 2 - # find start of the Dynkin graph - v = 0 - for i in roots - j = adj[i][1] - if length(adj[i]) == 1 && gcm[i, j] * gcm[j, i] == 1 - if length(adj[j]) == 2 && all(k -> gcm[j, k] == -1, adj[j]) - v = i - break - elseif v == 0 - v = i - end - end - end - push!(ord, v) - - n = 1 - adj3 = false # true if found a root with 3 adjacents - while n < num - nv = v - for vv in adj[v] - filter!(x -> x != v, adj[vv]) - push!(ord, vv) - n += 1 - if length(adj[vv]) > 0 - nv = vv - if length(adj[vv]) == 2 # +1 for the predecessor - adj3 = true - end - end - end - v = nv - end - - if adj3 - if isempty(adj[ord[end]]) && isempty(adj[ord[end - 1]]) - push!(type, (:D, num)) - else - push!(type, (:E, num)) - end - elseif num == 4 && - gcm[ord[end - 2], ord[end - 1]] * gcm[ord[end - 1], ord[end - 2]] > 1 - push!(type, (:F, 4)) - elseif gcm[ord[end - 1], ord[end]] * gcm[ord[end], ord[end - 1]] == 1 - push!(type, (:A, num)) - elseif gcm[ord[end - 1], ord[end]] == -1 - push!(type, (:B, num)) - else - push!(type, (:C, num)) - end - end - - # find next component - i = findfirst(undone) - if isnothing(i) - break - end - - # reset number of roots - num = 0 - empty!(roots) + # rank 2 + if length(adj[v0]) == 1 && length(adj[only(adj[v0])]) == 1 + v1 = only(adj[v0]) + if gcm[v0, v1] * gcm[v1, v0] == 1 + push!(type, (:A, 2)) + push!(ord, v0, v1) + elseif gcm[v0, v1] == -2 + push!(type, (:C, 2)) + push!(ord, v0, v1) + elseif gcm[v1, v0] == -2 + push!(type, (:B, 2)) + push!(ord, v0, v1) + elseif gcm[v0, v1] == -3 + push!(type, (:G, 2)) + push!(ord, v0, v1) + elseif gcm[v1, v0] == -3 + push!(type, (:G, 2)) + push!(ord, v1, v0) + else + error("unreachable") end - - j = 1 + done[v0] = true + done[v1] = true continue end - # plan to visit j if undone - if undone[j] - head += 1 - if head == 5 - head = 1 + # rank > 2 + # do a DFS to find the whole component + comp = [v0] + todo = [v0] + done[v0] = true + while !isempty(todo) + v = pop!(todo) + for w in adj[v] + if !done[w] + push!(comp, w) + push!(todo, w) + done[w] = true + end end - plan[head] = j end + sort!(comp) + len_comp = length(comp) + + deg3 = findfirst(v -> length(adj[v]) == 3, comp) + if isnothing(deg3) + # case A, B, C, F + + # find start of the Dynkin graph + start = 0 + for v1 in filter(v -> length(adj[v]) == 1, comp) + v2 = only(adj[v1]) + gcm[v1, v2] * gcm[v2, v1] == 1 || continue # discard right end of B and C + if len_comp == 4 + v3 = only(filter(!=(v1), adj[v2])) + gcm[v2, v3] == -1 || continue # discard right end of F + end - push!(adj[i], j) - j += 1 + # found start + start = v1 + break + end + @assert start != 0 + + # find the path + path = [start, only(adj[start])] + for _ in 1:(len_comp - 2) + push!(path, only(filter(!=(path[end - 1]), adj[path[end]]))) + end + # determine type + if len_comp == 4 && gcm[path[3], path[2]] == -2 + push!(type, (:F, 4)) + elseif gcm[path[end - 1], path[end]] == -2 + push!(type, (:C, len_comp)) + elseif gcm[path[end], path[end - 1]] == -2 + push!(type, (:B, len_comp)) + else + push!(type, (:A, len_comp)) + end + append!(ord, path) + else + # case D or E + + # find the three paths + v_deg3 = comp[deg3] + paths = [[v_deg3, v_n] for v_n in adj[v_deg3]] + for path in paths + while length(adj[path[end]]) == 2 + push!(path, only(filter(!=(path[end - 1]), adj[path[end]]))) + end + popfirst!(path) + end + sort!(paths; by=length) + @assert sum(length, paths) + 1 == len_comp + # determine type + if length(paths[2]) == 1 + # case D + push!(type, (:D, len_comp)) + if len_comp == 4 + push!(ord, only(paths[1]), v_deg3, only(paths[2]), only(paths[3])) + else + append!(ord, reverse!(paths[3])) + push!(ord, v_deg3, only(paths[1]), only(paths[2])) + end + elseif length(paths[2]) == 2 + # case E + push!(type, (:E, len_comp)) + push!(ord, paths[2][2], only(paths[1]), paths[2][1], v_deg3) + append!(ord, paths[3]) + else + error("unreachable") + end + end end return type, ord From 02bf3f69861718ada2fe4438d42a72b252a48e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 9 Feb 2024 18:36:07 +0100 Subject: [PATCH 06/12] Add Dynkin diagram printing from cartan matrix --- experimental/LieAlgebras/src/DynkinDiagram.jl | 45 +++++++- .../LieAlgebras/test/DynkinDiagram-test.jl | 108 ++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) diff --git a/experimental/LieAlgebras/src/DynkinDiagram.jl b/experimental/LieAlgebras/src/DynkinDiagram.jl index 6dc07b6fd6c6..d11c2c91ec33 100644 --- a/experimental/LieAlgebras/src/DynkinDiagram.jl +++ b/experimental/LieAlgebras/src/DynkinDiagram.jl @@ -1,3 +1,45 @@ +@doc raw""" + show_dynkin_diagram(cartan_matrix::ZZMatrix) -> Nothing + +Prints a string representation of the Dynkin diagram of the root system +with the given cartan matrix. +The labels of the nodes are the indices of the simple roots. + +Currently, only cartan matrices of finite type are supported. +""" +function show_dynkin_diagram(cartan_matrix::ZZMatrix) + type, label = cartan_type_with_ordering(cartan_matrix) + return show_dynkin_diagram(type, label) +end + +@doc raw""" + show_dynkin_diagram(type::Vector{Tuple{Symbol,Int}}) -> Nothing + +Prints a string representation of the Dynkin diagram of the root system of +the given cartan type. +""" +function show_dynkin_diagram(type::Vector{Tuple{Symbol,Int}}) + return show_dynkin_diagram(type, 1:sum(t[2] for t in type; init=0)) +end + +@doc raw""" + show_dynkin_diagram(type::Vector{Tuple{Symbol,Int}}, labels::AbstractVector{Int}) -> Nothing + +Prints a string representation of the Dynkin diagram of the root system of +the given cartan type. +""" +function show_dynkin_diagram(type::Vector{Tuple{Symbol,Int}}, labels::AbstractVector{Int}) + @req length(labels) == sum(t[2] for t in type; init=0) "Invalid number of labels" + offset = 0 + for (fam, rk) in type + show_dynkin_diagram(fam, rk, labels[(offset + 1):(offset + rk)]) + offset += rk + println() + println() + end + return nothing +end + @doc raw""" show_dynkin_diagram(fam::Symbol, rk::Int) -> Nothing @@ -5,7 +47,7 @@ Prints a string representation of the Dynkin diagram of the root system of the given cartan type. """ function show_dynkin_diagram(fam::Symbol, rk::Int) - show_dynkin_diagram(fam, rk, 1:rk) + return show_dynkin_diagram(fam, rk, 1:rk) end @doc raw""" @@ -49,4 +91,5 @@ function show_dynkin_diagram(fam::Symbol, rk::Int, labels::AbstractVector{Int}) end isempty(D) && error("Unreachable") print(D) + return nothing end diff --git a/experimental/LieAlgebras/test/DynkinDiagram-test.jl b/experimental/LieAlgebras/test/DynkinDiagram-test.jl index 1f13ccd76e79..074d1e3770cf 100644 --- a/experimental/LieAlgebras/test/DynkinDiagram-test.jl +++ b/experimental/LieAlgebras/test/DynkinDiagram-test.jl @@ -231,6 +231,114 @@ julia> show_dynkin_diagram(:F, 4, [105, 2, 99, 300]) julia> show_dynkin_diagram(:G, 2, [412, 5]) 412 <<< 5 ``` + +non-simple diagram with canonical labels + +```jldoctest show_ns_dynkin_diagram.test +julia> using Oscar + +julia> show_dynkin_diagram([(:B, 5), (:B, 5)]) +1 - 2 - 3 - 4 >=> 5 + +6 - 7 - 8 - 9 >=> 10 + +julia> show_dynkin_diagram([(:A, 2), (:B, 3), (:C, 4), (:D, 5), (:E, 6), (:F, 4), (:G, 2)]) +1 - 2 + +3 - 4 >=> 5 + +6 - 7 - 8 <=< 9 + +. 13 + / +10 - 11 - 12 + \ + 14 + +15 - 17 - 18 - 19 - 20 + | + 16 + +21 - 22 >=> 23 - 24 + +25 <<< 26 +``` + +non-simple diagram with non-canonical labels + +```jldoctest show_ns_dynkin_diagram_with_labels.test +julia> using Oscar + +julia> show_dynkin_diagram([(:B, 5), (:B, 5)], [15,3,6,0,1000,23,8,22,65,1]) +15 - 3 - 6 - 0 >=> 1000 + +23 - 8 - 22 - 65 >=> 1 + +julia> show_dynkin_diagram([(:A, 2), (:B, 3), (:C, 4), (:D, 5), (:E, 6), (:F, 4), (:G, 2)], 2*(2+3+4+5+6+4+2):-2:2) +52 - 50 + +48 - 46 >=> 44 + +42 - 40 - 38 <=< 36 + +. 28 + / +34 - 32 - 30 + \ + 26 + +24 - 20 - 18 - 16 - 14 + | + 22 + +12 - 10 >=> 8 - 6 + +4 <<< 2 +``` + +Dynkin diagram from cartan matrix + +```jldoctest show_ns_dynkin_diagram_cartan_matrix.test +julia> using Oscar + +julia> show_dynkin_diagram(cartan_matrix(:A, 3)) +1 - 2 - 3 + +julia> show_dynkin_diagram(cartan_matrix(:B, 4)) +1 - 2 - 3 >=> 4 + +julia> show_dynkin_diagram(cartan_matrix(:C, 5)) +1 - 2 - 3 - 4 <=< 5 + +julia> show_dynkin_diagram(cartan_matrix(:D, 6)) +. 5 + / +1 - 2 - 3 - 4 + \ + 6 + +julia> show_dynkin_diagram(cartan_matrix(:E, 7)) +1 - 3 - 4 - 5 - 6 - 7 + | + 2 + +julia> show_dynkin_diagram(cartan_matrix(:F, 4)) +1 - 2 >=> 3 - 4 + +julia> show_dynkin_diagram(cartan_matrix(:G, 2)) +1 <<< 2 + +julia> show_dynkin_diagram(ZZ[2 0 -1 0; 0 2 0 -2; -2 0 2 0; 0 -1 0 2]) +1 >=> 3 + +2 <=< 4 + +julia> show_dynkin_diagram(transpose(cartan_matrix(:F, 4))) +4 - 3 >=> 2 - 1 + +julia> show_dynkin_diagram(transpose(cartan_matrix(:G, 2))) +2 <<< 1 +``` """ function dummy_placeholder end From 6b00c2a5a2154903e774a198ca80551e388b61fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Sat, 10 Feb 2024 17:37:36 +0100 Subject: [PATCH 07/12] Rework root system type handling --- .../LieAlgebras/src/AbstractLieAlgebra.jl | 15 ------ experimental/LieAlgebras/src/DynkinDiagram.jl | 13 +++++ experimental/LieAlgebras/src/LieAlgebras.jl | 6 ++- experimental/LieAlgebras/src/RootSystem.jl | 51 +++++++++++++------ .../LieAlgebras/test/DynkinDiagram-test.jl | 43 +++++++++++++++- 5 files changed, 94 insertions(+), 34 deletions(-) diff --git a/experimental/LieAlgebras/src/AbstractLieAlgebra.jl b/experimental/LieAlgebras/src/AbstractLieAlgebra.jl index be4240d1c92e..a6de6661a38d 100644 --- a/experimental/LieAlgebras/src/AbstractLieAlgebra.jl +++ b/experimental/LieAlgebras/src/AbstractLieAlgebra.jl @@ -85,19 +85,6 @@ function root_system(L::LieAlgebra) return L.root_system end -has_root_system_type(L::AbstractLieAlgebra) = - has_root_system(L) && has_root_system_type(L.root_system) - -function root_system_type(L::AbstractLieAlgebra) - @req has_root_system_type(L) "No root system type known." - return root_system_type(root_system(L)) -end - -function root_system_type_string(L::AbstractLieAlgebra) - @req has_root_system_type(L) "No root system type known." - return root_system_type_string(root_system(L)) -end - @doc raw""" chevalley_basis(L::AbstractLieAlgebra{C}) -> NTuple{3,Vector{AbstractLieAlgebraElem{C}}} @@ -128,8 +115,6 @@ function Base.show(io::IO, ::MIME"text/plain", L::AbstractLieAlgebra) io = pretty(io) println(io, "Abstract Lie algebra") println(io, Indent(), "of dimension $(dim(L))", Dedent()) - has_root_system_type(L) && - println(io, Indent(), "of type $(root_system_type_string(L))", Dedent()) print(io, "over ") print(io, Lowercase(), coefficient_ring(L)) end diff --git a/experimental/LieAlgebras/src/DynkinDiagram.jl b/experimental/LieAlgebras/src/DynkinDiagram.jl index d11c2c91ec33..5aea2acc34be 100644 --- a/experimental/LieAlgebras/src/DynkinDiagram.jl +++ b/experimental/LieAlgebras/src/DynkinDiagram.jl @@ -12,6 +12,19 @@ function show_dynkin_diagram(cartan_matrix::ZZMatrix) return show_dynkin_diagram(type, label) end +@doc raw""" + show_dynkin_diagram(rs::RootSystem) -> Nothing + +Prints a string representation of the Dynkin diagram of the given root system. +The labels of the nodes are the indices of the simple roots. + +Currently, only root systems of finite type are supported. +""" +function show_dynkin_diagram(rs::RootSystem) + type, label = root_system_type_with_ordering(rs) + return show_dynkin_diagram(type, label) +end + @doc raw""" show_dynkin_diagram(type::Vector{Tuple{Symbol,Int}}) -> Nothing diff --git a/experimental/LieAlgebras/src/LieAlgebras.jl b/experimental/LieAlgebras/src/LieAlgebras.jl index d8c53b55cb19..ac341fa53464 100644 --- a/experimental/LieAlgebras/src/LieAlgebras.jl +++ b/experimental/LieAlgebras/src/LieAlgebras.jl @@ -167,8 +167,9 @@ export positive_root export positive_roots export reduced_expressions export reflect, reflect! -export root_system_type, has_root_system_type export root_system, has_root_system +export root_system_type, has_root_system_type +export root_system_type_with_ordering export show_dynkin_diagram export simple_coroot export simple_coroots @@ -290,8 +291,9 @@ export positive_roots export reduced_expressions export reflect, reflect! export root -export root_system_type, has_root_system_type export root_system, has_root_system +export root_system_type, has_root_system_type +export root_system_type_with_ordering export roots export show_dynkin_diagram export simple_coroot diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index 5c7377aafba8..1075d99b4826 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -13,6 +13,7 @@ mutable struct RootSystem # optional: type::Vector{Tuple{Symbol,Int}} + type_ordering::Vector{Int} function RootSystem(mat::ZZMatrix) pos_roots, pos_coroots, refl = positive_roots_and_reflections(mat) @@ -28,19 +29,22 @@ mutable struct RootSystem end @doc raw""" - root_system(cartan_matrix::ZZMatrix; check::Bool=true) -> RootSystem - root_system(cartan_matrix::Matrix{Int}; check::Bool=true) -> RootSystem + root_system(cartan_matrix::ZZMatrix; check::Bool=true, detect_type::Bool=true) -> RootSystem + root_system(cartan_matrix::Matrix{Int}; check::Bool=true, detect_type::Bool=true) -> RootSystem Constructs the root system defined by the Cartan matrix. If `check` is `true`, checks that `cartan_matrix` is a generalized Cartan matrix. +Passing `detect_type=false` will skip the detection of the root system type. """ -function root_system(cartan_matrix::ZZMatrix; check::Bool=true) +function root_system(cartan_matrix::ZZMatrix; check::Bool=true, detect_type::Bool=true) @req !check || is_cartan_matrix(cartan_matrix) "Requires a generalized Cartan matrix" - return RootSystem(cartan_matrix) + R = RootSystem(cartan_matrix) + detect_type && set_root_system_type(R, cartan_type_with_ordering(cartan_matrix)...) + return R end -function root_system(cartan_matrix::Matrix{<:Integer}; check::Bool=true) - return root_system(matrix(ZZ, cartan_matrix); check) +function root_system(cartan_matrix::Matrix{<:Integer}; kwargs...) + return root_system(matrix(ZZ, cartan_matrix); kwargs...) end @doc raw""" @@ -50,15 +54,15 @@ Constructs the root system of the given type. See `cartan_matrix(fam::Symbol, rk """ function root_system(fam::Symbol, rk::Int) cartan = cartan_matrix(fam, rk) - R = root_system(cartan; check=false) - R.type = [(fam, rk)] + R = root_system(cartan; check=false, detect_type=false) + set_root_system_type(R, [(fam, rk)]) return R end function root_system(type::Vector{Tuple{Symbol,Int}}) cartan = cartan_matrix(type) - R = root_system(cartan; check=false) - R.type = type + R = root_system(cartan; check=false, detect_type=false) + set_root_system_type(R, type) return R end @@ -137,12 +141,8 @@ function fundamental_weights(R::RootSystem) return [fundamental_weight(R, i) for i in 1:rank(R)] end -function has_root_system_type(R::RootSystem) - return isdefined(R, :type) -end - function is_simple(R::RootSystem) - if has_root_system_type(R) + if is_finite(weyl_group(R)) return length(root_system_type(R)) == 1 end error("Not implemented") # TODO: implement is_simple @@ -284,10 +284,29 @@ function rank(R::RootSystem) end function root_system_type(R::RootSystem) - @req has_root_system_type(R) "root system type not defined" return R.type end +function root_system_type_with_ordering(R::RootSystem) + return R.type, R.type_ordering +end + +function has_root_system_type(R::RootSystem) + return isdefined(R, :type) && isdefined(R, :type_ordering) +end + +function set_root_system_type(R::RootSystem, type::Vector{Tuple{Symbol,Int}}) + return set_root_system_type(R, type, 1:sum(t[2] for t in type; init=0)) +end + +function set_root_system_type( + R::RootSystem, type::Vector{Tuple{Symbol,Int}}, ordering::AbstractVector{Int} +) + R.type = type + R.type_ordering = collect(ordering) + return nothing +end + function root_system_type_string(R::RootSystem) return join([string(t[1]) * string(t[2]) for t in root_system_type(R)], " x ") end diff --git a/experimental/LieAlgebras/test/DynkinDiagram-test.jl b/experimental/LieAlgebras/test/DynkinDiagram-test.jl index 074d1e3770cf..d7c899013f65 100644 --- a/experimental/LieAlgebras/test/DynkinDiagram-test.jl +++ b/experimental/LieAlgebras/test/DynkinDiagram-test.jl @@ -298,7 +298,7 @@ julia> show_dynkin_diagram([(:A, 2), (:B, 3), (:C, 4), (:D, 5), (:E, 6), (:F, 4) Dynkin diagram from cartan matrix -```jldoctest show_ns_dynkin_diagram_cartan_matrix.test +```jldoctest show_dynkin_diagram_cartan_matrix.test julia> using Oscar julia> show_dynkin_diagram(cartan_matrix(:A, 3)) @@ -339,6 +339,47 @@ julia> show_dynkin_diagram(transpose(cartan_matrix(:F, 4))) julia> show_dynkin_diagram(transpose(cartan_matrix(:G, 2))) 2 <<< 1 ``` + +Dynkin diagram from root system + +```jldoctest show_dynkin_diagram_cartan_matrix.test +julia> using Oscar + +julia> show_dynkin_diagram(root_system(:A, 3)) +1 - 2 - 3 + +julia> show_dynkin_diagram(root_system([(:B, 4)])) +1 - 2 - 3 >=> 4 + +julia> show_dynkin_diagram(root_system(cartan_matrix(:C, 5))) +1 - 2 - 3 - 4 <=< 5 + +julia> show_dynkin_diagram(root_system([(:D, 8), (:E, 6), (:F, 4), (:G, 2)])) +. 7 + / +1 - 2 - 3 - 4 - 5 - 6 + \ + 8 + +9 - 11 - 12 - 13 - 14 + | + 10 + +15 - 16 >=> 17 - 18 + +19 <<< 20 + +julia> show_dynkin_diagram(root_system(ZZ[2 0 -1 0; 0 2 0 -2; -2 0 2 0; 0 -1 0 2])) +1 >=> 3 + +2 <=< 4 + +julia> show_dynkin_diagram(root_system(transpose(cartan_matrix(:F, 4)))) +4 - 3 >=> 2 - 1 + +julia> show_dynkin_diagram(root_system(transpose(cartan_matrix(:G, 2)))) +2 <<< 1 +``` """ function dummy_placeholder end From e49edf31b13b5f95ba448027c6ac1b30d9b3fa4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Sat, 10 Feb 2024 17:40:13 +0100 Subject: [PATCH 08/12] Fix test --- experimental/LieAlgebras/src/CartanMatrix.jl | 2 ++ experimental/LieAlgebras/src/RootSystem.jl | 2 +- experimental/LieAlgebras/src/WeylGroup.jl | 2 +- experimental/LieAlgebras/test/WeylGroup-test.jl | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/experimental/LieAlgebras/src/CartanMatrix.jl b/experimental/LieAlgebras/src/CartanMatrix.jl index e1c669a038aa..eba75788e150 100644 --- a/experimental/LieAlgebras/src/CartanMatrix.jl +++ b/experimental/LieAlgebras/src/CartanMatrix.jl @@ -117,6 +117,8 @@ julia> cartan_matrix((:A, 2), (:B, 2)) ``` """ function cartan_matrix(type::Tuple{Symbol,Int}...) + @req length(type) > 0 "At least one type is required" + return cartan_matrix(collect(type)) end diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index 1075d99b4826..de276cece2bc 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -39,7 +39,7 @@ Passing `detect_type=false` will skip the detection of the root system type. function root_system(cartan_matrix::ZZMatrix; check::Bool=true, detect_type::Bool=true) @req !check || is_cartan_matrix(cartan_matrix) "Requires a generalized Cartan matrix" R = RootSystem(cartan_matrix) - detect_type && set_root_system_type(R, cartan_type_with_ordering(cartan_matrix)...) + detect_type && is_finite(weyl_group(R)) && set_root_system_type(R, cartan_type_with_ordering(cartan_matrix)...) return R end diff --git a/experimental/LieAlgebras/src/WeylGroup.jl b/experimental/LieAlgebras/src/WeylGroup.jl index a6699f4dab15..e8c6a2a1a058 100644 --- a/experimental/LieAlgebras/src/WeylGroup.jl +++ b/experimental/LieAlgebras/src/WeylGroup.jl @@ -184,7 +184,7 @@ function order(::Type{T}, W::WeylGroup) where {T} end ord = T(1) - for (fam, rk) in type(root_system(W)) + for (fam, rk) in root_system_type(root_system(W)) if fam == :A ord *= T(factorial(rk + 1)) elseif fam == :B || fam == :C diff --git a/experimental/LieAlgebras/test/WeylGroup-test.jl b/experimental/LieAlgebras/test/WeylGroup-test.jl index e4ea8fbab3e6..2ee8a395f238 100644 --- a/experimental/LieAlgebras/test/WeylGroup-test.jl +++ b/experimental/LieAlgebras/test/WeylGroup-test.jl @@ -55,7 +55,7 @@ include( ("B4", weyl_group(root_system(:B, 4))), ("D5", weyl_group(cartan_matrix(:D, 5))), ("F4+G2", weyl_group((:F, 4), (:G, 2))), - ("E6+C3", weyl_group([(:E, 4), (:C, 2)])), + ("E6+C3", weyl_group([(:E, 6), (:C, 2)])), ("A_1^(1)", weyl_group(ZZ[2 -2; -2 2])), # TODO: replace with cartan_matrix(A_1^(1)), once functionality for affine type is added ( "complicated case 1", From 2c4ba91b9c123bedbc1be071f266ffb580af102e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 13 Feb 2024 18:51:18 +0100 Subject: [PATCH 09/12] Update experimental/LieAlgebras/test/WeylGroup-test.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix Röhrich <47457568+felix-roehrich@users.noreply.github.com> --- experimental/LieAlgebras/test/WeylGroup-test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/LieAlgebras/test/WeylGroup-test.jl b/experimental/LieAlgebras/test/WeylGroup-test.jl index 2ee8a395f238..9ffa1f51dde6 100644 --- a/experimental/LieAlgebras/test/WeylGroup-test.jl +++ b/experimental/LieAlgebras/test/WeylGroup-test.jl @@ -55,7 +55,7 @@ include( ("B4", weyl_group(root_system(:B, 4))), ("D5", weyl_group(cartan_matrix(:D, 5))), ("F4+G2", weyl_group((:F, 4), (:G, 2))), - ("E6+C3", weyl_group([(:E, 6), (:C, 2)])), + ("E6+C3", weyl_group([(:E, 6), (:C, 3)])), ("A_1^(1)", weyl_group(ZZ[2 -2; -2 2])), # TODO: replace with cartan_matrix(A_1^(1)), once functionality for affine type is added ( "complicated case 1", From ad189634e69759b0121dfe3566d1797429f44509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 14 Feb 2024 09:27:32 +0100 Subject: [PATCH 10/12] Add explicit error --- experimental/LieAlgebras/src/RootSystem.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index de276cece2bc..247f3d266698 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -284,6 +284,7 @@ function rank(R::RootSystem) end function root_system_type(R::RootSystem) + has_root_system_type(R) || error("Root system type not known and cannot be determined") return R.type end From 5905872780f8ea35e53e991a0b140391e374341c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 14 Feb 2024 09:32:21 +0100 Subject: [PATCH 11/12] Adapt `cartan_type_with_ordering` docstring --- experimental/LieAlgebras/src/CartanMatrix.jl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/experimental/LieAlgebras/src/CartanMatrix.jl b/experimental/LieAlgebras/src/CartanMatrix.jl index eba75788e150..fbce231ae372 100644 --- a/experimental/LieAlgebras/src/CartanMatrix.jl +++ b/experimental/LieAlgebras/src/CartanMatrix.jl @@ -278,6 +278,9 @@ This function is left inverse to `cartan_matrix`, i.e. in the case of isomorphic the ordering of the roots does matter (see the example below). The keyword argument `check` can be set to `false` to skip verification whether `gcm` is indeed a Cartan matrix of finite type. +The order of returned components is, in general, not unique and might change between versions. +If this function is called with the output of `cartan_matrix(type)`, it will keep the order of `type`. + # Example ```jldoctest julia> cartan_type(ZZ[2 -1; -2 2]) @@ -299,7 +302,12 @@ end Returns the Cartan type of a Cartan matrix `gcm` together with a vector indicating a canonical ordering of the roots in the Dynkin diagram (currently only Cartan matrices of finite type are supported). -The keyword argument `check` can be set to `false` to skip verification whether `gcm` is indeed a Cartan matrix of finite type. +The keyword argument `check` can be set to `false` to skip verification whether `gcm` is indeed a +Cartan matrix of finite type. + +The order of returned components and the ordering is, in general, not unique and might change between versions. +If this function is called with the output of `cartan_matrix(type)`, it will keep the order of `type` and the +returned ordering will be the identity. # Example ```jldoctest From 150ee57c3f2e14181e49bee1aca4273b140f2ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 14 Feb 2024 10:01:47 +0100 Subject: [PATCH 12/12] move common test code to a function --- .../LieAlgebras/test/CartanMatrix-test.jl | 186 ++++++++---------- 1 file changed, 79 insertions(+), 107 deletions(-) diff --git a/experimental/LieAlgebras/test/CartanMatrix-test.jl b/experimental/LieAlgebras/test/CartanMatrix-test.jl index f94f8929082a..a03474f0a56f 100644 --- a/experimental/LieAlgebras/test/CartanMatrix-test.jl +++ b/experimental/LieAlgebras/test/CartanMatrix-test.jl @@ -122,143 +122,115 @@ end @testset "cartan_type_with_ordering" begin + function test_cartan_type_with_ordering( + fam::Symbol, n::Int; autos::Vector{PermGroupElem}=[one(symmetric_group(n))] + ) + @req all(aut -> parent(aut) == symmetric_group(n), autos) "Incompatible permutation parent" + cm = cartan_matrix(fam, n) + for perm in symmetric_group(n) + type, ord = cartan_type_with_ordering( + permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); check=false + ) + @test type == [(fam, n)] + @test ord in [Vector{Int}(aut * perm) for aut in autos] + @test !is_one(perm) || ord == 1:n + end + end + @testset "A_n" begin @testset "A_$n" for n in 1:8 - cm = cartan_matrix(:A, n) - for perm in symmetric_group(n) - type, ord = cartan_type_with_ordering( - permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); - check=false, - ) - @test type == [(:A, n)] - # automorphism group of Dynkin diagram is S_2 - @test ord in [Vector{Int}(perm), reverse(Vector{Int}(perm))] - @test !is_one(perm) || ord == 1:n - end + # automorphism group of Dynkin diagram ≅ S_2 (horizontal reflection) + test_cartan_type_with_ordering( + :A, + n; + autos=[ + cperm(symmetric_group(n), Int[]), + cperm(symmetric_group(n), Vector{Int}[[i, n + 1 - i] for i in 1:div(n, 2)]), + ], + ) end end @testset "B_n" begin - @testset "B_$n" for n in 2:8 + @testset "B_2" begin + n = 2 + # B_2 is isomorphic to C_2; we decide based on the ordering cm = cartan_matrix(:B, n) - for perm in symmetric_group(n) - type, ord = cartan_type_with_ordering( - permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); - check=false, - ) - if n == 2 - # B_2 is isomorphic to C_2; we decide based on the ordering - if is_one(perm) - @test type == [(:B, n)] - @test ord == [1, 2] - else - @test type == [(:C, 2)] - @test ord == [1, 2] - end - else - @test type == [(:B, n)] - # no automorphisms of Dynkin diagram - @test ord == Vector{Int}(perm) - end - @test !is_one(perm) || ord == 1:n - end + # identity permutation + type, ord = cartan_type_with_ordering(cm; check=false) + @test type == [(:B, n)] + @test ord == [1, 2] + # non-identity permutation + type, ord = cartan_type_with_ordering(transpose(cm); check=false) + @test type == [(:C, 2)] + @test ord == [1, 2] + end + @testset "B_$n" for n in 3:8 + # no automorphisms of Dynkin diagram + test_cartan_type_with_ordering(:B, n) end end @testset "C_n" begin - @testset "C_$n" for n in 2:8 + @testset "C_2" begin + n = 2 + # C_2 is isomorphic to B_2; we decide based on the ordering cm = cartan_matrix(:C, n) - for perm in symmetric_group(n) - type, ord = cartan_type_with_ordering( - permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); - check=false, - ) - if n == 2 - # C_2 is isomorphic to B_2; we decide based on the ordering - if is_one(perm) - @test type == [(:C, n)] - @test ord == [1, 2] - else - @test type == [(:B, 2)] - @test ord == [1, 2] - end - else - @test type == [(:C, n)] - # no automorphisms of Dynkin diagram - @test ord == Vector{Int}(perm) - end - end + # identity permutation + type, ord = cartan_type_with_ordering(cm; check=false) + @test type == [(:C, n)] + @test ord == [1, 2] + # non-identity permutation + type, ord = cartan_type_with_ordering(transpose(cm); check=false) + @test type == [(:B, 2)] + @test ord == [1, 2] + end + @testset "C_$n" for n in 3:8 + # no automorphisms of Dynkin diagram + test_cartan_type_with_ordering(:C, n) end end @testset "D_n" begin @testset "D_$n" for n in 4:8 - cm = cartan_matrix(:D, n) - for perm in symmetric_group(n) - type, ord = cartan_type_with_ordering( - permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); - check=false, + if n == 4 + # automorphism group of Dynkin diagram ≅ S_3 + test_cartan_type_with_ordering( + :D, n; autos=(@perm 4 [(), (1, 3), (1, 4), (3, 4), (1, 3, 4), (1, 4, 3)]) + ) + else + # automorphism group of Dynkin diagram ≅ S_2 (vertical reflection) + test_cartan_type_with_ordering( + :D, + n; + autos=[ + cperm(symmetric_group(n), Int[]), cperm(symmetric_group(n), Int[n - 1, n]) + ], ) - @test type == [(:D, n)] - if n == 4 - # automorphism group of Dynkin diagram is S_3, only one fixpoint - @test ord[2] == perm(2) - else - # automorphism group of Dynkin diagram is S_2 - aut = @perm (n - 1, n) - @test ord in [Vector{Int}(perm), Vector{Int}(aut * perm)] - end - @test !is_one(perm) || ord == 1:n end end end @testset "E_n" begin @testset "E_$n" for n in 6:8 - cm = cartan_matrix(:E, n) - for perm in symmetric_group(n) - type, ord = cartan_type_with_ordering( - permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); - check=false, - ) - @test type == [(:E, n)] - if n == 6 - # automorphism group of Dynkin diagram is S_2 - aut = @perm (1, 6)(3, 5) - @test ord in [Vector{Int}(perm), Vector{Int}(aut * perm)] - else - # no automorphisms of Dynkin diagram - @test ord == Vector{Int}(perm) - end - @test !is_one(perm) || ord == 1:n + if n == 6 + # automorphism group of Dynkin diagram ≅ S_2 (horizontal reflection) + test_cartan_type_with_ordering(:E, n; autos=(@perm 6 [(), (1, 6)(3, 5)])) + else + # no automorphisms of Dynkin diagram + test_cartan_type_with_ordering(:E, n) end end end - @testset "F_$n" for n in 4:4 - cm = cartan_matrix(:F, n) - for perm in symmetric_group(n) - type, ord = cartan_type_with_ordering( - permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); check=false - ) - @test type == [(:F, n)] - # no automorphisms of Dynkin diagram - @test ord == Vector{Int}(perm) - @test !is_one(perm) || ord == 1:n - end + @testset "F_4" begin + # no automorphisms of Dynkin diagram + test_cartan_type_with_ordering(:F, 4) end - @testset "G_$n" for n in 2:2 - cm = cartan_matrix(:G, n) - for perm in symmetric_group(n) - type, ord = cartan_type_with_ordering( - permutation_matrix(ZZ, inv(perm)) * cm * permutation_matrix(ZZ, perm); check=false - ) - @test type == [(:G, n)] - # no automorphisms of Dynkin diagram - @test ord == Vector{Int}(perm) - @test !is_one(perm) || ord == 1:n - end + @testset "G_2" begin + # no automorphisms of Dynkin diagram + test_cartan_type_with_ordering(:G, 2) end @testset "non-simple cases" begin