Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For Modules over PBWAlgRing and PBWAlgQuo #3900

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
17 changes: 12 additions & 5 deletions src/Modules/FreeModElem-orderings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,20 @@ end
Return an array of `Tuple{Int, Int}` that puts the terms of `f` in the order
`ord`. The index tuple `(i, j)` corresponds to `term(f[i], j)`.
"""
function Orderings.permutation_of_terms(f::FreeModElem{<:MPolyRingElem}, ord::ModuleOrdering)
function Orderings.permutation_of_terms(f::FreeModElem{<:AdmissibleModuleFPRingElem}, ord::ModuleOrdering)
# redispatch to take advantage of the type of ord.o
return Orderings.__permutation_of_terms(f, ord.o)
end

function Orderings.__permutation_of_terms(f::FreeModElem{<:MPolyRingElem}, ord::Orderings.AbsOrdering)
function Orderings.__permutation_of_terms(f::FreeModElem{<:AdmissibleModuleFPRingElem}, ord::Orderings.AbsOrdering)
ff = coordinates(f)
p = collect((i, j) for i in ff.pos for j in 1:length(ff[i]))
sort!(p, lt = (k, l) -> (Orderings._cmp_vector_monomials(k[1], ff[k[1]], k[2],
l[1], ff[l[1]], l[2], ord) > 0))
return p
end

function Orderings.index_of_leading_term(f::FreeModElem{<:MPolyRingElem}, ord::ModuleOrdering)
function Orderings.index_of_leading_term(f::FreeModElem{<:AdmissibleModuleFPRingElem}, ord::ModuleOrdering)
p = Orderings.permutation_of_terms(f, ord)
@req !isempty(p) "zero element does not have a leading term"
return p[1]
Expand Down Expand Up @@ -99,11 +99,18 @@ end
@enable_all_show_via_expressify OscarPair{<:FreeModElem{<:MPolyRingElem}, <:Vector{Tuple{Int, Int}}}

# expressify wrt ordering
function expressify(a::OscarPair{<:FreeModElem{<:MPolyRingElem}, <:ModuleOrdering}; context = nothing)
function expressify(a::OscarPair{<:FreeModElem{<:AdmissibleModuleFPRingElem}, <:ModuleOrdering}; context = nothing)
perm = Orderings.permutation_of_terms(a.first, a.second)
return expressify(OscarPair(a.first, perm); context = context)
end
@enable_all_show_via_expressify OscarPair{<:FreeModElem{<:MPolyRingElem}, <:ModuleOrdering}
@enable_all_show_via_expressify OscarPair{<:FreeModElem{<:AdmissibleModuleFPRingElem}, <:ModuleOrdering}

#Note that for PBWAlgElem and PBWAlgQuoElem we do not 'permute' to return the smallest terms first.
function expressify(a::OscarPair{<:FreeModElem{<:AdmissibleModuleFPRingElem}, <:ModuleOrdering}; context = nothing)
return expressify(a.first)
end
@enable_all_show_via_expressify OscarPair{<:FreeModElem{<:AdmissibleModuleFPRingElem}, <:ModuleOrdering}


@doc raw"""
coefficients(f::FreeModElem; ordering::ModuleOrdering = default_ordering(parent(f)))
Expand Down
18 changes: 18 additions & 0 deletions src/Modules/UngradedModules/FreeMod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ function FreeMod(R::AdmissibleModuleFPRing, names::Vector{Symbol}; cached::Bool=
return FreeMod{elem_type(R)}(length(names), R, names)
end

function FreeMod(R::PBWAlgQuo, n::Int, name::VarName = :e; cached::Bool = false) # TODO cached?
return FreeMod{elem_type(R)}(n, R, [Symbol("$name[$i]") for i=1:n])
end

function FreeMod(R::PBWAlgRing, n::Int, name::VarName = :e; cached::Bool = false) # TODO cached?
return FreeMod{elem_type(R)}(n, R, [Symbol("$name[$i]") for i=1:n])
end

function FreeMod(R::PBWAlgQuo, names::Vector{<:VarName}; cached::Bool=false)
return FreeMod{elem_type(R)}(length(names), R, Symbol.(names))
end

function FreeMod(R::PBWAlgRing, names::Vector{<:VarName}; cached::Bool=false)
return FreeMod{elem_type(R)}(length(names), R, Symbol.(names))
end

@doc raw"""
free_module(R::MPolyRing, p::Int, name::VarName = :e; cached::Bool = false)
free_module(R::MPolyQuoRing, p::Int, name::VarName = :e; cached::Bool = false)
Expand Down Expand Up @@ -75,6 +91,8 @@ free_module(R::MPolyRing, p::Int, name::VarName = :e; cached::Bool = false) = Fr
free_module(R::MPolyQuoRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R, p, name, cached = cached)
free_module(R::MPolyLocRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R, p, name, cached = cached)
free_module(R::MPolyQuoLocRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R, p, name, cached = cached)
free_module(R::PBWAlgQuo, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R,p,name,cached = cached)
free_module(R::PBWAlgRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R,p,name,cached = cached)

#free_module(R::NCRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R, p, name, cached = cached)

Expand Down
12 changes: 12 additions & 0 deletions src/Modules/UngradedModules/Methods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ function default_ordering(F::FreeMod)
return F.default_ordering::ModuleOrdering{typeof(F)}
end

function default_ordering(F::FreeMod{T}) where T <: Union{PBWAlgQuoElem, PBWAlgElem}
return 42
end

function default_ordering(R::Union{PBWAlgRing, PBWAlgQuo})
return 42 #lex(R)
end

function number_of_variables(R::Union{PBWAlgRing, PBWAlgQuo})
return ngens(R)
end

##############################
#TODO: move to Singular.jl ?

Expand Down
29 changes: 27 additions & 2 deletions src/Modules/UngradedModules/ModuleGens.jl
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,20 @@ function (SF::Singular.FreeMod)(m::FreeModElem)
g = Singular.gens(SF)
e = SF()
Sx = base_ring(SF)
if Sx isa Singular.PluralRing
if base_ring(parent(m)) isa PBWAlgQuo
for (p,v) in coordinates(m)
w = v.data.sdata
e += Sx(w)*g[p]
end
elseif base_ring(parent(m)) isa PBWAlgRing
for (p,v) in coordinates(m)
w = v.sdata
e += Sx(w)*g[p]
end
end
return e
end
for (p,v) in coordinates(m)
e += Sx(v)*g[p]
end
Expand All @@ -269,16 +283,27 @@ function (F::FreeMod)(s::Singular.svector)
for (i, e, c) = s
f = Base.findfirst(x->x==i, pos)
if f === nothing
push!(values, MPolyBuildCtx(base_ring(F)))
push!(values, build_ctx(base_ring(F)))
f = length(values)
push!(pos, i)
end
push_term!(values[f], R(c), e)
if Rx isa PBWAlgRing
push_term!(values[f], (base_ring(R))(c), e)
elseif Rx isa PBWAlgQuo
push_term!(values[f], (base_ring(base_ring(R)))(c), e)
else
push_term!(values[f], R(c), e)
end
end
pv = Tuple{Int, elem_type(Rx)}[(pos[i], base_ring(F)(finish(values[i]))) for i=1:length(pos)]
return FreeModElem(sparse_row(base_ring(F), pv), F)
end

#This is a helper function used in the previous function. The specific case for PBWAlgRing and PBWAlgQuo are in the respective files.
function build_ctx(R::Any)
return MPolyBuildCtx(R)
end

# After creating the required infrastruture in Singular,
# to facilitate the double book-keeping, the signature
# lift(G1::ModuleGens{T}, G2::ModuleGens{T}) should go to Singular
Expand Down
2 changes: 1 addition & 1 deletion src/Modules/UngradedModules/SubquoModuleElem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ Return a standard basis of `F` as an object of type `ModuleGens`.
If `reduced` is set to `true` and the ordering of the underlying ring is global,
a reduced Gröbner basis is computed.
"""
function standard_basis(F::ModuleGens{T}, reduced::Bool=false) where {T <: MPolyRingElem}
function standard_basis(F::ModuleGens{T}, reduced::Bool=false) where {T <: Union{MPolyRingElem, PBWAlgQuoElem, PBWAlgElem}}
@req is_exact_type(elem_type(base_ring(F))) "This functionality is only supported over exact fields."
singular_assure(F)
if reduced
Expand Down
8 changes: 8 additions & 0 deletions src/Rings/PBWAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1308,3 +1308,11 @@ ErrorException("could not find elimination ordering")
function eliminate(I::PBWAlgIdeal, sigmaC::Vector{<:PBWAlgElem}; ordering = nothing)
return eliminate(I, [var_index(i) for i in sigmaC]; ordering = ordering)
end

function Oscar.degrevlex(R::PBWAlgRing)
return MonomialOrdering(R, Oscar.Orderings.SymbOrdering(:degrevlex, 1:nvars(R)))
end

function singular_poly_ring(Rx::PBWAlgRing, ord::Singular.sordering)
return Rx.sring
end
31 changes: 31 additions & 0 deletions src/Rings/PBWAlgebraQuo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,34 @@ end
# function exterior_algebra(K::Ring, xs::AbstractVector{<:VarName})
# throw(NotImplementedError(:exterior_algebra, K, xs))
# end

#required to create PBWAlgQuoElem from Singular.svector

function push_term!(M::OscarPair{<:PBWAlgQuo{T,S}, <:MPolyBuildCtx}, c, e::Vector{Int}) where {T, S}
c = coefficient_ring(M.first)(c)::T
c = base_ring(M.first.sring)(c)::S
push_term!(M.second, c, e)
end

function finish(M::OscarPair{<:PBWAlgQuo{T,S}, <:MPolyBuildCtx}) where {T, S}
tmp = PBWAlgElem(base_ring(M.first), finish(M.second))
return PBWAlgQuoElem(M.first, tmp)
end

function singular_poly_ring(Rx::PBWAlgQuo, ord::Singular.sordering)
return Rx.sring
end

function build_ctx(R::PBWAlgQuo)
return OscarPair(R, MPolyBuildCtx(R.sring))
end

function length(x::PBWAlgQuoElem)
return length(x.data.sdata)
end

#orderings

function Oscar.degrevlex(R::PBWAlgQuo)
return MonomialOrdering(R, Oscar.Orderings.SymbOrdering(:degrevlex, 1:nvars(R)))
end
8 changes: 7 additions & 1 deletion test/Modules/PBWModules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
E,x = exterior_algebra(QQ, 3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is part of experimental and should thus not be used in the tests for src/ code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Though maybe we need to look into promoting exterior_algebra one of these days?

In any case, note that this PR is still a very early draft, I mainly asked @Lax202 to open it so we can better see what she's doing and what the state is, and then discuss it. The code still needs to be consolidated into a new source file, and that may very well ultimately end up in the experimental tree. We'll see.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the meantime this was merged as part of PR #3988 which copied the tests from here. If we still don't want the exterior_algebra call here, then someone else should remove it from there.

M = FreeMod(E, 3)
@test ngens(M) == 3
@test M[1] in M
@test parent(M[1]) === M
v = [x[1], x[1] + x[2], 5*x[1]*x[2]]
@test M(2*v) == 2*M(v)
Expand All @@ -11,6 +12,9 @@
N = Oscar.SubModuleOfFreeModule(M, gens(M)[1:2])
@test gens(N) == gens(M)[1:2]
@test N[1] in M
#Groebner basis of submodule
GB = standard_basis(N; ordering=degrevlex(E)*invlex(M))
@test length(GB.O) == 2
#fails! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E
#@test M(v) in N

Expand All @@ -24,7 +28,6 @@
Q2 = SubquoModule(M, [x[2]*M[1]])
#fail! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E
#@test !is_canonically_isomorphic(Q2,Q1)
#simplify(Q[1])
end

@testset "modules over PBWAlgRing" begin
Expand All @@ -43,6 +46,9 @@ end
N = Oscar.SubModuleOfFreeModule(M, gens(M)[1:2])
@test gens(N) == gens(M)[1:2]
@test N[1] in M
#Groebner basis of submodule
GB = standard_basis(N; ordering=degrevlex(A)*invlex(M))
@test length(GB.O) == 2
#fails! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E
#@test M(v) in N

Expand Down
Loading