Skip to content

Commit

Permalink
Add hash methods for many types with == method (#2373)
Browse files Browse the repository at this point in the history
* Add `hash(::GAPGroupHomomorphism)`

* Add `hash(::FreeMod_dec)`

* Add `hash(::PBWAlgIdeal)`

* Add `hash(::ModuleFPHom)`

* Add `hash` for `(Affine/Linear)(Halfspace/Hyperplane)

* Add `hash(::SesquilinearForm)`

* Add `hash(::AbsMPolyMultSet)`

* Add `hash(::CohomologyClass)`

* Add `hash(::ElementOfGSet)`

* Add `hash(::MPolyLocalizedRingHom)`

* Add `hash(::MPolyQuoLocalizedRingHom)`

* Add `hash(::RationalEquivalenceClass)`

* Enhance `hash(::FreeMod)` and `hash(::AbstractFreeModElem)`

* Add `hash(::SubquoModuleElem)`

* Add `hash(::ToricDivisor)`

* Add `hash(::ToricDivisorClass)`

* Add `hash(::ToricLineBundle)`

* Add `hash(::ToricMorphism)`

* Add `hash(::TropicalSemiringElem)`

* Update `hash` for `MPolyQuoLocalizedRingHom` and `MPolyLocalizedRingHom`

* Update `==` and `hash` for toric types

* Let `hash` for `AbsMPolyMultSet` and `SubquoModuleElem` error

* Bump version (this PR is breaking)
  • Loading branch information
lgoettgens authored Jul 5, 2023
1 parent c5fef18 commit 4f262f5
Show file tree
Hide file tree
Showing 17 changed files with 158 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Oscar"
uuid = "f1435218-dba5-11e9-1e4d-f1a5fab5fc13"
authors = ["The OSCAR Team <[email protected]>"]
version = "0.12.2-DEV"
version = "0.13.0-DEV"

[deps]
AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,18 @@ end


####################################################
# 6: Equality
# 6: Equality and hash
####################################################

function Base.:(==)(ac1::RationalEquivalenceClass, ac2::RationalEquivalenceClass)
return toric_variety(ac1) === toric_variety(ac2) && iszero(polynomial(ac1-ac2))
return toric_variety(ac1) === toric_variety(ac2) && polynomial(ac1) == polynomial(ac2)
end

function Base.hash(ac::RationalEquivalenceClass, h::UInt)
b = 0xb5d4ac6b9084eb6e % UInt
h = hash(toric_variety(ac), h)
h = hash(polynomial(ac), h)
return xor(h, b)
end


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,19 @@ Base.:^(cc::CohomologyClass, p::T) where {T <: IntegerUnion} = CohomologyClass(t


########################
# 5: Equality
# 5: Equality and hash
########################

Base.:(==)(cc1::CohomologyClass, cc2::CohomologyClass) = toric_variety(cc1) === toric_variety(cc2) && iszero(polynomial(cc1-cc2))
function Base.:(==)(cc1::CohomologyClass, cc2::CohomologyClass)
toric_variety(cc1) === toric_variety(cc2) && polynomial(cc1) == polynomial(cc2)
end

function Base.hash(cc::CohomologyClass, h::UInt)
b = 0x4de32042e67d89c8 % UInt
h = hash(toric_variety(cc), h)
h = hash(polynomial(cc), h)
return xor(h, b)
end

######################
# 6: Display
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,18 @@ Base.:*(c::T, tdc::ToricDivisorClass) where {T <: IntegerUnion} = toric_divisor_


########################
# 5: Equality
# 5: Equality and hash
########################

function Base.:(==)(tdc1::ToricDivisorClass, tdc2::ToricDivisorClass)
return toric_variety(tdc1) === toric_variety(tdc2) && iszero(divisor_class(tdc1) - divisor_class(tdc2))
return toric_variety(tdc1) === toric_variety(tdc2) && divisor_class(tdc1) == divisor_class(tdc2)
end

function Base.hash(tdc::ToricDivisorClass, h::UInt)
b = 0x118eb1fba136490c % UInt
h = hash(toric_variety(tdc), h)
h = hash(divisor_class(tdc), h)
return xor(h, b)
end


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,20 @@ Base.:*(c::T, td::ToricDivisor) where {T <: IntegerUnion} = toric_divisor(toric_


######################
# 5: Equality
# 5: Equality and hash
######################s

function Base.:(==)(td1::ToricDivisor, td2::ToricDivisor)
return toric_variety(td1) === toric_variety(td2) && coefficients(td1) == coefficients(td2)
end

function Base.hash(td::ToricDivisor, h::UInt)
b = 0x92bd6ac4f87d834e % UInt
h = hash(toric_variety(td), h)
h = hash(coefficients(td), h)
return xor(h, b)
end


######################
# 6: Display
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,20 @@ Base.:^(l::ToricLineBundle, p::Int) = l^ZZRingElem(p)


########################
# 5: Equality
# 5: Equality and hash
########################

function Base.:(==)(l1::ToricLineBundle, l2::ToricLineBundle)
return toric_variety(l1) === toric_variety(l2) && picard_class(l1) == picard_class(l2)
end

function Base.hash(l::ToricLineBundle, h::UInt)
b = 0xa2b0a2cd60a8ffbf % UInt
h = hash(toric_variety(l), h)
h = hash(picard_class(l), h)
return xor(h, b)
end


########################
# 6: Display
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,24 @@ end


####################################################
# 6: Equality of toric morphisms
# 6: Equality and hash of toric morphisms
####################################################

function Base.:(==)(tm1::ToricMorphism, tm2::ToricMorphism)
return domain(tm1) == domain(tm2) && codomain(tm1) == codomain(tm2) && grid_morphism(tm1) == grid_morphism(tm2)
end

function Base.hash(tm::ToricMorphism, h::UInt)
b = 0x1a66f927cae2d409 % UInt
h = hash(domain(tm), h)
h = hash(codomain(tm), h)
h = hash(grid_morphism(tm), h)
return xor(h, b)
end


######################
# 6: Display
# 7: Display
######################

function Base.show(io::IO, tm::ToricMorphism)
Expand Down
10 changes: 9 additions & 1 deletion src/Groups/gsets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,15 @@ function ^(omega::ElementOfGSet, g::T) where {T<:AbstractAlgebra.GroupElem}
return ElementOfGSet(Omega, fun(omega.obj, g))
end

==(omega1::ElementOfGSet, omega2::ElementOfGSet) = ((omega1.gset == omega2.gset) && (omega1.obj == omega2.obj))
==(omega1::ElementOfGSet, omega2::ElementOfGSet) =
((omega1.gset == omega2.gset) && (omega1.obj == omega2.obj))

function Base.hash(omega::ElementOfGSet, h::UInt)
b = 0x4dd1b3e65edeab89 % UInt
h = hash(omega.gset, h)
h = hash(omega.obj, h)
return xor(h, b)
end

Base.in(omega::ElementOfGSet, Omega::GSet) = Base.in(omega.obj, Omega)

Expand Down
7 changes: 6 additions & 1 deletion src/Groups/homomorphisms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ function Base.show(io::IO, x::GAPGroupHomomorphism)
end

function ==(f::GAPGroupHomomorphism{S,T}, g::GAPGroupHomomorphism{S,T}) where S where T
return f.map == g.map
return f.map == g.map
end

function Base.hash(f::GAPGroupHomomorphism{S,T}, h::UInt) where S where T
b = 0xdc777737af4c0c7b % UInt
return xor(hash(f.map, hash((S, T), h)), b)
end

Base.:*(f::GAPGroupHomomorphism{S, T}, g::GAPGroupHomomorphism{T, U}) where S where T where U = compose(f, g)
Expand Down
9 changes: 8 additions & 1 deletion src/Groups/matrices/forms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,14 @@ end
########################################################################

#TODO: checking whether two quadratic forms coincide by checking their polynomials is not possible yet.
==(B::SesquilinearForm, C::SesquilinearForm) = gram_matrix(B)==gram_matrix(C) && B.descr==C.descr
==(B::SesquilinearForm, C::SesquilinearForm) = B.descr == C.descr && gram_matrix(B) == gram_matrix(C)

function Base.hash(f::SesquilinearForm, h::UInt)
b = 0xf64440baac005f8c % UInt
h = hash(f.descr, h)
h = hash(gram_matrix(f), h)
return xor(h, b)
end

function base_ring(B::SesquilinearForm)
if isdefined(B,:matrix) return base_ring(gram_matrix(B))
Expand Down
5 changes: 5 additions & 0 deletions src/Modules/ModulesGraded.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,11 @@ function Base.:(==)(F::FreeMod_dec, G::FreeMod_dec)
return forget_decoration(F) == forget_decoration(G) && F.d == G.d
end

function Base.hash(F::FreeMod_dec, h::UInt)
b = 0x13d6e1b453cb661a % UInt
return xor(hash(forget_decoration(F), hash(F.d, h)), b)
end

###############################################################################
# FreeModElem_dec constructors
###############################################################################
Expand Down
34 changes: 31 additions & 3 deletions src/Modules/UngradedModules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,12 @@ function (==)(F::FreeMod, G::FreeMod)
end

function hash(F::FreeMod, h::UInt)
is_graded(F) && return hash((base_ring(F), rank(F), F.S, F.d), h)
return hash((base_ring(F), rank(F), F.S), h)
b = is_graded(F) ? (0x2d55d561d3f7e215 % UInt) : (0x62ca4181ff3a12f4 % UInt)
h = hash(base_ring(F), h)
h = hash(rank(F), h)
h = hash(F.S, h)
is_graded(F) && (h = hash(F.d, h))
return xor(h, b)
end

@doc raw"""
Expand Down Expand Up @@ -490,7 +494,11 @@ function (==)(a::AbstractFreeModElem, b::AbstractFreeModElem)
end

function hash(a::AbstractFreeModElem, h::UInt)
return xor(hash(tuple(parent(a), coordinates(a)), h), hash(typeof(a)))
b = 0xaa2ba4a32dd0b431 % UInt
h = hash(typeof(a), h)
h = hash(parent(a), h)
h = hash(coordinates(a), h)
return xor(h, b)
end

function Base.deepcopy_internal(a::AbstractFreeModElem, dict::IdDict)
Expand Down Expand Up @@ -3515,39 +3523,50 @@ function +(a::SubquoModuleElem, b::SubquoModuleElem)
check_parent(a,b)
return SubquoModuleElem(coordinates(a)+coordinates(b), a.parent)
end

function -(a::SubquoModuleElem, b::SubquoModuleElem)
check_parent(a,b)
return SubquoModuleElem(coordinates(a)-coordinates(b), a.parent)
end

-(a::SubquoModuleElem) = SubquoModuleElem(-coordinates(a), a.parent)

function *(a::MPolyDecRingElem, b::SubquoModuleElem)
if parent(a) !== base_ring(parent(b))
return base_ring(parent(b))(a)*b # this will throw if conversion is not possible
end
return SubquoModuleElem(a*coordinates(b), b.parent)
end

function *(a::MPolyRingElem, b::SubquoModuleElem)
if parent(a) !== base_ring(parent(b))
return base_ring(parent(b))(a)*b # this will throw if conversion is not possible
end
return SubquoModuleElem(a*coordinates(b), b.parent)
end

function *(a::RingElem, b::SubquoModuleElem)
if parent(a) !== base_ring(parent(b))
return base_ring(parent(b))(a)*b # this will throw if conversion is not possible
end
return SubquoModuleElem(a*coordinates(b), b.parent)
end

*(a::Int, b::SubquoModuleElem) = SubquoModuleElem(a*coordinates(b), b.parent)
*(a::Integer, b::SubquoModuleElem) = SubquoModuleElem(a*coordinates(b), b.parent)
*(a::QQFieldElem, b::SubquoModuleElem) = SubquoModuleElem(a*coordinates(b), b.parent)

function (==)(a::SubquoModuleElem, b::SubquoModuleElem)
if parent(a) !== parent(b)
return false
end
return iszero(a-b)
end

function Base.hash(a::SubquoModuleElem, h::UInt)
error("not implemented")
end

function Base.deepcopy_internal(a::SubquoModuleElem, dict::IdDict)
return SubquoModuleElem(deepcopy_internal(coordinates(a), dict), a.parent)
end
Expand Down Expand Up @@ -4820,6 +4839,15 @@ function (==)(f::ModuleFPHom, g::ModuleFPHom)
end
return true
end

function Base.hash(f::ModuleFPHom, h::UInt)
b = 0x535bbdbb2bc54b46 % UInt
h = hash(typeof(f), h)
h = hash(domain(f), h)
h = hash(codomain(f), h)
return xor(h, b)
end

###################################################################

@doc raw"""
Expand Down
6 changes: 6 additions & 0 deletions src/PolyhedralGeometry/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ Base.:(==)(x::AffineHyperplane, y::AffineHyperplane) = x.a == y.a && x.b == y.b

Base.:(==)(x::LinearHyperplane, y::LinearHyperplane) = x.a == y.a

Base.hash(x::T, h::UInt) where {T<:Union{AffineHalfspace,AffineHyperplane}} =
hash((x.a, x.b), hash(T, h))

Base.hash(x::T, h::UInt) where {T<:Union{LinearHalfspace,LinearHyperplane}} =
hash(x.a, hash(T, h))

################################################################################

for T in [LinearHalfspace, LinearHyperplane]
Expand Down
4 changes: 4 additions & 0 deletions src/Rings/PBWAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,10 @@ function Base.:(==)(a::PBWAlgIdeal{D, T, S}, b::PBWAlgIdeal{D, T, S}) where {D,
return is_subset(a, b) && is_subset(b, a)
end

function Base.hash(a::PBWAlgIdeal{D, T, S}, h::UInt) where {D, T, S}
b = 0x91c65dda1eed350f % UInt
return xor(hash(base_ring(a), hash(D, h)), b)
end

#### elimination

Expand Down
14 changes: 14 additions & 0 deletions src/Rings/mpoly-localizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,10 @@ function ==(T::AbsMPolyMultSet, U::AbsMPolyMultSet)
return (issubset(T, U) && issubset(U, T))
end

function Base.hash(T::AbsMPolyMultSet{BRT, BRET, RT, RET}, h::UInt) where {BRT,BRET,RT,RET}
error("not implemented")
end

function issubset(
T::MPolyComplementOfPrimeIdeal{BRT, BRET, RT, RET},
U::MPolyComplementOfPrimeIdeal{BRT, BRET, RT, RET}
Expand Down Expand Up @@ -2890,6 +2894,16 @@ function ==(f::MPolyLocalizedRingHom, g::MPolyLocalizedRingHom)
return true
end

function Base.hash(f::MPolyLocalizedRingHom, h::UInt)
b = 0xe29cdc1ecb68b7a0 % UInt
h = hash(domain(f), h)
h = hash(codomain(f), h)
for x in gens(base_ring(domain(f)))
h = hash(f(x), h)
end
return xor(h, b)
end

function divides(a::MPolyLocRingElem, b::MPolyLocRingElem)
W = parent(a)
W == parent(b) || error("elements do not belong to the same ring")
Expand Down
10 changes: 10 additions & 0 deletions src/Rings/mpolyquo-localizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,16 @@ function ==(f::MPolyQuoLocalizedRingHom, g::MPolyQuoLocalizedRingHom)
return true
end

function Base.hash(f::MPolyQuoLocalizedRingHom, h::UInt)
b = 0xd6d389598ad28724 % UInt
h = hash(domain(f), h)
h = hash(codomain(f), h)
for x in gens(base_ring(domain(f)))
h = hash(f(x), h)
end
return xor(h, b)
end

### printing
function Base.show(io::IO, ::MIME"text/plain", phi::MPolyQuoLocalizedRingHom)
R = base_ring(domain(phi))
Expand Down
11 changes: 10 additions & 1 deletion src/TropicalGeometry/semiring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ Oscar.isone(x::TropicalSemiringElem) = !isinf(x) && iszero(data(x))

################################################################################
#
# Equality
# Equality and hash
#
################################################################################

Expand All @@ -237,6 +237,15 @@ function Base.:(==)(x::TropicalSemiringElem, y::TropicalSemiringElem)
return data(x) == data(y)
end

function Base.hash(x::TropicalSemiringElem, h::UInt)
b = 0x4df38853cc07aa27 % UInt
h = hash(isinf(x), h)
if !isinf(x)
h = hash(data(x), h)
end
return xor(h, b)
end

################################################################################
#
# Comparison
Expand Down

0 comments on commit 4f262f5

Please sign in to comment.