diff --git a/docs/doc.main b/docs/doc.main index 54e4c50eefa7..cf7b826648f0 100644 --- a/docs/doc.main +++ b/docs/doc.main @@ -168,6 +168,9 @@ "AlgebraicGeometry/Schemes/ProjectiveSchemes.md", "AlgebraicGeometry/Schemes/MorphismsOfProjectiveSchemes.md", ], + "Sheaf Cohomology" => [ + "AlgebraicGeometry/SheafCohomology/sheaf_cohomology.md", + ], "Algebraic Sets" => [ "AlgebraicGeometry/AlgebraicSets/AffineAlgebraicSet.md", "AlgebraicGeometry/AlgebraicSets/ProjectiveAlgebraicSet.md", diff --git a/docs/oscar_references.bib b/docs/oscar_references.bib index c30190c1f0a1..653efb529ac3 100644 --- a/docs/oscar_references.bib +++ b/docs/oscar_references.bib @@ -461,6 +461,18 @@ @Article{Cor21 doi = {10.1007/s00029-021-00679-6} } +@InCollection{DE02, + author = {Decker, Wolfram and Eisenbud, David}, + title = {Sheaf algorithms using the exterior algebra}, + booktitle = {Computations in algebraic geometry with Macaulay 2}, + zbl = {0994.14010}, + publisher = {Berlin: Springer}, + pages = {215--249}, + year = {2002}, + language = {English}, + zbmath = {1693054} +} + @Article{DES93, author = {Decker, Wolfram and Ein, Lawrence and Schreyer, Frank-Olaf}, title = {Construction of surfaces in ${\mathbb P}^4$}, @@ -631,6 +643,21 @@ @Article{Der99 doi = {10.1006/aima.1998.1787} } +@Article{EFS03, + author = {Eisenbud, David and Fl{\o}ystad, Gunnar and Schreyer, Frank-Olaf}, + title = {Sheaf cohomology and free resolutions over exterior algebras}, + zbl = {1063.14021}, + journal = {Trans. Am. Math. Soc.}, + fjournal = {Transactions of the American Mathematical Society}, + volume = {355}, + number = {11}, + pages = {4397--4426}, + year = {2003}, + doi = {10.1090/S0002-9947-03-03291-4}, + language = {English}, + zbmath = {1963988} +} + @Article{EHU03, author = {Eisenbud, David and Huneke, Craig and Ulrich, Bernd}, title = {What is the {Rees} algebra of a module?}, @@ -704,6 +731,16 @@ @Book{Eis95 year = {1995} } +@Book{Eis98, + author = {Eisenbud, David}, + title = {Computing cohomology. A chapter in W. Vasconcelos, Computational methods in commutative algebra and + algebraic geometry}, + publisher = {Berlin: Springer}, + pages = {209--216}, + year = {1998}, + language = {English} +} + @Article{FGLM93, author = {Faugère, J.C. and Gianni, P. and Lazard, D. and Mora, T.}, title = {Efficient Computation of Zero-dimensional Gröbner Bases by Change of Ordering}, diff --git a/docs/src/AlgebraicGeometry/SheafCohomology/sheaf_cohomology.md b/docs/src/AlgebraicGeometry/SheafCohomology/sheaf_cohomology.md new file mode 100644 index 000000000000..601a4aa0bde5 --- /dev/null +++ b/docs/src/AlgebraicGeometry/SheafCohomology/sheaf_cohomology.md @@ -0,0 +1,22 @@ +```@meta +CurrentModule = Oscar +DocTestSetup = quote + using Oscar +end +``` + +# Sheaves on Projective Space + +We present two algorithms for computing sheaf cohomology over projective $n$-space. +The algorithms are based on Tate resolutions via the **B**ernstein-**G**elfand-**G**elfand-correspondence +as introduced in [EFS03](@cite) and on local cohomology (see [Eis98](@cite)), respectively. While the first +algorithm makes use of syzygy computations over the exterior algebra, the second algorithm is based on +syzygy computations over the symmetric algebra (see [DE02](@cite) for a tutorial). Thus, in most examples, +the first algorithm is much faster. + +```@docs +sheaf_cohomology(M::ModuleFP{T}, l::Int, h::Int; algorithm::Symbol = :bgg) where {T <: MPolyDecRingElem} +``` + + + diff --git a/src/Modules/ModulesGraded.jl b/src/Modules/ModulesGraded.jl index f8369cf02db4..fabd79453858 100644 --- a/src/Modules/ModulesGraded.jl +++ b/src/Modules/ModulesGraded.jl @@ -1484,7 +1484,7 @@ mutable struct sheafCohTable end function Base.getindex(st::sheafCohTable, ind...) - row_ind = ind[1] + 1 + row_ind = size(st.values, 1) - ind[1] col_ind = ind[2] - first(st.twist_range) + 1 return st.values[row_ind, col_ind] end @@ -1503,7 +1503,7 @@ function Base.show(io::IO, table::sheafCohTable) # row labels row_label_length = max(_ndigits(nrows - 1), 3) + 3 for i in 1:nrows - pushfirst!(print_rows[i], rpad("$(i-1): ", row_label_length, " ")) + pushfirst!(print_rows[i], rpad("$(nrows-i): ", row_label_length, " ")) end pushfirst!(chi_print, rpad("chi: ", row_label_length, " ")) @@ -1524,18 +1524,22 @@ end @doc raw""" sheaf_cohomology(M::ModuleFP{T}, l::Int, h::Int; algorithm::Symbol = :bgg) where {T <: MPolyDecRingElem} -Compute the cohomology of twists of of the coherent sheaf on projective -space associated to `M`. The range of twists is between `l` and `h`. -In the displayed result, '-' refers to a zero enty and '*' refers to a -negative entry (= dimension not yet determined). To determine all values -in the desired range between `l` and `h` use `sheafCoh_BGG_regul(M, l-ngens(base_ring(M)), h+ngens(base_ring(M)))`. -The values of the returned table can be accessed by indexing it -with a cohomological index and a value between `l` and `h` as shown -in the example below. +If `M` is a graded module over a standard graded multivariate polynomial ring with coefficients in a field `K`, +say, and $\mathcal F = \widetilde{M}$ is the coherent sheaf associated to `M` on the corresponding projective +space $\mathbb P^n(K)$, consider the cohomology groups $H^i(\mathbb P^n(K), \mathcal F(d))$ as vector spaces +over $K$, and return their dimensions $h^i(\mathbb P^n(K), \mathcal F(d))$ in the range of twists $d$ +indicated by `l` and `h`. The result is presented as a table, where '-' indicates that +$h^i(\mathbb P^n(K), \mathcal F(d)) = 0$. The line starting with `chi` lists the Euler characteristic +of each twist under consideration. The values in the table can be accessed as shown in the +first example below. Note that this example addresses the cotangent bundle on projective 3-space, while the +second example is concerned with the structure sheaf of projective 4-space. The keyword `algorithm` can be set to -- `:bgg` (uses the Bernstein-Gelfand-Gelfand correspondence), -- `:loccoh` (uses local duality), +- `:bgg` (use the Tate resolution via the Bernstein-Gelfand-Gelfand correspondence), +- `:loccoh` (use local cohomology). + +!!! note + Due to the shape of the Tate resolution, the algorithm addressed by `bgg` does not compute all values in the given range `l` $<$ `h`. The missing values are indicated by a `*`. To determine all values in the range `l` $<$ `h`, enter `sheaf_cohomology(M, l-ngens(base_ring(M)), h+ngens(base_ring(M)))`. ```jldoctest julia> R, x = polynomial_ring(QQ, "x" => 1:4); @@ -1555,35 +1559,47 @@ julia> M = cokernel(map(FI, 2)); julia> tbl = sheaf_cohomology(M, -6, 2) twist: -6 -5 -4 -3 -2 -1 0 1 2 ------------------------------------------ -0: 70 36 15 4 - - - - * -1: * - - - - - - - - -2: * * - - - - 1 - - -3: * * * - - - - - 6 +3: 70 36 15 4 - - - - * +2: * - - - - - - - - +1: * * - - - - 1 - - +0: * * * - - - - - 6 ------------------------------------------ chi: * * * 4 - - 1 - * -julia> tbl[0, -6] -70 +julia> tbl[0, 2] +6 -julia> tbl[2, 0] +julia> tbl[1, 0] 1 +julia> sheaf_cohomology(M, -9, 5) +twist: -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 +--------------------------------------------------------------------------------- +3: 280 189 120 70 36 15 4 - - - - - * * * +2: * - - - - - - - - - - - - * * +1: * * - - - - - - - 1 - - - - * +0: * * * - - - - - - - - 6 20 45 84 +--------------------------------------------------------------------------------- +chi: * * * 70 36 15 4 - - 1 - 6 * * * +``` + +```jldoctest julia> R, x = polynomial_ring(QQ, "x" => 1:5); -julia> R, x = grade(R); +julia> S, _ = grade(R); -julia> F = graded_free_module(R, 1); +julia> F = graded_free_module(S, 1); -julia> sheaf_cohomology(F, -7, 2, algorithm = :bgg) -twist: -7 -6 -5 -4 -3 -2 -1 0 1 2 ----------------------------------------------- -0: 15 5 1 - - - * * * * -1: * - - - - - - * * * -2: * * - - - - - - * * -3: * * * - - - - - - * -4: * * * * - - - 1 5 15 ----------------------------------------------- -chi: * * * * - - * * * * +julia> sheaf_cohomology(F, -8, 3, algorithm = :loccoh) +twist: -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 +------------------------------------------------------ +4: 35 15 5 1 - - - - - - - - +3: - - - - - - - - - - - - +2: - - - - - - - - - - - - +1: - - - - - - - - - - - - +0: - - - - - - - - 1 5 15 35 +------------------------------------------------------ +chi: 35 15 5 1 - - - - 1 5 15 35 ``` """ function sheaf_cohomology(M::ModuleFP{T}, @@ -1611,6 +1627,36 @@ The values of the returned table can be accessed by indexing it with a cohomological index and a value between `l` and `h` as shown in the example below. +```jldoctest +julia> R, x = polynomial_ring(QQ, "x" => 1:5); + +julia> R, x = grade(R); + +julia> F = graded_free_module(R, 1); + +julia> Oscar._sheaf_cohomology_bgg(F, -7, 2) +twist: -7 -6 -5 -4 -3 -2 -1 0 1 2 +---------------------------------------------- +4: 15 5 1 - - - * * * * +3: * - - - - - - * * * +2: * * - - - - - - * * +1: * * * - - - - - - * +0: * * * * - - - 1 5 15 +---------------------------------------------- +chi: * * * * - - * * * * + +julia> sheaf_cohomology(F, -11, 6) +twist: -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 +------------------------------------------------------------------------------------------------ +4: 210 126 70 35 15 5 1 - - - - - - - * * * * +3: * - - - - - - - - - - - - - - * * * +2: * * - - - - - - - - - - - - - - * * +1: * * * - - - - - - - - - - - - - - * +0: * * * * - - - - - - - 1 5 15 35 70 126 210 +------------------------------------------------------------------------------------------------ +chi: * * * * 15 5 1 - - - - 1 5 15 * * * * +``` + ```jldoctest julia> R, x = polynomial_ring(QQ, "x" => 1:4); @@ -1626,38 +1672,21 @@ S^4 <---- S^6 <---- S^4 <---- S^1 <---- 0 julia> M = cokernel(map(FI, 2)); -julia> tbl = Oscar._sheaf_cohomology_bgg(M, -6, 2) +julia> tbl = sheaf_cohomology(M, -6, 2, algorithm = :loccoh) twist: -6 -5 -4 -3 -2 -1 0 1 2 ------------------------------------------ -0: 70 36 15 4 - - - - * -1: * - - - - - - - - -2: * * - - - - 1 - - -3: * * * - - - - - 6 +3: 70 36 15 4 - - - - - +2: - - - - - - - - - +1: - - - - - - 1 - - +0: - - - - - - - - 6 ------------------------------------------ -chi: * * * 4 - - 1 - * +chi: 70 36 15 4 - - 1 - 6 -julia> tbl[0, -6] +julia> tbl[3, -6] 70 -julia> tbl[2, 0] +julia> tbl[1, 0] 1 - -julia> R, x = polynomial_ring(QQ, "x" => 1:5); - -julia> R, x = grade(R); - -julia> F = graded_free_module(R, 1); - -julia> Oscar._sheaf_cohomology_bgg(F, -7, 2) -twist: -7 -6 -5 -4 -3 -2 -1 0 1 2 ----------------------------------------------- -0: 15 5 1 - - - * * * * -1: * - - - - - - * * * -2: * * - - - - - - * * -3: * * * - - - - - - * -4: * * * * - - - 1 5 15 ----------------------------------------------- -chi: * * * * - - * * * * ``` """ function _sheaf_cohomology_bgg(M::ModuleFP{T}, @@ -1703,17 +1732,17 @@ julia> M = cokernel(map(FI, 2)); julia> tbl = Oscar._sheaf_cohomology_loccoh(M, -6, 2) twist: -6 -5 -4 -3 -2 -1 0 1 2 ------------------------------------------ -0: 70 36 15 4 - - - - - -1: - - - - - - - - - -2: - - - - - - 1 - - -3: - - - - - - - - 6 +3: 70 36 15 4 - - - - - +2: - - - - - - - - - +1: - - - - - - 1 - - +0: - - - - - - - - 6 ------------------------------------------ chi: 70 36 15 4 - - 1 - 6 -julia> tbl[0, -6] +julia> tbl[3, -6] 70 -julia> tbl[2, 0] +julia> tbl[1, 0] 1 julia> R, x = polynomial_ring(QQ, "x" => 1:5); @@ -1725,11 +1754,11 @@ julia> F = graded_free_module(R, 1); julia> Oscar._sheaf_cohomology_loccoh(F, -7, 2) twist: -7 -6 -5 -4 -3 -2 -1 0 1 2 ---------------------------------------------- -0: 15 5 1 - - - - - - - -1: - - - - - - - - - - -2: - - - - - - - - - - +4: 15 5 1 - - - - - - - 3: - - - - - - - - - - -4: - - - - - - - 1 5 15 +2: - - - - - - - - - - +1: - - - - - - - - - - +0: - - - - - - - 1 5 15 ---------------------------------------------- chi: 15 5 1 - - - - 1 5 15 ``` @@ -1760,9 +1789,12 @@ function _ndigits(val::Int) end function _weights_and_sing_mod(M::ModuleFP{T}) where {T <: MPolyDecRingElem} + + CR = base_ring(base_ring(M)) + @assert isa(CR, AbstractAlgebra.Field) "Base ring of input module must be defined over a field." free_mod = ambient_free_module(M) - @assert is_graded(M) "Module must be graded." @assert is_standard_graded(free_mod) "Only supported for the standard grading of polynomials." + @assert is_graded(M) "Module must be graded." # get a cokernel presentation of M p = presentation(M) @@ -2052,6 +2084,8 @@ end elem_type(::Type{FreeMod_dec{T}}) where {T} = FreeModElem_dec{T} parent_type(::Type{FreeModElem_dec{T}}) where {T} = FreeMod_dec{T} +elem_type(::FreeMod_dec{T}) where {T} = FreeModElem_dec{T} +parent_type(::FreeModElem_dec{T}) where {T} = FreeMod_dec{T} @doc raw""" """ diff --git a/test/Modules/ModulesGraded.jl b/test/Modules/ModulesGraded.jl index 92d940049744..d0696fc8d730 100644 --- a/test/Modules/ModulesGraded.jl +++ b/test/Modules/ModulesGraded.jl @@ -1076,8 +1076,8 @@ end tbl = Oscar._sheaf_cohomology_bgg(M, -6, 2) lbt = sheaf_cohomology(M, -6, 2, algorithm = :bgg) @test tbl.values == lbt.values - @test tbl[0, -6] == 70 - @test tbl[2, 0] == 1 + @test tbl[3, -6] == 70 + @test tbl[1, 0] == 1 @test iszero(tbl[2, -2]) F = free_module(S, 1)