1
0
mirror of https://github.com/kalmarek/Groups.jl.git synced 2024-12-25 18:15:29 +01:00

formatting

This commit is contained in:
Marek Kaluba 2022-10-14 01:14:38 +02:00
parent 5752d67009
commit 29e2097f2f
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
23 changed files with 227 additions and 218 deletions

View File

@ -1,7 +1,7 @@
function _abelianize( function _abelianize(
i::Integer, i::Integer,
source::AutomorphismGroup{<:FreeGroup}, source::AutomorphismGroup{<:FreeGroup},
target::MatrixGroups.SpecialLinearGroup{N, T}) where {N, T} target::MatrixGroups.SpecialLinearGroup{N,T}) where {N,T}
n = ngens(object(source)) n = ngens(object(source))
@assert n == N @assert n == N
aut = alphabet(source)[i] aut = alphabet(source)[i]
@ -10,10 +10,10 @@ function _abelianize(
# Automorphisms act on the right which corresponds to action on # Automorphisms act on the right which corresponds to action on
# the columns in the matrix case # the columns in the matrix case
eij = MatrixGroups.ElementaryMatrix{N}( eij = MatrixGroups.ElementaryMatrix{N}(
aut.j, aut.j,
aut.i, aut.i,
ifelse(aut.inv, -one(T), one(T)) ifelse(aut.inv, -one(T), one(T))
) )
k = alphabet(target)[eij] k = alphabet(target)[eij]
return word_type(target)([k]) return word_type(target)([k])
else else
@ -24,7 +24,7 @@ end
function _abelianize( function _abelianize(
i::Integer, i::Integer,
source::AutomorphismGroup{<:Groups.SurfaceGroup}, source::AutomorphismGroup{<:Groups.SurfaceGroup},
target::MatrixGroups.SpecialLinearGroup{N, T}) where {N, T} target::MatrixGroups.SpecialLinearGroup{N,T}) where {N,T}
n = ngens(Groups.object(source)) n = ngens(Groups.object(source))
@assert n == N @assert n == N
g = alphabet(source)[i].autFn_word g = alphabet(source)[i].autFn_word
@ -39,8 +39,8 @@ end
function Groups._abelianize( function Groups._abelianize(
i::Integer, i::Integer,
source::AutomorphismGroup{<:Groups.SurfaceGroup}, source::AutomorphismGroup{<:Groups.SurfaceGroup},
target::MatrixGroups.SymplecticGroup{N, T} target::MatrixGroups.SymplecticGroup{N,T}
) where {N, T} ) where {N,T}
@assert iseven(N) @assert iseven(N)
As = alphabet(source) As = alphabet(source)
At = alphabet(target) At = alphabet(target)
@ -53,7 +53,7 @@ function Groups._abelianize(
ab = Groups.Homomorphism(Groups._abelianize, source, SlN, check=false) ab = Groups.Homomorphism(Groups._abelianize, source, SlN, check=false)
matrix_spn_map = let S = gens(target) matrix_spn_map = let S = gens(target)
Dict(MatrixGroups.matrix_repr(g)=> word(g) for g in union(S, inv.(S))) Dict(MatrixGroups.matrix_repr(g) => word(g) for g in union(S, inv.(S)))
end end
# renumeration: # renumeration:
@ -63,7 +63,7 @@ function Groups._abelianize(
p = [reverse(2:2:N); reverse(1:2:N)] p = [reverse(2:2:N); reverse(1:2:N)]
g = source([i]) g = source([i])
Mg = MatrixGroups.matrix_repr(ab(g))[p,p] Mg = MatrixGroups.matrix_repr(ab(g))[p, p]
return matrix_spn_map[Mg] return matrix_spn_map[Mg]
end end

View File

@ -1,4 +1,4 @@
function gersten_alphabet(n::Integer; commutative::Bool = true) function gersten_alphabet(n::Integer; commutative::Bool=true)
indexing = [(i, j) for i in 1:n for j in 1:n if i j] indexing = [(i, j) for i in 1:n for j in 1:n if i j]
S = [ϱ(i, j) for (i, j) in indexing] S = [ϱ(i, j) for (i, j) in indexing]
@ -6,7 +6,7 @@ function gersten_alphabet(n::Integer; commutative::Bool = true)
append!(S, [λ(i, j) for (i, j) in indexing]) append!(S, [λ(i, j) for (i, j) in indexing])
end end
return Alphabet(S) return Alphabet(mapreduce(x -> [x, inv(x)], union, S))
end end
function _commutation_rule( function _commutation_rule(
@ -41,12 +41,12 @@ function _hexagonal_rule(
end end
gersten_relations(n::Integer; commutative) = gersten_relations(n::Integer; commutative) =
gersten_relations(Word{UInt8}, n, commutative = commutative) gersten_relations(Word{UInt8}, n, commutative=commutative)
function gersten_relations(::Type{W}, n::Integer; commutative) where {W<:AbstractWord} function gersten_relations(::Type{W}, n::Integer; commutative) where {W<:AbstractWord}
@assert n > 1 "Gersten relations are defined only for n>1, got n=$n" @assert n > 1 "Gersten relations are defined only for n>1, got n=$n"
A = gersten_alphabet(n, commutative = commutative) A = gersten_alphabet(n, commutative=commutative)
@assert length(A) <= KnuthBendix._max_alphabet_length(W) "Type $W can not represent words over alphabet with $(length(A)) letters." @assert length(A) <= typemax(eltype(W)) "Type $W can not represent words over alphabet with $(length(A)) letters."
rels = Pair{W,W}[] rels = Pair{W,W}[]

View File

@ -17,7 +17,7 @@ function Base.show(io::IO, S::SurfaceGroup)
end end
end end
function SurfaceGroup(genus::Integer, boundaries::Integer) function SurfaceGroup(genus::Integer, boundaries::Integer, W=Word{Int16})
@assert genus > 1 @assert genus > 1
# The (confluent) rewriting systems comes from # The (confluent) rewriting systems comes from
@ -30,15 +30,15 @@ function SurfaceGroup(genus::Integer, boundaries::Integer)
ltrs = String[] ltrs = String[]
for i in 1:genus for i in 1:genus
subscript = join('₀'+d for d in reverse(digits(i))) subscript = join('₀' + d for d in reverse(digits(i)))
append!(ltrs, ["A" * subscript, "a" * subscript, "B" * subscript, "b" * subscript]) append!(ltrs, ["A" * subscript, "a" * subscript, "B" * subscript, "b" * subscript])
end end
Al = Alphabet(reverse!(ltrs)) Al = Alphabet(reverse!(ltrs))
for i in 1:genus for i in 1:genus
subscript = join('₀'+d for d in reverse(digits(i))) subscript = join('₀' + d for d in reverse(digits(i)))
KnuthBendix.set_inversion!(Al, "a" * subscript, "A" * subscript) KnuthBendix.setinverse!(Al, "a" * subscript, "A" * subscript)
KnuthBendix.set_inversion!(Al, "b" * subscript, "B" * subscript) KnuthBendix.setinverse!(Al, "b" * subscript, "B" * subscript)
end end
if boundaries == 0 if boundaries == 0
@ -46,10 +46,10 @@ function SurfaceGroup(genus::Integer, boundaries::Integer)
for i in reverse(1:genus) for i in reverse(1:genus)
x = 4 * i x = 4 * i
append!(word, [x, x-2, x-1, x-3]) append!(word, [x, x - 2, x - 1, x - 3])
end end
comms = Word(word) comms = W(word)
word_rels = [ comms => one(comms) ] word_rels = [comms => one(comms)]
rws = let R = KnuthBendix.RewritingSystem(word_rels, KnuthBendix.Recursive(Al)) rws = let R = KnuthBendix.RewritingSystem(word_rels, KnuthBendix.Recursive(Al))
KnuthBendix.IndexAutomaton(KnuthBendix.knuthbendix(R)) KnuthBendix.IndexAutomaton(KnuthBendix.knuthbendix(R))
@ -60,11 +60,11 @@ function SurfaceGroup(genus::Integer, boundaries::Integer)
KnuthBendix.IndexAutomaton(KnuthBendix.knuthbendix(R)) KnuthBendix.IndexAutomaton(KnuthBendix.knuthbendix(R))
end end
else else
throw("Not Implemented") throw("Not Implemented for MCG with $boundaryies boundary components")
end end
F = FreeGroup(alphabet(rws)) F = FreeGroup(Al)
rels = [F(lhs)=>F(rhs) for (lhs,rhs) in word_rels] rels = [F(lhs) => F(rhs) for (lhs, rhs) in word_rels]
return SurfaceGroup(genus, boundaries, [Al[i] for i in 2:2:length(Al)], rels, rws) return SurfaceGroup(genus, boundaries, [Al[i] for i in 2:2:length(Al)], rels, rws)
end end
@ -77,13 +77,13 @@ function symplectic_twists(π₁Σ::SurfaceGroup)
saut = SpecialAutomorphismGroup(FreeGroup(2g), max_rules=1000) saut = SpecialAutomorphismGroup(FreeGroup(2g), max_rules=1000)
Aij = [SymplecticMappingClass(saut, :A, i, j) for i in 1:g for j in 1:g if i≠j] Aij = [SymplecticMappingClass(saut, :A, i, j) for i in 1:g for j in 1:g if i j]
Bij = [SymplecticMappingClass(saut, :B, i, j) for i in 1:g for j in 1:g if i≠j] Bij = [SymplecticMappingClass(saut, :B, i, j) for i in 1:g for j in 1:g if i j]
mBij = [SymplecticMappingClass(saut, :B, i, j, minus=true) for i in 1:g for j in 1:g if i≠j] mBij = [SymplecticMappingClass(saut, :B, i, j, minus=true) for i in 1:g for j in 1:g if i j]
Bii = [SymplecticMappingClass(saut, :B, i, i) for i in 1:g] Bii = [SymplecticMappingClass(saut, :B, i, i) for i in 1:g]
mBii = [SymplecticMappingClass(saut, :B, i, i, minus=true) for i in 1:g] mBii = [SymplecticMappingClass(saut, :B, i, i, minus=true) for i in 1:g]
@ -99,6 +99,6 @@ function AutomorphismGroup(π₁Σ::SurfaceGroup; kwargs...)
# this is to fix the definitions of symplectic twists: # this is to fix the definitions of symplectic twists:
# with i->gens(π₁Σ, i) the corresponding automorphisms return # with i->gens(π₁Σ, i) the corresponding automorphisms return
# reversed words # reversed words
domain = ntuple(i->inv(gens(π₁Σ, i)), 2genus(π₁Σ)) domain = ntuple(i -> inv(gens(π₁Σ, i)), 2genus(π₁Σ))
return AutomorphismGroup(π₁Σ, S, A, domain) return AutomorphismGroup(π₁Σ, S, A, domain)
end end

View File

@ -1,7 +1,7 @@
include("transvections.jl") include("transvections.jl")
include("gersten_relations.jl") include("gersten_relations.jl")
function SpecialAutomorphismGroup(F::FreeGroup; ordering = KnuthBendix.LenLex, kwargs...) function SpecialAutomorphismGroup(F::FreeGroup; ordering=KnuthBendix.LenLex, kwargs...)
n = length(alphabet(F)) ÷ 2 n = length(alphabet(F)) ÷ 2
A, rels = gersten_relations(n, commutative=false) A, rels = gersten_relations(n, commutative=false)
@ -21,5 +21,5 @@ end
function relations(G::AutomorphismGroup{<:FreeGroup}) function relations(G::AutomorphismGroup{<:FreeGroup})
n = length(alphabet(object(G))) ÷ 2 n = length(alphabet(object(G))) ÷ 2
return last(gersten_relations(n, commutative = false)) return last(gersten_relations(n, commutative=false))
end end

View File

@ -73,7 +73,7 @@ function Te(λ::ΡΛ, ϱ::ΡΛ, i, j)
@assert λ.id == && ϱ.id == :ϱ @assert λ.id == && ϱ.id == :ϱ
@assert iseven(λ.N) @assert iseven(λ.N)
genus = λ.N÷2 genus = λ.N ÷ 2
i = mod1(i, genus) i = mod1(i, genus)
j = mod1(j, genus) j = mod1(j, genus)
@ -118,7 +118,7 @@ end
function rotation_element(λ::ΡΛ, ϱ::ΡΛ) function rotation_element(λ::ΡΛ, ϱ::ΡΛ)
@assert iseven(λ.N) @assert iseven(λ.N)
genus = λ.N÷2 genus = λ.N ÷ 2
A = λ.A A = λ.A
halftwists = map(1:genus-1) do i halftwists = map(1:genus-1) do i
@ -168,7 +168,7 @@ function mcg_twists(G::AutomorphismGroup{<:FreeGroup})
return Tas, Tαs, Tes return Tas, Tαs, Tes
end end
struct SymplecticMappingClass{T, F} <: GSymbol struct SymplecticMappingClass{T,F} <: GSymbol
id::Symbol # :A, :B id::Symbol # :A, :B
i::UInt i::UInt
j::UInt j::UInt
@ -187,13 +187,13 @@ function SymplecticMappingClass(
id::Symbol, id::Symbol,
i::Integer, i::Integer,
j::Integer; j::Integer;
minus = false, minus=false,
inverse = false, inverse=false
) )
@assert i > 0 && j > 0 @assert i > 0 && j > 0
id === :A && @assert i j id === :A && @assert i j
@assert iseven(ngens(object(sautFn))) @assert iseven(ngens(object(sautFn)))
genus = ngens(object(sautFn))÷2 genus = ngens(object(sautFn)) ÷ 2
A = alphabet(sautFn) A = alphabet(sautFn)
λ = ΡΛ(, A, 2genus) λ = ΡΛ(, A, 2genus)
@ -241,7 +241,7 @@ end
function Base.show(io::IO, smc::SymplecticMappingClass) function Base.show(io::IO, smc::SymplecticMappingClass)
smc.minus && print(io, 'm') smc.minus && print(io, 'm')
if smc.i < 10 && smc.j < 10 if smc.i < 10 && smc.j < 10
print(io, smc.id, subscriptify(smc.i), subscriptify(smc.j)) print(io, smc.id, subscriptify(smc.i), subscriptify(smc.j))
else else
print(io, smc.id, subscriptify(smc.i), ".", subscriptify(smc.j)) print(io, smc.id, subscriptify(smc.i), ".", subscriptify(smc.j))

View File

@ -4,7 +4,7 @@ struct Transvection <: GSymbol
j::UInt16 j::UInt16
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, i, j, inv) return new(id, i, j, inv)
end end
@ -33,7 +33,7 @@ Base.hash(t::Transvection, h::UInt) = hash(hash(t.id, hash(t.i)), hash(t.j, hash
Base.@propagate_inbounds @inline function evaluate!( Base.@propagate_inbounds @inline function evaluate!(
v::NTuple{T,N}, v::NTuple{T,N},
t::Transvection, t::Transvection,
tmp = one(first(v)), tmp=one(first(v)),
) where {T,N} ) where {T,N}
i, j = t.i, t.j i, j = t.i, t.j
@assert 1 i length(v) && 1 j length(v) @assert 1 i length(v) && 1 j length(v)
@ -92,4 +92,4 @@ Base.inv(p::PermRightAut) = PermRightAut(invperm(p.perm))
Base.:(==)(p::PermRightAut, q::PermRightAut) = p.perm == q.perm Base.:(==)(p::PermRightAut, q::PermRightAut) = p.perm == q.perm
Base.hash(p::PermRightAut, h::UInt) = hash(p.perm, hash(PermRightAut, h)) Base.hash(p::PermRightAut, h::UInt) = hash(p.perm, hash(PermRightAut, h))
evaluate!(v::NTuple{T,N}, p::PermRightAut, tmp = nothing) where {T,N} = v[p.perm] evaluate!(v::NTuple{T,N}, p::PermRightAut, tmp=nothing) where {T,N} = v[p.perm]

View File

@ -104,8 +104,8 @@ evaluate(f::AbstractFPGroupElement{<:AutomorphismGroup}) = evaluate!(domain(f),
function evaluate!( function evaluate!(
t::NTuple{N,T}, t::NTuple{N,T},
f::AbstractFPGroupElement{<:AutomorphismGroup{<:Group}}, f::AbstractFPGroupElement{<:AutomorphismGroup{<:Group}},
tmp = one(first(t)), tmp=one(first(t)),
) where {N, T<:FPGroupElement} ) where {N,T<:FPGroupElement}
A = alphabet(f) A = alphabet(f)
for idx in word(f) for idx in word(f)
t = @inbounds evaluate!(t, A[idx], tmp)::NTuple{N,T} t = @inbounds evaluate!(t, A[idx], tmp)::NTuple{N,T}
@ -113,12 +113,12 @@ function evaluate!(
return t return t
end end
evaluate!(t::NTuple{N, T}, s::GSymbol, tmp=nothing) where {N, T} = throw("you need to implement `evaluate!(::$(typeof(t)), ::$(typeof(s)), ::Alphabet, tmp=one(first(t)))`") evaluate!(t::NTuple{N,T}, s::GSymbol, tmp=nothing) where {N,T} = throw("you need to implement `evaluate!(::$(typeof(t)), ::$(typeof(s)), ::Alphabet, tmp=one(first(t)))`")
# forward evaluate by substitution # forward evaluate by substitution
struct LettersMap{T, A} struct LettersMap{T,A}
indices_map::Dict{Int, T} indices_map::Dict{Int,T}
A::A A::A
end end
@ -201,13 +201,14 @@ function generated_evaluate(a::FPGroupElement{<:AutomorphismGroup})
throw("Letter $l doesn't seem to be mapped anywhere!") throw("Letter $l doesn't seem to be mapped anywhere!")
end end
end end
locals = Dict{Expr, Symbol}() locals = Dict{Expr,Symbol}()
locals_counter = 0 locals_counter = 0
for (i,v) in enumerate(args) for (i, v) in enumerate(args)
@assert length(v.args) >= 2 @assert length(v.args) >= 2
if length(v.args) > 2 if length(v.args) > 2
for (j, a) in pairs(v.args) for (j, a) in pairs(v.args)
if a isa Expr && a.head == :call "$a" if a isa Expr && a.head == :call
"$a"
@assert a.args[1] == :inv @assert a.args[1] == :inv
if !(a in keys(locals)) if !(a in keys(locals))
locals[a] = Symbol("var_#$locals_counter") locals[a] = Symbol("var_#$locals_counter")
@ -222,7 +223,7 @@ function generated_evaluate(a::FPGroupElement{<:AutomorphismGroup})
end end
q = quote q = quote
$([:(local $v = $k) for (k,v) in locals]...) $([:(local $v = $k) for (k, v) in locals]...)
end end
# return args, locals # return args, locals

View File

@ -30,7 +30,7 @@ function Base.iterate(G::DirectPower)
res = iterate(itr) res = iterate(itr)
@assert res !== nothing @assert res !== nothing
elt = DirectPowerElement(first(res), G) elt = DirectPowerElement(first(res), G)
return elt, (iterator = itr, state = last(res)) return elt, (iterator=itr, state=last(res))
end end
function Base.iterate(G::DirectPower, state) function Base.iterate(G::DirectPower, state)
@ -38,7 +38,7 @@ function Base.iterate(G::DirectPower, state)
res = iterate(itr, st) res = iterate(itr, st)
res === nothing && return nothing res === nothing && return nothing
elt = DirectPowerElement(first(res), G) elt = DirectPowerElement(first(res), G)
return elt, (iterator = itr, state = last(res)) return elt, (iterator=itr, state=last(res))
end end
function Base.IteratorSize(::Type{<:DirectPower{Gr,N}}) where {Gr,N} function Base.IteratorSize(::Type{<:DirectPower{Gr,N}}) where {Gr,N}
@ -52,7 +52,7 @@ Base.size(G::DirectPower) = ntuple(_ -> length(G.group), _nfold(G))
GroupsCore.order(::Type{I}, G::DirectPower) where {I<:Integer} = GroupsCore.order(::Type{I}, G::DirectPower) where {I<:Integer} =
convert(I, order(I, G.group)^_nfold(G)) convert(I, order(I, G.group)^_nfold(G))
GroupsCore.ngens(G::DirectPower) = _nfold(G)*ngens(G.group) GroupsCore.ngens(G::DirectPower) = _nfold(G) * ngens(G.group)
function GroupsCore.gens(G::DirectPower, i::Integer) function GroupsCore.gens(G::DirectPower, i::Integer)
k = ngens(G.group) k = ngens(G.group)
@ -66,7 +66,7 @@ end
function GroupsCore.gens(G::DirectPower) function GroupsCore.gens(G::DirectPower)
N = _nfold(G) N = _nfold(G)
S = gens(G.group) S = gens(G.group)
tups = [ntuple(j->(i == j ? s : one(s)), N) for i in 1:N for s in S] tups = [ntuple(j -> (i == j ? s : one(s)), N) for i in 1:N for s in S]
return [DirectPowerElement(elts, G) for elts in tups] return [DirectPowerElement(elts, G) for elts in tups]
end end
@ -99,7 +99,7 @@ function Base.:(*)(g::DirectPowerElement, h::DirectPowerElement)
end end
GroupsCore.order(::Type{I}, g::DirectPowerElement) where {I<:Integer} = GroupsCore.order(::Type{I}, g::DirectPowerElement) where {I<:Integer} =
convert(I, reduce(lcm, (order(I, h) for h in g.elts), init = one(I))) convert(I, reduce(lcm, (order(I, h) for h in g.elts), init=one(I)))
Base.isone(g::DirectPowerElement) = all(isone, g.elts) Base.isone(g::DirectPowerElement) = all(isone, g.elts)

View File

@ -25,7 +25,7 @@ function Base.iterate(G::DirectProduct)
res = iterate(itr) res = iterate(itr)
@assert res !== nothing @assert res !== nothing
elt = DirectProductElement(first(res), G) elt = DirectProductElement(first(res), G)
return elt, (iterator = itr, state = last(res)) return elt, (iterator=itr, state=last(res))
end end
function Base.iterate(G::DirectProduct, state) function Base.iterate(G::DirectProduct, state)
@ -33,7 +33,7 @@ function Base.iterate(G::DirectProduct, state)
res = iterate(itr, st) res = iterate(itr, st)
res === nothing && return nothing res === nothing && return nothing
elt = DirectProductElement(first(res), G) elt = DirectProductElement(first(res), G)
return elt, (iterator = itr, state = last(res)) return elt, (iterator=itr, state=last(res))
end end
function Base.IteratorSize(::Type{<:DirectProduct{Gt,Ht}}) where {Gt,Ht} function Base.IteratorSize(::Type{<:DirectProduct{Gt,Ht}}) where {Gt,Ht}

View File

@ -52,7 +52,7 @@ function Base.iterate(G::WreathProduct)
res = iterate(itr) res = iterate(itr)
@assert res !== nothing @assert res !== nothing
elt = WreathProductElement(first(res)..., G) elt = WreathProductElement(first(res)..., G)
return elt, (iterator = itr, state = last(res)) return elt, (iterator=itr, state=last(res))
end end
function Base.iterate(G::WreathProduct, state) function Base.iterate(G::WreathProduct, state)
@ -60,7 +60,7 @@ function Base.iterate(G::WreathProduct, state)
res = iterate(itr, st) res = iterate(itr, st)
res === nothing && return nothing res === nothing && return nothing
elt = WreathProductElement(first(res)..., G) elt = WreathProductElement(first(res)..., G)
return elt, (iterator = itr, state = last(res)) return elt, (iterator=itr, state=last(res))
end end
function Base.IteratorSize(::Type{<:WreathProduct{DP,PGr}}) where {DP,PGr} function Base.IteratorSize(::Type{<:WreathProduct{DP,PGr}}) where {DP,PGr}

View File

@ -58,8 +58,8 @@ true
``` ```
""" """
struct Homomorphism{Gr1, Gr2, I, W} struct Homomorphism{Gr1,Gr2,I,W}
gens_images::Dict{I, W} gens_images::Dict{I,W}
source::Gr1 source::Gr1
target::Gr2 target::Gr2
@ -70,11 +70,11 @@ struct Homomorphism{Gr1, Gr2, I, W}
check=true check=true
) )
A = alphabet(source) A = alphabet(source)
dct = Dict(i=>convert(word_type(target), f(i, source, target)) dct = Dict(i => convert(word_type(target), f(i, source, target))
for i in 1:length(A)) for i in 1:length(A))
I = eltype(word_type(source)) I = eltype(word_type(source))
W = word_type(target) W = word_type(target)
hom = new{typeof(source), typeof(target), I, W}(dct, source, target) hom = new{typeof(source),typeof(target),I,W}(dct, source, target)
if check if check
@assert hom(one(source)) == one(target) @assert hom(one(source)) == one(target)
@ -83,8 +83,8 @@ struct Homomorphism{Gr1, Gr2, I, W}
@assert hom(x^-1) == hom(x)^-1 @assert hom(x^-1) == hom(x)^-1
for y in gens(source) for y in gens(source)
@assert hom(x*y) == hom(x)*hom(y) @assert hom(x * y) == hom(x) * hom(y)
@assert hom(x*y)^-1 == hom(y^-1)*hom(x^-1) @assert hom(x * y)^-1 == hom(y^-1) * hom(x^-1)
end end
end end
for (lhs, rhs) in relations(source) for (lhs, rhs) in relations(source)

View File

@ -1,4 +1,4 @@
mutable struct FPGroupIter{S, T, GEl} mutable struct FPGroupIter{S,T,GEl}
seen::S seen::S
seen_iter_state::T seen_iter_state::T
current::GEl current::GEl

View File

@ -1,12 +1,12 @@
include("eltary_matrices.jl") include("eltary_matrices.jl")
struct SpecialLinearGroup{N, T, R, A, S} <: MatrixGroup{N,T} struct SpecialLinearGroup{N,T,R,A,S} <: MatrixGroup{N,T}
base_ring::R base_ring::R
alphabet::A alphabet::A
gens::S gens::S
function SpecialLinearGroup{N}(base_ring) where N function SpecialLinearGroup{N}(base_ring) where {N}
S = [ElementaryMatrix{N}(i,j, one(base_ring)) for i in 1:N for j in 1:N if i≠j] S = [ElementaryMatrix{N}(i, j, one(base_ring)) for i in 1:N for j in 1:N if i j]
alphabet = Alphabet(S) alphabet = Alphabet(S)
return new{ return new{
@ -19,16 +19,16 @@ struct SpecialLinearGroup{N, T, R, A, S} <: MatrixGroup{N,T}
end end
end end
GroupsCore.ngens(SL::SpecialLinearGroup{N}) where N = N^2 - N GroupsCore.ngens(SL::SpecialLinearGroup{N}) where {N} = N^2 - N
Base.show(io::IO, SL::SpecialLinearGroup{N, T}) where {N, T} = Base.show(io::IO, SL::SpecialLinearGroup{N,T}) where {N,T} =
print(io, "special linear group of $N×$N matrices over $T") print(io, "special linear group of $N×$N matrices over $T")
function Base.show( function Base.show(
io::IO, io::IO,
::MIME"text/plain", ::MIME"text/plain",
sl::Groups.AbstractFPGroupElement{<:SpecialLinearGroup{N}} sl::Groups.AbstractFPGroupElement{<:SpecialLinearGroup{N}}
) where N ) where {N}
Groups.normalform!(sl) Groups.normalform!(sl)

View File

@ -1,11 +1,11 @@
include("eltary_symplectic.jl") include("eltary_symplectic.jl")
struct SymplecticGroup{N, T, R, A, S} <: MatrixGroup{N,T} struct SymplecticGroup{N,T,R,A,S} <: MatrixGroup{N,T}
base_ring::R base_ring::R
alphabet::A alphabet::A
gens::S gens::S
function SymplecticGroup{N}(base_ring) where N function SymplecticGroup{N}(base_ring) where {N}
S = symplectic_gens(N, eltype(base_ring)) S = symplectic_gens(N, eltype(base_ring))
alphabet = Alphabet(S) alphabet = Alphabet(S)
@ -21,7 +21,7 @@ end
GroupsCore.ngens(Sp::SymplecticGroup) = length(Sp.gens) GroupsCore.ngens(Sp::SymplecticGroup) = length(Sp.gens)
Base.show(io::IO, ::SymplecticGroup{N}) where N = print(io, "group of $N×$N symplectic matrices") Base.show(io::IO, ::SymplecticGroup{N}) where {N} = print(io, "group of $N×$N symplectic matrices")
function Base.show( function Base.show(
io::IO, io::IO,
@ -35,15 +35,15 @@ function Base.show(
Base.print_array(io, matrix_repr(sp)) Base.print_array(io, matrix_repr(sp))
end end
_offdiag_idcs(n) = ((i,j) for i in 1:n for j in 1:n if i j) _offdiag_idcs(n) = ((i, j) for i in 1:n for j in 1:n if i j)
function symplectic_gens(N, T=Int8) function symplectic_gens(N, T=Int8)
iseven(N) || throw(ArgumentError("N needs to be even!")) iseven(N) || throw(ArgumentError("N needs to be even!"))
n = N÷2 n = N ÷ 2
a_ijs = [ElementarySymplectic{N}(:A, i,j, one(T)) for (i,j) in _offdiag_idcs(n)] a_ijs = [ElementarySymplectic{N}(:A, i, j, one(T)) for (i, j) in _offdiag_idcs(n)]
b_is = [ElementarySymplectic{N}(:B, n+i,i, one(T)) for i in 1:n] b_is = [ElementarySymplectic{N}(:B, n + i, i, one(T)) for i in 1:n]
c_ijs = [ElementarySymplectic{N}(:B, n+i,j, one(T)) for (i,j) in _offdiag_idcs(n)] c_ijs = [ElementarySymplectic{N}(:B, n + i, j, one(T)) for (i, j) in _offdiag_idcs(n)]
S = [a_ijs; b_is; c_ijs] S = [a_ijs; b_is; c_ijs]
@ -53,18 +53,18 @@ function symplectic_gens(N, T=Int8)
end end
function _std_symplectic_form(m::AbstractMatrix) function _std_symplectic_form(m::AbstractMatrix)
r,c = size(m) r, c = size(m)
r == c || return false r == c || return false
iseven(r) || return false iseven(r) || return false
n = r÷2 n = r ÷ 2
𝕆 = zeros(eltype(m), n, n) 𝕆 = zeros(eltype(m), n, n)
𝕀 = one(eltype(m))*LinearAlgebra.I 𝕀 = one(eltype(m)) * LinearAlgebra.I
Ω = [𝕆 -𝕀 Ω = [𝕆 -𝕀
𝕀 𝕆] 𝕀 𝕆]
return Ω return Ω
end end
function issymplectic(mat::M, Ω = _std_symplectic_form(mat)) where M <: AbstractMatrix function issymplectic(mat::M, Ω=_std_symplectic_form(mat)) where {M<:AbstractMatrix}
return Ω == transpose(mat) * Ω * mat return Ω == transpose(mat) * Ω * mat
end end

View File

@ -1,17 +1,17 @@
abstract type MatrixGroup{N, T} <: Groups.AbstractFPGroup end abstract type MatrixGroup{N,T} <: Groups.AbstractFPGroup end
const MatrixGroupElement{N, T} = Groups.AbstractFPGroupElement{<:MatrixGroup{N, T}} const MatrixGroupElement{N,T} = Groups.AbstractFPGroupElement{<:MatrixGroup{N,T}}
Base.isone(g::MatrixGroupElement{N, T}) where {N, T} = Base.isone(g::MatrixGroupElement{N,T}) where {N,T} =
isone(word(g)) || matrix_repr(g) == LinearAlgebra.I isone(word(g)) || matrix_repr(g) == LinearAlgebra.I
function Base.:(==)(m1::M1, m2::M2) where {M1<:MatrixGroupElement, M2<:MatrixGroupElement} function Base.:(==)(m1::M1, m2::M2) where {M1<:MatrixGroupElement,M2<:MatrixGroupElement}
parent(m1) === parent(m2) || return false parent(m1) === parent(m2) || return false
word(m1) == word(m2) && return true word(m1) == word(m2) && return true
return matrix_repr(m1) == matrix_repr(m2) return matrix_repr(m1) == matrix_repr(m2)
end end
Base.size(m::MatrixGroupElement{N}) where N = (N, N) Base.size(m::MatrixGroupElement{N}) where {N} = (N, N)
Base.eltype(m::MatrixGroupElement{N, T}) where {N, T} = T Base.eltype(m::MatrixGroupElement{N,T}) where {N,T} = T
# three structural assumptions about matrix groups # three structural assumptions about matrix groups
Groups.word(sl::MatrixGroupElement) = sl.word Groups.word(sl::MatrixGroupElement) = sl.word
@ -22,9 +22,9 @@ Groups.rewriting(M::MatrixGroup) = alphabet(M)
Base.hash(sl::MatrixGroupElement, h::UInt) = Base.hash(sl::MatrixGroupElement, h::UInt) =
hash(matrix_repr(sl), hash(parent(sl), h)) hash(matrix_repr(sl), hash(parent(sl), h))
function matrix_repr(m::MatrixGroupElement{N, T}) where {N, T} function matrix_repr(m::MatrixGroupElement{N,T}) where {N,T}
if isone(word(m)) if isone(word(m))
return StaticArrays.SMatrix{N, N, T}(LinearAlgebra.I) return StaticArrays.SMatrix{N,N,T}(LinearAlgebra.I)
end end
A = alphabet(parent(m)) A = alphabet(parent(m))
return prod(matrix_repr(A[l]) for l in word(m)) return prod(matrix_repr(A[l]) for l in word(m))
@ -33,7 +33,7 @@ end
function Base.rand( function Base.rand(
rng::Random.AbstractRNG, rng::Random.AbstractRNG,
rs::Random.SamplerTrivial{<:MatrixGroup}, rs::Random.SamplerTrivial{<:MatrixGroup},
) )
Mgroup = rs[] Mgroup = rs[]
S = gens(Mgroup) S = gens(Mgroup)
return prod(g -> rand(Bool) ? g : inv(g), rand(S, rand(1:30))) return prod(g -> rand(Bool) ? g : inv(g), rand(S, rand(1:30)))

View File

@ -1,9 +1,9 @@
struct ElementaryMatrix{N, T} <: Groups.GSymbol struct ElementaryMatrix{N,T} <: Groups.GSymbol
i::Int i::Int
j::Int j::Int
val::T val::T
ElementaryMatrix{N}(i, j, val=1) where N = ElementaryMatrix{N}(i, j, val=1) where {N} =
(@assert i≠j; new{N, typeof(val)}(i, j, val)) (@assert i j; new{N,typeof(val)}(i, j, val))
end end
function Base.show(io::IO, e::ElementaryMatrix) function Base.show(io::IO, e::ElementaryMatrix)
@ -11,18 +11,18 @@ function Base.show(io::IO, e::ElementaryMatrix)
!isone(e.val) && print(io, "^$(e.val)") !isone(e.val) && print(io, "^$(e.val)")
end end
Base.:(==)(e::ElementaryMatrix{N}, f::ElementaryMatrix{N}) where N = Base.:(==)(e::ElementaryMatrix{N}, f::ElementaryMatrix{N}) where {N} =
e.i == f.i && e.j == f.j && e.val == f.val e.i == f.i && e.j == f.j && e.val == f.val
Base.hash(e::ElementaryMatrix, h::UInt) = Base.hash(e::ElementaryMatrix, h::UInt) =
hash(typeof(e), hash((e.i, e.j, e.val), h)) hash(typeof(e), hash((e.i, e.j, e.val), h))
Base.inv(e::ElementaryMatrix{N}) where N = Base.inv(e::ElementaryMatrix{N}) where {N} =
ElementaryMatrix{N}(e.i, e.j, -e.val) ElementaryMatrix{N}(e.i, e.j, -e.val)
function matrix_repr(e::ElementaryMatrix{N, T}) where {N, T} function matrix_repr(e::ElementaryMatrix{N,T}) where {N,T}
m = StaticArrays.MMatrix{N, N, T}(LinearAlgebra.I) m = StaticArrays.MMatrix{N,N,T}(LinearAlgebra.I)
m[e.i, e.j] = e.val m[e.i, e.j] = e.val
x = StaticArrays.SMatrix{N, N}(m) x = StaticArrays.SMatrix{N,N}(m)
return x return x
end end

View File

@ -1,18 +1,18 @@
struct ElementarySymplectic{N, T} <: Groups.GSymbol struct ElementarySymplectic{N,T} <: Groups.GSymbol
symbol::Symbol symbol::Symbol
i::Int i::Int
j::Int j::Int
val::T val::T
function ElementarySymplectic{N}(s::Symbol, i::Integer, j::Integer, val=1) where N function ElementarySymplectic{N}(s::Symbol, i::Integer, j::Integer, val=1) where {N}
@assert s (:A, :B) @assert s (:A, :B)
@assert iseven(N) @assert iseven(N)
n = N÷2 n = N ÷ 2
if s === :A if s === :A
@assert 1 i n && 1 j n && i j @assert 1 i n && 1 j n && i j
elseif s === :B elseif s === :B
@assert xor(1 i n, 1 j n) && xor(n < i N, n < j N) @assert xor(1 i n, 1 j n) && xor(n < i N, n < j N)
end end
return new{N, typeof(val)}(s, i, j, val) return new{N,typeof(val)}(s, i, j, val)
end end
end end
@ -22,12 +22,12 @@ function Base.show(io::IO, s::ElementarySymplectic)
!isone(s.val) && print(io, "^$(s.val)") !isone(s.val) && print(io, "^$(s.val)")
end end
_ind(s::ElementarySymplectic{N}) where N = (s.i, s.j) _ind(s::ElementarySymplectic{N}) where {N} = (s.i, s.j)
_local_ind(N_half::Integer, i::Integer) = ifelse(i<=N_half, i, i-N_half) _local_ind(N_half::Integer, i::Integer) = ifelse(i <= N_half, i, i - N_half)
function _dual_ind(s::ElementarySymplectic{N}) where N function _dual_ind(s::ElementarySymplectic{N}) where {N}
if s.symbol === :A && return _ind(s) if s.symbol === :A && return _ind(s)
else#if s.symbol === :B else#if s.symbol === :B
return _dual_ind(N÷2, s.i, s.j) return _dual_ind(N ÷ 2, s.i, s.j)
end end
end end
@ -41,7 +41,7 @@ function _dual_ind(N_half, i, j)
return i, j return i, j
end end
function Base.:(==)(s::ElementarySymplectic{N}, t::ElementarySymplectic{M}) where {N, M} function Base.:(==)(s::ElementarySymplectic{N}, t::ElementarySymplectic{M}) where {N,M}
N == M || return false N == M || return false
s.symbol == t.symbol || return false s.symbol == t.symbol || return false
s.val == t.val || return false s.val == t.val || return false
@ -51,18 +51,18 @@ end
Base.hash(s::ElementarySymplectic, h::UInt) = Base.hash(s::ElementarySymplectic, h::UInt) =
hash(Set([_ind(s); _dual_ind(s)]), hash(s.symbol, hash(s.val, h))) hash(Set([_ind(s); _dual_ind(s)]), hash(s.symbol, hash(s.val, h)))
LinearAlgebra.transpose(s::ElementarySymplectic{N}) where N = LinearAlgebra.transpose(s::ElementarySymplectic{N}) where {N} =
ElementarySymplectic{N}(s.symbol, s.j, s.i, s.val) ElementarySymplectic{N}(s.symbol, s.j, s.i, s.val)
Base.inv(s::ElementarySymplectic{N}) where N = Base.inv(s::ElementarySymplectic{N}) where {N} =
ElementarySymplectic{N}(s.symbol, s.i, s.j, -s.val) ElementarySymplectic{N}(s.symbol, s.i, s.j, -s.val)
function matrix_repr(s::ElementarySymplectic{N, T}) where {N, T} function matrix_repr(s::ElementarySymplectic{N,T}) where {N,T}
@assert iseven(N) @assert iseven(N)
n = div(N, 2) n = div(N, 2)
m = StaticArrays.MMatrix{N, N, T}(LinearAlgebra.I) m = StaticArrays.MMatrix{N,N,T}(LinearAlgebra.I)
i,j = _ind(s) i, j = _ind(s)
m[i,j] = s.val m[i, j] = s.val
if s.symbol === :A if s.symbol === :A
m[n+j, n+i] = -s.val m[n+j, n+i] = -s.val
else#if s.symbol === :B else#if s.symbol === :B
@ -72,5 +72,5 @@ function matrix_repr(s::ElementarySymplectic{N, T}) where {N, T}
m[j-n, i+n] = s.val m[j-n, i+n] = s.val
end end
end end
return StaticArrays.SMatrix{N, N}(m) return StaticArrays.SMatrix{N,N}(m)
end end

View File

@ -96,7 +96,7 @@ mutable struct FPGroupElement{Gr<:AbstractFPGroup,W<:AbstractWord} <:
FPGroupElement( FPGroupElement(
word::W, word::W,
G::AbstractFPGroup, G::AbstractFPGroup,
hash::UInt = UInt(0), hash::UInt=UInt(0),
) where {W<:AbstractWord} = new{typeof(G),W}(word, hash, G) ) 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} =
@ -222,8 +222,8 @@ rewriting(G::FPGroup) = G.rw
function FPGroup( function FPGroup(
G::AbstractFPGroup, G::AbstractFPGroup,
rels::AbstractVector{<:Pair{GEl,GEl}}; rels::AbstractVector{<:Pair{GEl,GEl}};
ordering = KnuthBendix.ordering(G), ordering=KnuthBendix.ordering(G),
kwargs..., kwargs...
) where {GEl<:FPGroupElement} ) where {GEl<:FPGroupElement}
for (lhs, rhs) in rels for (lhs, rhs) in rels
@assert parent(lhs) === parent(rhs) === G @assert parent(lhs) === parent(rhs) === G

View File

@ -1,20 +1,31 @@
""" """
wlmetric_ball(S::AbstractVector{<:GroupElem} wlmetric_ball(S::AbstractVector{<:GroupElem}
[, center=one(first(S)); radius=2, op=*]) [, center=one(first(S)); radius=2, op=*, threading=true])
Compute metric ball as a list of elements of non-decreasing length, given the Compute metric ball as a list of elements of non-decreasing length, given the
word-length metric on the group generated by `S`. The ball is centered at `center` word-length metric on the group generated by `S`. The ball is centered at `center`
(by default: the identity element). `radius` and `op` keywords specify the (by default: the identity element). `radius` and `op` keywords specify the
radius and multiplication operation to be used. radius and multiplication operation to be used.
""" """
function wlmetric_ball_serial(S::AbstractVector{T}, center::T=one(first(S)); radius = 2, op = *) where {T} function wlmetric_ball(
S::AbstractVector{T},
center::T=one(first(S));
radius=2,
op=*,
threading=true
) where {T}
threading && return wlmetric_ball_thr(S, center, radius=radius, op=op)
return wlmetric_ball_serial(S, center, radius=radius, op=op)
end
function wlmetric_ball_serial(S::AbstractVector{T}, center::T=one(first(S)); radius=2, op=*) where {T}
@assert radius >= 1 @assert radius >= 1
old = union!([center], [center*s for s in S]) old = union!([center], [center * s for s in S])
return _wlmetric_ball(S, old, radius, op, collect, unique!) return _wlmetric_ball(S, old, radius, op, collect, unique!)
end end
function wlmetric_ball_thr(S::AbstractVector{T}, center::T=one(first(S)); radius = 2, op = *) where {T} function wlmetric_ball_thr(S::AbstractVector{T}, center::T=one(first(S)); radius=2, op=*) where {T}
@assert radius >= 1 @assert radius >= 1
old = union!([center], [center*s for s in S]) old = union!([center], [center * s for s in S])
return _wlmetric_ball(S, old, radius, op, Folds.collect, Folds.unique) return _wlmetric_ball(S, old, radius, op, Folds.collect, Folds.unique)
end end
@ -26,6 +37,7 @@ function _wlmetric_ball(S, old, radius, op, collect, unique)
(g = op(o, s); hash(g); g) (g = op(o, s); hash(g); g)
for o in @view(old[sizes[end-1]:end]) for s in S for o in @view(old[sizes[end-1]:end]) for s in S
) )
append!(old, new) append!(old, new)
unique(old) unique(old)
end end
@ -34,13 +46,3 @@ function _wlmetric_ball(S, old, radius, op, collect, unique)
return old, sizes[2:end] return old, sizes[2:end]
end end
function wlmetric_ball(
S::AbstractVector{T},
center::T = one(first(S));
radius = 2,
op = *,
threading = true,
) where {T}
threading && return wlmetric_ball_thr(S, center, radius = radius, op = op)
return wlmetric_ball_serial(S, center, radius = radius, op = op)
end

View File

@ -29,54 +29,54 @@
end end
A4 = Alphabet( A4 = Alphabet(
[:a,:A,:b,:B,:c,:C,:d,:D], [:a, :A, :b, :B, :c, :C, :d, :D],
[ 2, 1, 4, 3, 6, 5, 8, 7] [2, 1, 4, 3, 6, 5, 8, 7]
) )
A5 = Alphabet( A5 = Alphabet(
[:a,:A,:b,:B,:c,:C,:d,:D,:e,:E], [:a, :A, :b, :B, :c, :C, :d, :D, :e, :E],
[ 2, 1, 4, 3, 6, 5, 8, 7,10, 9] [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
) )
F4 = FreeGroup([:a, :b, :c, :d], A4) F4 = FreeGroup([:a, :b, :c, :d], A4)
a,b,c,d = gens(F4) a, b, c, d = gens(F4)
D = ntuple(i->gens(F4, i), 4) D = ntuple(i -> gens(F4, i), 4)
@testset "Transvection action correctness" begin @testset "Transvection action correctness" begin
i,j = 1,2 i, j = 1, 2
r = Groups.Transvection(:ϱ,i,j) r = Groups.Transvection(:ϱ, i, j)
l = Groups.Transvection(,i,j) l = Groups.Transvection(, i, j)
(t::Groups.Transvection)(v::Tuple) = Groups.evaluate!(v, t) (t::Groups.Transvection)(v::Tuple) = Groups.evaluate!(v, t)
@test r(deepcopy(D)) == (a*b, b, c, d) @test r(deepcopy(D)) == (a * b, b, c, d)
@test inv(r)(deepcopy(D)) == (a*b^-1,b, c, d) @test inv(r)(deepcopy(D)) == (a * b^-1, b, c, d)
@test l(deepcopy(D)) == (b*a, b, c, d) @test l(deepcopy(D)) == (b * a, b, c, d)
@test inv(l)(deepcopy(D)) == (b^-1*a,b, c, d) @test inv(l)(deepcopy(D)) == (b^-1 * a, b, c, d)
i,j = 3,1 i, j = 3, 1
r = Groups.Transvection(:ϱ,i,j) r = Groups.Transvection(:ϱ, i, j)
l = Groups.Transvection(,i,j) l = Groups.Transvection(, i, j)
@test r(deepcopy(D)) == (a, b, c*a, d) @test r(deepcopy(D)) == (a, b, c * a, d)
@test inv(r)(deepcopy(D)) == (a, b, c*a^-1,d) @test inv(r)(deepcopy(D)) == (a, b, c * a^-1, d)
@test l(deepcopy(D)) == (a, b, a*c, d) @test l(deepcopy(D)) == (a, b, a * c, d)
@test inv(l)(deepcopy(D)) == (a, b, a^-1*c,d) @test inv(l)(deepcopy(D)) == (a, b, a^-1 * c, d)
i,j = 4,3 i, j = 4, 3
r = Groups.Transvection(:ϱ,i,j) r = Groups.Transvection(:ϱ, i, j)
l = Groups.Transvection(,i,j) l = Groups.Transvection(, i, j)
@test r(deepcopy(D)) == (a, b, c, d*c) @test r(deepcopy(D)) == (a, b, c, d * c)
@test inv(r)(deepcopy(D)) == (a, b, c, d*c^-1) @test inv(r)(deepcopy(D)) == (a, b, c, d * c^-1)
@test l(deepcopy(D)) == (a, b, c, c*d) @test l(deepcopy(D)) == (a, b, c, c * d)
@test inv(l)(deepcopy(D)) == (a, b, c, c^-1*d) @test inv(l)(deepcopy(D)) == (a, b, c, c^-1 * d)
i,j = 2,4 i, j = 2, 4
r = Groups.Transvection(:ϱ,i,j) r = Groups.Transvection(:ϱ, i, j)
l = Groups.Transvection(,i,j) l = Groups.Transvection(, i, j)
@test r(deepcopy(D)) == (a, b*d, c, d) @test r(deepcopy(D)) == (a, b * d, c, d)
@test inv(r)(deepcopy(D)) == (a, b*d^-1,c, d) @test inv(r)(deepcopy(D)) == (a, b * d^-1, c, d)
@test l(deepcopy(D)) == (a, d*b, c, d) @test l(deepcopy(D)) == (a, d * b, c, d)
@test inv(l)(deepcopy(D)) == (a, d^-1*b,c, d) @test inv(l)(deepcopy(D)) == (a, d^-1 * b, c, d)
end end
A = SpecialAutomorphismGroup(F4, max_rules=1000) A = SpecialAutomorphismGroup(F4, max_rules=1000)
@ -91,33 +91,33 @@
@testset "Automorphisms: hash and evaluate" begin @testset "Automorphisms: hash and evaluate" begin
@test Groups.domain(gens(A, 1)) == D @test Groups.domain(gens(A, 1)) == D
g, h = gens(A, 1), gens(A, 8) g, h = gens(A, 1), gens(A, 8) # (ϱ₁.₂, ϱ₃.₂)
@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, KnuthBendix.LenLex{Symbol}}, …}" @test contains(sprint(show, typeof(g)), "Automorphism{FreeGroup{Symbol")
a = g*h a = g * h
b = h*g b = h * g
@test hash(a) != zero(UInt) @test hash(a) != zero(UInt)
@test hash(a) == hash(b) @test hash(a) == hash(b)
@test a.savedhash == b.savedhash @test a.savedhash == b.savedhash
@test length(unique([a,b])) == 1 @test length(unique([a, b])) == 1
@test length(unique([g*h, h*g])) == 1 @test length(unique([g * h, h * g])) == 1
# Not so simple arithmetic: applying starting on the left: # Not so simple arithmetic: applying starting on the left:
# ϱ₁₂*ϱ₂₁⁻¹*λ₁₂*ε₂ == σ₂₁₃₄ # ϱ₁₂*ϱ₂₁⁻¹*λ₁₂*ε₂ == σ₂₁₃₄
g = gens(A, 1) g = gens(A, 1)
x1, x2, x3, x4 = Groups.domain(g) x1, x2, x3, x4 = Groups.domain(g)
@test evaluate(g) == (x1*x2, x2, x3, x4) @test evaluate(g) == (x1 * x2, x2, x3, x4)
g = g*inv(gens(A, 4)) # ϱ₂₁ g = g * inv(gens(A, 4)) # ϱ₂₁
@test evaluate(g) == (x1*x2, x1^-1, x3, x4) @test evaluate(g) == (x1 * x2, x1^-1, x3, x4)
g = g*gens(A, 13) g = g * gens(A, 13)
@test evaluate(g) == (x2, x1^-1, x3, x4) @test evaluate(g) == (x2, x1^-1, x3, x4)
end end
@ -128,7 +128,7 @@
S = gens(G) S = gens(G)
@test S isa Vector{<:FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}} @test S isa Vector{<:FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}}
@test length(S) == 2*N*(N-1) @test length(S) == 2 * N * (N - 1)
@test length(unique(S)) == length(S) @test length(unique(S)) == length(S)
S_sym = [S; inv.(S)] S_sym = [S; inv.(S)]
@ -136,12 +136,12 @@
pushfirst!(S_sym, one(G)) pushfirst!(S_sym, one(G))
B_2 = [i*j for (i,j) in Base.product(S_sym, S_sym)] B_2 = [i * j for (i, j) in Base.product(S_sym, S_sym)]
@test length(B_2) == 2401 @test length(B_2) == 2401
@test length(unique(B_2)) == 1777 @test length(unique(B_2)) == 1777
@test all(g->isone(inv(g)*g), B_2) @test all(g -> isone(inv(g) * g), B_2)
@test all(g->isone(g*inv(g)), B_2) @test all(g -> isone(g * inv(g)), B_2)
end end
@testset "Forward evaluate" begin @testset "Forward evaluate" begin
@ -153,7 +153,7 @@
f = gens(F) f = gens(F)
@test a(f[1]) == f[1]*f[2] @test a(f[1]) == f[1] * f[2]
@test all(a(f[i]) == f[i] for i in 2:length(f)) @test all(a(f[i]) == f[i] for i in 2:length(f))
S = let s = gens(G) S = let s = gens(G)

View File

@ -3,6 +3,8 @@
π₁Σ = Groups.SurfaceGroup(genus, 0) π₁Σ = Groups.SurfaceGroup(genus, 0)
@test contains(sprint(print, π₁Σ), "surface")
Groups.PermRightAut(p::Perm) = Groups.PermRightAut(p.d) Groups.PermRightAut(p::Perm) = Groups.PermRightAut(p.d)
# Groups.PermLeftAut(p::Perm) = Groups.PermLeftAut(p.d) # Groups.PermLeftAut(p::Perm) = Groups.PermLeftAut(p.d)
autπ₁Σ = let autπ₁Σ = AutomorphismGroup(π₁Σ) autπ₁Σ = let autπ₁Σ = AutomorphismGroup(π₁Σ)
@ -18,7 +20,7 @@
π₁Σ, π₁Σ,
autπ₁Σ.gens, autπ₁Σ.gens,
A, A,
ntuple(i->inv(gens(π₁Σ, i)), 2Groups.genus(π₁Σ)) ntuple(i -> inv(gens(π₁Σ, i)), 2Groups.genus(π₁Σ))
) )
autG autG
@ -36,7 +38,7 @@
λ = Groups.ΡΛ(, A, 2genus) λ = Groups.ΡΛ(, A, 2genus)
ϱ = Groups.ΡΛ(:ϱ, A, 2genus) ϱ = Groups.ΡΛ(:ϱ, A, 2genus)
@test sautFn(Groups.Te_diagonal(λ, ϱ, 1)) == @test sautFn(Groups.Te_diagonal(λ, ϱ, 1)) ==
conj(sautFn(Groups.Te_diagonal(λ, ϱ, 2)), τ) conj(sautFn(Groups.Te_diagonal(λ, ϱ, 2)), τ)
@test sautFn(Groups.Te_diagonal(λ, ϱ, 3)) == sautFn(Groups.Te(λ, ϱ, 3, 1)) @test sautFn(Groups.Te_diagonal(λ, ϱ, 3)) == sautFn(Groups.Te(λ, ϱ, 3, 1))
end end

View File

@ -1,5 +1,5 @@
@testset "FPGroups" begin @testset "FPGroups" begin
A = Alphabet([:a, :A, :b, :B, :c, :C], [2,1,4,3,6,5]) A = Alphabet([:a, :A, :b, :B, :c, :C], [2, 1, 4, 3, 6, 5])
@test FreeGroup(A) isa FreeGroup @test FreeGroup(A) isa FreeGroup
@test sprint(show, FreeGroup(A)) == "free group on 3 generators" @test sprint(show, FreeGroup(A)) == "free group on 3 generators"
@ -7,26 +7,26 @@
F = FreeGroup([:a, :b, :c], A) F = FreeGroup([:a, :b, :c], A)
@test sprint(show, F) == "free group on 3 generators" @test sprint(show, F) == "free group on 3 generators"
a,b,c = gens(F) a, b, c = gens(F)
@test c*b*a isa FPGroupElement @test c * b * a isa FPGroupElement
# quotient of F: # quotient of F:
G = FPGroup(F, [a*b=>b*a, a*c=>c*a, b*c=>c*b]) G = FPGroup(F, [a * b => b * a, a * c => c * a, b * c => c * b])
@test G isa FPGroup @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 @test rand(G) isa FPGroupElement
f = a*c*b f = a * c * b
@test word(f) isa Word{UInt8} @test word(f) isa Word{UInt8}
aG,bG,cG = gens(G) aG, bG, cG = gens(G)
@test aG isa FPGroupElement @test aG isa FPGroupElement
@test_throws AssertionError aG == a @test_throws AssertionError aG == a
@test word(aG) == word(a) @test word(aG) == word(a)
g = aG*cG*bG g = aG * cG * bG
@test_throws AssertionError f == g @test_throws AssertionError f == g
@test word(f) == word(g) @test word(f) == word(g)
@ -34,7 +34,7 @@
Groups.normalform!(g) Groups.normalform!(g)
@test word(g) == [1, 3, 5] @test word(g) == [1, 3, 5]
let g = aG*cG*bG let g = aG * cG * bG
# test that we normalize g before printing # test that we normalize g before printing
@test sprint(show, g) == "a*b*c" @test sprint(show, g) == "a*b*c"
end end
@ -46,7 +46,7 @@
@test h isa FPGroupElement @test h isa FPGroupElement
@test_throws AssertionError h == g @test_throws AssertionError h == g
@test_throws MethodError 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) @test_throws AssertionError one(H) == one(H)

View File

@ -4,23 +4,25 @@ using Groups.MatrixGroups
@testset "SL(n, )" begin @testset "SL(n, )" begin
SL3Z = SpecialLinearGroup{3}(Int8) SL3Z = SpecialLinearGroup{3}(Int8)
S = gens(SL3Z); union!(S, inv.(S)) S = gens(SL3Z)
union!(S, inv.(S))
E, sizes = Groups.wlmetric_ball(S, radius=4) _, sizes = Groups.wlmetric_ball(S, radius=4)
@test sizes == [13, 121, 883, 5455] @test sizes == [13, 121, 883, 5455]
E(i,j) = SL3Z([A[MatrixGroups.ElementaryMatrix{3}(i,j, Int8(1))]]) E(i, j) = SL3Z([A[MatrixGroups.ElementaryMatrix{3}(i, j, Int8(1))]])
A = alphabet(SL3Z) A = alphabet(SL3Z)
w = E(1,2) w = E(1, 2)
r = E(2,3)^-3 r = E(2, 3)^-3
s = E(1,3)^2*E(3,2)^-1 s = E(1, 3)^2 * E(3, 2)^-1
S = [w,r,s]; S = unique([S; inv.(S)]); S = [w, r, s]
_, sizes = Groups.wlmetric_ball(S, radius=4); S = unique([S; inv.(S)])
_, sizes = Groups.wlmetric_ball(S, radius=4)
@test sizes == [7, 33, 141, 561] @test sizes == [7, 33, 141, 561]
_, sizes = Groups.wlmetric_ball_serial(S, radius=4); _, sizes = Groups.wlmetric_ball_serial(S, radius=4)
@test sizes == [7, 33, 141, 561] @test sizes == [7, 33, 141, 561]
Logging.with_logger(Logging.NullLogger()) do Logging.with_logger(Logging.NullLogger()) do
@ -34,10 +36,10 @@ using Groups.MatrixGroups
end end
x = w*inv(w)*r x = w * inv(w) * r
@test length(word(x)) == 5 @test length(word(x)) == 5
@test size(x) == (3,3) @test size(x) == (3, 3)
@test eltype(x) == Int8 @test eltype(x) == Int8
@test contains(sprint(print, SL3Z), "special linear group of 3×3") @test contains(sprint(print, SL3Z), "special linear group of 3×3")
@ -50,12 +52,14 @@ using Groups.MatrixGroups
@testset "Sp(6, )" begin @testset "Sp(6, )" begin
Sp6 = MatrixGroups.SymplecticGroup{6}(Int8) Sp6 = MatrixGroups.SymplecticGroup{6}(Int8)
@testset "GroupsCore conformance" begin Logging.with_logger(Logging.NullLogger()) do
test_Group_interface(Sp6) @testset "GroupsCore conformance" begin
g = Sp6(rand(1:length(alphabet(Sp6)), 10)) test_Group_interface(Sp6)
h = Sp6(rand(1:length(alphabet(Sp6)), 10)) g = Sp6(rand(1:length(alphabet(Sp6)), 10))
h = Sp6(rand(1:length(alphabet(Sp6)), 10))
test_GroupElement_interface(g, h) test_GroupElement_interface(g, h)
end
end end
@test contains(sprint(print, Sp6), "group of 6×6 symplectic matrices") @test contains(sprint(print, Sp6), "group of 6×6 symplectic matrices")
@ -64,7 +68,7 @@ using Groups.MatrixGroups
x *= inv(x) * gens(Sp6, 2) x *= inv(x) * gens(Sp6, 2)
@test length(word(x)) == 3 @test length(word(x)) == 3
@test size(x) == (6,6) @test size(x) == (6, 6)
@test eltype(x) == Int8 @test eltype(x) == Int8
@test contains(sprint(show, MIME"text/plain"(), x), "6×6 symplectic matrix:") @test contains(sprint(show, MIME"text/plain"(), x), "6×6 symplectic matrix:")