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

Generic exterior algebra and relative BGG #4360

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d4a6286
Extend exterior algebra functionality.
HechtiDerLachs Jul 31, 2024
02fc5e2
Make ExteriorAlgebra an NCRing.
HechtiDerLachs Jul 31, 2024
d1a6d97
Some more tweaks.
HechtiDerLachs Jul 31, 2024
e3ae457
Implement homogeneous parts of morphisms and modules.
HechtiDerLachs Aug 1, 2024
f751991
Implement graded parts of SubModuleOfFreeModule.
HechtiDerLachs Aug 2, 2024
eef558e
Implement coordinates for homogeneous elements.
HechtiDerLachs Aug 2, 2024
34689bc
Implement kernels.
HechtiDerLachs Aug 2, 2024
00dfd60
WIP.
HechtiDerLachs Aug 2, 2024
75ab76c
Add verbosity scope for exterior algebras.
HechtiDerLachs Aug 2, 2024
524b120
Improvements for cohomology computations.
HechtiDerLachs Aug 2, 2024
9139fb6
Some tweaks.
HechtiDerLachs Aug 2, 2024
da52e5a
Implement generic method for derived pushforward with BGG.
HechtiDerLachs Aug 3, 2024
dd4605a
Add some auxiliary methods for modules and friends.
HechtiDerLachs Aug 5, 2024
e3acaab
Implement BGG cohomology computation for complexes of free modules.
HechtiDerLachs Aug 5, 2024
29ec53e
Add tests.
HechtiDerLachs Aug 5, 2024
717faf0
Add tests.
HechtiDerLachs Aug 5, 2024
612901f
Some tuning.
HechtiDerLachs Aug 5, 2024
13ccf5f
Extend degree signatures to accept check.
HechtiDerLachs Sep 16, 2024
5a60146
Some performance tuning
lgoettgens Sep 16, 2024
bc776fd
Widen signature of admissible rings.
HechtiDerLachs Nov 27, 2024
3205010
Move code for generic exterior algebras to src for the sake of inclus…
HechtiDerLachs Nov 27, 2024
6f79e1c
Revert "Move code for generic exterior algebras to src for the sake o…
HechtiDerLachs Nov 27, 2024
1413c12
Revert "Widen signature of admissible rings."
HechtiDerLachs Nov 27, 2024
8a4cb73
Widen signature for AdmissibleFPRing(Elem) again.
HechtiDerLachs Sep 16, 2024
1533887
check for unicode allowance.
HechtiDerLachs Nov 27, 2024
9351670
Take care of the keys problem in 1.6.
HechtiDerLachs Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
369 changes: 369 additions & 0 deletions experimental/ExteriorAlgebra/src/BGG_complex.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,369 @@
# Helper structure to transfer back and forth between S- and E-modules
mutable struct BGGHelper{T}
E::ExteriorAlgebra{T}
S::MPolyDecRing{T}
d::Int

# Fields for caching
ind_to_exp_dom::Vector{Vector{Int}}
exp_to_ind_dom::Dict{Vector{Int}, Int}
ind_to_exp_cod::Vector{Vector{Int}}
exp_to_ind_cod::Dict{Vector{Int}, Int}

dom::FreeMod{ExtAlgElem{T}} # the (co)domains of the BGG morphism
cod::FreeMod{ExtAlgElem{T}}
phi::FreeModuleHom{FreeMod{ExtAlgElem{T}}, FreeMod{ExtAlgElem{T}}, Nothing} # the actual morphism
K::SubquoModule{ExtAlgElem{T}} # its kernel
inc::SubQuoHom # the inclusion K ↪ dom
res::SimpleFreeResolution # a free resolution P of K
aug::FreeModuleHom # the augmentation map P₀ → K
all_monomials::Vector{<:MPolyDecRingElem}

function BGGHelper(E::ExteriorAlgebra{T}, S::MPolyDecRing{T}, d::Int) where {T}
return new{T}(E, S, d)
end
end

function domain(h::BGGHelper)
if !isdefined(h, :dom)
if h.d < 0
h.dom = graded_free_module(h.E, 0)

Check warning on line 30 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L30

Added line #L30 was not covered by tests
else
n = rank(h.E)
h.dom = graded_free_module(h.E, [-h.d for i in 1:length(WeakCompositions(h.d, n))])
end
end
return h.dom
end

