Skip to content

Commit 2de9082

Browse files
committed
Add new weight structures and enhance decomposition functions
1 parent 1a5823a commit 2de9082

File tree

12 files changed

+157
-49
lines changed

12 files changed

+157
-49
lines changed

src/DecomposingRepresentations.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ include("representations/irred-reprs.jl")
4040
include("representations/isotypic-comps.jl")
4141
include("representations/reprs.jl")
4242

43+
include("decompositions/abs-weight-struct.jl")
44+
4345
include("decompositions/irred-decomp.jl")
4446
include("decompositions/isotypic-decomp.jl")
4547

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
abstract type AbstractWeightStruct end
2+
3+
struct TensorWeightStruct <: AbstractWeightStruct
4+
w₁::Weight
5+
w₂::Weight
6+
end
7+
8+
Base.hash(s::TensorWeightStruct, h::UInt) = Base.hash((s.w₁, s.w₂), h)
9+
Base.:(==)(s₁::TensorWeightStruct, s₂::TensorWeightStruct) = ((s₁.w₁ == s₂.w₁) && (s₁.w₂ == s₂.w₂)) || ((s₁.w₁ == s₂.w₂) && (s₁.w₂ == s₂.w₁))
10+
11+
struct SymWeightStruct <: AbstractWeightStruct
12+
w::Weight
13+
p::Int
14+
end
15+
16+
Base.hash(s::SymWeightStruct, h::UInt) = Base.hash((s.w, s.p), h)
17+
Base.:(==)(s₁::SymWeightStruct, s₂::SymWeightStruct) = (s₁.w == s₂.w) && (s₁.p == s₂.p)

src/decompositions/irred-decomp.jl

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,19 @@ function common_nullspace_as_weight_vectors(
3333
)
3434
dim(ws) == 1 && return [WeightVector(weight(ws), v) for v in basis(space(ws))]
3535

36-
logging && printstyled("Looking for the highest weight vectors in $(str_irr("W", weight(ws))) of dimension $(dim(ws))...\n", color=:green)
36+
logging && printstyled("Looking for $(nhwv) highest weight vectors in $(str_irr("W", weight(ws))) of dimension $(dim(ws))...\n", color=:green)
3737
wsₙ = ws
3838
for X in Xs
3939
wsₙ = ws_nullspace(X, a, wsₙ)
40-
isnothing(wsₙ) && return WeightVector[]
40+
if isnothing(wsₙ)
41+
logging && printstyled("Found no common nullspace, smth is wrong!\n", color=:red)
42+
return WeightVector[] # error("Didn't find any highest weight vectors, had to find $(nhwv)")
43+
end
4144
end
4245

43-
@assert dim(wsₙ) == nhwv
46+
if dim(wsₙ) != nhwv
47+
error("Found $(dim(wsₙ)) highest weight vectors, expected $(nhwv)")
48+
end
4449
logging && printstyled("Found: ", color=:green)
4550
logging && printstyled("$(join(map(repr, basis(space(wsₙ))), ", "))\n", color=:green)
4651

@@ -70,7 +75,8 @@ end
7075

7176
function irreducibles(
7277
ρ::GroupRepresentation{A, S};
73-
logging::Bool=true
78+
logging::Bool=true,
79+
decomp_count::Union{Dict{AbstractWeightStruct, Int},Nothing}=nothing
7480
) where {A<:AbstractGroupAction{Lie}, S<:VariableSpace}
7581
logging && printstyled("Decomposing the space of variables $(to_string(space(ρ))) into irreducibles...\n", color=:red)
7682

@@ -86,14 +92,19 @@ end
8692

8793
function irreducibles(
8894
ρ::GroupRepresentation{A, S};
89-
logging::Bool=true
95+
logging::Bool=true,
96+
decomp_count::Dict{AbstractWeightStruct, Int}=nothing
9097
) where {T, F, A<:AbstractGroupAction{Lie}, S<:SymmetricPower{T, F, <:HighestWeightModule}}
9198
V = space(ρ)
9299
logging && printstyled("Decomposing $(to_string(V)) into irreducibles...\n", color=:blue)
93100

