Skip to content

Commit

Permalink
Add more monomial and module orderings (#723)
Browse files Browse the repository at this point in the history
  • Loading branch information
wbhart committed Jan 29, 2022
1 parent 8fdc22d commit 4d42596
Show file tree
Hide file tree
Showing 12 changed files with 1,364 additions and 637 deletions.
57 changes: 56 additions & 1 deletion docs/src/CommutativeAlgebra/ideals.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,62 @@ m_{i-1}\alpha\ =m_{i-1}\beta,\ m_i\alpha>m_i\beta$

To create matrix orderings, OSCAR allows for matrices with integer coefficients as input matrices.

### Normal Forms
#### Functions for creating orderings

When computing Gröbner bases an ordering must be supplied. Standard Singular
orderings, including block orderings, weighted orderings and local orderings
are available.

The basic orderings are `:lex`, `:revlex`, `:deglex`, `:degrevlex`,
`:neglex`, `:negrevlex`, `:negdeglex`, `:negdegrevlex`, `:wdeglex`,
`:wdegrevlex`, `:negwdeglex` and `:negwdegrevlex`.

The orderings starting with `w` are weighted orderings.

The following functions exist for creating orderings:

```@docs
lex(::AbstractVector{<:MPolyElem})
revlex(::AbstractVector{<:MPolyElem})
deglex(::AbstractVector{<:MPolyElem})
degrevlex(::AbstractVector{<:MPolyElem})
neglex(::AbstractVector{<:MPolyElem})
negrevlex(::AbstractVector{<:MPolyElem})
negdeglex(::AbstractVector{<:MPolyElem})
negdegrevlex(::AbstractVector{<:MPolyElem})
```

```@docs
wdeglex(::AbstractVector{<:MPolyElem}, ::Vector{Int})
wdegrevlex(::AbstractVector{<:MPolyElem}, ::Vector{Int})
negwdeglex(::AbstractVector{<:MPolyElem}, ::Vector{Int})
negwdegrevlex(::AbstractVector{<:MPolyElem}, ::Vector{Int})
```

Block orderings can be obtained by concatening monomial orderings using the `*`
operator.

Term over position and position over term module orderings are also available.
These are also specified byy concatenation using the `*` operator. One creates
the requisite module ordering (`lex` or `revlex`) for the generators of the
free module.

Term over position is specified by appending the module ordering to the
monomial ordering and position over term by prepending the module ordering.

###### Examples

```@repl oscar
R, (x, y, s, t, u) = PolynomialRing(QQ, ["x", "y", "s", "t", "u"])
O1 = degrevlex(gens(R))
O2 = lex([x, y])*deglex([s, t, u])
O3 = wdeglex(gens(R), [2, 3, 5, 7, 3])
K = FreeModule(R, 3)
O4 = revlex(gens(K))*degrevlex(gens(R))
```

## Normal Forms

```@docs
normal_form(f::T, J::MPolyIdeal) where { T <: MPolyElem }
Expand Down
23 changes: 17 additions & 6 deletions experimental/ModStd/ModStdQ.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ function Oscar.groebner_assure(I::MPolyIdeal{fmpq_mpoly}, ord::Symbol = :degrevl
end
end

function Oscar.groebner_basis_with_transform(I::MPolyIdeal{fmpq_mpoly}; ordering::Symbol = :degrevlex, complete_reduction::Bool = true, use_hilbert::Bool = false)

function groebner_basis_with_transform_inner(I::MPolyIdeal{fmpq_mpoly}, ord::MonomialOrdering; complete_reduction::Bool = true, use_hilbert::Bool = false)
if iszero(I)
I.gb = BiPolyArray(base_ring(I), fmpq_mpoly[], isGB = true, keep_ordering = false)
singular_assure(I.gb)
I.gb.ord = ord.o
singular_assure(I.gb, ord)
return fmpq_mpoly[], matrix(base_ring(I), ngens(I), 0, fmpq_mpoly[])
end

Expand Down Expand Up @@ -147,7 +147,7 @@ function Oscar.groebner_basis_with_transform(I::MPolyIdeal{fmpq_mpoly}; ordering
R = GF(p)
Rt, t = PolynomialRing(R, [string(s) for s = symbols(Qt)], cached = false)
@vtime :ModStdQ 3 Ip = Oscar.BiPolyArray([Rt(x) for x = gI], keep_ordering = false)
Gp, Tp = Oscar.groebner_basis_with_transform(Ip, ord = ordering, complete_reduction = complete_reduction)
Gp, Tp = Oscar.groebner_basis_with_transform(Ip, ord; complete_reduction = complete_reduction)
length_gc = length(Gp)
Jp = vcat(map(x->lift(Zt, x), Gp), map(x->lift(Zt, x), reshape(collect(Tp), :)))

Expand Down Expand Up @@ -193,10 +193,13 @@ function Oscar.groebner_basis_with_transform(I::MPolyIdeal{fmpq_mpoly}; ordering
T = matrix(Qt, length_gc, length(gI), gd[length_gc+1:end])
#at this point we SHOULD have T*gens(I) == G...
if T*matrix(Qt, length(gI), 1, gI) == matrix(Qt, length_gc, 1, G)
if ordering == :degrevlex && !isdefined(I, :gb)
if !isdefined(I.gens, :ord)
I.gens.ord = ord.o
end
if ord.o == I.gens.ord && !isdefined(I, :gb)
I.gb = BiPolyArray(gd[1:length_gc], keep_ordering = false)
I.gb.isGB = true
singular_assure(I.gb)
I.gb.S.isGB = true
end
return G, T
else
Expand All @@ -209,6 +212,14 @@ function Oscar.groebner_basis_with_transform(I::MPolyIdeal{fmpq_mpoly}; ordering
end
end

function Oscar.groebner_basis_with_transform(I::MPolyIdeal{fmpq_mpoly}; ordering::Symbol = :degrevlex, complete_reduction::Bool = true, use_hilbert::Bool = false)
ord = Oscar.Orderings.MonomialOrdering(base_ring(I), Oscar.Orderings.ordering(gens(base_ring(I)), ordering))
return groebner_basis_with_transform_inner(I, ord; complete_reduction=complete_reduction, use_hilbert=use_hilbert)
end

function Oscar.groebner_basis_with_transform(I::MPolyIdeal{fmpq_mpoly}, ord::MonomialOrdering; complete_reduction::Bool = true, use_hilbert::Bool = false)
return groebner_basis_with_transform_inner(I, ord; complete_reduction=complete_reduction, use_hilbert=use_hilbert)
end

function Oscar.lift(R::Nemo.Ring, f::Union{gfp_mpoly, nmod_mpoly})
g = MPolyBuildCtx(R)
Expand Down
4 changes: 2 additions & 2 deletions src/Modules/FreeModules-graded.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#TODO make d and S a function optionally - to support HUGE degree
export presentation, grading_group
export presentation, grading_group, ModuleOrdering

abstract type ModuleFP_dec{T} end

Expand Down Expand Up @@ -117,7 +117,7 @@ end
dim(F::FreeModule_dec) = length(F.d)
ngens(F::FreeModule_dec) = dim(F)

struct FreeModuleElem_dec{T}
struct FreeModuleElem_dec{T} <: AbstractAlgebra.ModuleElem{T}
r::SRow{T}
parent::FreeModule_dec{T}
end
Expand Down
1 change: 1 addition & 0 deletions src/Oscar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ include("Groups/GrpAb.jl")

include("Rings/integer.jl")
include("Rings/rational.jl")
include("Rings/orderings.jl")
include("Rings/mpoly.jl")
include("Rings/mpoly-graded.jl")
include("Rings/mpoly-ideals.jl")
Expand Down
1 change: 1 addition & 0 deletions src/Rings/MPolyQuo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ function simplify(f::MPolyQuoElem)
g = f.f
return R(I.gens.Ox(reduce(Sx(g), I.gb.S)))
end

function simplify!(f::MPolyQuoElem)
R = parent(f)
I = R.I
Expand Down
79 changes: 53 additions & 26 deletions src/Rings/groebner.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ export groebner_basis, groebner_basis_with_transformation_matrix, leading_ideal

# groebner stuff #######################################################
@doc Markdown.doc"""
groebner_assure(I::MPolyIdeal)
groebner_assure(I::MPolyIdeal; complete_reduction::Bool = false)
groebner_assure(I::MPolyIdeal, ord::MonomialOrdering; complete_reduction::Bool = false)
**Note**: Internal function, subject to change, do not use.
Expand All @@ -27,19 +28,15 @@ julia> Oscar.groebner_assure(I)
x^3 - 9//2*x
julia> I.gb
Oscar.BiPolyArray{fmpq_mpoly}(fmpq_mpoly[x*y - 3*x, y^3 - 6*x^2, x^3 - 9//2*x], Singular ideal over Singular Polynomial Ring (QQ),(x,y),(dp(2),C) with generators (x*y - 3*x, y^3 - 6*x^2, x^3 - 9//2*x), Multivariate Polynomial Ring in x, y over Rational Field, Singular Polynomial Ring (QQ),(x,y),(dp(2),C), false, #undef, false)
Oscar.BiPolyArray{fmpq_mpoly}(fmpq_mpoly[x*y - 3*x, y^3 - 6*x^2, x^3 - 9//2*x], Singular ideal over Singular Polynomial Ring (QQ),(x,y),(dp(2),C) with generators (x*y - 3*x, y^3 - 6*x^2, x^3 - 9//2*x), Multivariate Polynomial Ring in x, y over Rational Field, Singular Polynomial Ring (QQ),(x,y),(dp(2),C), true, #undef, false)
```
"""
function groebner_assure(I::MPolyIdeal; complete_reduction::Bool = false)
if !isdefined(I, :gb)
singular_assure(I)
# @show "std on", I.gens.S
if complete_reduction
i = Singular.std(I.gens.S, complete_reduction = complete_reduction)
I.gb = BiPolyArray(base_ring(I), i)
else
I.gb = BiPolyArray(base_ring(I), Singular.std(I.gens.S))
end
i = Singular.std(I.gens.S; complete_reduction = complete_reduction)
I.gb = BiPolyArray(base_ring(I), i)
I.gb.isGB = true
I.gb.O = [I.gb.Ox(x) for x = gens(I.gb.S)]
end
end
Expand Down Expand Up @@ -82,7 +79,7 @@ function groebner_basis(B::BiPolyArray; ordering::Symbol = :degrevlex, complete_
end

#= @doc Markdown.doc"""
= groebner_basis(I::MPolyIdeal)
= groebner_basis(I::MPolyIdeal; ordering::Symbol = :degrevlex, complete_reduction::Bool = false)
=
= Compute a Groebner basis w.r.t. the given monomial ordering of the polynomial ring.
=
Expand All @@ -108,7 +105,8 @@ end

@doc Markdown.doc"""
groebner_basis(I::MPolyIdeal; ordering::Symbol = :degrevlex, complete_reduction::Bool = false)
groebner_basis(I::MPolyIdeal, ord::MonomialOrdering; complete_reduction::Bool=false)
Given an ideal `I` and optional parameters monomial ordering `ordering` and `complete_reduction`,
compute a Groebner basis (if `complete_reduction = true` the reduced Groebner basis) of `I`
w.r.t. the given monomial ordering `ordering` (as default `:degrevlex`).
Expand All @@ -121,7 +119,7 @@ julia> R, (x, y) = PolynomialRing(QQ, ["x", "y"], ordering=:degrevlex)
julia> I = ideal([x*y-3*x,y^3-2*x^2*y])
ideal(x*y - 3*x, -2*x^2*y + y^3)
julia> H = groebner_basis(I, ordering=:lex)
julia> H = groebner_basis(I; ordering=:lex)
3-element Vector{fmpq_mpoly}:
y^4 - 3*y^3
x*y - 3*x
Expand All @@ -136,7 +134,8 @@ function groebner_basis(I::MPolyIdeal; ordering::Symbol = :degrevlex, complete_r
end

@doc Markdown.doc"""
groebner_basis_with_transform(B::BiPolyArray; ord::Symbol = :degrevlex, complete_reduction::Bool = false)
groebner_basis_with_transform(B::BiPolyArray; ordering::Symbol = :degrevlex, complete_reduction::Bool = false)
groebner_basis_with_transform(B::BiPolyArray, ord::MonomialOrdering; complete_reduction::Bool = false)
**Note**: Internal function, subject to change, do not use.
Expand Down Expand Up @@ -173,9 +172,9 @@ function groebner_basis_with_transform(B::BiPolyArray; ord::Symbol = :degrevlex,
return BiPolyArray(B.Ox, i), map_entries(x->B.Ox(x), m)
end


@doc Markdown.doc"""
groebner_basis_with_transformation_matrix(I::MPolyIdeal; ordering::Symbol = :degrevlex, complete_reduction::Bool=false)
groebner_basis_with_transformation_matrix(I::MPolyIdeal, ord::MonomialOrdering; complete_reduction::Bool=false)
Return a pair `G, m` where `G` is a Groebner basis of the ideal `I` with respect to the
monomial ordering `ordering`, and `m` is a transformation matrix from `gens(I)` to `G`. If
Expand All @@ -197,7 +196,7 @@ true
```
"""
function groebner_basis_with_transformation_matrix(I::MPolyIdeal; ordering::Symbol = :degrevlex, complete_reduction::Bool=false)
G, m = Oscar.groebner_basis_with_transform(I, ordering=ordering, complete_reduction=complete_reduction)
G, m = Oscar.groebner_basis_with_transform(I; ordering=ordering, complete_reduction=complete_reduction)
return G, Array(m)
end

Expand Down Expand Up @@ -277,6 +276,7 @@ end

@doc Markdown.doc"""
leading_ideal(I::MPolyIdeal)
leading_ideal(I::MPolyIdeal, ord::MonomialOrdering)
Given a multivariate polynomial ideal `Ì` this function returns the
leading ideal for `I`. This is done w.r.t. the given monomial ordering
Expand All @@ -300,7 +300,14 @@ function leading_ideal(I::MPolyIdeal)
singular_assure(I.gb)
return MPolyIdeal(base_ring(I), Singular.Ideal(I.gb.Sx, [Singular.leading_monomial(g) for g in gens(I.gb.S)]))
end


function leading_ideal(I::MPolyIdeal, ord::MonomialOrdering)
singular_assure(I, ord)
groebner_assure(I, ord)
singular_assure(I.gb, ord)
return MPolyIdeal(base_ring(I), Singular.Ideal(I.gb.Sx, [Singular.leading_monomial(g) for g in gens(I.gb.S)]))
end

@doc Markdown.doc"""
leading_ideal(I::MPolyIdeal, ordering::Symbol)
Expand All @@ -320,7 +327,7 @@ ideal(y^7, x*y^2, x^3)
```
"""
function leading_ideal(I::MPolyIdeal, ordering::Symbol)
return leading_ideal(groebner_basis(I, ordering=ordering), ordering)
return leading_ideal(groebner_basis(I; ordering=ordering), ordering)
end

@doc Markdown.doc"""
Expand Down Expand Up @@ -454,17 +461,37 @@ function groebner_assure(I::MPolyIdeal, ord::MonomialOrdering; complete_reductio
end

function groebner_basis(B::BiPolyArray, ord::MonomialOrdering; complete_reduction::Bool = false)
R = singular_ring(B.Ox, ord.o)
i = Singular.Ideal(R, [R(x) for x = B])
i = Singular.std(i, complete_reduction = complete_reduction)
return BiPolyArray(B.Ox, i)
singular_assure(B, ord)
R = B.Sx
!Oscar.Singular.has_global_ordering(R) && error("The ordering has to be a global ordering.")
I = Singular.Ideal(R, gens(B.S)...)
i = Singular.std(I, complete_reduction = complete_reduction)
return BiPolyArray(B.Ox, i)
end

function groebner_basis(I::MPolyIdeal, ord::MonomialOrdering; complete_reduction::Bool=false)
R = singular_ring(base_ring(I), ord.o)
!Oscar.Singular.has_global_ordering(R) && error("The ordering has to be a global ordering.")
i = Singular.std(Singular.Ideal(R, [R(x) for x = gens(I)]), complete_reduction = complete_reduction)
return collect(BiPolyArray(base_ring(I), i))
return collect(groebner_basis(I.gens, ord))
end


function groebner_basis_with_transform(B::BiPolyArray, ord::MonomialOrdering; complete_reduction::Bool = false)
if !isdefined(B, :ord)
singular_assure(B, ord)
elseif ord != B.ord
R = singular_ring(B.Ox, ord)
i = Singular.Ideal(R, [R(x) for x = B])
i, m = Singular.lift_std(i, complete_reduction = complete_reduction)
return BiPolyArray(B.Ox, i), map_entries(x->B.Ox(x), m)
end

if !isdefined(B, :S)
B.S = Singular.Ideal(B.Sx, [B.Sx(x) for x = B.O])
end

i, m = Singular.lift_std(B.S, complete_reduction = complete_reduction)
return BiPolyArray(B.Ox, i), map_entries(x->B.Ox(x), m)
end

function groebner_basis_with_transformation_matrix(I::MPolyIdeal, ord::MonomialOrdering; complete_reduction::Bool=false)
G, m = Oscar.groebner_basis_with_transform(I, ord; complete_reduction=complete_reduction)
return G, Array(m)
end
Loading

0 comments on commit 4d42596

Please sign in to comment.