mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-12-25 18:15:29 +01:00
introduce AbstractFPGroupElement
This commit is contained in:
parent
394d9a7aac
commit
29b6675a8a
@ -14,7 +14,7 @@ end
|
||||
object(G::AutomorphismGroup) = G.group
|
||||
rewriting(G::AutomorphismGroup) = G.rws
|
||||
|
||||
function equality_data(f::FPGroupElement{<:AutomorphismGroup})
|
||||
function equality_data(f::AbstractFPGroupElement{<:AutomorphismGroup})
|
||||
imf = evaluate(f)
|
||||
# return normalform!.(imf)
|
||||
|
||||
@ -26,7 +26,7 @@ function equality_data(f::FPGroupElement{<:AutomorphismGroup})
|
||||
return imf
|
||||
end
|
||||
|
||||
function Base.:(==)(g::A, h::A) where {A<:FPGroupElement{<:AutomorphismGroup}}
|
||||
function Base.:(==)(g::A, h::A) where {A<:AbstractFPGroupElement{<:AutomorphismGroup}}
|
||||
@assert parent(g) === parent(h)
|
||||
|
||||
if _isvalidhash(g) && _isvalidhash(h)
|
||||
@ -70,7 +70,7 @@ function Base.:(==)(g::A, h::A) where {A<:FPGroupElement{<:AutomorphismGroup}}
|
||||
return equal
|
||||
end
|
||||
|
||||
function Base.isone(g::FPGroupElement{<:AutomorphismGroup})
|
||||
function Base.isone(g::AbstractFPGroupElement{<:AutomorphismGroup})
|
||||
if length(word(g)) > 8
|
||||
normalform!(g)
|
||||
end
|
||||
@ -79,21 +79,21 @@ end
|
||||
|
||||
# eye-candy
|
||||
|
||||
Base.show(io::IO, ::Type{<:FPGroupElement{<:AutomorphismGroup{T}}}) where {T} =
|
||||
Base.show(io::IO, ::Type{<:AbstractFPGroupElement{<:AutomorphismGroup{T}}}) where {T} =
|
||||
print(io, "Automorphism{$T,…}")
|
||||
|
||||
Base.show(io::IO, A::AutomorphismGroup) = print(io, "automorphism group of ", object(A))
|
||||
|
||||
## Automorphism Evaluation
|
||||
|
||||
domain(f::FPGroupElement{<:AutomorphismGroup}) = deepcopy(parent(f).domain)
|
||||
domain(f::AbstractFPGroupElement{<:AutomorphismGroup}) = deepcopy(parent(f).domain)
|
||||
# tuple(gens(object(parent(f)))...)
|
||||
|
||||
evaluate(f::FPGroupElement{<:AutomorphismGroup}) = evaluate!(domain(f), f)
|
||||
evaluate(f::AbstractFPGroupElement{<:AutomorphismGroup}) = evaluate!(domain(f), f)
|
||||
|
||||
function evaluate!(
|
||||
t::NTuple{N,T},
|
||||
f::FPGroupElement{<:AutomorphismGroup{<:Group}},
|
||||
f::AbstractFPGroupElement{<:AutomorphismGroup{<:Group}},
|
||||
tmp = one(first(t)),
|
||||
) where {N, T}
|
||||
A = alphabet(f)
|
||||
|
@ -43,7 +43,7 @@ function SurfaceGroup(genus::Integer, boundaries::Integer)
|
||||
comms = Word(word)
|
||||
word_rels = [ comms => one(comms) ]
|
||||
|
||||
rws = RewritingSystem(word_rels, KnuthBendix.RecursivePathOrder(Al))
|
||||
rws = KnuthBendix.RewritingSystem(word_rels, KnuthBendix.RecursivePathOrder(Al))
|
||||
KnuthBendix.knuthbendix!(rws)
|
||||
elseif boundaries == 1
|
||||
S = typeof(one(Word(Int[])))
|
||||
|
@ -1,6 +1,6 @@
|
||||
## Hashing
|
||||
|
||||
equality_data(g::FPGroupElement) = (normalform!(g); word(g))
|
||||
equality_data(g::AbstractFPGroupElement) = (normalform!(g); word(g))
|
||||
|
||||
bitget(h::UInt, n::Int) = Bool((h & (1 << n)) >> n)
|
||||
bitclear(h::UInt, n::Int) = h & ~(1 << n)
|
||||
@ -14,30 +14,30 @@ bitset(h::UInt, v::Bool, n::Int) = v ? bitset(h, n) : bitclear(h, n)
|
||||
# * `savedhash & 2` (the second bit): is the hash valid?
|
||||
const __BITFLAGS_MASK = ~(~(UInt(0)) << 2)
|
||||
|
||||
isnormalform(g::FPGroupElement) = bitget(g.savedhash, 0)
|
||||
_isvalidhash(g::FPGroupElement) = bitget(g.savedhash, 1)
|
||||
isnormalform(g::AbstractFPGroupElement) = bitget(g.savedhash, 0)
|
||||
_isvalidhash(g::AbstractFPGroupElement) = bitget(g.savedhash, 1)
|
||||
|
||||
_setnormalform(h::UInt, v::Bool) = bitset(h, v, 0)
|
||||
_setvalidhash(h::UInt, v::Bool) = bitset(h, v, 1)
|
||||
|
||||
_setnormalform!(g::FPGroupElement, v::Bool) = g.savedhash = _setnormalform(g.savedhash, v)
|
||||
_setvalidhash!(g::FPGroupElement, v::Bool) = g.savedhash = _setvalidhash(g.savedhash, v)
|
||||
_setnormalform!(g::AbstractFPGroupElement, v::Bool) = g.savedhash = _setnormalform(g.savedhash, v)
|
||||
_setvalidhash!(g::AbstractFPGroupElement, v::Bool) = g.savedhash = _setvalidhash(g.savedhash, v)
|
||||
|
||||
# To update hash use this internal method, possibly only after computing the
|
||||
# normal form of `g`:
|
||||
function _update_savedhash!(g::FPGroupElement, data)
|
||||
function _update_savedhash!(g::AbstractFPGroupElement, data)
|
||||
h = hash(data, hash(parent(g)))
|
||||
h = (h << count_ones(__BITFLAGS_MASK)) | (__BITFLAGS_MASK & g.savedhash)
|
||||
g.savedhash = _setvalidhash(h, true)
|
||||
return g
|
||||
end
|
||||
|
||||
function Base.hash(g::FPGroupElement, h::UInt)
|
||||
function Base.hash(g::AbstractFPGroupElement, h::UInt)
|
||||
_isvalidhash(g) || _update_savedhash!(g, equality_data(g))
|
||||
return hash(g.savedhash >> count_ones(__BITFLAGS_MASK), h)
|
||||
end
|
||||
|
||||
function Base.copyto!(res::FPGroupElement, g::FPGroupElement)
|
||||
function Base.copyto!(res::AbstractFPGroupElement, g::AbstractFPGroupElement)
|
||||
@assert parent(res) === parent(g)
|
||||
resize!(word(res), length(word(g)))
|
||||
copyto!(word(res), word(g))
|
||||
|
@ -2,7 +2,7 @@
|
||||
normalform!(g::FPGroupElement)
|
||||
Compute the normal form of `g`, possibly modifying `g` in-place.
|
||||
"""
|
||||
@inline function normalform!(g::FPGroupElement)
|
||||
@inline function normalform!(g::AbstractFPGroupElement)
|
||||
isnormalform(g) && return g
|
||||
|
||||
let w = one(word(g))
|
||||
@ -21,7 +21,7 @@ end
|
||||
normalform!(res::GEl, g::GEl) where GEl<:FPGroupElement
|
||||
Compute the normal fom of `g`, storing it in `res`.
|
||||
"""
|
||||
function normalform!(res::GEl, g::GEl) where {GEl<:FPGroupElement}
|
||||
function normalform!(res::GEl, g::GEl) where {GEl<:AbstractFPGroupElement}
|
||||
@boundscheck @assert parent(res) === parent(g)
|
||||
if isnormalform(g)
|
||||
copyto!(res, g)
|
||||
@ -40,7 +40,7 @@ Append the normal form of `g` to word `res`, modifying `res` in place.
|
||||
|
||||
Defaults to the rewriting in the free group.
|
||||
"""
|
||||
@inline function normalform!(res::AbstractWord, g::FPGroupElement)
|
||||
@inline function normalform!(res::AbstractWord, g::AbstractFPGroupElement)
|
||||
isone(res) && isnormalform(g) && return append!(res, word(g))
|
||||
return KnuthBendix.rewrite_from_left!(res, word(g), rewriting(parent(g)))
|
||||
end
|
||||
|
37
src/types.jl
37
src/types.jl
@ -57,10 +57,12 @@ Base.isfinite(::AbstractFPGroup) = (@warn "using generic isfinite(::AbstractFPGr
|
||||
|
||||
## FPGroupElement
|
||||
|
||||
mutable struct FPGroupElement{G<:AbstractFPGroup,W<:AbstractWord} <: GroupElement
|
||||
abstract type AbstractFPGroupElement{Gr} <: GroupElement end
|
||||
|
||||
mutable struct FPGroupElement{Gr<:AbstractFPGroup,W<:AbstractWord} <: AbstractFPGroupElement{Gr}
|
||||
word::W
|
||||
savedhash::UInt
|
||||
parent::G
|
||||
parent::Gr
|
||||
|
||||
FPGroupElement(word::W, G::AbstractFPGroup) where {W<:AbstractWord} =
|
||||
new{typeof(G),W}(word, UInt(0), G)
|
||||
@ -69,22 +71,22 @@ mutable struct FPGroupElement{G<:AbstractFPGroup,W<:AbstractWord} <: GroupElemen
|
||||
new{typeof(G),W}(word, hash, G)
|
||||
end
|
||||
|
||||
word(f::FPGroupElement) = f.word
|
||||
word(f::AbstractFPGroupElement) = f.word
|
||||
|
||||
#convenience
|
||||
KnuthBendix.alphabet(g::FPGroupElement) = alphabet(parent(g))
|
||||
KnuthBendix.alphabet(g::AbstractFPGroupElement) = alphabet(parent(g))
|
||||
|
||||
function Base.show(io::IO, f::FPGroupElement)
|
||||
function Base.show(io::IO, f::AbstractFPGroupElement)
|
||||
f = normalform!(f)
|
||||
KnuthBendix.print_repr(io, word(f), alphabet(f))
|
||||
end
|
||||
|
||||
## GroupElement Interface for FPGroupElement
|
||||
|
||||
Base.parent(f::FPGroupElement) = f.parent
|
||||
GroupsCore.parent_type(::Type{<:FPGroupElement{G}}) where {G} = G
|
||||
Base.parent(f::AbstractFPGroupElement) = f.parent
|
||||
GroupsCore.parent_type(::Type{<:AbstractFPGroupElement{G}}) where {G} = G
|
||||
|
||||
function Base.:(==)(g::FPGroupElement, h::FPGroupElement)
|
||||
function Base.:(==)(g::AbstractFPGroupElement, h::AbstractFPGroupElement)
|
||||
@boundscheck @assert parent(g) === parent(h)
|
||||
normalform!(g)
|
||||
normalform!(h)
|
||||
@ -96,17 +98,20 @@ function Base.deepcopy_internal(g::FPGroupElement, stackdict::IdDict)
|
||||
return FPGroupElement(copy(word(g)), g.savedhash, parent(g))
|
||||
end
|
||||
|
||||
Base.inv(g::FPGroupElement) = (G = parent(g); FPGroupElement(inv(alphabet(G), word(g)), G))
|
||||
|
||||
function Base.:(*)(g::FPGroupElement, h::FPGroupElement)
|
||||
@boundscheck @assert parent(g) === parent(h)
|
||||
return FPGroupElement(word(g) * word(h), parent(g))
|
||||
function Base.inv(g::GEl) where GEl <: AbstractFPGroupElement
|
||||
G = parent(g)
|
||||
return GEl(inv(alphabet(G), word(g)), G)
|
||||
end
|
||||
|
||||
GroupsCore.isfiniteorder(g::FPGroupElement) = isone(g) ? true : (@warn "using generic isfiniteorder(::FPGroupElement): the returned `false` might be wrong"; false)
|
||||
function Base.:(*)(g::GEl, h::GEl) where GEl<:AbstractFPGroupElement
|
||||
@boundscheck @assert parent(g) === parent(h)
|
||||
return GEl(word(g) * word(h), parent(g))
|
||||
end
|
||||
|
||||
GroupsCore.isfiniteorder(g::AbstractFPGroupElement) = isone(g) ? true : (@warn "using generic isfiniteorder(::AbstractFPGroupElement): the returned `false` might be wrong"; false)
|
||||
|
||||
# additional methods:
|
||||
Base.isone(g::FPGroupElement) = (normalform!(g); isempty(word(g)))
|
||||
Base.isone(g::AbstractFPGroupElement) = (normalform!(g); isempty(word(g)))
|
||||
|
||||
## Free Groups
|
||||
|
||||
@ -157,7 +162,7 @@ relations(F::FreeGroup) = Pair{eltype(F)}[]
|
||||
# these are mathematically correct
|
||||
Base.isfinite(::FreeGroup) = false
|
||||
|
||||
GroupsCore.isfiniteorder(g::FPGroupElement{<:FreeGroup}) = isone(g) ? true : false
|
||||
GroupsCore.isfiniteorder(g::AbstractFPGroupElement{<:FreeGroup}) = isone(g) ? true : false
|
||||
|
||||
## FP Groups
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user