function codomain(h::BGGHelper)
if !isdefined(h, :cod)
if h.d < -1
h.cod = graded_free_module(h.E, 0)

Check warning on line 42 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L42

Added line #L42 was not covered by tests
else
n = rank(h.E)
h.cod = graded_free_module(h.E, [-(h.d+1) for i in 1:length(WeakCompositions(h.d + 1, n))])
end
end
return h.cod
end

function ind_to_exp_dom(h::BGGHelper)
if !isdefined(h, :ind_to_exp_dom)
h.ind_to_exp_dom = [a.c for a in WeakCompositions(h.d, rank(h.E))]
end
return h.ind_to_exp_dom
end

function exp_to_ind_dom(h::BGGHelper)
if !isdefined(h, :exp_to_ind_hom)
iter = WeakCompositions(h.d, rank(h.E))
r = length(iter)
h.exp_to_ind_dom = Dict{Vector{Int}, Int}(a.c => i for (i, a) in zip(1:r, iter))
end
return h.exp_to_ind_dom
end

function ind_to_exp_cod(h::BGGHelper)
if !isdefined(h, :ind_to_exp_cod)
h.ind_to_exp_cod = [a.c for a in WeakCompositions(h.d+1, rank(h.E))]
end
return h.ind_to_exp_cod
end

function exp_to_ind_cod(h::BGGHelper)
if !isdefined(h, :exp_to_ind_cod)
iter = WeakCompositions(h.d+1, rank(h.E))
r = length(iter)
h.exp_to_ind_cod = Dict{Vector{Int}, Int}(a.c => i for (i, a) in zip(1:r, iter))
end
return h.exp_to_ind_cod
end

# take a homogeneous polynomial in S and return the SRow corresponding
# element in the domain/codomain of the E-modules
function (h::BGGHelper{T})(f::MPolyDecRingElem{T}) where {T}
degf = Int(degree(f; check=false)[1])
E = h.E
S = h.S
R = base_ring(S)
if degf == h.d # element of the domain
to_ind_dom = exp_to_ind_dom(h)
return sparse_row(R, [to_ind_dom[e] for e in exponents(f)],
collect(coefficients(f)))
elseif degf == h.d + 1
to_ind_cod = exp_to_ind_cod(h)
return sparse_row(R, [to_ind_cod[e] for e in exponents(f)],

Check warning on line 96 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L94-L96

Added lines #L94 - L96 were not covered by tests
collect(coefficients(f)))
end
error("execution should never get here")

Check warning on line 99 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L99

Added line #L99 was not covered by tests
end

# take an element in the domain/codomain of h and turn it into a homogeneous polynomial
function (h::BGGHelper)(v::FreeModElem)
E = h.E
S = h.S
n = rank(E)
if parent(v) === domain(h)
return h(coordinates(v), :domain)
elseif parent(v) === codomain(h)
return h(coordinates(v), :codomain)

Check warning on line 110 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L103-L110

Added lines #L103 - L110 were not covered by tests
end
error("execution should never get here")

Check warning on line 112 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L112

Added line #L112 was not covered by tests
end

# for a list of integers indicating basis vectors,
# produce the list of corresponding monomials
function all_monomials(h::BGGHelper)
S = h.S
h.d < 0 && return elem_type(S)[]
R = base_ring(S)
if !isdefined(h, :all_monomials)
exp_list = ind_to_exp_dom(h)
result = sizehint!(elem_type(h.S)[], sizeof(exp_list))
for e in exp_list
ctx = MPolyBuildCtx(h.S)
push_term!(ctx, one(R), e)
push!(result, finish(ctx))
end
h.all_monomials = result
end
return h.all_monomials
end

function (h::BGGHelper)(v::SRow, s::Symbol=:domain)
@assert base_ring(v) === base_ring(h.S)
ctx = MPolyBuildCtx(h.S)
if s == :domain
to_exp_dom = ind_to_exp_dom(h)
for (i, c) in v
push_term!(ctx, c, to_exp_dom[i])
end
return finish(ctx)
elseif s == :codomain
to_exp_cod = ind_to_exp_cod(h)
for (i, c) in v
push_term!(ctx, c, to_exp_cod[i])
end
return finish(ctx)
end
error("execution should never get here")

Check warning on line 150 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L150

Added line #L150 was not covered by tests
end