94101
Vb = base_space(V)
95-
power(V) == 1 && return [IrreducibleRepresentation(action(ρ), Vb)]
96102
ws = weight_structure(Vb)
103+
104+
if !isnothing(decomp_count)
105+
t = SymWeightStruct(highest_weight(Vb), power(V))
106+
decomp_count[t] = get(decomp_count, t, 0) + 1
107+
end
97108

98109
logging && printstyled("Applying Clebsch-Gordan to decompose $(to_string(V)) into irreducibles...\n", color=:blue)
99110
sym_ws, cg_decomp = sym_weight_struct(highest_weight(Vb), algebra(action(ρ)), power(V), ws)
@@ -106,22 +117,24 @@ end
106117

107118
function irreducibles(
108119
ρ::GroupRepresentation{A, T};
109-
logging::Bool=true
120+
logging::Bool=true,
121+
decomp_count::Dict{AbstractWeightStruct, Int}=nothing
110122
) where {A<:AbstractGroupAction{Lie}, T<:SymmetricPower}
111123
V = space(ρ)
112124
logging && printstyled("Decomposing $(to_string(V)) into irreducibles...\n", color=:magenta)
113125

114126
ρ_base = GroupRepresentation(action(ρ), base_space(V))
115-
irreds_base = irreducibles(ρ_base)
127+
irreds_base = irreducibles(ρ_base; decomp_count=decomp_count)
116128
if length(irreds_base) == 1
117129
logging && printstyled("$(to_string(base_space(V))) is already irreducible, decomposing its symmetric power directly...\n", color=:magenta)
118130
V = SymmetricPower(space(first(irreds_base)), power(V))
119131
ρᵢ = GroupRepresentation(action(ρ), V)
120-
return irreducibles(ρᵢ)
132+
return irreducibles(ρᵢ; decomp_count=decomp_count)
121133
end
122134
mexps = multiexponents(degree=power(V), nvars=length(irreds_base))
123135

