1
0
mirror of https://github.com/kalmarek/Groups.jl.git synced 2024-12-25 02:05:30 +01:00

Merge pull request #20 from kalmarek/fix/==_via_equality_data

Fix/== via equality data
This commit is contained in:
Marek Kaluba 2021-12-13 10:53:36 +01:00 committed by GitHub
commit 667cd601ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 26 deletions

View File

@ -1,7 +1,7 @@
name = "Groups" name = "Groups"
uuid = "5d8bd718-bd84-11e8-3b40-ad14f4a32557" uuid = "5d8bd718-bd84-11e8-3b40-ad14f4a32557"
authors = ["Marek Kaluba <kalmar@amu.edu.pl>"] authors = ["Marek Kaluba <kalmar@amu.edu.pl>"]
version = "0.7.0" version = "0.7.1"
[deps] [deps]
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120" GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"

View File

@ -79,8 +79,8 @@ end
# eye-candy # eye-candy
Base.show(io::IO, ::Type{<:AbstractFPGroupElement{<:AutomorphismGroup{T}}}) where {T} = Base.show(io::IO, ::Type{<:FPGroupElement{<:AutomorphismGroup{T}}}) where {T} =
print(io, "Automorphism{$T,…}") print(io, "Automorphism{$T, …}")
Base.show(io::IO, A::AutomorphismGroup) = print(io, "automorphism group of ", object(A)) Base.show(io::IO, A::AutomorphismGroup) = print(io, "automorphism group of ", object(A))

View File

