Skip to content

Commit 3210ed1

Browse files
Implement syzygy_generators for lists of module elements (oscar-system#4204)
Co-authored-by: Tommy Hofmann <[email protected]>
1 parent f109e74 commit 3210ed1

File tree

4 files changed

+108
-25
lines changed

4 files changed

+108
-25
lines changed

src/Modules/UngradedModules/FreeMod.jl

+64
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,67 @@ end
308308

309309
rels(F::FreeMod) = elem_type(F)[]
310310

311+
function syzygy_generators(
312+
g::Vector{T};
313+
parent::Union{<:FreeMod, Nothing}=nothing
314+
) where {T<:FreeModElem}
315+
isempty(g) && return Vector{T}()
316+
F = Oscar.parent(first(g))
317+
@assert all(Oscar.parent(x) === F for x in g) "parent mismatch"
318+
R = base_ring(F)
319+
m = length(g)
320+
G = (parent === nothing ? FreeMod(R, m) : parent)::typeof(F)
321+
@req ngens(G) == m "given parent does not have the correct number of generators"
322+
phi = hom(G, F, g)
323+
K, _ = kernel(phi)
324+
return ambient_representatives_generators(K)
325+
end
326+
327+
@doc raw"""
328+
syzygy_generators(
329+
a::Vector{T};
330+
parent::Union{FreeMod{T}, Nothing} = nothing
331+
) where {T<:RingElem}
332+
333+
Return generators for the syzygies on the polynomials given as elements of `a`.
334+
The optional keyword argument can be used to specify the parent of the output.
335+
336+
# Examples
337+
```jldoctest
338+
julia> R, (x, y) = polynomial_ring(QQ, [:x, :y])
339+
(Multivariate polynomial ring in 2 variables over QQ, QQMPolyRingElem[x, y])
340+
341+
julia> S = syzygy_generators([x^3+y+2,x*y^2-13*x^2,y-14])
342+
3-element Vector{FreeModElem{QQMPolyRingElem}}:
343+
(-y + 14)*e[2] + (-13*x^2 + x*y^2)*e[3]
344+
(-169*y + 2366)*e[1] + (-13*x*y + 182*x - 196*y + 2744)*e[2] + (13*x^2*y^2 - 2548*x^2 + 196*x*y^2 + 169*y + 338)*e[3]
345+
(-13*x^2 + 196*x)*e[1] + (-x^3 - 16)*e[2] + (x^4*y + 14*x^4 + 13*x^2 + 16*x*y + 28*x)*e[3]
346+
```
347+
"""
348+
function syzygy_generators(
349+
a::Vector{T};
350+
parent::Union{FreeMod{T}, Nothing} = nothing
351+
) where {T<:RingElem}
352+
isempty(a) && return Vector{FreeModElem{T}}()
353+
R = Oscar.parent(first(a))
354+
@assert all(Oscar.parent(x) === R for x in a) "parent mismatch"
355+
F = FreeMod(R, 1)
356+
return syzygy_generators(elem_type(F)[x*F[1] for x in a]; parent)
357+
end
358+
359+
function syzygy_generators(
360+
a::Vector{T};
361+
parent::Union{FreeMod{T}, Nothing} = nothing
362+
) where {CT <: Union{<:FieldElem, ZZRingElem, QQPolyRingElem}, # Can be adjusted to whatever is digested by Singular
363+
T<:MPolyRingElem{CT}}
364+
isempty(a) && return Vector{FreeModElem{T}}()
365+
R = Oscar.parent(first(a))
366+
@assert all(Oscar.parent(x) === R for x in a) "parent mismatch"
367+
I = ideal(R, a)
368+
s = Singular.syz(singular_generators(I))
369+
F = (parent === nothing ? FreeMod(R, length(a)) : parent)::FreeMod{T}
370+
@req ngens(F) == length(a) "parent does not have the correct number of generators"
371+
@assert rank(s) == length(a)
372+
return elem_type(F)[F(s[i]) for i=1:Singular.ngens(s)]
373+
end
374+

src/Modules/UngradedModules/SubquoModule.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,11 @@ function set_default_ordering!(M::SubquoModule, ord::ModuleOrdering)
754754
set_default_ordering!(M.sum, ord)
755755
end
756756

757-
function standard_basis(M::SubquoModule; ordering::ModuleOrdering = default_ordering(M))
757+
function standard_basis(M::SubquoModule; ordering::Union{ModuleOrdering, Nothing} = nothing)
758+
error("standard basis computation is not supported for modules over rings of type $(typeof(base_ring(M)))")
759+
end
760+
761+
function standard_basis(M::SubquoModule{<:MPolyRingElem{T}}; ordering::ModuleOrdering = default_ordering(M)) where {T<:Union{<:FieldElem, ZZRingElem}}
758762
@req is_exact_type(elem_type(base_ring(M))) "This functionality is only supported over exact fields."
759763
if !haskey(M.groebner_basis, ordering)
760764
if isdefined(M, :quo)

src/Rings/groebner.jl

+1-24
Original file line numberDiff line numberDiff line change
@@ -506,30 +506,7 @@ function groebner_basis_with_transformation_matrix(I::MPolyIdeal; ordering::Mono
506506
end
507507

508508
# syzygies #######################################################
509-
@doc raw"""
510-
syzygy_generators(G::Vector{<:MPolyRingElem})
511-
512-
Return generators for the syzygies on the polynomials given as elements of `G`.
513-
514-
# Examples
515-
```jldoctest
516-
julia> R, (x, y) = polynomial_ring(QQ, [:x, :y])
517-
(Multivariate polynomial ring in 2 variables over QQ, QQMPolyRingElem[x, y])
518-
519-
julia> S = syzygy_generators([x^3+y+2,x*y^2-13*x^2,y-14])
520-
3-element Vector{FreeModElem{QQMPolyRingElem}}:
521-
(-y + 14)*e[2] + (-13*x^2 + x*y^2)*e[3]
522-
(-169*y + 2366)*e[1] + (-13*x*y + 182*x - 196*y + 2744)*e[2] + (13*x^2*y^2 - 2548*x^2 + 196*x*y^2 + 169*y + 338)*e[3]
523-
(-13*x^2 + 196*x)*e[1] + (-x^3 - 16)*e[2] + (x^4*y + 14*x^4 + 13*x^2 + 16*x*y + 28*x)*e[3]
524-
```
525-
"""
526-
function syzygy_generators(a::Vector{<:MPolyRingElem})
527-
I = ideal(a)
528-
s = Singular.syz(singular_generators(I))
529-
F = free_module(parent(a[1]), length(a))
530-
@assert rank(s) == length(a)
531-
return [F(s[i]) for i=1:Singular.ngens(s)]
532-
end
509+
# See src/Modules/UngradedModules/FreeMod.jl for the implementation.
533510

534511
# leading ideal #######################################################
535512
@doc raw"""

test/Modules/UngradedModules.jl

+38
Original file line numberDiff line numberDiff line change
@@ -1275,3 +1275,41 @@ end
12751275
F = graded_free_module(Pn, 1)
12761276
dualFIC = hom(FI.C, F)
12771277
end
1278+
1279+
@testset "issue 4203" begin
1280+
R, (x,y) = polynomial_ring(GF(2), ["x","y"]);
1281+
1282+
g = [x+1, y+1]
1283+
s = syzygy_generators(g)
1284+
F = parent(first(s))
1285+
s2 = syzygy_generators(g; parent=F)
1286+
@test s == s2
1287+
s3 = syzygy_generators(g)
1288+
@test s2 != s3
1289+
1290+
A, _ = quo(R, ideal(R, [x^2+1, y^2+1]));
1291+
1292+
g = A.([x+1, y+1])
1293+
s = syzygy_generators(g)
1294+
F = parent(first(s))
1295+
s2 = syzygy_generators(g; parent=F)
1296+
@test s == s2
1297+
s3 = syzygy_generators(g)
1298+
@test s2 != s3
1299+
1300+
F = free_module(A,2);
1301+
M,_ = sub(F, [F([A(x+1),A(y+1)])]);
1302+
FF = free_module(A, ngens(M));
1303+
phi = hom(FF, M, gens(M));
1304+
K, = kernel(phi);
1305+
@test ambient_representatives_generators(K) == [(x*y + x + y + 1)*FF[1]]
1306+
@test_throws ErrorException standard_basis(K)
1307+
s1 = syzygy_generators(ambient_representatives_generators(M))
1308+
G = parent(first(s1))
1309+
s2 = syzygy_generators(ambient_representatives_generators(M); parent=G)
1310+
@test s1 == s2
1311+
s3 = syzygy_generators(ambient_representatives_generators(M))
1312+
@test s3 != s2
1313+
@test_throws ArgumentError syzygy_generators(ambient_representatives_generators(M); parent=F)
1314+
end
1315+

0 commit comments

Comments
 (0)