From f68622024bba4c5866f86fe5ac445fb230b0d1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Thu, 26 Sep 2024 23:15:57 +0200 Subject: [PATCH] LieAlgebras: more optimizations regarding type stability (#4145) * Add second type param to `LieAlgebraModule` * Make more tests `@inferred` * Reduce test output spam * Another type annotation fix --- .../LieAlgebras/src/LieAlgebraModule.jl | 22 +++--- .../LieAlgebras/src/LieAlgebraModuleHom.jl | 4 +- experimental/LieAlgebras/src/Types.jl | 13 ++-- experimental/LieAlgebras/test/setup_tests.jl | 68 ++++++++++--------- test/Serialization/setup_tests.jl | 4 +- 5 files changed, 61 insertions(+), 50 deletions(-) diff --git a/experimental/LieAlgebras/src/LieAlgebraModule.jl b/experimental/LieAlgebras/src/LieAlgebraModule.jl index 69f3d934a98a..d1aba5521814 100644 --- a/experimental/LieAlgebras/src/LieAlgebraModule.jl +++ b/experimental/LieAlgebras/src/LieAlgebraModule.jl @@ -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 @@ -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) @@ -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 @@ -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) @@ -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 @@ -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) @@ -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 @@ -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) diff --git a/experimental/LieAlgebras/src/LieAlgebraModuleHom.jl b/experimental/LieAlgebras/src/LieAlgebraModuleHom.jl index 5ad15bf73ebf..3cd180ed9699 100644 --- a/experimental/LieAlgebras/src/LieAlgebraModuleHom.jl +++ b/experimental/LieAlgebras/src/LieAlgebraModuleHom.jl @@ -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)) ``` @@ -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) diff --git a/experimental/LieAlgebras/src/Types.jl b/experimental/LieAlgebras/src/Types.jl index 073a2c080081..3273a0bf4fa8 100644 --- a/experimental/LieAlgebras/src/Types.jl +++ b/experimental/LieAlgebras/src/Types.jl @@ -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 @@ -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} @@ -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) @@ -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 diff --git a/experimental/LieAlgebras/test/setup_tests.jl b/experimental/LieAlgebras/test/setup_tests.jl index 614a080af9e3..80dc1590266c 100644 --- a/experimental/LieAlgebras/test/setup_tests.jl +++ b/experimental/LieAlgebras/test/setup_tests.jl @@ -16,19 +16,20 @@ 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)) @@ -36,9 +37,10 @@ if !isdefined(Main, :lie_algebra_conformance_test) || isinteractive() @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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/test/Serialization/setup_tests.jl b/test/Serialization/setup_tests.jl index c519448dcafd..196803c5c95f 100644 --- a/test/Serialization/setup_tests.jl +++ b/test/Serialization/setup_tests.jl @@ -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