mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-08-25 12:06:57 +02:00
Merge pull request #29 from kalmarek/fix/#28_normalform_hashing
Fix for #28: normalform & hashing
This commit is contained in:
commit
d385992e92
@ -1,7 +1,7 @@
|
||||
name = "Groups"
|
||||
uuid = "5d8bd718-bd84-11e8-3b40-ad14f4a32557"
|
||||
authors = ["Marek Kaluba <kalmar@amu.edu.pl>"]
|
||||
version = "0.7.6"
|
||||
version = "0.7.7"
|
||||
|
||||
[deps]
|
||||
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
|
||||
|
@ -14,12 +14,7 @@ end
|
||||
λ(i, j) = Transvection(:λ, i, j)
|
||||
|
||||
function Base.show(io::IO, t::Transvection)
|
||||
id = if t.id === :ϱ
|
||||
'ϱ'
|
||||
else # if t.id === :λ
|
||||
'λ'
|
||||
end
|
||||
print(io, id, subscriptify(t.i), '.', subscriptify(t.j))
|
||||
print(io, t.id, subscriptify(t.i), '.', subscriptify(t.j))
|
||||
return t.inv && print(io, "^-1")
|
||||
end
|
||||
|
||||
|
@ -37,6 +37,7 @@ function _update_savedhash!(g::AbstractFPGroupElement, data)
|
||||
end
|
||||
|
||||
function Base.hash(g::AbstractFPGroupElement, h::UInt)
|
||||
g = normalform!(g)
|
||||
_isvalidhash(g) || _update_savedhash!(g, equality_data(g))
|
||||
return hash(g.savedhash >> count_ones(__BITFLAGS_MASK), h)
|
||||
end
|
||||
|
@ -23,7 +23,7 @@ end
|
||||
|
||||
function Base.show(io::IO, s::ElementarySymplectic)
|
||||
i, j = Groups.subscriptify(s.i), Groups.subscriptify(s.j)
|
||||
print(io, s.symbol, i, j)
|
||||
print(io, s.symbol, i, '.', j)
|
||||
return !isone(s.val) && print(io, "^$(s.val)")
|
||||
end
|
||||
|
||||
|
15
src/types.jl
15
src/types.jl
@ -88,6 +88,9 @@ end
|
||||
|
||||
abstract type AbstractFPGroupElement{Gr} <: GroupElement end
|
||||
|
||||
Base.copy(g::AbstractFPGroupElement) = one(g) * g
|
||||
word(f::AbstractFPGroupElement) = f.word
|
||||
|
||||
mutable struct FPGroupElement{Gr<:AbstractFPGroup,W<:AbstractWord} <:
|
||||
AbstractFPGroupElement{Gr}
|
||||
word::W
|
||||
@ -111,7 +114,9 @@ function Base.show(io::IO, ::Type{<:FPGroupElement{Gr}}) where {Gr}
|
||||
return print(io, FPGroupElement, "{$Gr, …}")
|
||||
end
|
||||
|
||||
word(f::AbstractFPGroupElement) = f.word
|
||||
function Base.copy(f::FPGroupElement)
|
||||
return FPGroupElement(copy(word(f)), parent(f), f.savedhash)
|
||||
end
|
||||
|
||||
#convenience
|
||||
KnuthBendix.alphabet(g::AbstractFPGroupElement) = alphabet(parent(g))
|
||||
@ -134,7 +139,13 @@ function Base.:(==)(g::AbstractFPGroupElement, h::AbstractFPGroupElement)
|
||||
end
|
||||
|
||||
function Base.deepcopy_internal(g::FPGroupElement, stackdict::IdDict)
|
||||
return FPGroupElement(copy(word(g)), parent(g), g.savedhash)
|
||||
haskey(stackdict, objectid(g)) && return stackdict[objectid(g)]
|
||||
cw = if haskey(stackdict, objectid(word(g)))
|
||||
stackdict[objectid(word(g))]
|
||||
else
|
||||
copy(word(g))
|
||||
end
|
||||
return FPGroupElement(cw, parent(g), g.savedhash)
|
||||
end
|
||||
|
||||
function Base.inv(g::GEl) where {GEl<:AbstractFPGroupElement}
|
||||
|
@ -26,8 +26,7 @@ function wlmetric_ball(
|
||||
new = collect(
|
||||
op(o, s) for o in @view(ball[sizes[end-1]:end]) for s in S
|
||||
)
|
||||
append!(ball, new)
|
||||
unique!(ball)
|
||||
ball = union!(ball, new)
|
||||
push!(sizes, length(ball))
|
||||
end
|
||||
end
|
||||
|
@ -14,7 +14,8 @@
|
||||
G = FPGroup(F, [a * b => b * a, a * c => c * a, b * c => c * b])
|
||||
|
||||
@test G isa FPGroup
|
||||
@test sprint(show, G) == "⟨ a b c | \n\t a*b => b*a a*c => c*a b*c => c*b ⟩"
|
||||
@test sprint(show, G) ==
|
||||
"⟨ a b c | \n\t a*b => b*a a*c => c*a b*c => c*b ⟩"
|
||||
@test rand(G) isa FPGroupElement
|
||||
|
||||
f = a * c * b
|
||||
@ -40,7 +41,7 @@
|
||||
end
|
||||
|
||||
# quotient of G
|
||||
H = FPGroup(G, [aG^2 => cG, bG * cG => aG], max_rules=200)
|
||||
H = FPGroup(G, [aG^2 => cG, bG * cG => aG]; max_rules = 200)
|
||||
|
||||
h = H(word(g))
|
||||
|
||||
@ -48,15 +49,21 @@
|
||||
@test_throws AssertionError h == g
|
||||
@test_throws MethodError h * g
|
||||
|
||||
H′ = FPGroup(G, [aG^2 => cG, bG * cG => aG], max_rules=200)
|
||||
H′ = FPGroup(G, [aG^2 => cG, bG * cG => aG]; max_rules = 200)
|
||||
@test_throws AssertionError one(H) == one(H′)
|
||||
|
||||
Groups.normalform!(h)
|
||||
@test h == H([5])
|
||||
|
||||
@test_logs (:warn, "using generic isfiniteorder(::AbstractFPGroupElement): the returned `false` might be wrong") isfiniteorder(h)
|
||||
@test_logs (
|
||||
:warn,
|
||||
"using generic isfiniteorder(::AbstractFPGroupElement): the returned `false` might be wrong",
|
||||
) isfiniteorder(h)
|
||||
|
||||
@test_logs (:warn, "using generic isfinite(::AbstractFPGroup): the returned `false` might be wrong") isfinite(H)
|
||||
@test_logs (
|
||||
:warn,
|
||||
"using generic isfinite(::AbstractFPGroup): the returned `false` might be wrong",
|
||||
) isfinite(H)
|
||||
|
||||
Logging.with_logger(Logging.NullLogger()) do
|
||||
@testset "GroupsCore conformance: H" begin
|
||||
@ -64,4 +71,24 @@
|
||||
test_GroupElement_interface(rand(H, 2)...)
|
||||
end
|
||||
end
|
||||
|
||||
@testset "hash/normalform #28" begin
|
||||
function cyclic_group(n::Integer)
|
||||
A = Alphabet([:a, :A], [2, 1])
|
||||
F = FreeGroup(A)
|
||||
a, = Groups.gens(F)
|
||||
e = one(F)
|
||||
Cₙ = FPGroup(F, [a^n => e])
|
||||
|
||||
return Cₙ
|
||||
end
|
||||
|
||||
n = 15
|
||||
G = cyclic_group(n)
|
||||
ball, sizes = Groups.wlmetric_ball(gens(G); radius = n)
|
||||
@test first(sizes) == 2
|
||||
@test last(sizes) == n
|
||||
|
||||
@test Set(ball) == Set([first(gens(G))^i for i in 0:n-1])
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user