diff --git a/src/DeformationBases/ArcDiagDeformBasis.jl b/src/DeformationBases/ArcDiagDeformBasis.jl index 9990e85..7d0b5c5 100644 --- a/src/DeformationBases/ArcDiagDeformBasis.jl +++ b/src/DeformationBases/ArcDiagDeformBasis.jl @@ -1,3 +1,6 @@ +const SO = Val{:special_orthogonal} +const GL = Val{:general_linear} + """ Concrete subtype of [`DeformBasis`](@ref). Each element of the basis is induced by an arc diagram of a suitable size, @@ -15,7 +18,17 @@ struct ArcDiagDeformBasis{C <: RingElem} <: DeformBasis{C} degs::AbstractVector{Int}; no_normalize::Bool=false, ) where {C <: RingElem} - @req get_attribute(base_lie_algebra(sp), :type, nothing) == :special_orthogonal "Only works for so_n." + T = get_attribute(base_lie_algebra(sp), :type, nothing) + @req T in [:special_orthogonal, :general_linear] "Only works for so_n and gl_n." + return ArcDiagDeformBasis{C}(Val(T), sp, degs; no_normalize) + end + + function ArcDiagDeformBasis{C}( + T::Union{SO, GL}, + sp::SmashProductLie{C}, + degs::AbstractVector{Int}; + no_normalize::Bool=false, + ) where {C <: RingElem} V = base_module(sp) V_nice, h = isomorphic_module_with_simple_structure(V) @@ -48,12 +61,12 @@ struct ArcDiagDeformBasis{C <: RingElem} <: DeformBasis{C} tensor_product(V_nice_summand_i_l, V_nice_summand_i_r) end - diag_iter = pbw_arc_diagrams__so(W, d) + diag_iter = pbw_arc_diagrams(T, W, d) len = length(diag_iter) iter = ( begin @vprintln :PBWDeformations 2 "Basis generation deg $(lpad(d, maximum(ndigits, degs))), $(lpad(floor(Int, 100*(debug_counter = (debug_counter % len) + 1) / len), 3))%, $(lpad(debug_counter, ndigits(len)))/$(len)" - _basis_elem = arcdiag_to_deformationmap__so(diag, sp, W) + _basis_elem = arcdiag_to_deformationmap(T, diag, sp, W) basis_elem = matrix(proj_to_summand_l) * _basis_elem * transpose(matrix(proj_to_summand_r)) if i_l != i_r basis_elem -= transpose(basis_elem) @@ -98,57 +111,161 @@ end Base.length(basis::ArcDiagDeformBasis) = basis.len -function pbw_arc_diagrams__so(V::LieAlgebraModule, d::Int) - n_upper_vertices = arc_diagram_num_points__so(V) - n_lower_vertices = 2d - upper_indep_sets = arc_diagram_indep_sets__so(V) - lower_indep_sets = Vector{Int}[[[2i - 1, 2i] for i in 1:div(n_lower_vertices, 2)]...] - indep_sets = Vector{Int}[[(-1) .* is for is in upper_indep_sets]; [is for is in lower_indep_sets]] - return all_arc_diagrams(Undirected, n_upper_vertices, n_lower_vertices; indep_sets) +function pbw_arc_diagrams(T::Union{SO, GL}, V::LieAlgebraModule, d::Int) + upper_verts = arc_diagram_upper_points(T, V) + lower_verts = arc_diagram_lower_points(T, V, d) + upper_iss = arc_diagram_upper_iss(T, V) + lower_iss = arc_diagram_lower_iss(T, V, d) + indep_sets = Vector{Int}[[(-1) .* is for is in upper_iss]; [is for is in lower_iss]] + return all_arc_diagrams(arc_diagram_type(T), upper_verts, lower_verts; indep_sets) end -function arc_diagram_num_points__so(V::LieAlgebraModule) + +arc_diagram_type(::SO) = Undirected + +arc_diagram_type(::GL) = Directed + + +function is_tensor_generator(::SO, V::LieAlgebraModule) + return is_standard_module(V) +end + +function is_tensor_generator(::GL, V::LieAlgebraModule) + return is_standard_module(V) || (is_dual(V) && is_standard_module(base_module(V))) +end + + +function arc_diagram_upper_points(T::SO, V::LieAlgebraModule) if is_standard_module(V) return 1 elseif is_tensor_product(V) - return sum(arc_diagram_num_points__so(W) for W in base_modules(V)) + return sum(arc_diagram_upper_points(T, W) for W in base_modules(V)) elseif is_exterior_power(V) || is_symmetric_power(V) || is_tensor_power(V) - return arc_diagram_num_points__so(base_module(V)) * get_attribute(V, :power) + return arc_diagram_upper_points(T, base_module(V)) * get_attribute(V, :power) else error("Not implemented.") end end -function arc_diagram_indep_sets__so(V::LieAlgebraModule) +function arc_diagram_upper_points(T::GL, V::LieAlgebraModule) if is_standard_module(V) + return 1 + elseif is_dual(V) && is_standard_module(base_module(V)) + return 0 + elseif is_tensor_product(V) + return reduce(vcat, arc_diagram_upper_points(T, W) for W in base_modules(V)) + elseif is_exterior_power(V) || is_symmetric_power(V) || is_tensor_power(V) + return reduce(vcat, [arc_diagram_upper_points(T, base_module(V)) for _ in 1:get_attribute(V, :power)]) + else + error("Not implemented.") + end +end + +function arc_diagram_num_upper_points(T::SO, V::LieAlgebraModule) + return arc_diagram_upper_points(T, V) +end + +function arc_diagram_num_upper_points(T::GL, V::LieAlgebraModule) + return length(arc_diagram_upper_points(T, V)) +end + + +function arc_diagram_upper_iss(T::Union{SO, GL}, V::LieAlgebraModule) + if is_tensor_generator(T, V) return Vector{Int}[] elseif is_tensor_product(V) - return Vector{Int}[] # TODO: proper implementation + inner_mods = base_modules(V) + offset = 0 + iss = Vector{Int}[] + for mod in inner_mods + append!(iss, [is .+ offset for is in arc_diagram_upper_iss(T, mod)]) + offset += arc_diagram_num_upper_points(T, mod) + end + return iss elseif is_exterior_power(V) || is_symmetric_power(V) || is_tensor_power(V) inner_mod = base_module(V) power = get_attribute(V, :power) - if is_standard_module(inner_mod) + if is_tensor_generator(T, inner_mod) if is_exterior_power(V) - return [1:power] + return [collect(1:power)] else return Vector{Int}[] end else - iss = arc_diagram_indep_sets__so(inner_mod) - return [map(i -> i + k * arc_diagram_num_points__so(inner_mod), is) for k in 0:power-1 for is in iss] + iss = arc_diagram_upper_iss(T, inner_mod) + return [is .+ k * arc_diagram_num_upper_points(T, inner_mod) for k in 0:power-1 for is in iss] end else error("Not implemented.") end end -function arc_diagram_label_iterator__so(V::LieAlgebraModule, base_labels::AbstractVector{Int}) - if is_standard_module(V) + +function arc_diagram_lower_points(::SO, _::LieAlgebraModule, d::Int) + # L ≅ Sᵈ ⋀² V + return 2d +end + +function arc_diagram_lower_points(::GL, _::LieAlgebraModule, d::Int) + # L ≅ Sᵈ (V ⊗ V*) + return reduce(vcat, ([1, 0] for _ in 1:d); init=Int[]) +end + +function arc_diagram_num_lower_points(T::SO, V::LieAlgebraModule, d::Int) + return arc_diagram_lower_points(T, V, d) +end + +function arc_diagram_num_lower_points(T::GL, V::LieAlgebraModule, d::Int) + return length(arc_diagram_lower_points(T, V, d)) +end + + +function arc_diagram_lower_iss(::SO, _::LieAlgebraModule, d::Int) + # L ≅ Sᵈ ⋀² V + return collect([2i - 1, 2i] for i in 1:d) +end + +function arc_diagram_lower_iss(::GL, _::LieAlgebraModule, _::Int) + # L ≅ Sᵈ (V ⊗ V*) + return Vector{Int}[] +end + +function arc_diagram_lower_pair_to_L(::SO, dim_stdmod_V::Int) + # L ≅ Sᵈ ⋀² V + iso_pair_to_L = Dict{Tuple{Int, Int}, Int}() + for (i, bs) in enumerate(combinations(dim_stdmod_V, 2) .|> NTuple{2}) + iso_pair_to_L[bs] = i + end + return function (k1::Int, k2::Int) + if k1 == k2 + return 0, 0 + elseif k1 < k2 + return iso_pair_to_L[(k1, k2)], 1 + else + return iso_pair_to_L[(k2, k1)], -1 + end + end +end + +function arc_diagram_lower_pair_to_L(::GL, dim_stdmod_V::Int) + # L ≅ Sᵈ (V ⊗ V*) + iso_pair_to_L = Dict{Tuple{Int, Int}, Int}() + for (i, bs) in enumerate(ProductIterator(1:dim_stdmod_V, 2) .|> reverse .|> NTuple{2}) + iso_pair_to_L[bs] = i + end + return function (k1::Int, k2::Int) + return iso_pair_to_L[(k1, k2)], 1 + end + return iso_pair_to_L +end + +function arc_diagram_label_iterator(T::Union{SO, GL}, V::LieAlgebraModule, base_labels::AbstractVector{Int}) + if is_tensor_generator(T, V) return [[l] for l in base_labels] elseif is_tensor_product(V) inner_mods = base_modules(V) return ProductIterator([ - arc_diagram_label_iterator__so(inner_mod, base_labels) for inner_mod in reverse(inner_mods) + arc_diagram_label_iterator(T, inner_mod, base_labels) for inner_mod in reverse(inner_mods) ]) .|> reverse .|> Iterators.flatten .|> @@ -156,19 +273,19 @@ function arc_diagram_label_iterator__so(V::LieAlgebraModule, base_labels::Abstra elseif is_exterior_power(V) inner_mod = base_module(V) power = get_attribute(V, :power) - return combinations(collect(arc_diagram_label_iterator__so(inner_mod, base_labels)), power) .|> + return combinations(collect(arc_diagram_label_iterator(T, inner_mod, base_labels)), power) .|> Iterators.flatten .|> collect elseif is_symmetric_power(V) inner_mod = base_module(V) power = get_attribute(V, :power) - return multicombinations(collect(arc_diagram_label_iterator__so(inner_mod, base_labels)), power) .|> + return multicombinations(collect(arc_diagram_label_iterator(T, inner_mod, base_labels)), power) .|> Iterators.flatten .|> collect elseif is_tensor_power(V) inner_mod = base_module(V) power = get_attribute(V, :power) - return ProductIterator(arc_diagram_label_iterator__so(inner_mod, base_labels), power) .|> + return ProductIterator(arc_diagram_label_iterator(T, inner_mod, base_labels), power) .|> reverse .|> Iterators.flatten .|> collect @@ -177,6 +294,7 @@ function arc_diagram_label_iterator__so(V::LieAlgebraModule, base_labels::Abstra end end + function basis_index_mapping(V::LieAlgebraModule) if is_tensor_product(V) inner_mods = base_modules(V) @@ -198,23 +316,25 @@ function basis_index_mapping(V::LieAlgebraModule) end end -function arc_diagram_label_permutations__so(V::LieAlgebraModule, label::AbstractVector{Int}) - if is_standard_module(V) + +function arc_diagram_label_permutations(T::Union{SO, GL}, V::LieAlgebraModule, label::AbstractVector{Int}) + if is_tensor_generator(T, V) @req length(label) == 1 "Number of labels mismatch." return [(label, 1)] elseif is_tensor_product(V) inner_mods = base_modules(V) - @req length(label) == sum(arc_diagram_num_points__so.(inner_mods)) "Number of labels mismatch." + @req length(label) == sum(mod -> arc_diagram_num_upper_points(T, mod), inner_mods) "Number of labels mismatch." return [ begin - inner_label = vcat(first.(inner_iter)...) + inner_label = reduce(vcat, first.(inner_iter)) inner_sign = prod(last.(inner_iter)) (inner_label, inner_sign) end for inner_iter in ProductIterator([ - arc_diagram_label_permutations__so( + arc_diagram_label_permutations( + T, inner_mod, - label[sum(arc_diagram_num_points__so, inner_mods[1:i-1]; init=0)+1:sum( - arc_diagram_num_points__so, + label[sum(mod -> arc_diagram_num_upper_points(T, mod), inner_mods[1:i-1]; init=0)+1:sum( + mod -> arc_diagram_num_upper_points(T, mod), inner_mods[1:i]; init=0, )], @@ -224,38 +344,38 @@ function arc_diagram_label_permutations__so(V::LieAlgebraModule, label::Abstract elseif is_exterior_power(V) || is_symmetric_power(V) || is_tensor_power(V) inner_mod = base_module(V) power = get_attribute(V, :power) - m = arc_diagram_num_points__so(inner_mod) + m = arc_diagram_num_upper_points(T, inner_mod) @req length(label) == m * power "Number of labels mismatch." if is_exterior_power(V) return [ begin - inner_label = vcat(first.(inner_iter)...) + inner_label = reduce(vcat, first.(inner_iter)) inner_sign = prod(last.(inner_iter)) (inner_label, inner_sign * outer_sign) end for (outer_perm, outer_sign) in permutations_with_sign(1:power) for inner_iter in ProductIterator([ - arc_diagram_label_permutations__so(inner_mod, label[(outer_perm[i]-1)*m+1:outer_perm[i]*m]) for + arc_diagram_label_permutations(T, inner_mod, label[(outer_perm[i]-1)*m+1:outer_perm[i]*m]) for i in 1:power ]) ] elseif is_symmetric_power(V) return [ begin - inner_label = vcat(first.(inner_iter)...) + inner_label = reduce(vcat, first.(inner_iter)) inner_sign = prod(last.(inner_iter)) (inner_label, inner_sign) end for outer_perm in permutations(1:power) for inner_iter in ProductIterator([ - arc_diagram_label_permutations__so(inner_mod, label[(outer_perm[i]-1)*m+1:outer_perm[i]*m]) for + arc_diagram_label_permutations(T, inner_mod, label[(outer_perm[i]-1)*m+1:outer_perm[i]*m]) for i in 1:power ]) ] elseif is_tensor_power(V) return [ begin - inner_label = vcat(first.(inner_iter)...) + inner_label = reduce(vcat, first.(inner_iter)) inner_sign = prod(last.(inner_iter)) (inner_label, inner_sign) end for inner_iter in - ProductIterator([arc_diagram_label_permutations__so(inner_mod, label[(i-1)*m+1:i*m]) for i in 1:power]) + ProductIterator([arc_diagram_label_permutations(T, inner_mod, label[(i-1)*m+1:i*m]) for i in 1:power]) ] else error("Unreachable.") @@ -266,21 +386,29 @@ function arc_diagram_label_permutations__so(V::LieAlgebraModule, label::Abstract end -function arcdiag_to_deformationmap__so( - diag::ArcDiagramUndirected, +function arcdiag_is_lower_pair_label_bad(::SO, labeled_diag::Vector{Int}, k::Int) + left_k = k % 2 == 1 ? k : k - 1 + return labeled_diag[left_k] == labeled_diag[left_k+1] +end + +function arcdiag_is_lower_pair_label_bad(::GL, labeled_diag::Vector{Int}, k::Int) + return false +end + + +function arcdiag_to_deformationmap( + T::Union{SO, GL}, + diag::ArcDiagram, sp::SmashProductLie{C}, W::LieAlgebraModule=exterior_power(base_module(sp), 2), ) where {C <: RingElem} @req !is_direct_sum(W) "Not permitted for direct sums." ind_map = basis_index_mapping(W) - # TODO: allow for genereal ArcDiagrams dim_stdmod_V = base_lie_algebra(sp).n - iso_wedge2V_to_L = Dict{Vector{Int}, Int}() - for (i, bs) in enumerate(combinations(dim_stdmod_V, 2)) - iso_wedge2V_to_L[bs] = i - end + iso_pair_to_L = arc_diagram_lower_pair_to_L(T, dim_stdmod_V) + if is_exterior_power(W) nrows_kappa = ncols_kappa = dim(base_module(W)) @@ -289,16 +417,17 @@ function arcdiag_to_deformationmap__so( end kappa = zero_matrix(underlying_algebra(sp), nrows_kappa, ncols_kappa) - for (label_index, upper_labels) in enumerate(arc_diagram_label_iterator__so(W, 1:dim_stdmod_V)) + for (label_index, upper_labels) in enumerate(arc_diagram_label_iterator(T, W, 1:dim_stdmod_V)) i, j = ind_map[label_index] - entry = arcdiag_to_deformationmap_entry__so( + entry = arcdiag_to_deformationmap_entry( + T, diag, W, upper_labels, underlying_algebra(sp), - iso_wedge2V_to_L, + iso_pair_to_L, dim_stdmod_V, ) @@ -312,17 +441,39 @@ function arcdiag_to_deformationmap__so( return kappa end -function arcdiag_to_deformationmap_entry__so( + +function arcdiag_to_deformationmap_entry( + T::GL, + diag::ArcDiagramDirected, + W::LieAlgebraModule{C}, + upper_labels::AbstractVector{Int}, + sp_alg::FreeAssAlgebra{C}, + iso_pair_to_L::Function, + max_label::Int, +) where {C <: RingElem} + return arcdiag_to_deformationmap_entry( + T, + arc_diagram(Undirected, diag), + W, + upper_labels, + sp_alg, + iso_pair_to_L, + max_label, + ) +end + +function arcdiag_to_deformationmap_entry( + T::Union{SO, GL}, diag::ArcDiagramUndirected, W::LieAlgebraModule{C}, upper_labels::AbstractVector{Int}, sp_alg::FreeAssAlgebra{C}, - iso_pair_to_L::Dict{Vector{Int}, Int}, + iso_pair_to_L::Function, max_label::Int, ) where {C <: RingElem} entry = zero(sp_alg) - for (upper_labels, sgn_upper_labels) in arc_diagram_label_permutations__so(W, upper_labels) + for (upper_labels, sgn_upper_labels) in arc_diagram_label_permutations(T, W, upper_labels) zeroprod = false lower_labels = [0 for _ in 1:n_lower_vertices(diag)] frees = Int[] @@ -352,26 +503,22 @@ function arcdiag_to_deformationmap_entry__so( while true if nextindex > length(frees) # begin inner - zeroelem = false - sign_lower_labels = 1 + coeff_lower_labels = 1 basiselem = Int[] for k in 1:2:length(lower_labels) - if lower_labels[k] == lower_labels[k+1] - zeroelem = true + gen_ind, coeff = iso_pair_to_L(lower_labels[k], lower_labels[k+1]) + coeff_lower_labels *= coeff + if iszero(coeff_lower_labels) break - elseif lower_labels[k] > lower_labels[k+1] - sign_lower_labels *= -1 - append!(basiselem, iso_pair_to_L[[lower_labels[k+1], lower_labels[k]]]) - else - append!(basiselem, iso_pair_to_L[[lower_labels[k], lower_labels[k+1]]]) end + append!(basiselem, gen_ind) end - if !zeroelem + if !iszero(coeff_lower_labels) symm_basiselem = sp_alg( fill(C(1 // factorial(length(basiselem))), factorial(length(basiselem))), [ind for ind in permutations(basiselem)], ) - entry_summand += sign_lower_labels * symm_basiselem # TODO: benchmark removal of normal_form + entry_summand += coeff_lower_labels * symm_basiselem end # end inner @@ -388,18 +535,19 @@ function arcdiag_to_deformationmap_entry__so( end lower_labels[frees[nextindex]] += 1 lower_labels[vertex_index(_neighbor_of_lower_vertex(diag, frees[nextindex]))] += 1 - if ispairgood(lower_labels, frees[nextindex]) && - ispairgood(lower_labels, vertex_index(_neighbor_of_lower_vertex(diag, frees[nextindex]))) - nextindex += 1 + + if arcdiag_is_lower_pair_label_bad(T, lower_labels, frees[nextindex]) || arcdiag_is_lower_pair_label_bad( + T, + lower_labels, + vertex_index(_neighbor_of_lower_vertex(diag, frees[nextindex])), + ) + continue end + + nextindex += 1 end entry += sgn_upper_labels * entry_summand end return entry end - -function ispairgood(labeled_diag::Vector{Int}, k::Int) - left_k = k % 2 == 1 ? k : k - 1 - return labeled_diag[left_k] != labeled_diag[left_k+1] -end diff --git a/src/DeformationBases/PseudographDeformBasis.jl b/src/DeformationBases/PseudographDeformBasis.jl index 8389b6f..44260b9 100644 --- a/src/DeformationBases/PseudographDeformBasis.jl +++ b/src/DeformationBases/PseudographDeformBasis.jl @@ -16,7 +16,17 @@ struct PseudographDeformBasis{C <: RingElem} <: DeformBasis{C} degs::AbstractVector{Int}; no_normalize::Bool=false, ) where {C <: RingElem} - @req get_attribute(base_lie_algebra(sp), :type, nothing) == :special_orthogonal "Only works for so_n." + T = get_attribute(base_lie_algebra(sp), :type, nothing) + @req T == :special_orthogonal "Only works for so_n." + return PseudographDeformBasis{C}(Val(T), sp, degs; no_normalize) + end + + function PseudographDeformBasis{C}( + T::Union{Val{:special_orthogonal}}, + sp::SmashProductLie{C}, + degs::AbstractVector{Int}; + no_normalize::Bool=false, + ) where {C <: RingElem} @req is_exterior_power(base_module(sp)) && is_standard_module(base_module(base_module(sp))) "Only works for exterior powers of the standard module." e = get_attribute(base_module(sp), :power) @@ -34,7 +44,7 @@ struct PseudographDeformBasis{C <: RingElem} <: DeformBasis{C} begin @vprintln :PBWDeformations 2 "Basis generation deg $(lpad(d, maximum(ndigits, degs))), $(lpad(floor(Int, 100*(debug_counter = (debug_counter % len) + 1) / len), 3))%, $(lpad(debug_counter, ndigits(len)))/$(len)" diag = to_arcdiag(pg, part) - basis_elem = arcdiag_to_deformationmap__so(diag, sp) + basis_elem = arcdiag_to_deformationmap(T, diag, sp) if !no_normalize basis_elem = normalize(basis_elem) end diff --git a/src/SmashProductLie.jl b/src/SmashProductLie.jl index f08e721..a0a9ebd 100644 --- a/src/SmashProductLie.jl +++ b/src/SmashProductLie.jl @@ -3,7 +3,7 @@ The struct representing a Lie algebra smash product. It consists of the underlying FreeAssAlgebra with relations and some metadata. It gets created by calling [`smash_product`](@ref). """ -@attributes mutable struct SmashProductLie{C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} <: NCRing +@attributes mutable struct SmashProductLie{C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} <: NCRing coeff_ring::Ring L::LieAlgebra{LieC} V::LieAlgebraModule{LieC} @@ -17,12 +17,12 @@ It gets created by calling [`smash_product`](@ref). V::LieAlgebraModule{LieC}, alg::FreeAssAlgebra{C}, rels::Matrix{Union{Nothing, FreeAssAlgElem{C}}}, - ) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} + ) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} new{C, LieC, LieT}(coeff_ring, L, V, alg, rels) end end -mutable struct SmashProductLieElem{C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} <: NCRingElem +mutable struct SmashProductLieElem{C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} <: NCRingElem p::SmashProductLie{C, LieC, LieT} # parent alg_elem::FreeAssAlgElem{C} simplified::Bool @@ -31,7 +31,7 @@ mutable struct SmashProductLieElem{C <: RingElem, LieC <: RingElem, LieT <: LieA p::SmashProductLie{C, LieC, LieT}, alg_elem::FreeAssAlgElem{C}; simplified::Bool=false, - ) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} + ) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} @req underlying_algebra(p) === parent(alg_elem) "Incompatible algebras." return new{C, LieC, LieT}(p, alg_elem, simplified) end @@ -45,25 +45,25 @@ end parent_type( ::Type{SmashProductLieElem{C, LieC, LieT}}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLie{C, LieC, LieT} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLie{C, LieC, LieT} elem_type( ::Type{SmashProductLie{C, LieC, LieT}}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLieElem{C, LieC, LieT} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLieElem{C, LieC, LieT} parent(e::SmashProductLieElem) = e.p coefficient_ring( Sp::SmashProductLie{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = Sp.coeff_ring::parent_type(C) +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = Sp.coeff_ring::parent_type(C) coefficient_ring(e::SmashProductLieElem) = coefficient_ring(parent(e)) base_lie_algebra( Sp::SmashProductLie{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = Sp.L::parent_type(LieT) +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = Sp.L::parent_type(LieT) -base_module(Sp::SmashProductLie{C, LieC, LieT}) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = +base_module(Sp::SmashProductLie{C, LieC, LieT}) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = Sp.V::LieAlgebraModule{LieC} underlying_algebra(Sp::SmashProductLie) = Sp.alg @@ -114,7 +114,7 @@ end function check_parent( e1::SmashProductLieElem{C, LieC, LieT}, e2::SmashProductLieElem{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} parent(e1) != parent(e2) && error("Incompatible smash products.") end @@ -124,7 +124,7 @@ end # ############################################################################### -function show(io::IO, Sp::SmashProductLie{C, LieC}) where {C <: RingElem, LieC <: RingElem} +function show(io::IO, Sp::SmashProductLie{C, LieC}) where {C <: RingElem, LieC <: FieldElem} print(io, "Smash Product") if LieC != C print(io, " over ") @@ -165,11 +165,25 @@ end function (Sp::SmashProductLie{C, LieC, LieT})( e::SmashProductLieElem{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} @req parent(e) == Sp "Incompatible smash products." return e end +function (Sp::SmashProductLie{C, LieC, LieT})( + x::LieT, +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} + @req parent(x) == base_lie_algebra(Sp) "Incompatible smash products." + return sum(c * b for (c, b) in zip(coefficients(x), gens(Sp, :L))) +end + +function (Sp::SmashProductLie{C, LieC, LieT})( + v::LieAlgebraModuleElem{LieC}, +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} + @req parent(v) == base_module(Sp) "Incompatible smash products." + return sum(c * b for (c, b) in zip(coefficients(v), gens(Sp, :V))) +end + ############################################################################### # # Arithmetic operations @@ -239,7 +253,7 @@ end function Base.:(==)( e1::SmashProductLieElem{C, LieC, LieT}, e2::SmashProductLieElem{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} return parent(e1) === parent(e2) && simplify(e1).alg_elem == simplify(e2).alg_elem end diff --git a/src/SmashProductLieDeform.jl b/src/SmashProductLieDeform.jl index b10019a..50e80d6 100644 --- a/src/SmashProductLieDeform.jl +++ b/src/SmashProductLieDeform.jl @@ -3,7 +3,7 @@ The struct representing a deformation of a Lie algebra smash product. It consists of the underlying FreeAssAlgebra with relations and some metadata. It gets created by calling [`deform`](@ref). """ -@attributes mutable struct SmashProductLieDeform{C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} <: +@attributes mutable struct SmashProductLieDeform{C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} <: NCRing sp::SmashProductLie{C, LieC, LieT} rels::Matrix{Union{Nothing, FreeAssAlgElem{C}}} @@ -14,12 +14,12 @@ It gets created by calling [`deform`](@ref). sp::SmashProductLie{C, LieC, LieT}, rels::Matrix{Union{Nothing, FreeAssAlgElem{C}}}, kappa::DeformationMap{C}, - ) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} + ) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} new{C, LieC, LieT}(sp, rels, kappa) end end -mutable struct SmashProductLieDeformElem{C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} <: NCRingElem +mutable struct SmashProductLieDeformElem{C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} <: NCRingElem p::SmashProductLieDeform{C, LieC, LieT} # parent alg_elem::FreeAssAlgElem{C} simplified::Bool @@ -28,7 +28,7 @@ mutable struct SmashProductLieDeformElem{C <: RingElem, LieC <: RingElem, LieT < p::SmashProductLieDeform{C, LieC, LieT}, alg_elem::FreeAssAlgElem{C}; simplified::Bool=false, - ) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} + ) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} @req underlying_algebra(p) === parent(alg_elem) "Incompatible algebras." return new{C, LieC, LieT}(p, alg_elem, simplified) end @@ -42,27 +42,27 @@ end arent_type( ::Type{SmashProductLieDeformElem{C, LieC, LieT}}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLieDeform{C, LieC, LieT} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLieDeform{C, LieC, LieT} elem_type( ::Type{SmashProductLieDeform{C, LieC, LieT}}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLieDeformElem{C, LieC, LieT} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = SmashProductLieDeformElem{C, LieC, LieT} parent(e::SmashProductLieDeformElem) = e.p coefficient_ring( D::SmashProductLieDeform{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = coefficient_ring(D.sp)::parent_type(C) +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = coefficient_ring(D.sp)::parent_type(C) coefficient_ring(e::SmashProductLieDeformElem) = coefficient_ring(parent(e)) base_lie_algebra( D::SmashProductLieDeform{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = base_lie_algebra(D.sp)::parent_type(LieT) +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = base_lie_algebra(D.sp)::parent_type(LieT) base_module( D::SmashProductLieDeform{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} = base_module(D.sp)::LieAlgebraModule{LieC} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} = base_module(D.sp)::LieAlgebraModule{LieC} underlying_algebra(D::SmashProductLieDeform) = underlying_algebra(D.sp) # TODO: create new algebra for D @@ -111,7 +111,7 @@ end function check_parent( e1::SmashProductLieDeformElem{C, LieC, LieT}, e2::SmashProductLieDeformElem{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} parent(e1) != parent(e2) && error("Incompatible smash product deformations.") end @@ -159,18 +159,32 @@ end function (D::SmashProductLieDeform{C, LieC, LieT})( e::SmashProductLieDeformElem{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} @req parent(e) == D "Incompatible smash product deformations." return e end function (D::SmashProductLieDeform{C, LieC, LieT})( e::SmashProductLieElem{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} @req parent(e) == D.sp "Incompatible smash products." return D(e.alg_elem) end +function (D::SmashProductLieDeform{C, LieC, LieT})( + x::LieT, +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} + @req parent(x) == base_lie_algebra(D) "Incompatible smash products." + return sum(c * b for (c, b) in zip(coefficients(x), gens(D, :L))) +end + +function (D::SmashProductLieDeform{C, LieC, LieT})( + v::LieAlgebraModuleElem{LieC}, +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} + @req parent(v) == base_module(D) "Incompatible smash products." + return sum(c * b for (c, b) in zip(coefficients(v), gens(D, :V))) +end + ############################################################################### # # Arithmetic operations @@ -240,7 +254,7 @@ end function Base.:(==)( e1::SmashProductLieDeformElem{C, LieC, LieT}, e2::SmashProductLieDeformElem{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} return parent(e1) === parent(e2) && simplify(e1).alg_elem == simplify(e2).alg_elem end @@ -281,7 +295,7 @@ Returns a [`SmashProductLieDeform`](@ref) struct and a two-part basis. function deform( sp::SmashProductLie{C, LieC, LieT}, kappa::DeformationMap{C}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} dimL = dim(base_lie_algebra(sp)) dimV = dim(base_module(sp)) @@ -311,6 +325,14 @@ function deform( return d end +function deform( + sp::SmashProductLie{C, LieC, LieT}, + kappa::MatElem{SmashProductLieElem{C, LieC, LieT}}, +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} + @req all(x -> parent(x) == sp, kappa) "Incompatible smash products." + return deform(sp, map_entries(x -> x.alg_elem, kappa)) +end + """ symmetric_deformation(sp::SmashProductLie{C}) where {C <: RingElem} @@ -318,7 +340,7 @@ Constructs the symmetric deformation of the smash product `sp`. """ function symmetric_deformation( sp::SmashProductLie{C, LieC, LieT}, -) where {C <: RingElem, LieC <: RingElem, LieT <: LieAlgebraElem{LieC}} +) where {C <: RingElem, LieC <: FieldElem, LieT <: LieAlgebraElem{LieC}} kappa = zero_matrix(underlying_algebra(sp), dim(base_module(sp)), dim(base_module(sp))) d = deform(sp, kappa) return d diff --git a/test/DeformationBases-test.jl b/test/DeformationBases-test.jl index 07ee674..c96ff5d 100644 --- a/test/DeformationBases-test.jl +++ b/test/DeformationBases-test.jl @@ -1,19 +1,20 @@ @testset "DeformationBases/*.jl tests" begin @testset "ArcDiagDeformBasis.jl" begin - @testset "arcdiag_to_deformationmap__so(:exterior)" begin + @testset "arcdiag_to_deformationmap(:special_orthogonal, :exterior)" begin L = special_orthogonal_lie_algebra(QQ, 4) + T = Val(:special_orthogonal) V = exterior_power(standard_module(L), 2) sp = smash_product(L, V) @testset "not all specialisations are zero" begin diag = arc_diagram(Undirected, "ABBD,AD") - dm = PD.arcdiag_to_deformationmap__so(diag, sp) + dm = PD.arcdiag_to_deformationmap(T, diag, sp) @test !iszero(dm) end @testset "deformation is equivariant, d = $deg" for deg in 1:3 - for diag in PD.pbw_arc_diagrams__so(V, deg) - dm = PD.arcdiag_to_deformationmap__so(diag, sp) + for diag in PD.pbw_arc_diagrams(T, V, deg) + dm = PD.arcdiag_to_deformationmap(T, diag, sp) d = deform(sp, dm) @test all(iszero, pbwdeform_eqs(d, disabled=[:b, :c, :d])) end diff --git a/test/runtests.jl b/test/runtests.jl index 326aaae..096c0ae 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,13 +1,15 @@ include("setup.jl") -include("Aqua.jl") - +# short include("ArcDiagram-test.jl") include("DeformationBases-test.jl") include("Pseudograph-test.jl") include("SmashProductLie-test.jl") include("SmashProductLieDeform-test.jl") include("SmashProductPBWDeformLie-test.jl") + +# long +include("Aqua.jl") include("ModuleSimpleStructure-test.jl") if VERSION >= v"1.7-"