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

Eagon northcott complex #4327

Draft
wants to merge 36 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c8c93b6
Widen strands to accept ZZm-gradings.
HechtiDerLachs Aug 14, 2024
af2c627
WIP on derived pushforward.
HechtiDerLachs Aug 14, 2024
6051869
Implement iterators over strands for general ZZm-gradings.
HechtiDerLachs Aug 14, 2024
64d69c1
Externalize functionality for strands.
HechtiDerLachs Aug 14, 2024
d6e0c20
Implement Koszul complexes for graded rings.
HechtiDerLachs Aug 14, 2024
f8b04e7
Update inclusions.
HechtiDerLachs Aug 14, 2024
fb5d1c1
Externalize functionality for tensor products.
HechtiDerLachs Aug 14, 2024
e679c20
Add assertion for graded presentations.
HechtiDerLachs Aug 15, 2024
b950497
Allow zero dimensional complexes.
HechtiDerLachs Aug 2, 2024
32acac6
Raw implementation of CA resolutions.
HechtiDerLachs Aug 3, 2024
86f5f32
Fix inclusions.
HechtiDerLachs Aug 3, 2024
7ca9009
Fixes to make the code actually run.
HechtiDerLachs Aug 3, 2024
fbf835e
Preserve bounds for base changes.
HechtiDerLachs Aug 5, 2024
5165485
Clean up CA resolutions.
HechtiDerLachs Aug 5, 2024
964a538
Extend degree signatures to accept check.
HechtiDerLachs Sep 16, 2024
2b6e192
Fix dirty WIP.
HechtiDerLachs Oct 25, 2024
cb3bf2e
Remove deprecated code.
HechtiDerLachs Oct 25, 2024
5b67864
Add tests.
HechtiDerLachs Oct 25, 2024
3e47b29
Add Eagon-Northcott complexes constructed from matrices.
HechtiDerLachs Oct 25, 2024
7adbe7c
Fix contraction.
HechtiDerLachs Oct 25, 2024
eeba92f
Add some getters.
HechtiDerLachs Oct 25, 2024
b09f03b
Add induced Eagon-Northcott complexes.
HechtiDerLachs Oct 25, 2024
fa923ae
Allow to specify module for ENCs.
HechtiDerLachs Oct 25, 2024
a32b74d
Overhaul type specification for CA-resolution.
HechtiDerLachs Oct 25, 2024
aef74f3
Some tweaks on simplify for complexes.
HechtiDerLachs Oct 30, 2024
5f6c854
Disable some internal checks.
HechtiDerLachs Oct 30, 2024
e06ebf6
Make change_base_ring preserve gradings.
HechtiDerLachs Oct 30, 2024
2d0919c
Extend functionality for derived pushforward.
HechtiDerLachs Oct 30, 2024
5486643
Remove some debug messages.
HechtiDerLachs Oct 30, 2024
ff38ba7
WIP.
HechtiDerLachs Nov 13, 2024
983cb6c
Fix up eltype methods.
HechtiDerLachs Nov 25, 2024
c57126a
Temporarily disable some tests.
HechtiDerLachs Nov 25, 2024
2073df1
Address comments.
HechtiDerLachs Nov 25, 2024
fa2634c
Disable input check for non-zero generators.
HechtiDerLachs Nov 25, 2024
54a2176
Revert "Temporarily disable some tests."
HechtiDerLachs Nov 25, 2024
3ead720
Repair constructor.
HechtiDerLachs Nov 25, 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
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
include("Objects/Types.jl")
include("Objects/Attributes.jl")
include("Objects/tensor_products.jl")
include("Objects/tensor_product_functionality.jl")
include("Objects/tor.jl")
include("Objects/vector_spaces.jl")
include("Objects/Constructors.jl")
include("Objects/total_complexes.jl")
include("Objects/koszul_complexes.jl")
include("Objects/new_koszul_complexes.jl")
include("Objects/degree_zero_complexes.jl")
include("Objects/new_complex_template.jl")
include("Objects/linear_strands.jl")
include("Objects/eagon_northcott_complex.jl")
include("Objects/induced_ENC.jl")

