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

Adresses issue with equality/hashing on module orderings #3400

Merged
merged 8 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 69 additions & 12 deletions src/Rings/orderings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1717,33 +1717,89 @@ end

# Module orderings (not module Orderings)

# For ordering the generators (I think)
mutable struct ModOrdering{T} <: AbsModOrdering
gens::T
ord::Symbol
function ModOrdering(u::T, s::Symbol) where {T <: AbstractVector{Int}}
r = new{T}()
r.gens = u
r.ord = s
return r
end
gens::T
ord::Symbol
function ModOrdering(u::T, s::Symbol) where {T <: AbstractVector{Int}}
r = new{T}()
r.gens = u
r.ord = s
return r
end
end

mutable struct ModuleOrdering{S}
M::S
o::AbsModOrdering # must allow gen*mon or mon*gen product ordering
M::S
o::AbsModOrdering # must allow gen*mon or mon*gen product ordering

canonical_matrix::ZZMatrix

function ModuleOrdering(M::S, o::AbsModOrdering) where {S}
return new{S}(M, o)
end
end

base_ring(a::ModuleOrdering) = a.M

mutable struct ModProdOrdering <: AbsModOrdering
a::AbsOrdering
b::AbsOrdering
a::AbsOrdering
b::AbsOrdering
end

Base.:*(a::AbsGenOrdering, b::AbsModOrdering) = ModProdOrdering(a, b)

Base.:*(a::AbsModOrdering, b::AbsGenOrdering) = ModProdOrdering(a, b)

# For equality checking and hashing
# we produce a matrix representation by embedding the underlying free module (and its ordering) into a polynomial ring
# then we build the matrix in this ring

function _embedded_ring_ordering(o::ModuleOrdering)
return _embedded_ring_ordering(o.o)
end

function _embedded_ring_ordering(o::ModOrdering)
return SymbOrdering(o.ord, o.gens)
end

function _embedded_ring_ordering(o::AbsGenOrdering)
return deepcopy(o)
end

function _embedded_ring_ordering(o::ModProdOrdering)
ea = _embedded_ring_ordering(o.a)
shift = maximum(ea.vars)
eb = _embedded_ring_ordering(o.b)
eb.vars .+= shift
return ea*eb
end

function _canonical_matrix_intern(o::ModuleOrdering)
nvrs = ngens(o.M) + ngens(base_ring(o.M))
eo = _embedded_ring_ordering(o)
return canonical_matrix(nvrs, eo)
end

function canonical_matrix(o::ModuleOrdering)
if !isdefined(o, :canonical_matrix)
if isone(ngens(o.M))
o.canonical_matrix = canonical_matrix(induced_ring_ordering(o))
else
o.canonical_matrix = _canonical_matrix_intern(o)
end
end
return o.canonical_matrix
end

function Base.:(==)(o1::ModuleOrdering, o2::ModuleOrdering)
return canonical_matrix(o1) == canonical_matrix(o2)
Copy link
Member

Choose a reason for hiding this comment

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

I think that == should compare the underlying modules of the orderings as well. And then same for the hash: the field M should be used there as well

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I completely understand why. If I have two different modules and I want to find out if both share the same ordering, how shall I do that? Note that also for MonomialOrdering we do not compare the corresponding rings.

Copy link
Member

Choose a reason for hiding this comment

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

In that case, we should definitely keep it consistent and revert the change here. Sorry for the double work @RafaelDavidMohr

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No worries, it's reverted.

end

function Base.hash(o::ModuleOrdering, h::UInt)
return hash(canonical_matrix(o), h)
end

#### _cmp_vector_monomials: cmp f[k]*gen(m) with g[l]*gen(n)

function _cmp_vector_monomials(
Expand Down Expand Up @@ -2147,3 +2203,4 @@ end
end # module Orderings

import Oscar.Orderings: induce # needed at least for group characters

15 changes: 15 additions & 0 deletions test/Rings/orderings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,18 @@ end
@test invlex([a, b])*neglex([c]) == induce([a, b, c], invlex([x, y])*neglex([z]))
@test lex([a])*lex([b])*lex([c]) == induce([a, b, c], lex([x])*lex([y])*lex([z]))
end

@testset "Monomial Orderings comparison" begin
R, (x,y,z,w) = polynomial_ring(GF(32003), ["x", "y", "z", "w"]);
F = FreeMod(R, 2)
o = lex(gens(F))*lex(gens(R))
oo = lex(gens(F))*lex(gens(R))
@test o == oo
@test hash(o) == hash(oo)

F = FreeMod(R, 1)
o = lex(gens(F))*degrevlex(gens(R))
oo = degrevlex(gens(R))*invlex(gens(F))
@test o == oo
@test hash(o) == hash(oo)
end
Loading