diff --git a/src/Modules/UngradedModules/FreeResolutions.jl b/src/Modules/UngradedModules/FreeResolutions.jl index 672d8c4696e..b7312236e7b 100644 --- a/src/Modules/UngradedModules/FreeResolutions.jl +++ b/src/Modules/UngradedModules/FreeResolutions.jl @@ -1,4 +1,4 @@ - function map(FR::FreeResolution, i::Int) +function map(FR::FreeResolution, i::Int) return map(FR.C, i) end @@ -313,7 +313,7 @@ function free_resolution(M::SubquoModule{<:MPolyRingElem}; cc_complete = false #= Start with presentation =# - pm = presentation(M) + pm = algorithm == :mres ? _presentation_minimal(M, minimal_kernel=false) : presentation(M) maps = [pm.maps[j] for j in 2:3] br = base_ring(M) diff --git a/src/Modules/UngradedModules/Presentation.jl b/src/Modules/UngradedModules/Presentation.jl index 9820cf8f114..24ba8ce886d 100644 --- a/src/Modules/UngradedModules/Presentation.jl +++ b/src/Modules/UngradedModules/Presentation.jl @@ -1,12 +1,16 @@ #################### @doc raw""" - presentation(M::SubquoModule) + presentation(M::SubquoModule; minimal=false) -Return a free presentation of `M`. +Return a free presentation of `M`. If `minimal` is set to `true`, the returned +presentation is minimal. """ -function presentation(SQ::SubquoModule) - if is_graded(SQ) +function presentation(SQ::SubquoModule; + minimal=false) + if minimal + return _presentation_minimal(SQ) + elseif is_graded(SQ) return _presentation_graded(SQ) else return _presentation_simple(SQ) @@ -559,6 +563,56 @@ function prune_with_map(M::ModuleFP{T}) where {T<:MPolyRingElem{<:FieldElem}} # return M_new, phi end +function _presentation_minimal(SQ::ModuleFP{T}; + minimal_kernel::Bool=true) where {T<:MPolyRingElem{<:FieldElem}} + R = base_ring(SQ) + + # Prepare to set some names + br_name = AbstractAlgebra.get_name(R) + if br_name === nothing + br_name = "br" + end + + SQ_new, phi = prune_with_map(SQ) + F0 = ambient_free_module(SQ_new) + + # M_new is a quotient of a free module + proj_map = hom(F0, SQ_new, gens(SQ_new), check=false) + F0_to_SQ = compose(proj_map, phi) + F0_to_SQ.generators_map_to_generators = true + AbstractAlgebra.set_name!(F0, "$br_name^$(ngens(F0))") + + # if we want a minimal kernel too, we go to prune_with_map + K, inc = sub(F0, relations(SQ_new)) + if minimal_kernel + K, inc2 = prune_with_map(K) + inc = compose(inc2, inc) + end + F1 = if is_graded(SQ) + graded_free_module(R, degrees_of_generators(K)) + else + free_module(R, ngens(K)) + end + F1_to_F0 = compose(hom(F1, K, gens(K), check=false), inc) + AbstractAlgebra.set_name!(F1, "$br_name^$(ngens(F1))") + + # When there is no kernel, clean things up + if is_zero(F1) + F1 = FreeMod(R, 0) + F1_to_F0 = hom(F1, F0, elem_type(F0)[]; check=false) + end + + # prepare the end of the presentation + Z = FreeMod(R, 0) + AbstractAlgebra.set_name!(Z, "0") + SQ_to_Z = hom(SQ, Z, elem_type(Z)[zero(Z) for i in 1:ngens(SQ)]; check=false) + + # compile the presentation complex + CC = Hecke.ComplexOfMorphisms(ModuleFP, ModuleFPHom[F1_to_F0, F0_to_SQ, SQ_to_Z], check=false, seed = -2) + set_attribute!(CC, :show => Hecke.pres_show) + return CC +end + function prune_with_map(F::FreeMod) return F, hom(F, F, gens(F)) end diff --git a/test/Modules/ModulesGraded.jl b/test/Modules/ModulesGraded.jl index a918dbe0929..fa11bbea94f 100644 --- a/test/Modules/ModulesGraded.jl +++ b/test/Modules/ModulesGraded.jl @@ -339,6 +339,12 @@ end @test codomain(psi) == N @test is_bijective(phi) @test is_bijective(psi) + I = ideal(Rg, [x^2, x*y, y]) + A, _ = quo(Rg, I) + M = quotient_ring_as_module(A) + mp = presentation(M, minimal = true) + @test rank(mp[0]) == 1 + @test rank(mp[1]) == 2 end