mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-12-25 18:15:29 +01:00
formatting
This commit is contained in:
parent
84bfbd7408
commit
75b7d9fab3
@ -7,6 +7,7 @@ version = "0.5.2"
|
|||||||
AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d"
|
AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d"
|
||||||
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||||
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
|
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
|
||||||
|
KnuthBendix = "c2604015-7b3d-4a30-8a26-9074551ec60a"
|
||||||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||||
ThreadsX = "ac1d9e8a-700a-412c-b207-f0111f4b6c0d"
|
ThreadsX = "ac1d9e8a-700a-412c-b207-f0111f4b6c0d"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
mutable struct FPIterState{GEl, T}
|
mutable struct FPIterState{GEl,T}
|
||||||
elts::OrderedSet{GEl}
|
elts::OrderedSet{GEl}
|
||||||
u::GEl
|
u::GEl
|
||||||
v::GEl
|
v::GEl
|
||||||
@ -42,12 +42,12 @@ function Base.iterate(G::AbstractFPGroup, state)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if res in iter
|
if res in iter
|
||||||
return iterate(G, (iter, elt, gen_idx+1))
|
return iterate(G, (iter, elt, gen_idx + 1))
|
||||||
else
|
else
|
||||||
w = deepcopy(res)
|
w = deepcopy(res)
|
||||||
@assert isnormalform(w)
|
@assert isnormalform(w)
|
||||||
push!(iter, w)
|
push!(iter, w)
|
||||||
return w, (iter, elt, gen_idx+1)
|
return w, (iter, elt, gen_idx + 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ function KnuthBendix.Alphabet(S::AbstractVector{<:GSymbol})
|
|||||||
return Alphabet(S, inversions)
|
return Alphabet(S, inversions)
|
||||||
end
|
end
|
||||||
|
|
||||||
struct AutomorphismGroup{G<:Group, T, R, S} <: AbstractFPGroup
|
struct AutomorphismGroup{G<:Group,T,R,S} <: AbstractFPGroup
|
||||||
group::G
|
group::G
|
||||||
gens::Vector{T}
|
gens::Vector{T}
|
||||||
rws::R
|
rws::R
|
||||||
@ -13,29 +13,28 @@ end
|
|||||||
|
|
||||||
object(G::AutomorphismGroup) = G.group
|
object(G::AutomorphismGroup) = G.group
|
||||||
|
|
||||||
function SpecialAutomorphismGroup(F::FreeGroup;
|
function SpecialAutomorphismGroup(F::FreeGroup; ordering = KnuthBendix.LenLex, kwargs...)
|
||||||
ordering=KnuthBendix.LenLex, kwargs...)
|
|
||||||
|
|
||||||
n = length(KnuthBendix.alphabet(F))÷2
|
n = length(KnuthBendix.alphabet(F)) ÷ 2
|
||||||
A, rels = gersten_relations(n, commutative=false)
|
A, rels = gersten_relations(n, commutative = false)
|
||||||
S = KnuthBendix.letters(A)[1:2(n^2 - n)]
|
S = KnuthBendix.letters(A)[1:2(n^2-n)]
|
||||||
|
|
||||||
rws = KnuthBendix.RewritingSystem(rels, ordering(A))
|
rws = KnuthBendix.RewritingSystem(rels, ordering(A))
|
||||||
KnuthBendix.knuthbendix!(rws; kwargs...)
|
KnuthBendix.knuthbendix!(rws; kwargs...)
|
||||||
return AutomorphismGroup(F, S, rws, ntuple(i->gens(F, i), n))
|
return AutomorphismGroup(F, S, rws, ntuple(i -> gens(F, i), n))
|
||||||
end
|
end
|
||||||
|
|
||||||
KnuthBendix.alphabet(G::AutomorphismGroup{<:FreeGroup}) = alphabet(rewriting(G))
|
KnuthBendix.alphabet(G::AutomorphismGroup{<:FreeGroup}) = alphabet(rewriting(G))
|
||||||
rewriting(G::AutomorphismGroup) = G.rws
|
rewriting(G::AutomorphismGroup) = G.rws
|
||||||
|
|
||||||
function relations(G::AutomorphismGroup)
|
function relations(G::AutomorphismGroup)
|
||||||
n = length(KnuthBendix.alphabet(object(G)))÷2
|
n = length(KnuthBendix.alphabet(object(G))) ÷ 2
|
||||||
return last(gersten_relations(n, commutative=false))
|
return last(gersten_relations(n, commutative = false))
|
||||||
end
|
end
|
||||||
|
|
||||||
equality_data(f::FPGroupElement{<:AutomorphismGroup}) = normalform!.(evaluate(f))
|
equality_data(f::FPGroupElement{<:AutomorphismGroup}) = normalform!.(evaluate(f))
|
||||||
|
|
||||||
function Base.:(==)(g::A, h::A) where A<:FPGroupElement{<:AutomorphismGroup}
|
function Base.:(==)(g::A, h::A) where {A<:FPGroupElement{<:AutomorphismGroup}}
|
||||||
@assert parent(g) === parent(h)
|
@assert parent(g) === parent(h)
|
||||||
|
|
||||||
if _isvalidhash(g) && _isvalidhash(h)
|
if _isvalidhash(g) && _isvalidhash(h)
|
||||||
@ -81,15 +80,15 @@ end
|
|||||||
|
|
||||||
# eye-candy
|
# eye-candy
|
||||||
|
|
||||||
Base.show(io::IO, ::Type{<:FPGroupElement{<:AutomorphismGroup{T}}}) where T <: FreeGroup = print(io, "Automorphism{$T}")
|
Base.show(io::IO, ::Type{<:FPGroupElement{<:AutomorphismGroup{T}}}) where {T<:FreeGroup} =
|
||||||
|
print(io, "Automorphism{$T,…}")
|
||||||
|
|
||||||
## Automorphism Evaluation
|
## Automorphism Evaluation
|
||||||
|
|
||||||
domain(f::FPGroupElement{<:AutomorphismGroup}) = deepcopy(parent(f).domain)
|
domain(f::FPGroupElement{<:AutomorphismGroup}) = deepcopy(parent(f).domain)
|
||||||
# tuple(gens(object(parent(f)))...)
|
# tuple(gens(object(parent(f)))...)
|
||||||
|
|
||||||
evaluate(f::FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}) =
|
evaluate(f::FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}) = evaluate!(domain(f), f)
|
||||||
evaluate!(domain(f), f)
|
|
||||||
|
|
||||||
function evaluate!(
|
function evaluate!(
|
||||||
t::NTuple{N,T},
|
t::NTuple{N,T},
|
||||||
|
@ -20,10 +20,8 @@ _isvalidhash(g::FPGroupElement) = bitget(g.savedhash, 1)
|
|||||||
_setnormalform(h::UInt, v::Bool) = bitset(h, v, 0)
|
_setnormalform(h::UInt, v::Bool) = bitset(h, v, 0)
|
||||||
_setvalidhash(h::UInt, v::Bool) = bitset(h, v, 1)
|
_setvalidhash(h::UInt, v::Bool) = bitset(h, v, 1)
|
||||||
|
|
||||||
_setnormalform!(g::FPGroupElement, v::Bool) =
|
_setnormalform!(g::FPGroupElement, v::Bool) = g.savedhash = _setnormalform(g.savedhash, v)
|
||||||
g.savedhash = _setnormalform(g.savedhash, v)
|
_setvalidhash!(g::FPGroupElement, v::Bool) = g.savedhash = _setvalidhash(g.savedhash, v)
|
||||||
_setvalidhash!(g::FPGroupElement, v::Bool) =
|
|
||||||
g.savedhash = _setvalidhash(g.savedhash, v)
|
|
||||||
|
|
||||||
# To update hash use this internal method, possibly only after computing the
|
# To update hash use this internal method, possibly only after computing the
|
||||||
# normal form of `g`:
|
# normal form of `g`:
|
||||||
@ -36,7 +34,7 @@ end
|
|||||||
|
|
||||||
function Base.hash(g::FPGroupElement, h::UInt)
|
function Base.hash(g::FPGroupElement, h::UInt)
|
||||||
_isvalidhash(g) || _update_savedhash!(g, equality_data(g))
|
_isvalidhash(g) || _update_savedhash!(g, equality_data(g))
|
||||||
return hash(g.savedhash >> count_ones(__BITFLAGS_MASK) , h)
|
return hash(g.savedhash >> count_ones(__BITFLAGS_MASK), h)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Base.copyto!(res::FPGroupElement, g::FPGroupElement)
|
function Base.copyto!(res::FPGroupElement, g::FPGroupElement)
|
||||||
|
@ -6,16 +6,16 @@ struct Transvection <: GSymbol
|
|||||||
ij::UInt8
|
ij::UInt8
|
||||||
inv::Bool
|
inv::Bool
|
||||||
|
|
||||||
function Transvection(id::Symbol, i::Integer, j::Integer, inv=false)
|
function Transvection(id::Symbol, i::Integer, j::Integer, inv = false)
|
||||||
@assert id in (:ϱ, :λ)
|
@assert id in (:ϱ, :λ)
|
||||||
return new(id, _indices(UInt8(i),UInt8(j)), inv)
|
return new(id, _indices(UInt8(i), UInt8(j)), inv)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ϱ(i, j) = Transvection(:ϱ, i, j)
|
ϱ(i, j) = Transvection(:ϱ, i, j)
|
||||||
λ(i, j) = Transvection(:λ, i, j)
|
λ(i, j) = Transvection(:λ, i, j)
|
||||||
|
|
||||||
_indices(ij::UInt8) = (ij & 0xf0)>>4, (ij & 0x0f)
|
_indices(ij::UInt8) = (ij & 0xf0) >> 4, (ij & 0x0f)
|
||||||
|
|
||||||
function _indices(i::UInt8, j::UInt8)
|
function _indices(i::UInt8, j::UInt8)
|
||||||
@boundscheck @assert i < typemax(i) ÷ 2
|
@boundscheck @assert i < typemax(i) ÷ 2
|
||||||
|
@ -29,10 +29,11 @@ word_type(G::AbstractFPGroup) = word_type(typeof(G))
|
|||||||
# the default:
|
# the default:
|
||||||
word_type(::Type{<:AbstractFPGroup}) = Word{UInt16}
|
word_type(::Type{<:AbstractFPGroup}) = Word{UInt16}
|
||||||
|
|
||||||
|
# the default (results in free rewriting)
|
||||||
rewriting(G::AbstractFPGroup) = alphabet(G)
|
rewriting(G::AbstractFPGroup) = alphabet(G)
|
||||||
|
|
||||||
function (G::AbstractFPGroup)(word::AbstractVector{<:Integer})
|
function (G::AbstractFPGroup)(word::AbstractVector{<:Integer})
|
||||||
@boundscheck @assert all(l -> 1<= l <=length(KnuthBendix.alphabet(G)), word)
|
@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
|
||||||
|
|
||||||
@ -40,25 +41,21 @@ 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} =
|
Base.eltype(::Type{FPG}) where {FPG<:AbstractFPGroup} = FPGroupElement{FPG,word_type(FPG)}
|
||||||
FPGroupElement{FPG, word_type(FPG)}
|
|
||||||
|
|
||||||
include("iteration.jl")
|
include("iteration.jl")
|
||||||
|
|
||||||
GroupsCore.ngens(G::AbstractFPGroup) = length(G.gens)
|
GroupsCore.ngens(G::AbstractFPGroup) = length(G.gens)
|
||||||
|
|
||||||
function GroupsCore.gens(G::AbstractFPGroup, i::Integer)
|
function GroupsCore.gens(G::AbstractFPGroup, i::Integer)
|
||||||
@boundscheck 1<=i<=GroupsCore.ngens(G)
|
@boundscheck 1 <= i <= GroupsCore.ngens(G)
|
||||||
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(
|
function Base.rand(rng::Random.AbstractRNG, rs::Random.SamplerTrivial{<:AbstractFPGroup})
|
||||||
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))
|
||||||
@ -67,16 +64,16 @@ end
|
|||||||
|
|
||||||
## FPGroupElement
|
## FPGroupElement
|
||||||
|
|
||||||
mutable struct FPGroupElement{G<:AbstractFPGroup, W<:AbstractWord} <: GroupElement
|
mutable struct FPGroupElement{G<:AbstractFPGroup,W<:AbstractWord} <: GroupElement
|
||||||
word::W
|
word::W
|
||||||
savedhash::UInt
|
savedhash::UInt
|
||||||
parent::G
|
parent::G
|
||||||
|
|
||||||
FPGroupElement(word::W, G::AbstractFPGroup) where W<:AbstractWord =
|
FPGroupElement(word::W, G::AbstractFPGroup) where {W<:AbstractWord} =
|
||||||
new{typeof(G), W}(word, UInt(0), G)
|
new{typeof(G),W}(word, UInt(0), G)
|
||||||
|
|
||||||
FPGroupElement(word::W, hash::UInt, G::AbstractFPGroup) where W<:AbstractWord =
|
FPGroupElement(word::W, hash::UInt, G::AbstractFPGroup) where {W<:AbstractWord} =
|
||||||
new{typeof(G), W}(word, hash, G)
|
new{typeof(G),W}(word, hash, G)
|
||||||
end
|
end
|
||||||
|
|
||||||
word(f::FPGroupElement) = f.word
|
word(f::FPGroupElement) = f.word
|
||||||
@ -92,7 +89,7 @@ end
|
|||||||
## GroupElement Interface for FPGroupElement
|
## GroupElement Interface for FPGroupElement
|
||||||
|
|
||||||
Base.parent(f::FPGroupElement) = f.parent
|
Base.parent(f::FPGroupElement) = f.parent
|
||||||
GroupsCore.parent_type(::Type{<:FPGroupElement{G}}) where G = G
|
GroupsCore.parent_type(::Type{<:FPGroupElement{G}}) where {G} = G
|
||||||
|
|
||||||
function Base.:(==)(g::FPGroupElement, h::FPGroupElement)
|
function Base.:(==)(g::FPGroupElement, h::FPGroupElement)
|
||||||
@boundscheck @assert parent(g) === parent(h)
|
@boundscheck @assert parent(g) === parent(h)
|
||||||
@ -106,12 +103,11 @@ function Base.deepcopy_internal(g::FPGroupElement, stackdict::IdDict)
|
|||||||
return FPGroupElement(copy(word(g)), g.savedhash, parent(g))
|
return FPGroupElement(copy(word(g)), g.savedhash, parent(g))
|
||||||
end
|
end
|
||||||
|
|
||||||
Base.inv(g::FPGroupElement) =
|
Base.inv(g::FPGroupElement) = (G = parent(g); FPGroupElement(inv(alphabet(G), word(g)), G))
|
||||||
(G = parent(g); FPGroupElement(inv(alphabet(G), word(g)), G))
|
|
||||||
|
|
||||||
function Base.:(*)(g::FPGroupElement, h::FPGroupElement)
|
function Base.:(*)(g::FPGroupElement, h::FPGroupElement)
|
||||||
@boundscheck @assert parent(g) === parent(h)
|
@boundscheck @assert parent(g) === parent(h)
|
||||||
return FPGroupElement(word(g)*word(h), parent(g))
|
return FPGroupElement(word(g) * word(h), parent(g))
|
||||||
end
|
end
|
||||||
|
|
||||||
GroupsCore.isfiniteorder(g::FPGroupElement) = isone(g) ? true : throw("Not Implemented")
|
GroupsCore.isfiniteorder(g::FPGroupElement) = isone(g) ? true : throw("Not Implemented")
|
||||||
@ -125,16 +121,15 @@ struct FreeGroup{T} <: AbstractFPGroup
|
|||||||
gens::Vector{T}
|
gens::Vector{T}
|
||||||
alphabet::KnuthBendix.Alphabet{T}
|
alphabet::KnuthBendix.Alphabet{T}
|
||||||
|
|
||||||
function FreeGroup(gens, A::KnuthBendix.Alphabet) where W
|
function FreeGroup(gens, A::KnuthBendix.Alphabet) where {W}
|
||||||
@assert length(gens) == length(unique(gens))
|
@assert length(gens) == length(unique(gens))
|
||||||
@assert all(l->l in KnuthBendix.letters(A), gens)
|
@assert all(l -> l in KnuthBendix.letters(A), gens)
|
||||||
return new{eltype(gens)}(gens, A)
|
return new{eltype(gens)}(gens, A)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function FreeGroup(A::Alphabet)
|
function FreeGroup(A::Alphabet)
|
||||||
@boundscheck @assert all(KnuthBendix.hasinverse(l, A)
|
@boundscheck @assert all(KnuthBendix.hasinverse(l, A) for l in KnuthBendix.letters(A))
|
||||||
for l in KnuthBendix.letters(A))
|
|
||||||
return FreeGroup(KnuthBendix.letters(A), A)
|
return FreeGroup(KnuthBendix.letters(A), A)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -146,9 +141,9 @@ relations(F::FreeGroup) = Pair{eltype(F)}[]
|
|||||||
|
|
||||||
## FP Groups
|
## FP Groups
|
||||||
|
|
||||||
struct FPGroup{T, R, S} <: AbstractFPGroup
|
struct FPGroup{T,R,S} <: AbstractFPGroup
|
||||||
gens::Vector{T}
|
gens::Vector{T}
|
||||||
relations::Vector{Pair{S, S}}
|
relations::Vector{Pair{S,S}}
|
||||||
rws::R
|
rws::R
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -159,15 +154,16 @@ relations(G::FPGroup) = G.relations
|
|||||||
|
|
||||||
function FPGroup(
|
function FPGroup(
|
||||||
G::AbstractFPGroup,
|
G::AbstractFPGroup,
|
||||||
rels::AbstractVector{<:Pair{GEl, GEl}};
|
rels::AbstractVector{<:Pair{GEl,GEl}};
|
||||||
ordering=KnuthBendix.LenLex,
|
ordering = KnuthBendix.LenLex,
|
||||||
kwargs...) where GEl<:FPGroupElement
|
kwargs...,
|
||||||
|
) 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
|
||||||
end
|
end
|
||||||
word_rels = [word(lhs)=>word(rhs) for (lhs, rhs) in [relations(G); rels]]
|
word_rels = [word(lhs) => word(rhs) for (lhs, rhs) in [relations(G); rels]]
|
||||||
rws = RewritingSystem(word_rels, O)
|
rws = RewritingSystem(word_rels, O)
|
||||||
|
|
||||||
KnuthBendix.knuthbendix!(rws; kwargs...)
|
KnuthBendix.knuthbendix!(rws; kwargs...)
|
||||||
@ -177,7 +173,7 @@ end
|
|||||||
|
|
||||||
function Base.show(io::IO, G::FPGroup)
|
function Base.show(io::IO, G::FPGroup)
|
||||||
print(io, "⟨")
|
print(io, "⟨")
|
||||||
Base.print_array(io, reshape(gens(G), (1, New.ngens(G))))
|
Base.print_array(io, reshape(gens(G), (1, ngens(G))))
|
||||||
print(io, " | ")
|
print(io, " | ")
|
||||||
Base.print_array(io, relations(G))
|
Base.print_array(io, relations(G))
|
||||||
print(io, "⟩")
|
print(io, "⟩")
|
||||||
|
@ -21,7 +21,7 @@ end
|
|||||||
normalform!(res::GEl, g::GEl) where GEl<:FPGroupElement
|
normalform!(res::GEl, g::GEl) where GEl<:FPGroupElement
|
||||||
Compute the normal fom of `g`, storing it in `res`.
|
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<:FPGroupElement}
|
||||||
@boundscheck @assert parent(res) === parent(g)
|
@boundscheck @assert parent(res) === parent(g)
|
||||||
if isnormalform(g)
|
if isnormalform(g)
|
||||||
copyto!(res, g)
|
copyto!(res, g)
|
||||||
|
Loading…
Reference in New Issue
Block a user