From 6b9dcc66ce9150f40dbe7cb3c1309ba9b359975b Mon Sep 17 00:00:00 2001 From: Rafael Mohr Date: Thu, 6 Jun 2024 17:00:20 +0200 Subject: [PATCH 01/13] adapt module gens to quotient rings --- src/Modules/UngradedModules/FreeResolutions.jl | 5 ++--- src/Modules/UngradedModules/ModuleGens.jl | 12 ++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Modules/UngradedModules/FreeResolutions.jl b/src/Modules/UngradedModules/FreeResolutions.jl index b7312236e7b0..d09680b42522 100644 --- a/src/Modules/UngradedModules/FreeResolutions.jl +++ b/src/Modules/UngradedModules/FreeResolutions.jl @@ -303,9 +303,8 @@ R^2 <---- R^6 <---- R^6 <---- R^2 <---- 0 **Note:** Over rings other than polynomial rings, the method will default to a lazy, iterative kernel computation. """ -function free_resolution(M::SubquoModule{<:MPolyRingElem}; - ordering::ModuleOrdering = default_ordering(M), - length::Int=0, algorithm::Symbol=:fres) +function free_resolution(M::SubquoModule{T}; + length::Int=0, algorithm::Symbol=:fres) where {T <: Union{MPolyRingElem, MPolyQuoRingElem}} coefficient_ring(base_ring(M)) isa AbstractAlgebra.Field || error("Must be defined over a field.") diff --git a/src/Modules/UngradedModules/ModuleGens.jl b/src/Modules/UngradedModules/ModuleGens.jl index 7a9f5933f376..d77cd1df6e9c 100644 --- a/src/Modules/UngradedModules/ModuleGens.jl +++ b/src/Modules/UngradedModules/ModuleGens.jl @@ -263,19 +263,19 @@ Convert a Singular vector to a free module element. """ function (F::FreeMod)(s::Singular.svector) pos = Int[] - values = [] Rx = base_ring(F) - R = base_ring(Rx) - for (i, e, c) = s + R = coefficient_ring(Rx) + values = elem_type(Rx)[] + for (i, e, c) in s f = Base.findfirst(x->x==i, pos) if f === nothing - push!(values, MPolyBuildCtx(base_ring(F))) + push!(values, zero(Rx)) f = length(values) push!(pos, i) end - push_term!(values[f], R(c), e) + values[f] += R(c)*prod(gens(Rx) .^ e) end - pv = Tuple{Int, elem_type(Rx)}[(pos[i], base_ring(F)(finish(values[i]))) for i=1:length(pos)] + pv = [(pos[i], values[i]) for i=1:length(pos)] return FreeModElem(sparse_row(base_ring(F), pv), F) end From f8a555bc6aebcda3e0c200b989dff5b99a98e50e Mon Sep 17 00:00:00 2001 From: Rafael Mohr Date: Tue, 18 Jun 2024 12:10:22 +0200 Subject: [PATCH 02/13] adjusts signatures of `prune_with_map` and `_presentation_minimal` --- src/Modules/UngradedModules/Presentation.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Modules/UngradedModules/Presentation.jl b/src/Modules/UngradedModules/Presentation.jl index 24ba8ce886df..121a15c0d72a 100644 --- a/src/Modules/UngradedModules/Presentation.jl +++ b/src/Modules/UngradedModules/Presentation.jl @@ -519,7 +519,7 @@ function prune_with_map(M::ModuleFP) return N, b end -function prune_with_map(M::ModuleFP{T}) where {T<:MPolyRingElem{<:FieldElem}} # The case that can be handled by Singular +function prune_with_map(M::ModuleFP{T}) where {T<:Union{MPolyRingElem, MPolyQuoRingElem}} # The case that can be handled by Singular # Singular presentation pm = presentation(M) @@ -564,7 +564,7 @@ function prune_with_map(M::ModuleFP{T}) where {T<:MPolyRingElem{<:FieldElem}} # end function _presentation_minimal(SQ::ModuleFP{T}; - minimal_kernel::Bool=true) where {T<:MPolyRingElem{<:FieldElem}} + minimal_kernel::Bool=true) where {T <: Union{MPolyRingElem, MPolyQuoRingElem}} R = base_ring(SQ) # Prepare to set some names From 6925b562295296d06022e7ffbe1af5cbb2f2b894 Mon Sep 17 00:00:00 2001 From: Rafael Mohr Date: Mon, 23 Sep 2024 16:25:46 +0200 Subject: [PATCH 03/13] compute free resolutions over quotients with sres --- src/Modules/UngradedModules/FreeResolutions.jl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Modules/UngradedModules/FreeResolutions.jl b/src/Modules/UngradedModules/FreeResolutions.jl index f99b4e85cec5..3296fede85b7 100644 --- a/src/Modules/UngradedModules/FreeResolutions.jl +++ b/src/Modules/UngradedModules/FreeResolutions.jl @@ -396,11 +396,16 @@ julia> matrix(map(FM3, 1)) iterative kernel computation. """ function free_resolution(M::SubquoModule{T}; - length::Int=0, algorithm::Symbol=:fres) where {T <: Union{MPolyRingElem, MPolyQuoRingElem}} + length::Int=0, + algorithm::Symbol = T <:MPolyRingElem ? :fres : :sres) where {T <: Union{MPolyRingElem, MPolyQuoRingElem}} coefficient_ring(base_ring(M)) isa AbstractAlgebra.Field || error("Must be defined over a field.") + if T <: MPolyQuoRingElem + !iszero(length) || error("Specify a length up to which a free resolution should be computed") + end + cc_complete = false #= Start with presentation =# @@ -434,6 +439,9 @@ function free_resolution(M::SubquoModule{T}; elseif algorithm == :nres gbpres = singular_kernel_entry res = Singular.nres(gbpres, length) + elseif algorithm == :sres && T <: MPolyQuoRingElem + gbpres = Singular.std(singular_kernel_entry) + res = Singular.sres(gbpres, length) else error("Unsupported algorithm $algorithm") end From f47f4568f02c8192c601102dce26bd4298342ca4 Mon Sep 17 00:00:00 2001 From: Rafael Mohr Date: Mon, 23 Sep 2024 16:30:31 +0200 Subject: [PATCH 04/13] updates docu --- src/Modules/UngradedModules/FreeResolutions.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Modules/UngradedModules/FreeResolutions.jl b/src/Modules/UngradedModules/FreeResolutions.jl index 3296fede85b7..8af80f5b6b6e 100644 --- a/src/Modules/UngradedModules/FreeResolutions.jl +++ b/src/Modules/UngradedModules/FreeResolutions.jl @@ -230,15 +230,15 @@ function _extend_free_resolution(cc::Hecke.ComplexOfMorphisms, idx::Int) end @doc raw""" - free_resolution(M::SubquoModule{<:MPolyRingElem}; - ordering::ModuleOrdering = default_ordering(M), - length::Int = 0, algorithm::Symbol = :fres - ) + free_resolution(M::SubquoModule{T}; + length::Int=0, + algorithm::Symbol = T <:MPolyRingElem ? :fres : :sres) where {T <: Union{MPolyRingElem, MPolyQuoRingElem}} Return a free resolution of `M`. If `length != 0`, the free resolution is only computed up to the `length`-th free module. -Current options for `algorithm` are `:fres`, `:nres`, and `:mres`. +Current options for `algorithm` are `:fres`, `:nres`, and `:mres` for modules over +polynomial rings and `:sres` for modules over quotients of polynomial rings. !!! note The function first computes a presentation of `M`. It then successively computes @@ -255,6 +255,10 @@ Current options for `algorithm` are `:fres`, `:nres`, and `:mres`. [EMSS16](@cite). Typically, this is more efficient than the approaches above, but the resulting resolution is far from being minimal. +!!! note + If `M` is a module over a quotient of a polynomial ring then the `length` keyword must + be set to a nonzero value. + # Examples ```jldoctest julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) @@ -392,7 +396,7 @@ julia> matrix(map(FM3, 1)) ``` -**Note:** Over rings other than polynomial rings, the method will default to a lazy, +**Note:** Over rings other than polynomial rings or quotients of polynomial rings, the method will default to a lazy, iterative kernel computation. """ function free_resolution(M::SubquoModule{T}; From 14c7ab3ad16424e64b747ec9bf92b2af9c848333 Mon Sep 17 00:00:00 2001 From: Rafael Mohr Date: Mon, 23 Sep 2024 16:34:59 +0200 Subject: [PATCH 05/13] adds test --- test/Modules/UngradedModules.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/Modules/UngradedModules.jl b/test/Modules/UngradedModules.jl index c417bbc9368c..55a8f5e64812 100644 --- a/test/Modules/UngradedModules.jl +++ b/test/Modules/UngradedModules.jl @@ -275,6 +275,14 @@ end @test relations(C) == [zero(F)] @test domain(isom) == F @test codomain(isom) == C + + R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]); + A, p = quo(R, ideal(R, x^5)) + M1 = identity_matrix(A, 2) + M2 = A[-x-y 2*x^2+x; z^4 0; 0 z^4; 8*x^3*y - 4*x^3 - 4*x^2*y + 2*x^2 + 2*x*y - x - y x; x^4 0] + M = SubquoModule(M1, M2) + fr = free_resolution(M, length = 9) + @test all(iszero, homology(fr[2:end])) end @testset "Prune With Map" begin From 452dd0279c98ee5f4952191b2c8926b64d750dd1 Mon Sep 17 00:00:00 2001 From: Rafael Mohr Date: Tue, 24 Sep 2024 10:28:12 +0200 Subject: [PATCH 06/13] fix tests --- test/Modules/UngradedModules.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Modules/UngradedModules.jl b/test/Modules/UngradedModules.jl index 55a8f5e64812..b696702483b4 100644 --- a/test/Modules/UngradedModules.jl +++ b/test/Modules/UngradedModules.jl @@ -282,7 +282,7 @@ end M2 = A[-x-y 2*x^2+x; z^4 0; 0 z^4; 8*x^3*y - 4*x^3 - 4*x^2*y + 2*x^2 + 2*x*y - x - y x; x^4 0] M = SubquoModule(M1, M2) fr = free_resolution(M, length = 9) - @test all(iszero, homology(fr[2:end])) + @test all(iszero, homology(fr)[2:end]) end @testset "Prune With Map" begin From 8588359603bff425d4ec528f5fb965978a9eedcd Mon Sep 17 00:00:00 2001 From: Rafael Mohr Date: Tue, 24 Sep 2024 16:22:35 +0200 Subject: [PATCH 07/13] fix another test --- test/Modules/MPolyQuo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Modules/MPolyQuo.jl b/test/Modules/MPolyQuo.jl index ef654cacf178..4505b9e6c3a0 100644 --- a/test/Modules/MPolyQuo.jl +++ b/test/Modules/MPolyQuo.jl @@ -96,7 +96,7 @@ end A2 = FreeMod(A, 2) v = [x*A2[1] + y*A2[2], z*A2[1] + (x-1)*A2[2]] M, _ = quo(A2, v) - p = free_resolution(M) + p = free_resolution(M, length = 11) @test !iszero(p[10]) end From 145394ce7c7417c0c8997b2f8530ce19eba889fe Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 24 Sep 2024 18:48:13 +0200 Subject: [PATCH 08/13] Replace kernel routine for mpolyquos. --- src/Modules/mpolyquo.jl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Modules/mpolyquo.jl b/src/Modules/mpolyquo.jl index e2aca6b078ef..cda716f8145e 100644 --- a/src/Modules/mpolyquo.jl +++ b/src/Modules/mpolyquo.jl @@ -11,17 +11,15 @@ CodomainType<:FreeMod{<:MPolyQuoRingElem} } R = base_ring(codomain(f)) - P = base_ring(R) - F = _poly_module(domain(f)) - M = _as_poly_module(codomain(f)) - id = _iso_with_poly_module(codomain(f)) - # Why does img_gens(f) return a list of SubQuoElems??? - phi = _lifting_iso(codomain(f)) - g = hom(F, M, phi.(f.(gens(domain(f))))) - K, inc = kernel(g) - tr = compose(inc, _poly_module_restriction(domain(f))) - KK, inc2 = sub(domain(f), unique!(filter!(!iszero, tr.(gens(K))))) - return KK, inc2 + SR = singular_poly_ring(R) + F = domain(f) + G = codomain(f) + img_gens = images_of_generators(f) + MG = ModuleGens(img_gens, G) + singular_assure(MG) + sing_ker_gens = Singular.syz(singular_generators(MG)) + KG = ModuleGens(F, sing_ker_gens) + return sub(F, oscar_generators(KG)) end function Base.in(a::FreeModElem{T}, M::SubModuleOfFreeModule{T}) where {T<:MPolyQuoRingElem} From 52fce1e44f2ecb8cddf696f58dbead5a27831dc4 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 24 Sep 2024 20:01:15 +0200 Subject: [PATCH 09/13] Add debug comments. --- src/Modules/mpolyquo.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Modules/mpolyquo.jl b/src/Modules/mpolyquo.jl index cda716f8145e..375cac6eb658 100644 --- a/src/Modules/mpolyquo.jl +++ b/src/Modules/mpolyquo.jl @@ -10,6 +10,7 @@ DomainType<:FreeMod{<:MPolyQuoRingElem}, CodomainType<:FreeMod{<:MPolyQuoRingElem} } + @show "this kernel" R = base_ring(codomain(f)) SR = singular_poly_ring(R) F = domain(f) @@ -18,6 +19,7 @@ MG = ModuleGens(img_gens, G) singular_assure(MG) sing_ker_gens = Singular.syz(singular_generators(MG)) + @show "done with syzygy computations" KG = ModuleGens(F, sing_ker_gens) return sub(F, oscar_generators(KG)) end From 98e7f1830db0bf10433b30aa1cda15b8b5d99381 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Thu, 19 Sep 2024 16:45:21 +0200 Subject: [PATCH 10/13] Attempt to speed up mapping of polynomials. --- src/Rings/MPolyMap/MPolyAnyMap.jl | 10 +++++++++- src/Rings/MPolyMap/MPolyRing.jl | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Rings/MPolyMap/MPolyAnyMap.jl b/src/Rings/MPolyMap/MPolyAnyMap.jl index 873365b9ad5f..ce09648d1567 100644 --- a/src/Rings/MPolyMap/MPolyAnyMap.jl +++ b/src/Rings/MPolyMap/MPolyAnyMap.jl @@ -42,6 +42,10 @@ const _DomainTypes = Union{MPolyRing, MPolyQuoRing} coeff_map::U img_gens::Vector{V} temp_ring # temporary ring used when evaluating maps + variable_indices::Vector{Int} # a table where the i-th entry contains the + # index of the variable where it's mapped to + # in case the mapping takes such a particularly + # simple form. function MPolyAnyMap{D, C, U, V}(domain::D, codomain::C, @@ -51,7 +55,11 @@ const _DomainTypes = Union{MPolyRing, MPolyQuoRing} for g in img_gens @assert parent(g) === codomain "elements does not have the correct parent" end - return new{D, C, U, V}(domain, codomain, coeff_map, img_gens) + result = new{D, C, U, V}(domain, codomain, coeff_map, img_gens) + if all(x in gens(codomain) for x in img_gens) && length(unique(img_gens)) == ngens(domain) + result.variable_indices = [findfirst(x==y for y in gens(codomain)) for x in img_gens] + end + return result end end diff --git a/src/Rings/MPolyMap/MPolyRing.jl b/src/Rings/MPolyMap/MPolyRing.jl index 4a14a083baae..a64931ce7091 100644 --- a/src/Rings/MPolyMap/MPolyRing.jl +++ b/src/Rings/MPolyMap/MPolyRing.jl @@ -132,12 +132,43 @@ end # ################################################################################ +function _evaluate_plain(F::MPolyAnyMap{<:MPolyRing, <:MPolyRing}, u) + if isdefined(F, :variable_indices) + S = codomain(F)::MPolyRing + r = ngens(S) + ctx = MPolyBuildCtx(S) + for (c, e) in zip(coefficients(u), exponents(u)) + ee = [0 for _ in 1:r] + for (i, k) in enumerate(e) + ee[F.variable_indices[i]] = k + end + push_term!(ctx, c, ee) + end + return finish(ctx) + end + + return evaluate(u, F.img_gens) +end + function _evaluate_plain(F::MPolyAnyMap{<: MPolyRing}, u) return evaluate(u, F.img_gens) end # See the comment in MPolyQuo.jl function _evaluate_plain(F::MPolyAnyMap{<:MPolyRing, <:MPolyQuoRing}, u) + if isdefined(F, :variable_indices) + S = base_ring(codomain(F))::MPolyRing + r = ngens(S) + ctx = MPolyBuildCtx(S) + for (c, e) in zip(coefficients(u), exponents(u)) + ee = [0 for _ in 1:r] + for (i, k) in enumerate(e) + ee[F.variable_indices[i]] = k + end + push_term!(ctx, c, ee) + end + return codomain(F)(finish(ctx)) + end A = codomain(F) v = evaluate(lift(u), lift.(_images(F))) return simplify(A(v)) From dceb60769eedecc3cec5ae1fe653f142fe5d6676 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Thu, 19 Sep 2024 17:43:20 +0200 Subject: [PATCH 11/13] Some more steps towards making stuff faster. --- src/Rings/MPolyMap/MPolyAnyMap.jl | 28 ++++++++++++++++++++-------- src/Rings/MPolyMap/MPolyRing.jl | 6 +++++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/Rings/MPolyMap/MPolyAnyMap.jl b/src/Rings/MPolyMap/MPolyAnyMap.jl index ce09648d1567..03384f28d7ad 100644 --- a/src/Rings/MPolyMap/MPolyAnyMap.jl +++ b/src/Rings/MPolyMap/MPolyAnyMap.jl @@ -48,15 +48,27 @@ const _DomainTypes = Union{MPolyRing, MPolyQuoRing} # simple form. function MPolyAnyMap{D, C, U, V}(domain::D, - codomain::C, - coeff_map::U, - img_gens::Vector{V}) where {D, C, U, V} - @assert V === elem_type(C) - for g in img_gens - @assert parent(g) === codomain "elements does not have the correct parent" - end + codomain::C, + coeff_map::U, + img_gens::Vector{V}) where {D, C, U, V} + @assert V === elem_type(C) + for g in img_gens + @assert parent(g) === codomain "elements does not have the correct parent" + end + return new{D, C, U, V}(domain, codomain, coeff_map, img_gens) + end + function MPolyAnyMap{D, C, U, V}(domain::D, + codomain::C, + coeff_map::U, + img_gens::Vector{V}) where {D <: Union{<:MPolyRing, <:MPolyQuoRing}, + C <: Union{<:MPolyRing, <:MPolyQuoRing}, + U, V} + @assert V === elem_type(C) + for g in img_gens + @assert parent(g) === codomain "elements does not have the correct parent" + end result = new{D, C, U, V}(domain, codomain, coeff_map, img_gens) - if all(x in gens(codomain) for x in img_gens) && length(unique(img_gens)) == ngens(domain) + if all(is_gen(x) for x in img_gens) && allunique(img_gens) result.variable_indices = [findfirst(x==y for y in gens(codomain)) for x in img_gens] end return result diff --git a/src/Rings/MPolyMap/MPolyRing.jl b/src/Rings/MPolyMap/MPolyRing.jl index a64931ce7091..09d77229006b 100644 --- a/src/Rings/MPolyMap/MPolyRing.jl +++ b/src/Rings/MPolyMap/MPolyRing.jl @@ -132,12 +132,16 @@ end # ################################################################################ +# Some additional methods needed for the test in the constructor for MPolyAnyMap +is_gen(x::MPolyQuoRingElem) = is_gen(lift(x)) +is_gen(x::MPolyDecRingElem) = is_gen(forget_grading(x)) + function _evaluate_plain(F::MPolyAnyMap{<:MPolyRing, <:MPolyRing}, u) if isdefined(F, :variable_indices) S = codomain(F)::MPolyRing r = ngens(S) ctx = MPolyBuildCtx(S) - for (c, e) in zip(coefficients(u), exponents(u)) + for (c, e) in zip(AbstractAlgebra.coefficients(u), AbstractAlgebra.exponent_vectors(u)) ee = [0 for _ in 1:r] for (i, k) in enumerate(e) ee[F.variable_indices[i]] = k From f8204cb827329a4eb6b4a1773eb4f7287721a9de Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 24 Sep 2024 20:52:21 +0200 Subject: [PATCH 12/13] Try to make general evaluation faster. --- src/Rings/MPolyMap/MPolyRing.jl | 51 ++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Rings/MPolyMap/MPolyRing.jl b/src/Rings/MPolyMap/MPolyRing.jl index 09d77229006b..d248208f2cd9 100644 --- a/src/Rings/MPolyMap/MPolyRing.jl +++ b/src/Rings/MPolyMap/MPolyRing.jl @@ -178,6 +178,55 @@ function _evaluate_plain(F::MPolyAnyMap{<:MPolyRing, <:MPolyQuoRing}, u) return simplify(A(v)) end +function _evaluate_general(F::MPolyAnyMap{<:MPolyRing, <:MPolyRing}, u) + if domain(F) === codomain(F) && coefficient_map(F) === nothing + return evaluate(map_coefficients(coefficient_map(F), u, + parent = domain(F)), F.img_gens) + else + S = temp_ring(F) + if S !== nothing + if !isdefined(F, :variable_indices) || coefficient_ring(S) !== codomain(F) + return evaluate(map_coefficients(coefficient_map(F), u, + parent = S), F.img_gens) + else + tmp_poly = map_coefficients(coefficient_map(F), u, parent = S) + cod_ring = codomain(F)::MPolyRing + r = ngens(cod_ring) + ctx = MPolyBuildCtx(cod_ring) + for (p, e) in zip(coefficients(tmp_poly), exponents(tmp_poly)) + ee = [0 for _ in 1:r] + for (i, k) in enumerate(e) + ee[F.variable_indices[i]] = k + end + p::MPolyRingElem + @assert parent(p) === cod_ring + for (c, d) in zip(coefficients(p), exponents(p)) + push_term!(ctx, c, ee+d) + end + end + return finish(ctx) + end + else + if !isdefined(F, :variable_indices) + return evaluate(map_coefficients(coefficient_map(F), u), F.img_gens) + else + tmp_poly = map_coefficients(coefficient_map(F), u) + cod_ring = codomain(F)::MPolyRing + r = ngens(cod_ring) + ctx = MPolyBuildCtx(cod_ring) + for (c, e) in zip(coefficients(tmp_poly), exponents(tmp_poly)) + ee = [0 for _ in 1:r] + for (i, k) in enumerate(e) + ee[F.variable_indices[i]] = k + end + push_term!(ctx, c, ee) + end + return finish(ctx) + end + end + end +end + function _evaluate_general(F::MPolyAnyMap{<: MPolyRing}, u) if domain(F) === codomain(F) && coefficient_map(F) === nothing return evaluate(map_coefficients(coefficient_map(F), u, @@ -186,7 +235,7 @@ function _evaluate_general(F::MPolyAnyMap{<: MPolyRing}, u) S = temp_ring(F) if S !== nothing return evaluate(map_coefficients(coefficient_map(F), u, - parent = S), F.img_gens) + parent = S), F.img_gens) else return evaluate(map_coefficients(coefficient_map(F), u), F.img_gens) end From dafc8afc748fe7f26ab97bdbd5fe7fa6c1435468 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 24 Sep 2024 20:52:58 +0200 Subject: [PATCH 13/13] Add dispatche for singular-to-oscar conversion. --- src/Modules/UngradedModules/ModuleGens.jl | 49 ++++++++++++++++++----- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/Modules/UngradedModules/ModuleGens.jl b/src/Modules/UngradedModules/ModuleGens.jl index d77cd1df6e9c..445269c65b83 100644 --- a/src/Modules/UngradedModules/ModuleGens.jl +++ b/src/Modules/UngradedModules/ModuleGens.jl @@ -261,22 +261,49 @@ end Convert a Singular vector to a free module element. """ -function (F::FreeMod)(s::Singular.svector) - pos = Int[] +function (F::FreeMod{<:MPolyRingElem})(s::Singular.svector) Rx = base_ring(F) R = coefficient_ring(Rx) - values = elem_type(Rx)[] + ctx = MPolyBuildCtx(Rx) + + # shortcut in order not to allocate the dictionary +# if isone(length(s)) # TODO: length doesn't work! +# (i, e, c) = first(s) +# push_term!(ctx, R(c), e) +# return FreeModElem(sparse_row(Qx, [(i, finish(ctx))])) +# end + + cache = IdDict{Int, typeof(ctx)}() for (i, e, c) in s - f = Base.findfirst(x->x==i, pos) - if f === nothing - push!(values, zero(Rx)) - f = length(values) - push!(pos, i) + ctx = get!(cache, i) do + MPolyBuildCtx(Rx) end - values[f] += R(c)*prod(gens(Rx) .^ e) + push_term!(ctx, R(c), e) end - pv = [(pos[i], values[i]) for i=1:length(pos)] - return FreeModElem(sparse_row(base_ring(F), pv), F) + return FreeModElem(sparse_row(Rx, [(i, finish(ctx)) for (i, ctx) in cache]), F) +end + +function (F::FreeMod{<:MPolyQuoRingElem})(s::Singular.svector) + Qx = base_ring(F)::MPolyQuoRing + Rx = base_ring(Qx)::MPolyRing + R = coefficient_ring(Rx) + ctx = MPolyBuildCtx(Rx) + + # shortcut in order not to allocate the dictionary +# if isone(length(s)) # TODO: length doesn't work! +# (i, e, c) = first(s) +# push_term!(ctx, R(c), e) +# return FreeModElem(sparse_row(Qx, [(i, Qx(finish(ctx)))])) +# end + + cache = IdDict{Int, typeof(ctx)}() + for (i, e, c) in s + ctx = get!(cache, i) do + MPolyBuildCtx(Rx) + end + push_term!(ctx, R(c), e) + end + return FreeModElem(sparse_row(Qx, [(i, Qx(finish(ctx))) for (i, ctx) in cache]), F) end # After creating the required infrastruture in Singular,