diff --git a/deps/src/ideals.cpp b/deps/src/ideals.cpp index fc4a52766..88628b255 100644 --- a/deps/src/ideals.cpp +++ b/deps/src/ideals.cpp @@ -677,6 +677,22 @@ void singular_define_ideals(jlcxx::Module & Singular) delete v; rChangeCurrRing(origin); }); + Singular.method("scHilbPoly", [](ideal I, ring r, ring Qt) { + const ring origin = currRing; + rChangeCurrRing(r); + poly h=hFirstSeries0p(I,r->qideal,NULL,r,Qt); + rChangeCurrRing(origin); + return h; + }); + Singular.method("scHilbPolyWeighted", [](ideal I, ring r, jlcxx::ArrayRef weights, ring Qt) { + intvec *w = to_intvec(weights); + const ring origin = currRing; + rChangeCurrRing(r); + poly h=hFirstSeries0p(I,r->qideal,w,r,Qt); + delete w; + rChangeCurrRing(origin); + return h; + }); Singular.method("id_Homogen", id_Homogen); Singular.method("id_HomModule", [](jlcxx::ArrayRef weights, ideal I, ring r) { intvec* w = NULL; diff --git a/src/ideal/ideal.jl b/src/ideal/ideal.jl index 7b51b8205..bd15742bc 100644 --- a/src/ideal/ideal.jl +++ b/src/ideal/ideal.jl @@ -1278,6 +1278,38 @@ function hilbert_series(I::sideal{spoly{T}}, w::Vector{<:Integer}) where T <: Ne return z end +@doc raw""" + hilbert_series(I::sideal{spoly{T}}, Qt::PolyRing) where T <: Nemo.FieldElem + +Return the polynomial $Q(t)$ as element of Qt where `Q(t)/(1-t)^nvars(base_ring(I))` +is the Hilbert-Poincare series of $I$ for weights $(1, \dots, 1)$. +The generators of $I$ must be given as a Groebner basis. +""" +function hilbert_series(I::sideal{spoly{T}}, Qt::PolyRing) where T <: Nemo.FieldElem + I.isGB || error("Not a Groebner basis") + R = base_ring(I) + GC.@preserve I R Qt new_ptr = libSingular.scHilbPoly(I.ptr, R.ptr, Qt.ptr) + return Qt(new_ptr) +end + +@doc raw""" + hilbert_series(I::sideal{spoly{T}}, w::Vector{<:Integer}) where T <: Nemo.FieldElem + +Return the polynomial $Q(t)$ of Qt where $\frac{Q(t)}{\prod_i (1-t^{w_i})}$ +is the Hilbert-Poincare series of $I$ for weights $\{w_i\}$. Each weight must be +positive $w_i > 0$. +The generators of $I$ must be given as a Groebner basis. +""" +function hilbert_series(I::sideal{spoly{T}}, w::Vector{<:Integer}, Qt::PolyRing) where T <: Nemo.FieldElem + I.isGB || error("Not a Groebner basis") + R = base_ring(I) + length(w) == nvars(R) || error("wrong number of weights") + all(x -> x > 0, w) || error("weights must be positive") + w = convert(Vector{Int32}, w) + GC.@preserve I R Qt new_ptr = libSingular.scHilbPolyWeighted(I.ptr, R.ptr, w, Qt.ptr) + return Qt(new_ptr) +end + @doc raw""" std_hilbert(I::sideal{spoly{T}}, hs::Vector{Int32}; complete_reduction::Bool=false) where T <: Nemo.FieldElem diff --git a/test/ideal/sideal-test.jl b/test/ideal/sideal-test.jl index 240e585d2..fcdcdbd3f 100644 --- a/test/ideal/sideal-test.jl +++ b/test/ideal/sideal-test.jl @@ -686,6 +686,10 @@ end @test ngens(std_hilbert(j, h, w, complete_reduction = true)) == ngens(std(j, complete_reduction = true)) + Qt,(t,)= polynomial_ring(QQ, ["t"]) + I=Ideal(R,[x,y,z]) + I=std(I) + @test hilbert_series(I,Qt) == -t^3+3*t^2-3*t+1 end @testset "sideal.oscar#1702" begin