function morphism(h::BGGHelper)
G = codomain(h)
img_gens = elem_type(G)[]
n = rank(h.E)
h.d < 0 && return hom(domain(h), codomain(h), elem_type(codomain(h))[])
# iterate through the monomials of degree d in n variables
for (i, a) in enumerate(WeakCompositions(h.d, n))
e = a.c # the exponent vector of the monomial
y = [copy(e) for i in 1:n]
for j in 1:n
y[j][j] += 1 # multiplication by xⱼ
end
to_ind_cod = exp_to_ind_cod(h)
indices = [to_ind_cod[a] for a in y]
push!(img_gens, G(sparse_row(h.E, indices, gens(h.E))))
end
return hom(domain(h), G, img_gens)
end

function kernel(h::BGGHelper)
if !isdefined(h, :K)
K, inc = kernel(morphism(h))
h.K = K
h.inc = inc
end
return h.K
end

function kernel_inclusion(h::BGGHelper)
if !isdefined(h, :inc)
kernel(h)

Check warning on line 183 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L181-L183

Added lines #L181 - L183 were not covered by tests
end
return h.inc

Check warning on line 185 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L185

Added line #L185 was not covered by tests
end

function resolution(h::BGGHelper)
if !isdefined(h, :res)
res, aug = free_resolution(SimpleFreeResolution, kernel(h))
h.res = res
h.aug = aug[0]
end
return h.res
end

function augmentation_map(h::BGGHelper)
if !isdefined(h, :aug)
resolution(h)

Check warning on line 199 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L197-L199

Added lines #L197 - L199 were not covered by tests
end
return h.aug

Check warning on line 201 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L201

Added line #L201 was not covered by tests
end


### Production of the chains
struct BGGChainFactory{ChainType} <: HyperComplexChainFactory{ChainType}
# Fields needed for production
orig::AbsHyperComplex
S::MPolyDecRing
E::ExteriorAlgebra
d::Int
helper::Dict{Int, <:BGGHelper}
helper_combinations::Dict{<:Tuple, <:Vector{<:BGGHelper}}
bgg_maps::Dict{Tuple, FreeModuleHom}

function BGGChainFactory(
S::MPolyDecRing, E::ExteriorAlgebra, orig::AbsHyperComplex{T}, d::Int
) where {T<:ModuleFP{<:MPolyDecRingElem}}
@assert dim(orig) == 1 "complex must be one-dimensional"
@assert direction(orig, 1) == :chain "only chain complexes are supported"
@assert is_z_graded(S) "ring must be standard graded"
return new{ModuleFP{elem_type(E)}}(orig, S, E, d,
Dict{Int, BGGHelper}(),
Dict{Tuple, Vector{<:BGGHelper}}(),
Dict{Tuple, FreeModuleHom}()
)
end
end

function get_helper(fac::BGGChainFactory, d::Int)
if !haskey(fac.helper, d)
fac.helper[d] = BGGHelper(fac.E, fac.S, d)
end
return fac.helper[d]
end

function (fac::BGGChainFactory)(self::AbsHyperComplex, I::Tuple)
return _build_BGG_module!(fac, fac.orig[I], I)
end

function _build_BGG_module!(fac::BGGChainFactory, F::SubquoModule, I::Tuple)
error("not implemented")

Check warning on line 242 in experimental/ExteriorAlgebra/src/BGG_complex.jl

View check run for this annotation

Codecov / codecov/patch

experimental/ExteriorAlgebra/src/BGG_complex.jl#L241-L242

Added lines #L241 - L242 were not covered by tests
end

function _build_BGG_module!(fac::BGGChainFactory, F::FreeMod, I::Tuple)
E = fac.E
is_zero(rank(F)) && return graded_free_module(E, 0)
S = fac.S
n = rank(E)
s = fac.d
R = base_ring(E)
@assert ngens(S) == rank(E)
@assert base_ring(S) === R
@assert is_graded(F)
maps = FreeModuleHom[]
kernels = SubquoModule[]
helpers = BGGHelper[]
for (i, d) in enumerate(degrees_of_generators(F))
dd = Int(d[1])
helper = get_helper(fac, s-dd)
phi = morphism(helper)
dom_twist, amb_twist = twist(domain(phi), dd)
phi_twist = twist(phi, dd; domain_twist=amb_twist)
K_twist, _ = twist(kernel(helper), d; ambient_twist=amb_twist)
@assert all(Int(e[1]) == -s for e in degrees_of_generators(dom_twist))
push!(maps, phi_twist)
push!(helpers, helper)
push!(kernels, K_twist)
end
phi = direct_sum(maps)
dom = domain(phi)
cod = codomain(phi)
fac.helper_combinations[I] = helpers
fac.bgg_maps[I] = phi
K = direct_sum(kernels...)[1]
return K
end