include("Morphisms/Types.jl")
include("Objects/cartan_eilenberg_resolution.jl")
include("Morphisms/cartan_eilenberg_resolutions.jl")
include("Morphisms/ext.jl")
include("Morphisms/simplified_complexes.jl")
include("Morphisms/free_resolutions.jl")
include("Morphisms/strands.jl")
include("Morphisms/strand_functionality.jl")
include("Morphisms/koszul_complexes.jl")
include("Morphisms/morphism_from_maps.jl")
include("Morphisms/linear_strands.jl")
Expand All @@ -25,3 +31,4 @@ include("Exports.jl")

include("base_change_types.jl")
include("base_change.jl")

20 changes: 20 additions & 0 deletions experimental/DoubleAndHyperComplexes/src/Morphisms/Types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,23 @@ end
underlying_complex(c::SimpleFreeResolution) = c.underlying_complex
original_module(c::SimpleFreeResolution) = c.M

### Lifting morphisms through projective resolutions
mutable struct MapLifter{MorphismType} <: HyperComplexMorphismFactory{MorphismType}
dom::AbsHyperComplex
cod::AbsHyperComplex
orig_map::Map
start_index::Int
offset::Int
check::Bool

function MapLifter(::Type{MorphismType}, dom::AbsHyperComplex, cod::AbsHyperComplex, phi::Map;
start_index::Int=0, offset::Int=0, check::Bool=true
) where {MorphismType}
@assert dim(dom) == 1 && dim(cod) == 1 "lifting of maps is only implemented in dimension one"
@assert (is_chain_complex(dom) && is_chain_complex(cod)) || (is_cochain_complex(dom) && is_cochain_complex(cod))
@assert domain(phi) === dom[start_index]
@assert codomain(phi) === cod[start_index + offset]
return new{MorphismType}(dom, cod, phi, start_index, offset)
end
end

Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
mutable struct MapLifter{MorphismType} <: HyperComplexMorphismFactory{MorphismType}
dom::AbsHyperComplex
cod::AbsHyperComplex
orig_map::Map
start_index::Int
offset::Int
check::Bool

function MapLifter(::Type{MorphismType}, dom::AbsHyperComplex, cod::AbsHyperComplex, phi::Map;
start_index::Int=0, offset::Int=0, check::Bool=true
) where {MorphismType}
@assert dim(dom) == 1 && dim(cod) == 1 "lifting of maps is only implemented in dimension one"
@assert (is_chain_complex(dom) && is_chain_complex(cod)) || (is_cochain_complex(dom) && is_cochain_complex(cod))
@assert domain(phi) === dom[start_index]
@assert codomain(phi) === cod[start_index + offset]
return new{MorphismType}(dom, cod, phi, start_index, offset)
end
end

### Lifting maps through projective resolutions
is_chain_complex(c::AbsHyperComplex) = (dim(c) == 1 ? direction(c, 1) == (:chain) : error("complex is not one-dimensional"))
is_cochain_complex(c::AbsHyperComplex) = (dim(c) == 1 ? direction(c, 1) == (:cochain) : error("complex is not one-dimensional"))

