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

LieAlgebras: More Lie algebra constructions from/to GAP #2207

Merged
merged 10 commits into from
May 17, 2023
17 changes: 12 additions & 5 deletions experimental/LieAlgebras/src/AbstractLieAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,16 @@ function lie_algebra(
end

function lie_algebra(R::Ring, dynkin::Tuple{Char,Int}; cached::Bool=true)
struct_consts, gapL = lie_algebra_struct_consts_gap(R, dynkin)
L = lie_algebra(R, struct_consts; cached, check=false)
set_attribute!(L, :dynkin => dynkin)
_set_gap_object!(L, gapL)
return L
@req is_valid_dynkin(dynkin...) "Input not allowed by GAP."

coeffs_iso = inv(Oscar.iso_oscar_gap(R))
LG = GAP.Globals.SimpleLieAlgebra(
GAP.Obj(string(dynkin[1])), dynkin[2], domain(coeffs_iso)
)
s = [Symbol("x_$i") for i in 1:GAPWrap.Dimension(LG)]
LO = codomain(
_iso_gap_oscar_abstract_lie_algebra(LG, s; coeffs_iso, cached)
)::AbstractLieAlgebra{elem_type(R)}

return LO
end
60 changes: 8 additions & 52 deletions experimental/LieAlgebras/src/GapWrapper.jl
Original file line number Diff line number Diff line change
@@ -1,66 +1,22 @@
function lie_algebra_struct_consts_gap(R::Ring, dynkin::Tuple{Char,Int})
@req is_valid_dynkin(dynkin...) "Input not allowed by GAP."

isoR = Oscar.iso_oscar_gap(R)
gapL = GAP.Globals.SimpleLieAlgebra(GAP.Obj(string(dynkin[1])), dynkin[2], codomain(isoR))
dimL = GAPWrap.Dimension(gapL)
comm_table_L =
(
entry -> (entry[1], Vector{elem_type(R)}(map(c -> preimage(isoR, c), entry[2])))
).(
Matrix{Tuple{Vector{Int},Vector{GAP.Obj}}}(
(GAP.Globals.StructureConstantsTable(GAPWrap.Basis(gapL)))[1:dimL]
)
)

struct_consts = Matrix{SRow{elem_type(R)}}(undef, dimL, dimL)
for i in 1:dimL, j in 1:dimL
struct_consts[i, j] = sparse_row(
R, Tuple{Int,elem_type(R)}[(k, R(c)) for (k, c) in zip(comm_table_L[i, j]...)]
)
end

return struct_consts, gapL
end

function gap_lie_algebra_by_struct_consts(L::LieAlgebra{C}) where {C<:RingElement}
R = base_ring(L)
isoR = Oscar.iso_oscar_gap(R)

gap_sc_table = [
[
[
begin
pairs = filter(
pair -> !iszero(last(pair)), collect(enumerate(coefficients(xi * xj)))
)
(map(first, pairs), GAP.Obj[isoR(c) for c in map(last, pairs)])
end for xj in basis(L)
] for xi in basis(L)
]
-1
isoR(zero(R))
]

gapL = GAP.Globals.LieAlgebraByStructureConstants(
codomain(isoR), GAP.Obj(gap_sc_table; recursive=true)
)
return gapL
end
################################################################################
#
# Lie algebra modules
#
################################################################################

function lie_algebra_highest_weight_module_struct_consts_gap(
L::LieAlgebra{C}, weight::Vector{Int}
) where {C<:RingElement}
R = base_ring(L)
isoR = Oscar.iso_oscar_gap(R)

gapL = _gap_object(L)
gapL = codomain(Oscar.iso_oscar_gap(L))
dimL = GAPWrap.Dimension(gapL)
@assert dimL == dim(L)
basisL = GAP.Globals.BasisVectors(GAPWrap.Basis(gapL))
basisL = GAPWrap.Basis(gapL)
gapV = GAP.Globals.HighestWeightModule(gapL, GAP.Obj(weight))
dimV = GAPWrap.Dimension(gapV)
basisV = GAP.Globals.BasisVectors(GAPWrap.Basis(gapV))
basisV = GAPWrap.Basis(gapV)

struct_consts = Matrix{SRow{elem_type(R)}}(undef, dimL, dimV)
for i in 1:dimL, j in 1:dimV
Expand Down
61 changes: 14 additions & 47 deletions experimental/LieAlgebras/src/LieAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -193,57 +193,24 @@ function Base.hash(x::LieAlgebraElem{C}, h::UInt) where {C<:RingElement}
return xor(hash(coefficients(x), hash(parent(x), h)), b)
end

###############################################################################
#
# Attribute accessors
#
###############################################################################

function _gap_object(L::LieAlgebra{C}) where {C<:RingElement}
# later change to storing an isomorphism instead
get_attribute!(L, :gap_object) do
gap_lie_algebra_by_struct_consts(L)
end
end

function _set_gap_object!(L::LieAlgebra{C}, gapL::GAP.Obj) where {C<:RingElement}
set_attribute!(L, :gap_object => gapL)
end

###############################################################################
#
# Constructor
#
###############################################################################

function general_linear_lie_algebra(R::Ring, n::Int)
basis = [(b = zero_matrix(R, n, n); b[i, j] = 1; b) for i in 1:n for j in 1:n]
s = ["x_$(i)_$(j)" for i in 1:n for j in 1:n]
L = lie_algebra(R, n, basis, s)
set_attribute!(L, :type => :general_linear)
return L
end

function special_linear_lie_algebra(R::Ring, n::Int)
basis_e = [(b = zero_matrix(R, n, n); b[i, j] = 1; b) for i in 1:n for j in (i + 1):n]
basis_f = [(b = zero_matrix(R, n, n); b[j, i] = 1; b) for i in 1:n for j in (i + 1):n]
basis_h = [
(b = zero_matrix(R, n, n); b[i, i] = 1; b[i + 1, i + 1] = -1; b) for i in 1:(n - 1)
]
s_e = ["e_$(i)_$(j)" for i in 1:n for j in (i + 1):n]
s_f = ["f_$(i)_$(j)" for i in 1:n for j in (i + 1):n]
s_h = ["h_$(i)" for i in 1:(n - 1)]
L = lie_algebra(R, n, [basis_e; basis_f; basis_h], [s_e; s_f; s_h])
set_attribute!(L, :type => :special_linear)
return L
end

function special_orthogonal_lie_algebra(R::Ring, n::Int)
basis = [
(b = zero_matrix(R, n, n); b[i, j] = 1; b[j, i] = -1; b) for i in 1:n for j in (i + 1):n
]
s = ["x_$(i)_$(j)" for i in 1:n for j in (i + 1):n]
L = lie_algebra(R, n, basis, s)
set_attribute!(L, :type => :special_orthogonal)
return L
function lie_algebra(
gapL::GAP.GapObj,
s::Vector{<:VarName}=[Symbol("x_$i") for i in 1:GAPWrap.Dimension(gapL)];
cached::Bool=true,
)
@req GAPWrap.IsLieAlgebra(gapL) "gapL must be a Lie algebra."
if GAPWrap.IsFiniteDimensional(gapL)
if GAPWrap.IsLieObjectCollection(gapL)
return codomain(_iso_gap_oscar_linear_lie_algebra(gapL, s; cached))
else
return codomain(_iso_gap_oscar_abstract_lie_algebra(gapL, s; cached))
end
end
error("Not implemented.")
end
3 changes: 3 additions & 0 deletions experimental/LieAlgebras/src/LieAlgebras.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ using Base: deepcopy_internal

# functions with new methods
import ..Oscar:
_iso_oscar_gap,
action,
base_ring,
basis,
Expand Down Expand Up @@ -73,6 +74,8 @@ include("LieAlgebra.jl")
include("AbstractLieAlgebra.jl")
include("LinearLieAlgebra.jl")
include("LieAlgebraModule.jl")
include("iso_oscar_gap.jl")
include("iso_gap_oscar.jl")
include("GapWrapper.jl")

end
Expand Down
32 changes: 32 additions & 0 deletions experimental/LieAlgebras/src/LinearLieAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,35 @@ function lie_algebra(
) where {C<:RingElement}
return LinearLieAlgebra{elem_type(R)}(R, n, basis, Symbol.(s); cached)
end

function general_linear_lie_algebra(R::Ring, n::Int)
basis = [(b = zero_matrix(R, n, n); b[i, j] = 1; b) for i in 1:n for j in 1:n]
s = ["x_$(i)_$(j)" for i in 1:n for j in 1:n]
L = lie_algebra(R, n, basis, s)
set_attribute!(L, :type => :general_linear)
return L
end

function special_linear_lie_algebra(R::Ring, n::Int)
basis_e = [(b = zero_matrix(R, n, n); b[i, j] = 1; b) for i in 1:n for j in (i + 1):n]
basis_f = [(b = zero_matrix(R, n, n); b[j, i] = 1; b) for i in 1:n for j in (i + 1):n]
basis_h = [
(b = zero_matrix(R, n, n); b[i, i] = 1; b[i + 1, i + 1] = -1; b) for i in 1:(n - 1)
]
s_e = ["e_$(i)_$(j)" for i in 1:n for j in (i + 1):n]
s_f = ["f_$(i)_$(j)" for i in 1:n for j in (i + 1):n]
s_h = ["h_$(i)" for i in 1:(n - 1)]
L = lie_algebra(R, n, [basis_e; basis_f; basis_h], [s_e; s_f; s_h])
set_attribute!(L, :type => :special_linear)
return L
end

function special_orthogonal_lie_algebra(R::Ring, n::Int)
basis = [
(b = zero_matrix(R, n, n); b[i, j] = 1; b[j, i] = -1; b) for i in 1:n for j in (i + 1):n
]
s = ["x_$(i)_$(j)" for i in 1:n for j in (i + 1):n]
L = lie_algebra(R, n, basis, s)
set_attribute!(L, :type => :special_orthogonal)
return L
end
86 changes: 86 additions & 0 deletions experimental/LieAlgebras/src/iso_gap_oscar.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
###############################################################################
#
# Lie algebras
#
###############################################################################

function _iso_gap_oscar_lie_algebra(F::GAP.GapObj)
if GAPWrap.IsFiniteDimensional(F)
if GAPWrap.IsLieObjectCollection(F)
return _iso_gap_oscar_linear_lie_algebra(F)
else
return _iso_gap_oscar_abstract_lie_algebra(F)
end
end

error("no method found")
end

push!(Oscar._iso_gap_oscar_methods, "IsLieAlgebra" => _iso_gap_oscar_lie_algebra)

function _iso_gap_oscar_abstract_lie_algebra(
LG::GAP.GapObj,
s::Vector{<:VarName}=[Symbol("x_$i") for i in 1:GAPWrap.Dimension(LG)];
coeffs_iso::Map{GAP.GapObj}=Oscar.iso_gap_oscar(GAPWrap.LeftActingDomain(LG)),
cached::Bool=true,
)
LO = _abstract_lie_algebra_from_GAP(LG, coeffs_iso, s; cached)
finv, f = _iso_oscar_gap_lie_algebra_functions(LO, LG, inv(coeffs_iso))

iso = MapFromFunc(f, finv, LG, LO)
set_attribute!(LO, :iso_oscar_gap => inv(iso))
return iso
end

function _iso_gap_oscar_linear_lie_algebra(
LG::GAP.GapObj,
s::Vector{<:VarName}=[Symbol("x_$i") for i in 1:GAPWrap.Dimension(LG)];
coeffs_iso::Map{GAP.GapObj}=Oscar.iso_gap_oscar(GAPWrap.LeftActingDomain(LG)),
cached::Bool=true,
)
LO = _linear_lie_algebra_from_GAP(LG, coeffs_iso, s; cached)
finv, f = _iso_oscar_gap_lie_algebra_functions(LO, LG, inv(coeffs_iso))

iso = MapFromFunc(f, finv, LG, LO)
set_attribute!(LO, :iso_oscar_gap => inv(iso))
return iso
end

function _abstract_lie_algebra_from_GAP(
LG::GAP.GapObj, coeffs_iso::Map{GAP.GapObj}, s::Vector{<:VarName}; cached::Bool=true
)
RO = codomain(coeffs_iso)
dimL = GAPWrap.Dimension(LG)
sc_table_G =
(
entry -> (entry[1], Vector{elem_type(RO)}(map(coeffs_iso, entry[2])))
).(
Matrix{Tuple{Vector{Int},Vector{GAP.Obj}}}(
(GAP.Globals.StructureConstantsTable(GAPWrap.Basis(LG)))[1:dimL]
)
)

struct_consts = Matrix{SRow{elem_type(RO)}}(undef, dimL, dimL)
for i in 1:dimL, j in 1:dimL
struct_consts[i, j] = sparse_row(
RO, Tuple{Int,elem_type(RO)}[(k, RO(c)) for (k, c) in zip(sc_table_G[i, j]...)]
)
end

LO = AbstractLieAlgebra{elem_type(RO)}(RO, struct_consts, Symbol.(s); cached, check=false)
return LO
end

function _linear_lie_algebra_from_GAP(
LG::GAP.GapObj, coeffs_iso::Map{GAP.GapObj}, s::Vector{<:VarName}; cached::Bool=true
)
@req GAPWrap.IsLieObjectCollection(LG) "Input is not a linear Lie algebra."

RO = codomain(coeffs_iso)
basis = [
map_entries(coeffs_iso, GAPWrap.UnderlyingRingElement(b)) for b in GAPWrap.Basis(LG)
]
n = size(basis[1])[1]
LO = LinearLieAlgebra{elem_type(RO)}(RO, n, basis, Symbol.(s); cached)
return LO
end
62 changes: 62 additions & 0 deletions experimental/LieAlgebras/src/iso_oscar_gap.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
###############################################################################
#
# Lie algebras
#
###############################################################################

function _iso_oscar_gap_lie_algebra_functions(
LO::LieAlgebra{C}, LG::GAP.GapObj, coeffs_iso::MapFromFunc
) where {C<:RingElement}
basis_LG = GAPWrap.Basis(LG)

f = function (x::LieAlgebraElem{C})
cfs = GAP.Obj([coeffs_iso(c) for c in coefficients(x)])
return GAPWrap.LinearCombination(basis_LG, cfs)
end

finv = function (x)
cfs = Vector{GAP.Obj}(GAPWrap.Coefficients(basis_LG, x))
return LO([preimage(coeffs_iso, c) for c in cfs])
end

return (f, finv)
end

function _iso_oscar_gap(LO::LinearLieAlgebra{C}) where {C<:RingElement}
coeffs_iso = Oscar.iso_oscar_gap(base_ring(LO))
LG = GAP.Globals.LieAlgebra(
codomain(coeffs_iso),
GAP.Obj([map_entries(coeffs_iso, xi) for xi in matrix_repr_basis(LO)]),
GAP.Obj("basis"),
)

f, finv = _iso_oscar_gap_lie_algebra_functions(LO, LG, coeffs_iso)

return MapFromFunc(f, finv, LO, LG)
end

function _iso_oscar_gap(LO::AbstractLieAlgebra{C}) where {C<:RingElement}
coeffs_iso = Oscar.iso_oscar_gap(base_ring(LO))
sc_table_G = [
[
[
begin
pairs = filter(
pair -> !iszero(last(pair)), collect(enumerate(Generic._matrix(xi * xj)))
)
(map(first, pairs), GAP.Obj[coeffs_iso(c) for c in map(last, pairs)])
end for xj in basis(LO)
] for xi in basis(LO)
]
-1
coeffs_iso(zero(base_ring(LO)))
]

LG = GAP.Globals.LieAlgebraByStructureConstants(
codomain(coeffs_iso), GAP.Obj(sc_table_G; recursive=true)
)

f, finv = _iso_oscar_gap_lie_algebra_functions(LO, LG, coeffs_iso)

return MapFromFunc(f, finv, LO, LG)
end
Loading