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

Improve test coverage for CartanMatrix.jl #4295

Merged
merged 1 commit into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 30 additions & 59 deletions experimental/LieAlgebras/src/CartanMatrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@

If `check=true` the function will verify that `gcm` is indeed a generalized Cartan matrix.

!!! warning
Currently only Cartan matrices of finite type are supported.

# Examples
```jldoctest
julia> cartan_symmetrizer(cartan_matrix(:B, 2))
Expand All @@ -178,69 +181,37 @@
```
"""
function cartan_symmetrizer(gcm::ZZMatrix; check::Bool=true)
check && @req is_cartan_matrix(gcm) "not a Cartan matrix"
rk = nrows(gcm)
diag = ones(ZZRingElem, rk)

# used for traversal
undone = trues(rk)
plan = zeros(Int, rk) # roots planned sorted asc grouped by component
head = 0
tail = 0

# we collect roots of the same length
# once we know if they are short or long we scale appropriately
while any(undone)
if head == tail
head += 1
plan[head] = findfirst(undone)::Int
undone[plan[head]] = false
end

prev = head
i = plan[head]
for j in 1:rk
if i == j
continue
end

if !undone[j] || is_zero_entry(gcm, i, j)
continue
end

head += 1
plan[head] = j
undone[j] = false

if diag[i] * gcm[i, j] == diag[j] * gcm[j, i]
continue
elseif gcm[i, j] == gcm[j, i]
diag[i] = lcm(diag[i], diag[j])
diag[j] = diag[i]
continue
ct, ord = cartan_type_with_ordering(gcm; check=check)

i = 1
d = ones(ZZRingElem, length(ord))
for (fam, rk) in ct
if fam == :A
i += rk
elseif fam == :B
for j in i:(i + rk - 2)
d[j] = 2
end

if gcm[j, i] < -1
tail += 1
v = -gcm[j, i]
while tail < head
diag[plan[tail]] *= v
tail += 1
end
end
if gcm[i, j] < -1
diag[j] *= -gcm[i, j]
tail = head - 1
end
end

# we found new roots, meaning we are done with this component of the root system
if prev == head
tail = head
i += rk
elseif fam == :C
i += rk
d[i - 1] = 2
elseif fam == :D
i += rk
elseif fam == :E
i += rk
elseif fam == :F
d[i] = d[i + 1] = 2
i += rk
elseif fam == :G
d[i + 1] = 3
i += rk
else
error("unreachable")

Check warning on line 210 in experimental/LieAlgebras/src/CartanMatrix.jl

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/CartanMatrix.jl#L210

Added line #L210 was not covered by tests
end
end

return diag
return invpermute!(d, ord)
end

@doc raw"""
Expand Down
150 changes: 84 additions & 66 deletions experimental/LieAlgebras/test/CartanMatrix-test.jl
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
@testset "LieAlgebras.CartanMatrix" begin
@testset "cartan_matrix(fam::Symbol, rk::Int)" begin
@testset "cartan_matrix" begin
for fam in (:A, :B, :C, :D, :E, :F, :G, :X), i in -1:10
if is_cartan_type(fam, i)
cartan_matrix(fam, i)
else
@test_throws ArgumentError cartan_matrix(fam, i)
end
end
felix-roehrich marked this conversation as resolved.
Show resolved Hide resolved

@test cartan_matrix(:A, 1) == matrix(ZZ, 1, 1, [2])
@test cartan_matrix(:A, 2) == ZZ[2 -1; -1 2]

@test cartan_matrix(:B, 2) == ZZ[2 -1; -2 2]
@test cartan_matrix(:B, 3) == ZZ[2 -1 0; -1 2 -1; 0 -2 2]

@test cartan_matrix(:C, 2) == ZZ[2 -2; -1 2]
@test cartan_matrix(:C, 3) == ZZ[2 -1 0; -1 2 -2; 0 -1 2]

@test cartan_matrix(:D, 4) == ZZ[2 -1 0 0; -1 2 -1 -1; 0 -1 2 0; 0 -1 0 2]

@test_throws ArgumentError root_system(:X, 1)
@test_throws ArgumentError root_system(:A, 0)
@test_throws ArgumentError root_system(:B, 1)
@test_throws ArgumentError root_system(:C, 1)
@test_throws ArgumentError root_system(:D, 2)
@test_throws ArgumentError root_system(:E, 5)
@test_throws ArgumentError root_system(:E, 9)
@test_throws ArgumentError root_system(:F, 3)
@test_throws ArgumentError root_system(:F, 5)
@test_throws ArgumentError root_system(:G, 1)
@test_throws ArgumentError root_system(:G, 3)
end

@testset "cartan_matrix(type::Tuple{Symbol,Int}...)" begin
Expand All @@ -32,25 +25,41 @@
@test_throws MethodError cartan_matrix()
end

@testset "is_cartan_matrix(mat::ZZMatrix; generalized::Bool=true)" begin
# test finite type
@test is_cartan_matrix(cartan_matrix(:A, 1)) == true
@test is_cartan_matrix(cartan_matrix(:A, 1); generalized=false) == true

