Skip to content

Commit

Permalink
LieAlgebras: more optimizations regarding type stability (#4145)
Browse files Browse the repository at this point in the history
* Add second type param to `LieAlgebraModule`

* Make more tests `@inferred`

* Reduce test output spam

* Another type annotation fix
  • Loading branch information
lgoettgens authored Sep 26, 2024
1 parent 5371a13 commit 46abff7
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 50 deletions.
22 changes: 13 additions & 9 deletions experimental/LieAlgebras/src/LieAlgebraModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#
###############################################################################

parent_type(::Type{LieAlgebraModuleElem{C}}) where {C<:FieldElem} = LieAlgebraModule{C}
parent_type(
::Type{LieAlgebraModuleElem{C,LieT}}
) where {C<:FieldElem,LieT<:LieAlgebraElem{C}} = LieAlgebraModule{C,LieT}

elem_type(::Type{LieAlgebraModule{C}}) where {C<:FieldElem} = LieAlgebraModuleElem{C}
elem_type(::Type{LieAlgebraModule{C,LieT}}) where {C<:FieldElem,LieT<:LieAlgebraElem{C}} =
LieAlgebraModuleElem{C,LieT}

parent(v::LieAlgebraModuleElem) = v.parent

Expand All @@ -19,7 +22,8 @@ coefficient_ring(v::LieAlgebraModuleElem) = coefficient_ring(parent(v))
Return the Lie algebra `V` is a module over.
"""
base_lie_algebra(V::LieAlgebraModule) = V.L
base_lie_algebra(V::LieAlgebraModule{C,LieT}) where {C<:FieldElem,LieT<:LieAlgebraElem{C}} =
V.L::parent_type(LieT)

number_of_generators(L::LieAlgebraModule) = dim(L)

Expand Down Expand Up @@ -977,7 +981,7 @@ julia> L = special_linear_lie_algebra(QQ, 2);
julia> V = symmetric_power(standard_module(L), 2)[1]; # some module
julia> E, map = exterior_power(V, 2)
(Exterior power module of dimension 3 over L, Map: parent of tuples of type Tuple{LieAlgebraModuleElem{QQFieldElem}, LieAlgebraModuleElem{QQFieldElem}} -> E)
(Exterior power module of dimension 3 over L, Map: parent of tuples of type Tuple{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}, LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}} -> E)
julia> E
Exterior power module
Expand All @@ -988,7 +992,7 @@ Exterior power module
over special linear Lie algebra of degree 2 over QQ
julia> basis(E)
3-element Vector{LieAlgebraModuleElem{QQFieldElem}}:
3-element Vector{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}}:
(v_1^2)^(v_1*v_2)
(v_1^2)^(v_2^2)
(v_1*v_2)^(v_2^2)
Expand Down Expand Up @@ -1106,7 +1110,7 @@ julia> L = special_linear_lie_algebra(QQ, 4);
julia> V = exterior_power(standard_module(L), 3)[1]; # some module
julia> S, map = symmetric_power(V, 2)
(Symmetric power module of dimension 10 over L, Map: parent of tuples of type Tuple{LieAlgebraModuleElem{QQFieldElem}, LieAlgebraModuleElem{QQFieldElem}} -> S)
(Symmetric power module of dimension 10 over L, Map: parent of tuples of type Tuple{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}, LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}} -> S)
julia> S
Symmetric power module
Expand All @@ -1117,7 +1121,7 @@ Symmetric power module
over special linear Lie algebra of degree 4 over QQ
julia> basis(S)
10-element Vector{LieAlgebraModuleElem{QQFieldElem}}:
10-element Vector{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}}:
(v_1^v_2^v_3)^2
(v_1^v_2^v_3)*(v_1^v_2^v_4)
(v_1^v_2^v_3)*(v_1^v_3^v_4)
Expand Down Expand Up @@ -1260,7 +1264,7 @@ julia> L = special_linear_lie_algebra(QQ, 3);
julia> V = exterior_power(standard_module(L), 2)[1]; # some module
julia> T, map = tensor_power(V, 2)
(Tensor power module of dimension 9 over L, Map: parent of tuples of type Tuple{LieAlgebraModuleElem{QQFieldElem}, LieAlgebraModuleElem{QQFieldElem}} -> T)
(Tensor power module of dimension 9 over L, Map: parent of tuples of type Tuple{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}, LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}} -> T)
julia> T
Tensor power module
Expand All @@ -1271,7 +1275,7 @@ Tensor power module
over special linear Lie algebra of degree 3 over QQ
julia> basis(T)
9-element Vector{LieAlgebraModuleElem{QQFieldElem}}:
9-element Vector{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}}:
(v_1^v_2)(x)(v_1^v_2)
(v_1^v_2)(x)(v_1^v_3)
(v_1^v_2)(x)(v_2^v_3)
Expand Down
4 changes: 2 additions & 2 deletions experimental/LieAlgebras/src/LieAlgebraModuleHom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ Lie algebra module morphism
to direct sum module of dimension 5 over L
julia> [(v, h(v)) for v in basis(V1)]
2-element Vector{Tuple{LieAlgebraModuleElem{QQFieldElem}, LieAlgebraModuleElem{QQFieldElem}}}:
2-element Vector{Tuple{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}, LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}}}:
(v_1, v_1^(1))
(v_2, v_2^(1))
```
Expand Down Expand Up @@ -227,7 +227,7 @@ Lie algebra module morphism
to abstract Lie algebra module of dimension 1 over L
julia> [(v, h(v)) for v in basis(V1)]
3-element Vector{Tuple{LieAlgebraModuleElem{QQFieldElem}, LieAlgebraModuleElem{QQFieldElem}}}:
3-element Vector{Tuple{LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}, LieAlgebraModuleElem{QQFieldElem, LinearLieAlgebraElem{QQFieldElem}}}}:
(v_1, 0)
(v_2, 0)
(v_3, 0)
Expand Down
13 changes: 7 additions & 6 deletions experimental/LieAlgebras/src/Types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ end
R::Field
n::Int # the n of the gl_n this embeds into
dim::Int
basis::Vector{MatElem{C}}
basis::Vector{<:MatElem{C}}
s::Vector{Symbol}

# only set if known
Expand Down Expand Up @@ -413,8 +413,9 @@ end
#
###############################################################################

@attributes mutable struct LieAlgebraModule{C<:FieldElem} <: AbstractAlgebra.Set
L::LieAlgebra{C}
@attributes mutable struct LieAlgebraModule{C<:FieldElem,LieT<:LieAlgebraElem{C}} <:
AbstractAlgebra.Set
L::LieAlgebra{C} # parent_type(LieT)
dim::Int
transformation_matrices::Vector{<:MatElem{C}} # Vector{dense_matrix_type(C)}
s::Vector{Symbol}
Expand All @@ -430,7 +431,7 @@ end
@req dim(L) == length(transformation_matrices) "Invalid number of transformation matrices."
@req all(m -> size(m) == (dimV, dimV), transformation_matrices) "Invalid transformation matrix dimensions."

V = new{C}(L, dimV, transformation_matrices, s)
V = new{C,elem_type(L)}(L, dimV, transformation_matrices, s)
if check
@req all(m -> all(e -> parent(e) === coefficient_ring(V), m), transformation_matrices) "Invalid transformation matrix entries."
for xi in basis(L), xj in basis(L), v in basis(V)
Expand All @@ -441,8 +442,8 @@ end
end
end

struct LieAlgebraModuleElem{C<:FieldElem} <: AbstractAlgebra.SetElem
parent::LieAlgebraModule{C}
struct LieAlgebraModuleElem{C<:FieldElem,LieT<:LieAlgebraElem{C}} <: AbstractAlgebra.SetElem
parent::LieAlgebraModule{C,LieT}
mat::MatElem{C}
end

Expand Down
68 changes: 36 additions & 32 deletions experimental/LieAlgebras/test/setup_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,31 @@ if !isdefined(Main, :lie_algebra_conformance_test) || isinteractive()
@test L isa parentT
@test x isa elemT

@test parent_type(elemT) == parentT
@test elem_type(parentT) == elemT
@test (@inferred parent_type(elemT)) == parentT
@test (@inferred elem_type(parentT)) == elemT

@test parent(x) === L
@test (@inferred parent(x)) === L

@test coefficient_ring(x) === coefficient_ring(L)
@test elem_type(coefficient_ring(L)) == C
@test (@inferred coefficient_ring(x)) === (@inferred coefficient_ring(L))
@test (@inferred elem_type(coefficient_ring(L))) == C

@test characteristic(L) == characteristic(coefficient_ring(L))
@test (@inferred characteristic(L)) == characteristic(coefficient_ring(L))

# this block stays only as long as `ngens` and `gens` are not specialized for Lie algebras
@test dim(L) == ngens(L)
@test basis(L) == gens(L)
@test (@inferred dim(L)) == (@inferred ngens(L))
@test (@inferred basis(L)) == (@inferred gens(L))
dim(L) >= 1 && @test (@inferred basis(L, 1)) == (@inferred gen(L, 1))
@test all(i -> basis(L, i) == gen(L, i), 1:dim(L))

@test dim(L) == length(basis(L))
@test all(i -> basis(L, i) == basis(L)[i], 1:dim(L))

@test dim(L) == length(symbols(L))

@test iszero(zero(L))
z = @inferred zero(L)
@test @inferred iszero(z)

@test coefficients(x) == [coeff(x, i) for i in 1:dim(L)]
@test (@inferred coefficients(x)) == [@inferred coeff(x, i) for i in 1:dim(L)]
@test all(i -> coeff(x, i) == x[i], 1:dim(L))
@test sum(x[i] * basis(L, i) for i in 1:dim(L); init=zero(L)) == x

Expand All @@ -52,11 +54,11 @@ if !isdefined(Main, :lie_algebra_conformance_test) || isinteractive()

for _ in 1:num_random_tests
coeffs = rand(-10:10, dim(L))
x1 = L(coeffs)
x2 = L(coefficient_ring(L).(coeffs))
x3 = L(matrix(coefficient_ring(L), 1, dim(L), coeffs))
x4 = L(sparse_row(matrix(coefficient_ring(L), 1, dim(L), coeffs)))
x5 = L(x1)
x1 = @inferred L(coeffs)
x2 = @inferred L(coefficient_ring(L).(coeffs))
x3 = @inferred L(matrix(coefficient_ring(L), 1, dim(L), coeffs))
x4 = @inferred L(sparse_row(matrix(coefficient_ring(L), 1, dim(L), coeffs)))
x5 = @inferred L(x1)
@test x1 == x2
@test x1 == x3
@test x1 == x4
Expand Down Expand Up @@ -190,8 +192,8 @@ if !isdefined(Main, :lie_algebra_module_conformance_test) || isinteractive()
function lie_algebra_module_conformance_test(
L::LieAlgebra{C},
V::LieAlgebraModule{C},
parentT::DataType=LieAlgebraModule{C},
elemT::DataType=LieAlgebraModuleElem{C};
parentT::DataType=LieAlgebraModule{C,elem_type(L)},
elemT::DataType=LieAlgebraModuleElem{C,elem_type(L)};
num_random_tests::Int=10,
) where {C<:FieldElem}
@testset "basic manipulation" begin
Expand All @@ -202,27 +204,29 @@ if !isdefined(Main, :lie_algebra_module_conformance_test) || isinteractive()
@test V isa parentT
@test v isa elemT

@test parent_type(elemT) == parentT
@test elem_type(parentT) == elemT
@test (@inferred parent_type(elemT)) == parentT
@test (@inferred elem_type(parentT)) == elemT

@test parent(v) === V
@test (@inferred parent(v)) === V

@test coefficient_ring(v) === coefficient_ring(V)
@test elem_type(coefficient_ring(V)) == C
@test (@inferred coefficient_ring(v)) === (@inferred coefficient_ring(V))
@test (@inferred elem_type(coefficient_ring(V))) == C

@test base_lie_algebra(V) === L
@test (@inferred base_lie_algebra(V)) === L

# this block stays only as long as `ngens` and `gens` are not specialized for Lie algebra modules
@test dim(V) == ngens(V)
@test basis(V) == gens(V)
@test (@inferred dim(V)) == (@inferred ngens(V))
@test (@inferred basis(V)) == (@inferred gens(V))
dim(V) >= 1 && @test (@inferred basis(V, 1)) == (@inferred gen(V, 1))
@test all(i -> basis(V, i) == gen(V, i), 1:dim(V))

@test dim(V) == length(basis(V))
@test all(i -> basis(V, i) == basis(V)[i], 1:dim(V))

@test iszero(zero(V))
z = @inferred zero(V)
@test @inferred iszero(z)

@test coefficients(v) == [coeff(v, i) for i in 1:dim(V)]
@test (@inferred coefficients(v)) == [@inferred coeff(v, i) for i in 1:dim(V)]
@test all(i -> coeff(v, i) == v[i], 1:dim(V))
@test sum(v[i] * basis(V, i) for i in 1:dim(V); init=zero(V)) == v

Expand All @@ -236,11 +240,11 @@ if !isdefined(Main, :lie_algebra_module_conformance_test) || isinteractive()

for _ in 1:num_random_tests
coeffs = rand(-10:10, dim(V))
v1 = V(coeffs)
v2 = V(coefficient_ring(V).(coeffs))
v3 = V(matrix(coefficient_ring(V), 1, dim(V), coeffs))
v4 = V(sparse_row(matrix(coefficient_ring(V), 1, dim(V), coeffs)))
v5 = V(v1)
v1 = @inferred V(coeffs)
v2 = @inferred V(coefficient_ring(V).(coeffs))
v3 = @inferred V(matrix(coefficient_ring(V), 1, dim(V), coeffs))
v4 = @inferred V(sparse_row(matrix(coefficient_ring(V), 1, dim(V), coeffs)))
v5 = @inferred V(v1)
@test v1 == v2
@test v1 == v3
@test v1 == v4
Expand Down
4 changes: 3 additions & 1 deletion test/Serialization/setup_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ using JSONSchema, Oscar.JSON

# we only need to define this once

if !isdefined(Main, :test_save_load_roundtrip) || isinteractive()
if !isdefined(Main, :mrdi_schema)
mrdi_schema = Schema(JSON.parsefile(joinpath(Oscar.oscardir, "data", "schema.json")))
end

if !isdefined(Main, :test_save_load_roundtrip) || isinteractive()
function test_save_load_roundtrip(func, path, original::T;
params=nothing, check_func=nothing, kw...) where {T}
# save and load from a file
Expand Down

0 comments on commit 46abff7

Please sign in to comment.