124136
Vs = [TensorProduct([SymmetricPower(space(irreds_base[idx]), val) for (val, idx) in zip(mexp.nzval, mexp.nzind)]) for mexp in mexps]
137+
@assert dim(V) == sum([dim(Vᵢ) for Vᵢ in Vs])
125138
if logging
126139
printstyled("Sym$(superscript(power(V)))(", color=:magenta)
127140
printstyled(join([to_string(space(irr)) for irr in irreds_base], ""), ") = ", color=:magenta)
@@ -132,22 +145,40 @@ function irreducibles(
132145
irreds = IrreducibleRepresentation{A}[]
133146
for Vᵢ in Vs
134147
ρᵢ = GroupRepresentation(action(ρ), Vᵢ)
135-
append!(irreds, irreducibles(ρᵢ))
148+
append!(irreds, irreducibles(ρᵢ; decomp_count=decomp_count))
136149
end
137150
return irreds
138151
end
139152

140153
function irreducibles(
141154
ρ::GroupRepresentation{A, S};
142-
logging::Bool=true
155+
logging::Bool=true,
156+
decomp_count::Dict{AbstractWeightStruct, Int}=nothing
143157
) where {T, F, A<:AbstractGroupAction{Lie}, S<:TensorProduct{T, F, <:HighestWeightModule, <:HighestWeightModule}}
144-
logging && printstyled("Decomposing $(to_string(V)) into irreducibles...\n", color=:blue)
145158
V = space(ρ)
146-
hw₁, hw₂ = highest_weight(first(V)), highest_weight(second(V))
159+
logging && printstyled("Decomposing $(to_string(V)) into irreducibles...\n", color=:blue)
160+
161+
V₁, V₂ = first(V), second(V)
162+
if dim(V₁) == 1 || dim(V₂) == 1
163+
logging && printstyled("One of the factors is 1-dimensional, returning the tensor product of the highest weight vectors\n", color=:red)
164+
return [IrreducibleRepresentation(action(ρ), hw_vector(V₁)*hw_vector(V₂))]
165+
end
166+
167+
hw₁, hw₂ = highest_weight(V₁), highest_weight(V₂)
168+
if !isnothing(decomp_count)
169+
t = TensorWeightStruct(hw₁, hw₂)
170+
decomp_count[t] = get(decomp_count, t, 0) + 1
171+
end
147172

148173
logging && printstyled("Applying Clebsch-Gordan to decompose $(to_string(V)) into irreducibles...\n", color=:blue)
149-
ws₁, ws₂ = weight_structure(first(V)), weight_structure(second(V)) # TODO: save once computed
150-
tensor_ws, cg_decomp = tensor_weight_struct(hw₁, hw₂, algebra(action(ρ)), ws₁, ws₂)
174+
cg_decomp = tensor(hw₁, hw₂, algebra(action(ρ)))
175+
if length(cg_decomp) == 1
176+
logging && printstyled("The tensor product is irreducible, returning the tensor product of the highest weight vectors\n", color=:red)
177+
return [IrreducibleRepresentation(action(ρ), hw_vector(V₁)*hw_vector(V₂))]
178+
end
179+
180+
ws₁, ws₂ = weight_structure(V₁), weight_structure(V₂) # TODO: speed up, but how?
181+
tensor_ws = tensor_weight_struct(cg_decomp, ws₁, ws₂)
151182
logging && printstyled(to_string(V), " = ", join([str_irr("V", w) for w in weights(tensor_ws)], ""), "\n", color=:blue)
152183

153184
Xs = positive_root_elements(algebra(action(ρ)))
@@ -157,12 +188,17 @@ end
157188

158189
function irreducibles(
159190
ρ::GroupRepresentation{A, S};
160-
logging::Bool=true
191+
logging::Bool=true,
192+
decomp_count::Dict{AbstractWeightStruct, Int}=nothing
161193
) where {A<:AbstractGroupAction{Lie}, S<:TensorProduct}
162194
V = space(ρ)
163195
logging && printstyled("Decomposing $(to_string(V)) into irreducibles...\n", color=:magenta)
164-
irrs₁ = irreducibles(GroupRepresentation(action(ρ), first(space(ρ))))
165-
irrs₂ = irreducibles(GroupRepresentation(action(ρ), second(space(ρ))))
196+
197+
irrs₁ = irreducibles(GroupRepresentation(action(ρ), first(space(ρ))); decomp_count=decomp_count)
198+
@assert sum([dim(space(irr)) for irr in irrs₁]) == dim(first(space(ρ)))
199+
200+
irrs₂ = irreducibles(GroupRepresentation(action(ρ), second(space(ρ))); decomp_count=decomp_count)
201+
@assert sum([dim(space(irr)) for irr in irrs₂]) == dim(second(space(ρ)))
166202

167203
logging && printstyled("Decomposing tensor product knowing irreducibles of the factors...\n", color=:magenta)
168204
logging && printstyled("($(join([to_string(space(irr)) for irr in irrs₁], ""))) ⊗ ", color=:magenta)
@@ -173,7 +209,9 @@ function irreducibles(
173209
for irr₁ in irrs₁, irr₂ in irrs₂
174210
V = TensorProduct([space(irr₁), space(irr₂)])
175211
ρV = GroupRepresentation(action(ρ), V)
176-
append!(irreds, irreducibles(ρV))
212+
irrs = irreducibles(ρV; decomp_count=decomp_count)
213+
@assert sum([dim(space(irr)) for irr in irrs]) == dim(V)
214+
append!(irreds, irrs)
177215
end
178216
return irreds
179217
end
@@ -182,14 +220,16 @@ function irreducibles(
182220
ρ::GroupRepresentation{A, S}
183221
) where {A<:AbstractGroupAction{Lie}, S<:FixedDegreePolynomials}
184222
V = space(ρ)
185-
return irreducibles(GroupRepresentation(action(ρ), SymmetricPower(var_space(V), degree(V))))
223+
d = Dict{AbstractWeightStruct, Int}()
224+
return irreducibles(GroupRepresentation(action(ρ), SymmetricPower(var_space(V), degree(V))); decomp_count=d), d
186225
end
187226

188227
function irreducibles(
189228
ρ::GroupRepresentation{A, S}
190229
) where {A<:AbstractGroupAction{Lie}, S<:FixedMultidegreePolynomials}
191230
V = space(ρ)
192-
return irreducibles(GroupRepresentation(action(ρ), TensorProduct([SymmetricPower(Vᵢ, dᵢ) for (Vᵢ, dᵢ) in zip(var_spaces(V), degrees(V))])))
231+
d = Dict{AbstractWeightStruct, Int}()
232+
return irreducibles(GroupRepresentation(action(ρ), TensorProduct([SymmetricPower(Vᵢ, dᵢ) for (Vᵢ, dᵢ) in zip(var_spaces(V), degrees(V))])); decomp_count=d), d
193233
end
194234

195235

src/decompositions/isotypic-decomp.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export IsotypicDecomposition,
2-
invariant_component
2+
invariant_component,
3+
representation
34

45
struct IsotypicDecomposition{A<:AbstractGroupAction{Lie}, T<:GroupRepresentation{A}, W<:Weight, Ic<:IsotypicComponent}
56
ρ::T
@@ -62,8 +63,8 @@ Base.iterate(ID::IsotypicDecomposition, state) = iterate(isotypic_components(ID)
6263
function Base.show(io::IO, iso::IsotypicDecomposition)
6364
println(io, "IsotypicDecomposition of $(name(group(iso)))-action on $(dim(iso))-dimensional vector space")
6465
println(io, " number of isotypic components: ", nisotypic(iso))
65-
println(io, " multiplicities of irreducibles: ", join([mul(ic) for ic in isotypic_components(iso)], ", "))
66-
print(io, " dimensions of isotypic components: ", join([dim(ic) for ic in isotypic_components(iso)], ", "))
66+
println(io, " maximum multiplicity of irreducibles: ", maximum([mul(ic) for ic in isotypic_components(iso)]))
67+
print(io, " maximum dimension of isotypic components: ", maximum([dim(ic) for ic in isotypic_components(iso)]))
6768
end
6869

6970
invariant_component(

src/lie-groups/lie-algebras/weights/decompose-weights.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export sym_weight_muls_dict
1+
export sym_weight_muls_dict,
22

33
# TODO: works only for so(3)
44
function (hw₁::Weight, hw₂::Weight, ::LieAlgebra)
@@ -32,9 +32,16 @@ end
3232

3333
function tensor(hw₁::Weight, hw₂::Weight, A::AbstractLieAlgebra)
3434
ws = (hw₁, hw₂, A)
35-
return Dict(zip(ws, ones(Int, length(ws)))) # TODO: Each weight has multiplicity 1
35+
ws_muls = Dict(zip(ws, ones(Int, length(ws)))) # TODO: Each weight has multiplicity 1
36+
@assert weyl_dim(ws_muls, A) == weyl_dim(hw₁, A)*weyl_dim(hw₂, A)
37+
return ws_muls
3638
end
3739

40+
weyl_dim(
41+
ws_muls::Dict{W, Int},
42+
A::AbstractLieAlgebra
43+
) where W<:Weight = sum([weyl_dim(w, A)*m for (w, m) in ws_muls])
44+
3845
# TODO: works only for so(3)
3946
hw2all(hw::Weight, ::LieAlgebra) = [Weight([j]) for j in -hw[1]:hw[1]]
4047
hw2all(hw::Weight, ::ScalingLieAlgebra) = [hw]
@@ -114,5 +121,6 @@ function sym(hw::W, A::AbstractLieAlgebra, p::Int) where W<:Weight
114121
sym_hw, ws_dict = sym_weight_muls_dict(hw, A, p)
115122
decomp_hws = Dict{W, Int}() # for the weight key gives its multiplicity
116123
sym!(sym_hw, A, ws_dict, decomp_hws)
124+
@assert weyl_dim(decomp_hws, A) == binomial(weyl_dim(hw, A) + p - 1, p)
117125
return decomp_hws
118126
end

src/lie-groups/lie-algebras/weights/weight-struct.jl

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,17 @@ function tensor_weight_combs_dict(ws₁::Vector{W}, ws₂::Vector{W}) where W<:W
142142
end
143143

144144
function tensor_weight_struct(
145-
hw₁::W,
146-
hw₂::W,
147-
A::AbstractLieAlgebra,
145+
cg_decomp::Dict{W, Int},
148146
ws₁::WeightStructure{T,W},
149147
ws₂::WeightStructure{T,W}
150148
) where {T, W<:Weight}
151-
dir_sum_hws = tensor(hw₁, hw₂, A)
152149
ws_dict = tensor_weight_combs_dict(weights(ws₁), weights(ws₂))
153150
new_ws = WeightStructure{T,W}()
154-
for hw in keys(dir_sum_hws)
151+
for hw in keys(cg_decomp)
155152
combs = ws_dict[hw]
156153
w_sps = [*([weight_space(ws₁, comb[1]; as_space=true), weight_space(ws₂, comb[2]; as_space=true)]) for comb in combs]
157154
total_ws = +(w_sps...)
158155
push!(new_ws, WeightSpace(hw, total_ws))
159156
end
160-
return new_ws, dir_sum_hws
157+
return new_ws
161158
end

src/lie-groups/lie-algebras/weights/weight-vector.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@ end
1717

1818
function Base.show(io::IO, wv::WeightVector)
1919
print(io, "WeightVector with weight $(weight(wv))")
20-
end
20+
end
21+
22+
Base.:*(
23+
wv₁::WeightVector{T, W},
24+
wv₂::WeightVector{T, W}
25+
) where {T<:Polynomial, W<:Weight} = WeightVector(wv₁.weight + wv₂.weight, wv₁.vector * wv₂.vector)

src/representations/irred-reprs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ action(ρ::IrreducibleRepresentation) = ρ.action
1919
hw_vector(ρ::IrreducibleRepresentation) = hw_vector(ρ.hw_module)
2020
space(ρ::IrreducibleRepresentation) = HighestWeightModule(action(ρ), hw_vector(ρ))
2121
highest_weight(ρ::IrreducibleRepresentation) = weight(hw_vector(ρ))
22-
irreducibles(ρ::IrreducibleRepresentation) = [ρ]
22+
irreducibles(ρ::IrreducibleRepresentation; decomp_count=nothing) = [ρ]
2323
isotypic_components(ρ::IrreducibleRepresentation) = [IsotypicComponent(ρ)]
2424

2525
function Base.show(io::IO, ::MIME"text/plain", ρ::IrreducibleRepresentation)

src/representations/isotypic-comps.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export IsotypicComponent,
2-
mul
2+
mul,
3+
hw_vectors
34

45

56
struct IsotypicComponent{
@@ -18,7 +19,7 @@ mul(ρ::IsotypicComponent) = length(ρ.irreds)
1819
space(ρ::IsotypicComponent) = DirectSum([space(ρᵢ) for ρᵢ in irreducibles(ρ)])
1920
basis(ρ::IsotypicComponent) = basis(space(ρ))
2021
dim(ρ::IsotypicComponent) = sum([dim(ρᵢ) for ρᵢ in irreducibles(ρ)])
21-
hw_vectors(ρ::IsotypicComponent) = [hw_vector(ρᵢ) for ρᵢ in irreducibles(ρ)]
22+
hw_vectors(ρ::IsotypicComponent; as_vectors::Bool=false) = [as_vectors ? vector(hw_vector(ρᵢ)) : hw_vector(ρᵢ) for ρᵢ in irreducibles(ρ)]
2223
isotypic_components(ρ::IsotypicComponent) = [ρ]
2324

2425
function Base.show(io::IO, ::MIME"text/plain", ρ::IsotypicComponent)

0 commit comments

Comments
 (0)