mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-12-25 18:15:29 +01:00
Merge pull request #20 from kalmarek/fix/==_via_equality_data
Fix/== via equality data
This commit is contained in:
commit
667cd601ce
@ -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"
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
73
src/types.jl
73
src/types.jl
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user