function can_compute(fac::BGGChainFactory, self::AbsHyperComplex, i::Tuple)
return can_compute_index(fac.orig, i)
end

### Production of the morphisms
struct BGGMapFactory{MorphismType} <: HyperComplexMapFactory{MorphismType} end

function (fac::BGGMapFactory)(self::AbsHyperComplex, p::Int, I::Tuple)
@assert isone(p)
i = first(I)
cfac = chain_factory(self)
orig = cfac.orig
dom = self[I]
cod = self[(i-1,)]
(is_zero(dom) || is_zero(cod)) && return zero_morphism(dom, cod)
dom_amb = ambient_free_module(dom)
cod_amb = ambient_free_module(cod)
orig_dom = orig[I]::FreeMod
orig_cod = orig[(i-1,)]::FreeMod
orig_phi = map(orig, 1, I)

# We first build the morphism on the ambient modules

# transfer these elements to homogeneous S-module elements
helpers = cfac.helper_combinations[I]::Vector{<:BGGHelper}
img_gens = elem_type(orig_dom)[]
w = zero(orig_dom)
for (j, h) in enumerate(helpers) # corresponding to the direct summands
delta = rank(domain(h))
g = orig_dom[j]
# the generators of the E-module for this summand were just the
# monomials of the S-module in this degree
img_gens = vcat(img_gens, [x*g for x in all_monomials(h)])
end

# now we map the monomials over to the other side
img_gens2 = orig_phi.(img_gens)

# and translate them back
helpers = cfac.helper_combinations[(i-1,)]
img_gens3 = elem_type(cod_amb)[]
offsets = rank.(domain.(helpers))
for j = length(offsets):-1:2
offsets[j] = sum(offsets[1:j])
end
pushfirst!(offsets, 0)

for v in img_gens2
w = zero(cod_amb)
for (j, poly) in coordinates(v)
helper = helpers[j]
coord = helper(poly) # convert the polynomial into an element of the summand
coord.pos.+=offsets[j] # a dirty hack to shift the vector to its correct position in the total sum
w += cod_amb(map_entries(cfac.E, coord))
end
push!(img_gens3, w)
end

# this gives us the map on the ambient free E-modules
amb_map = hom(dom_amb, cod_amb, img_gens3)

# finally we need to compute the induced map on the kernels

img_gens4 = elem_type(cod)[SubquoModuleElem(amb_map(g), cod) for g in ambient_representatives_generators(dom)]
return hom(dom, cod, img_gens4; check=false)
end

function can_compute(fac::BGGMapFactory, self::AbsHyperComplex, p::Int, i::Tuple)
return can_compute_map(chain_factory(self).orig, p, i)
end

### The concrete struct
@attributes mutable struct BGGComplex{ChainType, MorphismType} <: AbsHyperComplex{ChainType, MorphismType}
internal_complex::HyperComplex{ChainType, MorphismType}

function BGGComplex(E::ExteriorAlgebra{T}, S::MPolyDecRing{T}, orig::AbsHyperComplex{CT, MT}, s::Int) where {T <: RingElem, CT <: ModuleFP, MT<:ModuleFPHom}
chain_fac = BGGChainFactory(S, E, orig, s)
map_fac = BGGMapFactory{ModuleFPHom}()

# Assuming d is the dimension of the new complex
internal_complex = HyperComplex(1, chain_fac, map_fac, [:chain],
lower_bounds = Union{Int, Nothing}[has_lower_bound(orig, 1) ? lower_bound(orig, 1) : nothing],
upper_bounds = Union{Int, Nothing}[has_upper_bound(orig, 1) ? upper_bound(orig, 1) : nothing])
# Assuming that ChainType and MorphismType are provided by the input
return new{ModuleFP{ExtAlgElem{T}}, ModuleFPHom}(internal_complex)
end
end

### Implementing the AbsHyperComplex interface via `underlying_complex`
underlying_complex(c::BGGComplex) = c.internal_complex

Loading
Loading