@test is_cartan_matrix(cartan_matrix(:A, 2)) == true
@test is_cartan_matrix(cartan_matrix(:A, 2); generalized=false) == true
@testset "is_cartan_matrix" begin
# test non cartan
@test is_cartan_matrix(ZZ[2 -1; -1 1]) == false
@testset for i in 1:3
is_cartan_matrix(ZZ[2 -i; 0 2]) == false
end

@test is_cartan_matrix(cartan_matrix(:B, 2)) == true
@test is_cartan_matrix(cartan_matrix(:B, 2); generalized=false) == true
# test finite type
function test_is_cartan_matrix_finite_type(cm::ZZMatrix)
rk = nrows(cm)
for _ in 1:50
i, j = rand(1:rk, 2)
if i != j
swap_rows!(cm, i, j)
swap_cols!(cm, i, j)
end
end

@test is_cartan_matrix(cartan_matrix(:C, 2)) == true
@test is_cartan_matrix(cartan_matrix(:C, 2); generalized=false) == true
@test is_cartan_matrix(cm) == true
@test is_cartan_matrix(cm; generalized=false) == true
end

@test is_cartan_matrix(cartan_matrix(:D, 4)) == true
@test is_cartan_matrix(cartan_matrix(:D, 4); generalized=false) == true
test_is_cartan_matrix_finite_type(cartan_matrix(:A, 1))
test_is_cartan_matrix_finite_type(cartan_matrix(:A, 3))
test_is_cartan_matrix_finite_type(cartan_matrix(:B, 4))
test_is_cartan_matrix_finite_type(cartan_matrix(:C, 2))
test_is_cartan_matrix_finite_type(cartan_matrix(:D, 5))
test_is_cartan_matrix_finite_type(cartan_matrix(:E, 6))
test_is_cartan_matrix_finite_type(cartan_matrix(:E, 7))
test_is_cartan_matrix_finite_type(cartan_matrix(:E, 8))
test_is_cartan_matrix_finite_type(cartan_matrix(:F, 4))
test_is_cartan_matrix_finite_type(cartan_matrix(:G, 2))

@test is_cartan_matrix(cartan_matrix(:G, 2)) == true
@test is_cartan_matrix(cartan_matrix(:G, 2); generalized=false) == true
test_is_cartan_matrix_finite_type(cartan_matrix((:A, 3), (:C, 3), (:E, 6), (:G, 2)))
test_is_cartan_matrix_finite_type(cartan_matrix((:F, 4), (:B, 2), (:E, 7), (:G, 2)))

# test affine type
@test is_cartan_matrix(ZZ[2 -2; -2 2]) == true
Expand All @@ -63,62 +72,71 @@
@test is_cartan_matrix(ZZ[2 -1 -1; -1 2 -1; -1 -1 2]; generalized=false) == false
end

@testset "cartan_symmetrizer(gcm::ZZMatrix; check::Bool)" begin
@testset "cartan_symmetrizer" begin
# cartan_symmetrizer function is indirectly covered by the cartan_bilinear_form tests
# here we simply guarantee that the choice of the symmetrizer is as expected

# finite type
@test cartan_symmetrizer(cartan_matrix(:A, 1)) == [1]
@test cartan_symmetrizer(cartan_matrix(:A, 2)) == [1, 1]

@test cartan_symmetrizer(cartan_matrix(:B, 2)) == [2, 1]
@test cartan_symmetrizer(cartan_matrix(:B, 4)) == [2, 2, 2, 1]

@test cartan_symmetrizer(cartan_matrix(:C, 2)) == [1, 2]
@test cartan_symmetrizer(cartan_matrix(:C, 4)) == [1, 1, 1, 2]

@test cartan_symmetrizer(cartan_matrix(:D, 4)) == [1, 1, 1, 1]

@test cartan_symmetrizer(cartan_matrix(:E, 6)) == [1, 1, 1, 1, 1, 1]
@test cartan_symmetrizer(cartan_matrix(:E, 7)) == [1, 1, 1, 1, 1, 1, 1]
@test cartan_symmetrizer(cartan_matrix(:E, 8)) == [1, 1, 1, 1, 1, 1, 1, 1]

@test cartan_symmetrizer(cartan_matrix(:F, 4)) == [2, 2, 1, 1]
@test cartan_symmetrizer(cartan_matrix(:G, 2)) == [1, 3]

@test cartan_symmetrizer(cartan_matrix((:A, 3), (:B, 3))) == [[1, 1, 1]; [2, 2, 1]]
@test cartan_symmetrizer(cartan_matrix((:F, 4), (:D, 4))) ==
[[2, 2, 1, 1]; [1, 1, 1, 1]]
@test cartan_symmetrizer(cartan_matrix((:C, 4), (:G, 2))) == [[1, 1, 1, 2]; [1, 3]]

