-
Notifications
You must be signed in to change notification settings - Fork 126
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 #4097
Draft
HechtiDerLachs
wants to merge
28
commits into
oscar-system:master
Choose a base branch
from
HechtiDerLachs:exterior_algebra_rebase
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
generic exterior algebra #4097
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
3ed0c9a
Extend exterior algebra functionality.
HechtiDerLachs 77c00e3
Make ExteriorAlgebra an NCRing.
HechtiDerLachs e74c643
Some more tweaks.
HechtiDerLachs e2d137b
Implement homogeneous parts of morphisms and modules.
HechtiDerLachs eba9689
Implement graded parts of SubModuleOfFreeModule.
HechtiDerLachs 53be68d
Implement coordinates for homogeneous elements.
HechtiDerLachs 7fa96c3
Implement kernels.
HechtiDerLachs af8db31
Allow zero dimensional complexes.
HechtiDerLachs 6f642a5
WIP.
HechtiDerLachs ad298cf
Add verbosity scope for exterior algebras.
HechtiDerLachs 9853b99
Improvements for cohomology computations.
HechtiDerLachs 3ac15d9
Some tweaks.
HechtiDerLachs ce71692
Implement generic method for derived pushforward with BGG.
HechtiDerLachs 0afcc67
Raw implementation of CA resolutions.
HechtiDerLachs 4e1d049
Fix inclusions.
HechtiDerLachs 105fdd9
Fixes to make the code actually run.
HechtiDerLachs 5be5b3a
Preserve bounds for base changes.
HechtiDerLachs 7cda603
Add some auxiliary methods for modules and friends.
HechtiDerLachs 9560bd1
Clean up CA resolutions.
HechtiDerLachs 80ab1d9
Implement BGG cohomology computation for complexes of free modules.
HechtiDerLachs 0551a44
Add tests.
HechtiDerLachs 0df246d
Add tests.
HechtiDerLachs 2a3d73a
Some tuning.
HechtiDerLachs ba6d7ce
Extend degree signatures to accept check.
HechtiDerLachs f7f7c17
Widen signature for AdmissibleFPRing(Elem) again.
HechtiDerLachs f4e3b51
Correct the is_right and is_two_sided methods.
HechtiDerLachs 439784e
Some performance tuning
lgoettgens 321739a
Merge branch 'master' into exterior_algebra_rebase
lgoettgens File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
279 changes: 279 additions & 0 deletions
279
experimental/DoubleAndHyperComplexes/src/Objects/cartan_eilenberg_resolution.jl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
#= Cartan Eilenberg resolutions of 1-dimensional complexes | ||
# | ||
# Suppose | ||
# | ||
# 0 ← C₀ ← C₁ ← C₂ ← … | ||
# | ||
# is a bounded below complex. We compute a double complex | ||
# | ||
# 0 0 0 | ||
# ↑ ↑ ↑ | ||
# 0 ← P₀₀ ← P₀₁ ← P₀₂ ← … | ||
# ↑ ↑ ↑ | ||
# 0 ← P₁₀ ← P₁₁ ← P₁₂ ← … | ||
# ↑ ↑ ↑ | ||
# 0 ← P₂₀ ← P₂₁ ← P₂₂ ← … | ||
# ↑ ↑ ↑ | ||
# ⋮ ⋮ ⋮ | ||
# | ||
# which is quasi-isomorphic to C via some augmentation map | ||
# | ||
# ε = (εᵢ : P₀ᵢ → Cᵢ)ᵢ | ||
# | ||
# The challenge is that if we were only computing resolutions of the Cᵢ's | ||
# and lifting the maps, then the rows of the resulting diagrams would | ||
# not necessarily form complexes. To accomplish that, we split the original | ||
# complex into short exact sequences | ||
# | ||
# 0 ← Bᵢ ← Cᵢ ← Zᵢ ← 0 | ||
# | ||
# and apply the Horse shoe lemma to these. Together with the induced maps | ||
# from Bᵢ ↪ Zᵢ₋₁ we get the desired double complex. | ||
# | ||
# If the original complex C is known to be exact, then there is no need | ||
# to compute the resolutions of both Bᵢ and Zᵢ and we can shorten the procedure. | ||
=# | ||
### Production of the chains | ||
struct CEChainFactory{ChainType} <: HyperComplexChainFactory{ChainType} | ||
c::AbsHyperComplex | ||
is_exact::Bool | ||
kernel_resolutions::Dict{Int, <:AbsHyperComplex} # the kernels of Cᵢ → Cᵢ₋₁ | ||
boundary_resolutions::Dict{Int, <:AbsHyperComplex} # the boundaries of Cᵢ₊₁ → Cᵢ | ||
induced_maps::Dict{Int, <:AbsHyperComplexMorphism} # the induced maps from the free | ||
# resolutions of the boundary and kernel | ||
|
||
function CEChainFactory(c::AbsHyperComplex; is_exact::Bool=false) | ||
@assert dim(c) == 1 "complex must be 1-dimensional" | ||
#@assert has_lower_bound(c, 1) "complex must be bounded from below" | ||
return new{chain_type(c)}(c, is_exact, Dict{Int, AbsHyperComplex}(), Dict{Int, AbsHyperComplex}(), Dict{Int, AbsHyperComplexMorphism}()) | ||
end | ||
end | ||
|
||
function kernel_resolution(fac::CEChainFactory, i::Int) | ||
if !haskey(fac.kernel_resolutions, i) | ||
Z, _ = kernel(fac.c, i) | ||
fac.kernel_resolutions[i] = free_resolution(SimpleFreeResolution, Z)[1] | ||
end | ||
return fac.kernel_resolutions[i] | ||
end | ||
|
||
function boundary_resolution(fac::CEChainFactory, i::Int) | ||
if !haskey(fac.boundary_resolutions, i) | ||
Z, _ = boundary(fac.c, i) | ||
fac.boundary_resolutions[i] = free_resolution(SimpleFreeResolution, Z)[1] | ||
end | ||
return fac.boundary_resolutions[i] | ||
end | ||
|
||
function induced_map(fac::CEChainFactory, i::Int) | ||
if !haskey(fac.induced_maps, i) | ||
Z, inc = kernel(fac.c, i) | ||
B, pr = boundary(fac.c, i) | ||
@assert ambient_free_module(Z) === ambient_free_module(B) | ||
img_gens = elem_type(Z)[Z(g) for g in ambient_representatives_generators(B)] | ||
res_Z = kernel_resolution(fac, i) | ||
res_B = boundary_resolution(fac, i) | ||
aug_Z = augmentation_map(res_Z) | ||
aug_B = augmentation_map(res_B) | ||
img_gens = gens(res_B[0]) | ||
img_gens = aug_B[0].(img_gens) | ||
img_gens = elem_type(res_Z[0])[preimage(aug_Z[0], Z(repres(aug_B[0](g)))) for g in gens(res_B[0])] | ||
psi = hom(res_B[0], res_Z[0], img_gens; check=true) # TODO: Set to false | ||
@assert domain(psi) === boundary_resolution(fac, i)[0] | ||
@assert codomain(psi) === kernel_resolution(fac, i)[0] | ||
fac.induced_maps[i] = lift_map(boundary_resolution(fac, i), kernel_resolution(fac, i), psi; start_index=0) | ||
end | ||
return fac.induced_maps[i] | ||
end | ||
|
||
function (fac::CEChainFactory)(self::AbsHyperComplex, I::Tuple) | ||
(i, j) = I # i the resolution index, j the index in C | ||
|
||
res_Z = kernel_resolution(fac, j) | ||
|
||
if can_compute_map(fac.c, 1, (j,)) | ||
if fac.is_exact # Use the next kernel directly | ||
res_B = kernel_resolution(fac, j-1) | ||
return direct_sum(res_B[i], res_Z[i])[1] | ||
else | ||
res_B = boundary_resolution(fac, j-1) | ||
return direct_sum(res_B[i], res_Z[i])[1] | ||
end | ||
end | ||
# We may assume that the next map can not be computed and is, hence, zero. | ||
return res_Z[i] | ||
end | ||
|
||
function can_compute(fac::CEChainFactory, self::AbsHyperComplex, I::Tuple) | ||
(i, j) = I | ||
can_compute_index(fac.c, (j,)) || return false | ||
return i >= 0 | ||
end | ||
|
||
### Production of the morphisms | ||
struct CEMapFactory{MorphismType} <: HyperComplexMapFactory{MorphismType} end | ||
|
||
function (fac::CEMapFactory)(self::AbsHyperComplex, p::Int, I::Tuple) | ||
(i, j) = I | ||
cfac = chain_factory(self) | ||
if p == 1 # vertical upwards maps | ||
if can_compute_map(cfac.c, 1, (j,)) | ||
# both dom and cod are direct sums in this case | ||
dom = self[I] | ||
cod = self[(i-1, j)] | ||
pr1 = canonical_projection(dom, 1) | ||
pr2 = canonical_projection(dom, 2) | ||
@assert domain(pr1) === domain(pr2) === dom | ||
inc1 = canonical_injection(cod, 1) | ||
inc2 = canonical_injection(cod, 2) | ||
@assert codomain(inc1) === codomain(inc2) === cod | ||
res_Z = kernel_resolution(cfac, j) | ||
@assert domain(map(res_Z, i)) === codomain(pr2) | ||
@assert codomain(map(res_Z, i)) === domain(inc2) | ||
res_B = boundary_resolution(cfac, j-1) | ||
@assert domain(map(res_B, i)) === codomain(pr1) | ||
@assert codomain(map(res_B, i)) === domain(inc1) | ||
return compose(pr1, compose(map(res_B, i), inc1)) + compose(pr2, compose(map(res_Z, i), inc2)) | ||
else | ||
res_Z = kernel_resolution(cfac, j) | ||
return map(res_Z, i) | ||
end | ||
error("execution should never reach this point") | ||
elseif p == 2 # the horizontal maps | ||
dom = self[I] | ||
cod = self[(i, j-1)] | ||
if can_compute_map(cfac.c, 1, (j-1,)) | ||
# the codomain is also a direct sum | ||
if !cfac.is_exact | ||
psi = induced_map(cfac, j-1) | ||
phi = psi[i] | ||
inc = canonical_injection(cod, 2) | ||
pr = canonical_projection(dom, 1) | ||
@assert codomain(phi) === domain(inc) | ||
@assert codomain(pr) === domain(phi) | ||
return compose(pr, compose(phi, inc)) | ||
else | ||
inc = canonical_injection(cod, 2) | ||
pr = canonical_projection(dom, 1) | ||
return compose(pr, inc) | ||
end | ||
error("execution should never reach this point") | ||
else | ||
# the codomain is just the kernel | ||
if !cfac.is_exact | ||
psi = induced_map(cfac, j-1) | ||
phi = psi[i] | ||
pr = canonical_projection(dom, 1) | ||
return compose(pr, phi) | ||
else | ||
pr = canonical_projection(dom, 1) | ||
return pr | ||
end | ||
error("execution should never reach this point") | ||
end | ||
error("execution should never reach this point") | ||
end | ||
|
||
#= | ||
C = cfac.c[(i,)] | ||
B, pr_B = boundary(cfac.c, 1, (i-1,)) | ||
if cfac.is_exact | ||
# use the kernel instead; we have to adjust the map | ||
Z, inc_Z = kernel(cfac.c, 1, (i-1,)) | ||
B = Z | ||
phi = map(cfac.c, 1, (i,)) | ||
img_gens = [preimage(inc_Z, phi(g)) for g in gens(C)] | ||
pr_B = hom(C, B, img_gens; check=true) # TODO: Set to false | ||
end | ||
Z, inc_Z = kernel(cfac.c, 1, (i,)) | ||
@assert domain(pr_B) === C | ||
@assert codomain(inc_Z) === C | ||
if j == 1 | ||
img_gens = elem_type(C)[preimage(pr_B, g) for g in gens(B)] | ||
img_gens = vcat(img_gens, elem_type(C)[inc_Z(g) for g in gens(Z)]) | ||
return hom(B_plus_Z, C, img_gens; check=true) # TODO: Set to false | ||
else | ||
# may assume j > 1 | ||
cod = self[(i, j-1)] | ||
res_Z = getindex!(cfac.kernel_resolutions, i) do | ||
Z, _ = kernel(fac.c, i) | ||
return free_resolution(SimpleFreeResolution, Z) | ||
end | ||
b = map(res_Z, 1, (j,)) | ||
inc2 = canonical_injection(cod, 2) | ||
@assert domain(inc2) === res_Z[j-1] === codomain(b) | ||
@assert codomain(inc2) === cod | ||
|
||
if cfac.isexact | ||
res_Z1 = getindex!(cfac.kernel_resolutions, i-1) do | ||
Z, _ = kernel(cfac.c, i) | ||
return free_resolution(SimpleFreeResolution, Z) | ||
end | ||
a = map(res_Z1, 1, (j,)) | ||
inc1 = canonical_injection(cod, 1) | ||
@assert domain(inc1) === res_Z1[j-1] === codomain(a) | ||
@assert codomain(inc1) === cod | ||
img_gens = elem_type(cod)[inc1(a(g)) for g in gens(res_Z1[j])] | ||
img_gens = vcat(img_gens, elem_type(cod)[inc2(b(g)) for g in gens(res_Z[j])]) | ||
return hom(B_plus_Z, cod, img_gens; check=true) # TODO: Set to false | ||
else | ||
res_B = getindex!(cfac.boundary_resolutions, i-1) do | ||
B, _ = boundary(cfac.c, i) | ||
return free_resolution(SimpleFreeResolution, B) | ||
end | ||
a = map(res_B, 1, (j,)) | ||
inc1 = canonical_injection(cod, 1) | ||
@assert domain(inc1) === res_B[j-1] === codomain(a) | ||
@assert codomain(inc1) === cod | ||
img_gens = elem_type(cod)[inc1(a(g)) for g in gens(res_Z1[j])] | ||
img_gens = vcat(img_gens, elem_type(cod)[inc2(b(g)) for g in gens(res_Z[j])]) | ||
return hom(B_plus_Z, cod, img_gens; check=true) # TODO: Set to false | ||
end | ||
error("execution should never reach this point") | ||
end | ||
else | ||
res = getindex!(cfac.kernel_resolutions, i) do | ||
Z, _ = kernel(fac.c, i) | ||
return free_resolution(SimpleFreeResolution, Z) | ||
end | ||
return map(res, 1, (j,)) | ||
end | ||
end | ||
=# | ||
error("direction $p out of bounds") | ||
end | ||
|
||
function can_compute(fac::CEMapFactory, self::AbsHyperComplex, p::Int, I::Tuple) | ||
(i, j) = I | ||
if p == 1 # vertical maps | ||
return i > 0 && can_compute(chain_factory(self).c, j) | ||
elseif p == 2 # horizontal maps | ||
return i >= 0 && can_compute_map(chain_factory(self).c, j) | ||
end | ||
return false | ||
end | ||
|
||
### The concrete struct | ||
@attributes mutable struct CartanEilenbergResolution{ChainType, MorphismType} <: AbsHyperComplex{ChainType, MorphismType} | ||
internal_complex::HyperComplex{ChainType, MorphismType} | ||
|
||
function CartanEilenbergResolution( | ||
c::AbsHyperComplex{ChainType, MorphismType}; | ||
is_exact::Bool=false | ||
) where {ChainType, MorphismType} | ||
@assert dim(c) == 1 "complexes must be 1-dimensional" | ||
@assert has_lower_bound(c, 1) "complexes must be bounded from below" | ||
@assert direction(c, 1) == :chain "resolutions are only implemented for chain complexes" | ||
chain_fac = CEChainFactory(c; is_exact) | ||
map_fac = CEMapFactory{MorphismType}() # TODO: Do proper type inference here! | ||
|
||
# Assuming d is the dimension of the new complex | ||
internal_complex = HyperComplex(2, chain_fac, map_fac, [:chain, :chain]; lower_bounds = Union{Int, Nothing}[0, lower_bound(c, 1)]) | ||
# Assuming that ChainType and MorphismType are provided by the input | ||
return new{ChainType, MorphismType}(internal_complex) | ||
end | ||
end | ||
|
||
### Implementing the AbsHyperComplex interface via `underlying_complex` | ||
underlying_complex(c::CartanEilenbergResolution) = c.internal_complex | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the kind of code for which
get!
exists to avoid performing and hashing three times (forhaskey
, for storing, and then for looking it up again)Same applies to
boundary_resolution
andinduced_map