@ -23,8 +23,13 @@ word_type(::Type{<:AbstractFPGroup}) = Word{UInt8}
# the default (results in free rewriting) # the default (results in free rewriting)
rewriting(G::AbstractFPGroup) = alphabet(G) rewriting(G::AbstractFPGroup) = alphabet(G)
Base.@propagate_inbounds function (G::AbstractFPGroup)(word::AbstractVector{<:Integer}) Base.@propagate_inbounds function (G::AbstractFPGroup)(
@boundscheck @assert all(l -> 1 <= l <= length(KnuthBendix.alphabet(G)), word) word::AbstractVector{<:Integer},
)
@boundscheck @assert all(
l -> 1 <= l <= length(KnuthBendix.alphabet(G)),
word,
)
return FPGroupElement(word_type(G)(word), G) return FPGroupElement(word_type(G)(word), G)
end end
@ -32,7 +37,8 @@ end
Base.one(G::AbstractFPGroup) = FPGroupElement(one(word_type(G)), G) Base.one(G::AbstractFPGroup) = FPGroupElement(one(word_type(G)), G)
Base.eltype(::Type{FPG}) where {FPG<:AbstractFPGroup} = FPGroupElement{FPG,word_type(FPG)} Base.eltype(::Type{FPG}) where {FPG<:AbstractFPGroup} =
FPGroupElement{FPG,word_type(FPG)}
include("iteration.jl") include("iteration.jl")
@ -43,34 +49,47 @@ function GroupsCore.gens(G::AbstractFPGroup, i::Integer)
l = alphabet(G)[G.gens[i]] l = alphabet(G)[G.gens[i]]
return FPGroupElement(word_type(G)([l]), G) return FPGroupElement(word_type(G)([l]), G)
end end
GroupsCore.gens(G::AbstractFPGroup) = [gens(G, i) for i in 1:GroupsCore.ngens(G)] GroupsCore.gens(G::AbstractFPGroup) =
[gens(G, i) for i in 1:GroupsCore.ngens(G)]
# TODO: ProductReplacementAlgorithm # TODO: ProductReplacementAlgorithm
function Base.rand(rng::Random.AbstractRNG, rs::Random.SamplerTrivial{<:AbstractFPGroup}) function Base.rand(
rng::Random.AbstractRNG,
rs::Random.SamplerTrivial{<:AbstractFPGroup},
)
l = rand(10:100) l = rand(10:100)
G = rs[] G = rs[]
nletters = length(alphabet(G)) nletters = length(alphabet(G))
return FPGroupElement(word_type(G)(rand(1:nletters, l)), G) return FPGroupElement(word_type(G)(rand(1:nletters, l)), G)
end end
Base.isfinite(::AbstractFPGroup) = (@warn "using generic isfinite(::AbstractFPGroup): the returned `false` might be wrong"; false) Base.isfinite(::AbstractFPGroup) = (
@warn "using generic isfinite(::AbstractFPGroup): the returned `false` might be wrong"; false
)
## FPGroupElement ## FPGroupElement
abstract type AbstractFPGroupElement{Gr} <: GroupElement end abstract type AbstractFPGroupElement{Gr} <: GroupElement end
mutable struct FPGroupElement{Gr<:AbstractFPGroup,W<:AbstractWord} <: AbstractFPGroupElement{Gr} mutable struct FPGroupElement{Gr<:AbstractFPGroup,W<:AbstractWord} <:
AbstractFPGroupElement{Gr}
word::W word::W
savedhash::UInt savedhash::UInt
parent::Gr parent::Gr
FPGroupElement(word::W, G::AbstractFPGroup, hash::UInt=UInt(0)) where {W<:AbstractWord} = FPGroupElement(
new{typeof(G),W}(word, hash, G) word::W,
G::AbstractFPGroup,
hash::UInt = UInt(0),
) where {W<:AbstractWord} = new{typeof(G),W}(word, hash, G)
FPGroupElement{Gr, W}(word::AbstractWord, G::Gr) where {Gr, W} = FPGroupElement{Gr,W}(word::AbstractWord, G::Gr) where {Gr,W} =
new{Gr, W}(word, UInt(0), G) new{Gr,W}(word, UInt(0), G)
end end
Base.show(io::IO, ::Type{<:FPGroupElement{Gr}}) where {Gr} =
print(io, FPGroupElement, "{$Gr, …}")
word(f::AbstractFPGroupElement) = f.word word(f::AbstractFPGroupElement) = f.word
#convenience #convenience
@ -78,7 +97,7 @@ KnuthBendix.alphabet(g::AbstractFPGroupElement) = alphabet(parent(g))
function Base.show(io::IO, f::AbstractFPGroupElement) function Base.show(io::IO, f::AbstractFPGroupElement)
f = normalform!(f) f = normalform!(f)
KnuthBendix.print_repr(io, word(f), alphabet(f)) return KnuthBendix.print_repr(io, word(f), alphabet(f))
end end
## GroupElement Interface for FPGroupElement ## GroupElement Interface for FPGroupElement
@ -90,24 +109,28 @@ function Base.:(==)(g::AbstractFPGroupElement, h::AbstractFPGroupElement)
normalform!(g) normalform!(g)
normalform!(h) normalform!(h)
hash(g) != hash(h) && return false hash(g) != hash(h) && return false
return word(g) == word(h) return equality_data(g) == equality_data(h)
end end
function Base.deepcopy_internal(g::FPGroupElement, stackdict::IdDict) function Base.deepcopy_internal(g::FPGroupElement, stackdict::IdDict)
return FPGroupElement(copy(word(g)), parent(g), g.savedhash) return FPGroupElement(copy(word(g)), parent(g), g.savedhash)
end end
function Base.inv(g::GEl) where GEl <: AbstractFPGroupElement function Base.inv(g::GEl) where {GEl<:AbstractFPGroupElement}
G = parent(g) G = parent(g)
return GEl(inv(alphabet(G), word(g)), G) return GEl(inv(alphabet(G), word(g)), G)
end end
function Base.:(*)(g::GEl, h::GEl) where GEl<:AbstractFPGroupElement function Base.:(*)(g::GEl, h::GEl) where {GEl<:AbstractFPGroupElement}
@boundscheck @assert parent(g) === parent(h) @boundscheck @assert parent(g) === parent(h)
return GEl(word(g) * word(h), parent(g)) return GEl(word(g) * word(h), parent(g))
end end
GroupsCore.isfiniteorder(g::AbstractFPGroupElement) = isone(g) ? true : (@warn "using generic isfiniteorder(::AbstractFPGroupElement): the returned `false` might be wrong"; false) GroupsCore.isfiniteorder(g::AbstractFPGroupElement) =
isone(g) ? true :
(
@warn "using generic isfiniteorder(::AbstractFPGroupElement): the returned `false` might be wrong"; false
)
# additional methods: # additional methods:
Base.isone(g::AbstractFPGroupElement) = (normalform!(g); isempty(word(g))) Base.isone(g::AbstractFPGroupElement) = (normalform!(g); isempty(word(g)))
@ -126,7 +149,9 @@ struct FreeGroup{T} <: AbstractFPGroup
end end
function FreeGroup(A::Alphabet) function FreeGroup(A::Alphabet)
@boundscheck @assert all(KnuthBendix.hasinverse(l, A) for l in KnuthBendix.letters(A)) @boundscheck @assert all(
KnuthBendix.hasinverse(l, A) for l in KnuthBendix.letters(A)
)
ltrs = KnuthBendix.letters(A) ltrs = KnuthBendix.letters(A)
gens = Vector{eltype(ltrs)}() gens = Vector{eltype(ltrs)}()
invs = Vector{eltype(ltrs)}() invs = Vector{eltype(ltrs)}()
@ -146,12 +171,13 @@ function FreeGroup(n::Integer)
sizehint!(inverses, 2n) sizehint!(inverses, 2n)
for i in 1:n for i in 1:n
push!(symbols, Symbol(:f, i), Symbol(:F, i)) push!(symbols, Symbol(:f, i), Symbol(:F, i))
push!(inverses, 2i, 2i-1) push!(inverses, 2i, 2i - 1)
end end
return FreeGroup(symbols[1:2:2n], Alphabet(symbols, inverses)) return FreeGroup(symbols[1:2:2n], Alphabet(symbols, inverses))
end end
Base.show(io::IO, F::FreeGroup) = print(io, "free group on $(ngens(F)) generators") Base.show(io::IO, F::FreeGroup) =
print(io, "free group on $(ngens(F)) generators")
# mandatory methods: # mandatory methods:
KnuthBendix.alphabet(F::FreeGroup) = F.alphabet KnuthBendix.alphabet(F::FreeGroup) = F.alphabet
@ -161,7 +187,8 @@ relations(F::FreeGroup) = Pair{eltype(F)}[]
# these are mathematically correct # these are mathematically correct
Base.isfinite(::FreeGroup) = false Base.isfinite(::FreeGroup) = false
GroupsCore.isfiniteorder(g::AbstractFPGroupElement{<:FreeGroup}) = isone(g) ? true : false GroupsCore.isfiniteorder(g::AbstractFPGroupElement{<:FreeGroup}) =
isone(g) ? true : false
## FP Groups ## FP Groups
@ -182,7 +209,6 @@ function FPGroup(
ordering = KnuthBendix.LenLex, ordering = KnuthBendix.LenLex,
kwargs..., kwargs...,
) where {GEl<:FPGroupElement} ) where {GEl<:FPGroupElement}
O = ordering(alphabet(G)) O = ordering(alphabet(G))
for (lhs, rhs) in rels for (lhs, rhs) in rels
@assert parent(lhs) === parent(rhs) === G @assert parent(lhs) === parent(rhs) === G
@ -200,9 +226,12 @@ function Base.show(io::IO, G::FPGroup)
join(io, gens(G), ", ") join(io, gens(G), ", ")
print(io, " | ") print(io, " | ")
join(io, relations(G), ", ") join(io, relations(G), ", ")
print(io, "") return print(io, "")
end end
Base.show(io::IO, ::Type{<:FPGroup{T}}) where {T} =
print(io, FPGroup, "{$T, …}")
## GSymbol aka letter of alphabet ## GSymbol aka letter of alphabet
abstract type GSymbol end abstract type GSymbol end

View File

@ -96,7 +96,7 @@
@test evaluate(g*h) == evaluate(h*g) @test evaluate(g*h) == evaluate(h*g)
@test (g*h).savedhash == zero(UInt) @test (g*h).savedhash == zero(UInt)
@test sprint(show, typeof(g)) == "Automorphism{FreeGroup{Symbol},…}" @test sprint(show, typeof(g)) == "Automorphism{FreeGroup{Symbol}, …}"
a = g*h a = g*h
b = h*g b = h*g