Expand Down Expand Up @@ -57,3 +39,6 @@ function lift_map(dom::AbsHyperComplex{DomChainType}, cod::AbsHyperComplex{CodCh
end

morphism_type(::Type{T1}, ::Type{T2}) where {T1<:ModuleFP, T2<:ModuleFP} = ModuleFPHom{<:T1, <:T2}

### Cartan Eilenberg resolutions

Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ function (fac::SimplifiedChainFactory)(d::AbsHyperComplex, Ind::Tuple)
w = Sinv[i]
v = zero(new_dom)
for j in 1:length(I)
a = w[I[j]]
!iszero(a) && (v += a*new_dom[j])
success, a = _has_index(w, I[j])
success && (v += a*new_dom[j])
end
push!(img_gens_dom, v)
end
Expand Down Expand Up @@ -401,13 +401,13 @@ function _simplify_matrix!(A::SMat; find_pivot=nothing)
# Initialize the base change matrices in domain and codomain
S = sparse_matrix(R, m, m)
for i in 1:m
S[i] = sparse_row(R, [(i, one(R))])
S[i] = sparse_row(R, [(i, one(R))]; sort=false)
end
Sinv_transp = deepcopy(S)

T = sparse_matrix(R, n, n)
for i in 1:n
T[i] = sparse_row(R, [(i, one(R))])
T[i] = sparse_row(R, [(i, one(R))]; sort=false)
end
Tinv_transp = deepcopy(T)

Expand Down Expand Up @@ -479,7 +479,7 @@ function _simplify_matrix!(A::SMat; find_pivot=nothing)
# been treated.

a_row = deepcopy(A[p])
a_row_del = a_row - sparse_row(R, [(q, u)])
a_row_del = a_row - sparse_row(R, [(q, u)]; sort=false)

col_entries = Vector{Tuple{Int, elem_type(R)}}()
for i in 1:m
Expand All @@ -488,8 +488,8 @@ function _simplify_matrix!(A::SMat; find_pivot=nothing)
success, c = _has_index(A, i, q)
success && push!(col_entries, (i, c::elem_type(R)))
end
a_col = sparse_row(R, col_entries)
a_col_del = a_col - sparse_row(R, [(p, u)])
a_col = sparse_row(R, col_entries; sort=false)
a_col_del = a_col - sparse_row(R, [(p, u)]; sort=false)

uinv = inv(u)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
function (fac::StrandChainFactory)(c::AbsHyperComplex, i::Tuple)
M = fac.orig[i]
@assert is_graded(M) "module must be graded"
R = base_ring(M)
kk = coefficient_ring(R)
return FreeMod(kk, length(all_exponents(fac.orig[i], fac.d)))
end

function can_compute(fac::StrandChainFactory, c::AbsHyperComplex, i::Tuple)
return can_compute_index(fac.orig, i)
end


function (fac::StrandMorphismFactory)(c::AbsHyperComplex, p::Int, i::Tuple)
I = collect(i)
Next = I + (direction(c, p) == :chain ? -1 : 1)*[(k==p ? 1 : 0) for k in 1:dim(c)]
next = Tuple(Next)
orig_dom = fac.orig[i]
orig_cod = fac.orig[next]
dom = c[i]
cod = c[next]

orig_map = map(fac.orig, p, i)

# Use a dictionary for fast mapping of the monomials to the
# generators of `cod`.
cod_dict = Dict{Tuple{Vector{Int}, Int}, elem_type(cod)}(m=>cod[k] for (k, m) in enumerate(all_exponents(orig_cod, fac.d)))
#cod_dict = Dict{Tuple{Vector{Int}, Int}, elem_type(cod)}(first(exponents(m))=>cod[k] for (k, m) in enumerate(all_monomials(orig_cod, fac.d)))
# Hashing of FreeModElem's can not be assumed to be non-trivial. Hence we use the exponents directly.
img_gens_res = elem_type(cod)[]
R = base_ring(orig_dom)
vv = gens(R)
for (e, i) in all_exponents(orig_dom, fac.d) # iterate through the generators of `dom`
m = prod(x^k for (x, k) in zip(vv, e); init=one(R))*orig_dom[i]
v = orig_map(m) # map the monomial
# take preimage of the result using the previously built dictionary.
# TODO: Iteration over the terms of v is VERY slow due to its suboptimal implementation.
# We have to iterate manually. This saves us roughly 2/3 of the memory consumption and
# it also runs three times as fast.
w = zero(cod)
for (i, b) in coordinates(v)
#g = orig_cod[i]
w += sum(c*cod_dict[(n, i)] for (c, n) in zip(coefficients(b), exponents(b)); init=zero(cod))
end
push!(img_gens_res, w)
end
return hom(dom, cod, img_gens_res)
end

function can_compute(fac::StrandMorphismFactory, c::AbsHyperComplex, p::Int, i::Tuple)
return can_compute_map(fac.orig, p, i)
end

### User facing constructor
function strand(c::AbsHyperComplex{T}, d::Union{Int, FinGenAbGroupElem}) where {T<:ModuleFP}
result = StrandComplex(c, d)
inc = StrandInclusionMorphism(result)
result.inclusion_map = inc
return result, inc
end

### Some missing methods
# (Disabled for the moment because the use case was disabled due to slowness)
#=
function sparse_matrix(phi::SubQuoHom{<:SubquoModule, <:ModuleFP, Nothing})
R = base_ring(domain(phi))
m = ngens(domain(phi))
n = ngens(codomain(phi))
result = sparse_matrix(R, m, n)
for (i, g) in enumerate(gens(domain(phi)))
result[i] = coordinates(phi(g))
end
return result
end

function sparse_matrix(phi::FreeModuleHom{FreeMod{T}, SubquoModule{T}, Nothing}) where {T}
V = domain(phi)
W = codomain(phi)
kk = base_ring(V)
m = ngens(V)
n = ngens(W)
result = sparse_matrix(kk, m, n)
for (i, g) in enumerate(gens(V))
result[i] = coordinates(phi(g))
end
return result
end
=#

# TODO: Code duplicated from `monomial_basis`. Clean this up!
function all_exponents(W::MPolyDecRing, d::FinGenAbGroupElem)
D = W.D
is_free(D) || error("Grading group must be free")
h = hom(free_abelian_group(ngens(W)), W.d)
fl, p = has_preimage_with_preimage(h, d)
R = base_ring(W)
B = Vector{Int}[]
if fl
k, im = kernel(h)
#need the positive elements in there...
#Ax = b, Cx >= 0
C = identity_matrix(FlintZZ, ngens(W))
A = reduce(vcat, [x.coeff for x = W.d])
k = solve_mixed(transpose(A), transpose(d.coeff), C)
B = Vector{Int}[k[ee, :] for ee in 1:nrows(k)]
end
return B
end

102 changes: 7 additions & 95 deletions experimental/DoubleAndHyperComplexes/src/Morphisms/strands.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
########################################################################
# Strands of hyper complexs of graded free modules.
# Strands of hyper complexes of graded free modules.
#
# Suppose S = 𝕜[x₀,…,xₙ] is a standard graded ring and C a
# hypercomplex of modules over it with all morphisms of degree
Expand All @@ -14,89 +14,36 @@
### Production of the chains
struct StrandChainFactory{ChainType<:ModuleFP} <: HyperComplexChainFactory{ChainType}
orig::AbsHyperComplex
d::Int
d::Union{Int, FinGenAbGroupElem}

function StrandChainFactory(
orig::AbsHyperComplex{ChainType}, d::Int
orig::AbsHyperComplex{ChainType}, d::Union{Int, FinGenAbGroupElem}
) where {ChainType<:ModuleFP}
return new{FreeMod}(orig, d) # TODO: Specify the chain type better
end
end

function (fac::StrandChainFactory)(c::AbsHyperComplex, i::Tuple)
M = fac.orig[i]
@assert is_graded(M) "module must be graded"
R = base_ring(M)
@assert is_standard_graded(R) "the base ring must be standard graded"
kk = coefficient_ring(R)
return FreeMod(kk, length(all_exponents(fac.orig[i], fac.d)))
end

function can_compute(fac::StrandChainFactory, c::AbsHyperComplex, i::Tuple)
return can_compute_index(fac.orig, i)
end

### Production of the morphisms
struct StrandMorphismFactory{MorphismType<:ModuleFPHom} <: HyperComplexMapFactory{MorphismType}
orig::AbsHyperComplex
d::Int
d::Union{Int, FinGenAbGroupElem}
monomial_mappings::Dict{<:Tuple{<:Tuple, Int}, <:Map}

function StrandMorphismFactory(orig::AbsHyperComplex, d::Int)
function StrandMorphismFactory(orig::AbsHyperComplex, d::Union{Int, FinGenAbGroupElem})
monomial_mappings = Dict{Tuple{Tuple, Int}, Map}()
return new{FreeModuleHom}(orig, d, monomial_mappings)
end
end

function (fac::StrandMorphismFactory)(c::AbsHyperComplex, p::Int, i::Tuple)
I = collect(i)
Next = I + (direction(c, p) == :chain ? -1 : 1)*[(k==p ? 1 : 0) for k in 1:dim(c)]
next = Tuple(Next)
orig_dom = fac.orig[i]
orig_cod = fac.orig[next]
dom = c[i]
cod = c[next]

orig_map = map(fac.orig, p, i)

# Use a dictionary for fast mapping of the monomials to the
# generators of `cod`.
cod_dict = Dict{Tuple{Vector{Int}, Int}, elem_type(cod)}(m=>cod[k] for (k, m) in enumerate(all_exponents(orig_cod, fac.d)))
#cod_dict = Dict{Tuple{Vector{Int}, Int}, elem_type(cod)}(first(exponents(m))=>cod[k] for (k, m) in enumerate(all_monomials(orig_cod, fac.d)))
# Hashing of FreeModElem's can not be assumed to be non-trivial. Hence we use the exponents directly.
img_gens_res = elem_type(cod)[]
R = base_ring(orig_dom)
vv = gens(R)
for (e, i) in all_exponents(orig_dom, fac.d) # iterate through the generators of `dom`
m = prod(x^k for (x, k) in zip(vv, e); init=one(R))*orig_dom[i]
v = orig_map(m) # map the monomial
# take preimageof the result using the previously built dictionary.
# TODO: Iteration over the terms of v is VERY slow due to its suboptimal implementation.
# We have to iterate manually. This saves us roughly 2/3 of the memory consumption and
# it also runs three times as fast.
w = zero(cod)
for (i, b) in coordinates(v)
#g = orig_cod[i]
w += sum(c*cod_dict[(n, i)] for (c, n) in zip(coefficients(b), exponents(b)); init=zero(cod))
end
push!(img_gens_res, w)
end
return hom(dom, cod, img_gens_res)
end

function can_compute(fac::StrandMorphismFactory, c::AbsHyperComplex, p::Int, i::Tuple)
return can_compute_map(fac.orig, p, i)
end

### The concrete struct
@attributes mutable struct StrandComplex{ChainType, MorphismType} <: AbsHyperComplex{ChainType, MorphismType}
internal_complex::HyperComplex{ChainType, MorphismType}
original_complex::AbsHyperComplex
d::Int
d::Union{Int, FinGenAbGroupElem}
inclusion_map::AbsHyperComplexMorphism

function StrandComplex(
orig::AbsHyperComplex{ChainType, MorphismType}, d::Int
orig::AbsHyperComplex{ChainType, MorphismType}, d::Union{Int, FinGenAbGroupElem}
) where {ChainType <: ModuleFP, MorphismType <: ModuleFPHom}
chain_fac = StrandChainFactory(orig, d)
map_fac = StrandMorphismFactory(orig, d)
Expand Down Expand Up @@ -160,38 +107,3 @@ end

underlying_morphism(phi::StrandInclusionMorphism) = phi.internal_morphism

### User facing constructor
function strand(c::AbsHyperComplex{T}, d::Int) where {T<:ModuleFP}
result = StrandComplex(c, d)
inc = StrandInclusionMorphism(result)
result.inclusion_map = inc
return result, inc
end

### Some missing methods
# (Disabled for the moment because the use case was disabled due to slowness)
#=
function sparse_matrix(phi::SubQuoHom{<:SubquoModule, <:ModuleFP, Nothing})
R = base_ring(domain(phi))
m = ngens(domain(phi))
n = ngens(codomain(phi))
result = sparse_matrix(R, m, n)
for (i, g) in enumerate(gens(domain(phi)))
result[i] = coordinates(phi(g))
end
return result
end

function sparse_matrix(phi::FreeModuleHom{FreeMod{T}, SubquoModule{T}, Nothing}) where {T}
V = domain(phi)
W = codomain(phi)
kk = base_ring(V)
m = ngens(V)
n = ngens(W)
result = sparse_matrix(kk, m, n)
for (i, g) in enumerate(gens(V))
result[i] = coordinates(phi(g))
end
return result
end
=#
Loading
Loading