diff --git a/src/ideal/ideal.jl b/src/ideal/ideal.jl index 7b51b8205..b5ae38502 100644 --- a/src/ideal/ideal.jl +++ b/src/ideal/ideal.jl @@ -918,11 +918,10 @@ end ############################################################################### @doc raw""" - fres(id::Union{sideal{spoly{T}}, smodule{spoly{T}}}, - max_length::Int, method::String="complete") where T <: Nemo.FieldElem + fres(id::sideal{spoly{T}}, max_length::Int, method::String="complete") where T <: Nemo.FieldElem -Compute a free resolution of the given ideal/module up to the maximum given -length. The ideal/module must be over a polynomial ring over a field, and +Compute a free resolution of the given ideal up to the maximum given +length. The ideal must be over a polynomial ring over a field, and a Groebner basis. The possible methods are "complete", "frame", "extended frame" and "single module". The result is given as a resolution, whose i-th entry is @@ -930,7 +929,7 @@ the syzygy module of the previous module, starting with the given ideal/module. The `max_length` can be set to $0$ if the full free resolution is required. """ -function fres(id::Union{sideal{spoly{T}}, smodule{spoly{T}}}, max_length::Int, method::String = "complete") where T <: Nemo.FieldElem +function fres(id::sideal{spoly{T}}, max_length::Int, method::String = "complete") where T <: Nemo.FieldElem id.isGB || error("Not a Groebner basis") max_length < 0 && error("length for fres must not be negative") R = base_ring(id) diff --git a/src/module/module.jl b/src/module/module.jl index c67d72f1a..70a3b970f 100644 --- a/src/module/module.jl +++ b/src/module/module.jl @@ -241,6 +241,35 @@ end # Resolutions # ############################################################################### +@doc raw""" + fres(id::smodule{spoly{T}}, max_length::Int, method::String="complete") where T <: Nemo.FieldElem + +Compute a free resolution of the given module up to the maximum given +length. The module must be over a polynomial ring over a field, and +a Groebner basis. +The possible methods are "complete", "frame", "extended frame" and +"single module". The result is given as a resolution, whose i-th entry is +the syzygy module of the previous module, starting with the given +ideal/module. +The `max_length` can be set to $0$ if the full free resolution is required. +""" +function fres(id::smodule{spoly{T}}, max_length::Int, method::String = "complete") where T <: Nemo.FieldElem + id.isGB || error("Not a Groebner basis") + max_length < 0 && error("length for fres must not be negative") + R = base_ring(id) + if max_length == 0 + max_length = nvars(R) + # TODO: consider qrings + end + if (method != "complete" + && method != "frame" + && method != "extended frame" + && method != "single module") + error("wrong optional argument for fres") + end + r, minimal = GC.@preserve id R libSingular.id_fres(id.ptr, Cint(max_length + 1), method, R.ptr) + return sresolution{spoly{T}}(R, r, Bool(minimal), false) +end @doc raw""" sres(I::smodule{spoly{T}}, max_length::Int) where T <: Singular.FieldElem diff --git a/test/resolution/sresolution-test.jl b/test/resolution/sresolution-test.jl index 55964e673..4feb7b3fb 100644 --- a/test/resolution/sresolution-test.jl +++ b/test/resolution/sresolution-test.jl @@ -81,3 +81,29 @@ end @test iszero(M1*M2) end +@testset "sresolution.fres_module" begin + R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) + + I = Singular.Ideal(R, y*z + z^2, y^2 + x*z, x*y + z^2, z^3, x*z^2, x^2*z) + M = std(syz(I)) + + F = fres(M, 0) + + # We have R^6 <- R^9 <- R^5 <- R^1 + # All references agree that when written as follows: + # 0 <- M <- R^6 <- R^9 <- R^5 <- R^1 <- 0 + # the length is 3, as numbering starts at index 0 with R^6 + + @test length(F) == 3 + @test F[1] isa smodule + @test F[2] isa smodule + + M1 = Singular.Matrix(F[1]) + M2 = Singular.Matrix(F[2]) + M3 = Singular.Matrix(F[3]) + + @test Singular.Matrix(Singular.Module(M1)) == M1 + + @test iszero(M1*M2) + @test iszero(M2*M3) +end