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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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,14 +1,18 @@
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")
Expand All @@ -17,6 +21,7 @@ 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 Down
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)

Check warning on line 99 in experimental/DoubleAndHyperComplexes/src/Morphisms/strand_functionality.jl

View check run for this annotation

Codecov / codecov/patch

experimental/DoubleAndHyperComplexes/src/Morphisms/strand_functionality.jl#L91-L99

Added lines #L91 - L99 were not covered by tests
#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)]

Check warning on line 105 in experimental/DoubleAndHyperComplexes/src/Morphisms/strand_functionality.jl

View check run for this annotation

Codecov / codecov/patch

experimental/DoubleAndHyperComplexes/src/Morphisms/strand_functionality.jl#L102-L105

Added lines #L102 - L105 were not covered by tests
end
return B

Check warning on line 107 in experimental/DoubleAndHyperComplexes/src/Morphisms/strand_functionality.jl

View check run for this annotation

Codecov / codecov/patch

experimental/DoubleAndHyperComplexes/src/Morphisms/strand_functionality.jl#L107

Added line #L107 was not covered by tests
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
=#
29 changes: 29 additions & 0 deletions experimental/DoubleAndHyperComplexes/src/Objects/Methods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,32 @@
end
end

### Koszul contraction
# Given a free `R`-module `F`, a morphism φ: F → R, and an element `v` in ⋀ ᵖ F,
# compute the contraction φ(v) ∈ ⋀ ᵖ⁻¹ F.
# Note: For this internal method φ is only represented as a dense (column) vector.
function _contract(
v::FreeModElem{T}, phi::Vector{T};
parent::FreeMod{T}=begin
success, F0, p = _is_exterior_power(Oscar.parent(v))
@req success "parent is not an exterior power"

Check warning on line 351 in experimental/DoubleAndHyperComplexes/src/Objects/Methods.jl

View check run for this annotation

Codecov / codecov/patch

experimental/DoubleAndHyperComplexes/src/Objects/Methods.jl#L350-L351

Added lines #L350 - L351 were not covered by tests
exterior_power(F0, p-1)
end
) where {T}
success, F0, p = _is_exterior_power(Oscar.parent(v))
@req success "parent is not an exterior power"
@assert length(phi) == ngens(F0) "lengths are incompatible"
result = zero(parent)
n = ngens(F0)
for (i, ind) in enumerate(OrderedMultiIndexSet(p, n))
is_zero(v[i]) && continue
for j in 1:p
I = deleteat!(copy(indices(ind)), j)
new_ind = OrderedMultiIndex(I, n)
result = result + (-1)^j * v[i] * phi[ind[j]] * parent[linear_index(new_ind)]
end
end
return result
end


Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct CEChainFactory{ChainType} <: HyperComplexChainFactory{ChainType}
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}())
return new{FreeMod}(c, is_exact, Dict{Int, AbsHyperComplex}(), Dict{Int, AbsHyperComplex}(), Dict{Int, AbsHyperComplexMorphism}())
end
end

Expand Down Expand Up @@ -198,12 +198,12 @@ end
@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!
map_fac = CEMapFactory{FreeModuleHom}() # 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)
return new{FreeMod, FreeModuleHom}(internal_complex)
end
end

Expand Down
Loading
Loading