@test cartan_symmetrizer(ZZ[2 -2 0; -1 2 -1; 0 -1 2]) == [1, 2, 2]
@test cartan_symmetrizer(ZZ[2 0 -1 0; 0 2 0 -2; -2 0 2 0; 0 -1 0 2]) == [2, 1, 1, 2]
felix-roehrich marked this conversation as resolved.
Show resolved Hide resolved

# affine type
@test cartan_symmetrizer(ZZ[2 -2; -2 2]) == [1, 1] # A1~1
@test cartan_symmetrizer(ZZ[2 -2 0; -1 2 -1; 0 -2 2]) == [1, 2, 1] # D3~2
@test cartan_symmetrizer(ZZ[2 -4; -1 2]) == [1, 4] # A1~2
#@test cartan_symmetrizer(ZZ[2 -2; -2 2]) == [1, 1] # A1~1
#@test cartan_symmetrizer(ZZ[2 -2 0; -1 2 -1; 0 -2 2]) == [1, 2, 1] # D3~2
#@test cartan_symmetrizer(ZZ[2 -4; -1 2]) == [1, 4] # A1~2

# hyperbolic type
@test cartan_symmetrizer(ZZ[2 -2; -3 2]) == [3, 2]
#@test cartan_symmetrizer(ZZ[2 -2; -3 2]) == [3, 2]
end

@testset "cartan_bilinear_form(gcm::ZZMatrix; check::Bool)" begin
# finite type
@test cartan_bilinear_form(cartan_matrix(:A, 2)) == ZZ[2 -1; -1 2]
@test cartan_bilinear_form(cartan_matrix(:B, 4)) ==
ZZ[4 -2 0 0; -2 4 -2 0; 0 -2 4 -2; 0 0 -2 2]
@test cartan_bilinear_form(cartan_matrix(:C, 4)) ==
ZZ[2 -1 0 0; -1 2 -1 0; 0 -1 2 -2; 0 0 -2 4]
@test cartan_bilinear_form(cartan_matrix(:F, 4)) ==
ZZ[4 -2 0 0; -2 4 -2 0; 0 -2 2 -1; 0 0 -1 2]
@test cartan_bilinear_form(cartan_matrix(:G, 2)) == ZZ[2 -3; -3 6]

@test cartan_bilinear_form(cartan_matrix((:B, 2), (:A, 1))) == ZZ[4 -2 0; -2 2 0; 0 0 2]
@test cartan_bilinear_form(ZZ[2 0 -1 0; 0 2 0 -2; -2 0 2 0; 0 -1 0 2]) ==
ZZ[4 0 -2 0; 0 2 0 -2; -2 0 2 0; 0 -2 0 4]
@testset "cartan_bilinear_form" begin
function test_cartan_bilinear_form(cm::ZZMatrix)
rk = nrows(cm)
for _ in 1:10
for _ in 1:10
i, j = rand(1:rk, 2)
if i != j
swap_rows!(cm, i, j)
swap_cols!(cm, i, j)
end
end

bil = cartan_bilinear_form(cm)
@test is_symmetric(bil)
@test all(cm[i, j] == div(2 * bil[i, j], bil[i, i]) for i in 1:rk, j in 1:rk)
end
end

# irreducible matrices
test_cartan_bilinear_form(cartan_matrix(:A, 1))
test_cartan_bilinear_form(cartan_matrix(:A, 3))
test_cartan_bilinear_form(cartan_matrix(:B, 4))
test_cartan_bilinear_form(cartan_matrix(:C, 2))
test_cartan_bilinear_form(cartan_matrix(:D, 5))
test_cartan_bilinear_form(cartan_matrix(:E, 6))
test_cartan_bilinear_form(cartan_matrix(:E, 7))
test_cartan_bilinear_form(cartan_matrix(:E, 8))
test_cartan_bilinear_form(cartan_matrix(:F, 4))
test_cartan_bilinear_form(cartan_matrix(:G, 2))

# reducible matrices
test_cartan_bilinear_form(cartan_matrix((:A, 3), (:C, 3), (:E, 6), (:G, 2)))
test_cartan_bilinear_form(cartan_matrix((:F, 4), (:B, 2), (:E, 7), (:G, 2)))

# affine type
@test cartan_bilinear_form(ZZ[2 -2; -2 2]) == ZZ[2 -2; -2 2]
@test cartan_bilinear_form(ZZ[2 -2 0; -1 2 -1; 0 -2 2]) == ZZ[2 -2 0; -2 4 -2; 0 -2 2]
@test cartan_bilinear_form(ZZ[2 -4; -1 2]) == ZZ[2 -4; -4 8]
#@test cartan_bilinear_form(ZZ[2 -2; -2 2]) == ZZ[2 -2; -2 2]
#@test cartan_bilinear_form(ZZ[2 -2 0; -1 2 -1; 0 -2 2]) == ZZ[2 -2 0; -2 4 -2; 0 -2 2]
#@test cartan_bilinear_form(ZZ[2 -4; -1 2]) == ZZ[2 -4; -4 8]
end

@testset "cartan_type_with_ordering" begin
Expand Down
Loading