diff --git a/docs/make.jl b/docs/make.jl index 2c8afa0ae..ee0ee45d0 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -20,6 +20,7 @@ makedocs( "polynomial.md", "noncommutative.md", "ideal.md", + "qring.md", "Modules" => [ "module.md", "vector.md" diff --git a/docs/src/ideal.md b/docs/src/ideal.md index 9489cf117..e7e959a4f 100644 --- a/docs/src/ideal.md +++ b/docs/src/ideal.md @@ -90,7 +90,7 @@ iszero(::sideal) ``` ```@docs -is_zerodim(::sideal) +is_zerodim(I::sideal) ``` ```@docs diff --git a/docs/src/polynomial.md b/docs/src/polynomial.md index f458a91cf..22c559943 100644 --- a/docs/src/polynomial.md +++ b/docs/src/polynomial.md @@ -253,10 +253,6 @@ has_local_ordering(R::PolyRing) degree_bound(R::PolyRing) ``` -```@docs -leading_exponent_vector(p::spoly) -``` - ```@docs total_degree(p::spoly) ``` diff --git a/docs/src/qring.md b/docs/src/qring.md new file mode 100644 index 000000000..60e3e9847 --- /dev/null +++ b/docs/src/qring.md @@ -0,0 +1,39 @@ +```@meta +CurrentModule = Singular +``` + +# Quotient Rings + +Quotient rings $Q = R/I$ in Singular.jl are constructed with the constructor +`QuotientRing(R, I)`. The input ideal $I$ to the constructor must be a Groebner +basis. The $R$-ideal $I$ may be recovered as `quotient_ideal(Q)`. + +```@docs +is_quotient_ring(R::PolyRingUnion) +quotient_ideal(Q::PolyRing{T}) where T <: Nemo.RingElem +``` + +**Examples** + +```julia +julia> R, (x, y) = PolynomialRing(QQ, ["x", "y"]); + +julia> is_quotient_ring(R) +false + +julia> Q1, (x, y) = QuotientRing(R, Ideal(R, x^2+y^2)); + +julia> is_quotient_ring(Q1) +true + +julia> quotient_ideal(Q1) +Singular ideal over Singular Polynomial Ring (QQ),(x,y),(dp(2),C) with generators (x^2 + y^2) + +julia> Q2, (x, y) = QuotientRing(Q1, std(Ideal(Q1, x*y))); + +julia> quotient_ideal(Q2) +Singular ideal over Singular Polynomial Ring (QQ),(x,y),(dp(2),C) with generators (x*y, y^3, x^2 + y^2) + +julia> base_ring(quotient_ideal(Q1)) == base_ring(quotient_ideal(Q2)) +true +``` diff --git a/src/ideal/ideal.jl b/src/ideal/ideal.jl index 2ad5a3da9..513565c00 100644 --- a/src/ideal/ideal.jl +++ b/src/ideal/ideal.jl @@ -82,7 +82,6 @@ end Return `true` if the given ideal is zero dimensional, i.e. the Krull dimension of $R/I$ is zero, where $R$ is the polynomial ring over which $I$ is an ideal.. """ - function is_zerodim(I::sideal) I.isGB || error("Not a Groebner basis") R = base_ring(I) diff --git a/src/ideal/quotient.jl b/src/ideal/quotient.jl index fa7bd1b5d..6328e6b10 100644 --- a/src/ideal/quotient.jl +++ b/src/ideal/quotient.jl @@ -1,7 +1,7 @@ -export is_quotient_ring, QuotientRing +export is_quotient_ring, QuotientRing, quotient_ideal @doc Markdown.doc""" - is_quotient_ring(R::PolyRing) + is_quotient_ring(R::PolyRingUnion) Return `true` if the given ring is the quotient of a polynomial ring with a non - zero ideal. @@ -10,6 +10,20 @@ function is_quotient_ring(R::PolyRingUnion) GC.@preserve R return Bool(Singular.libSingular.rIsQuotientRing(R.ptr)) end +@doc Markdown.doc""" + quotient_ideal(Q::PolyRing{T}) where T <: Nemo.RingElem + +Return `I` for a given quotient ring `Q = R/I`. +""" +function quotient_ideal(Q::PolyRing{T}) where T <: Nemo.RingElem + is_quotient_ring(Q) || ArgumentError("input ring is not a quotient ring") + R = PolyRing{T}(base_ring(Q), symbols(Q), ordering(Q), true, degree_bound(Q)) + GC.@preserve Q begin + iptr = libSingular.r_get_qideal(Q.ptr) + return sideal{spoly{T}}(R, libSingular.id_Copy(iptr, R.ptr), true) + end +end + ############################################################################### # # Quotient ring construction diff --git a/test/ideal/quotient-test.jl b/test/ideal/quotient-test.jl index 2f893bb0d..314faae3a 100644 --- a/test/ideal/quotient-test.jl +++ b/test/ideal/quotient-test.jl @@ -3,6 +3,7 @@ Q, (x, y, z) = @inferred QuotientRing(R, Ideal(R, x^2 - y*z)) @test is_quotient_ring(Q) + @test isequal(quotient_ideal(Q), Ideal(R, x^2 - y*z)) I = Ideal(Q, x) @test !I.isGB