mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-11-24 15:50:28 +01:00
Compare commits
6 Commits
8bd3f7ede6
...
7230106bfc
Author | SHA1 | Date | |
---|---|---|---|
|
7230106bfc | ||
751850568c | |||
038fc29b81 | |||
c69eff1540 | |||
a1bc334fb2 | |||
1f1e51917a |
@ -1,20 +1,19 @@
|
|||||||
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.5"
|
version = "0.7.6"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
Folds = "41a02a25-b8f0-4f67-bc48-60067656b558"
|
|
||||||
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
|
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
|
||||||
KnuthBendix = "c2604015-7b3d-4a30-8a26-9074551ec60a"
|
KnuthBendix = "c2604015-7b3d-4a30-8a26-9074551ec60a"
|
||||||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||||
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||||
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
||||||
PermutationGroups = "8bc5a954-2dfc-11e9-10e6-cd969bffa420"
|
PermutationGroups = "8bc5a954-2dfc-11e9-10e6-cd969bffa420"
|
||||||
|
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||||
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
|
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
|
||||||
|
|
||||||
[compat]
|
[compat]
|
||||||
Folds = "0.2.7"
|
|
||||||
GroupsCore = "0.4"
|
GroupsCore = "0.4"
|
||||||
KnuthBendix = "0.4"
|
KnuthBendix = "0.4"
|
||||||
OrderedCollections = "1"
|
OrderedCollections = "1"
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
module Groups
|
module Groups
|
||||||
|
|
||||||
import Folds
|
|
||||||
import Logging
|
import Logging
|
||||||
|
|
||||||
using GroupsCore
|
using GroupsCore
|
||||||
import GroupsCore.Random
|
import Random
|
||||||
|
|
||||||
import OrderedCollections: OrderedSet
|
|
||||||
|
|
||||||
import KnuthBendix
|
import KnuthBendix
|
||||||
import KnuthBendix: AbstractWord, Alphabet, Word
|
import KnuthBendix: AbstractWord, Alphabet, Word
|
||||||
|
@ -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,RW,S} <: AbstractFPGroup
|
mutable struct AutomorphismGroup{G<:Group,T,RW,S} <: AbstractFPGroup
|
||||||
group::G
|
group::G
|
||||||
gens::Vector{T}
|
gens::Vector{T}
|
||||||
rw::RW
|
rw::RW
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Hashing
|
## Hashing
|
||||||
|
|
||||||
equality_data(g::AbstractFPGroupElement) = (normalform!(g); word(g))
|
equality_data(g::AbstractFPGroupElement) = word(g)
|
||||||
|
|
||||||
bitget(h::UInt, n::Int) = Bool((h & (1 << n)) >> n)
|
bitget(h::UInt, n::Int) = Bool((h & (1 << n)) >> n)
|
||||||
bitclear(h::UInt, n::Int) = h & ~(1 << n)
|
bitclear(h::UInt, n::Int) = h & ~(1 << n)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import OrderedCollections: OrderedSet
|
||||||
|
|
||||||
mutable struct FPGroupIter{S,T,GEl}
|
mutable struct FPGroupIter{S,T,GEl}
|
||||||
seen::S
|
seen::S
|
||||||
seen_iter_state::T
|
seen_iter_state::T
|
||||||
|
13
src/types.jl
13
src/types.jl
@ -144,7 +144,18 @@ 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))
|
A = alphabet(parent(g))
|
||||||
|
k = 0
|
||||||
|
while k + 1 ≤ min(length(word(g)), length(word(h)))
|
||||||
|
if inv(word(g)[end-k], A) == word(h)[k+1]
|
||||||
|
k += 1
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
w = @view(word(g)[1:end-k]) * @view(word(h)[k+1:end])
|
||||||
|
res = GEl(w, parent(g))
|
||||||
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
function GroupsCore.isfiniteorder(g::AbstractFPGroupElement)
|
function GroupsCore.isfiniteorder(g::AbstractFPGroupElement)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
wlmetric_ball(S::AbstractVector{<:GroupElem}
|
wlmetric_ball(S::AbstractVector{<:GroupElem}
|
||||||
[, center=one(first(S)); radius=2, op=*, threading=true])
|
[, center=one(first(S)); radius=2, op=*])
|
||||||
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
|
||||||
@ -11,57 +11,27 @@ function wlmetric_ball(
|
|||||||
center::T = one(first(S));
|
center::T = one(first(S));
|
||||||
radius = 2,
|
radius = 2,
|
||||||
op = *,
|
op = *,
|
||||||
threading = true,
|
|
||||||
) where {T}
|
) where {T}
|
||||||
threading && return wlmetric_ball_thr(S, center; radius = radius, op = op)
|
ball = [center]
|
||||||
return wlmetric_ball_serial(S, center; radius = radius, op = op)
|
sizes = [1]
|
||||||
end
|
if radius ≤ 0
|
||||||
|
return ball, sizes[2:end]
|
||||||
function wlmetric_ball_serial(
|
else
|
||||||
S::AbstractVector{T},
|
ball = union!(ball, [center * s for s in S])
|
||||||
center::T = one(first(S));
|
push!(sizes, length(ball))
|
||||||
radius = 2,
|
if radius == 1
|
||||||
op = *,
|
return ball, sizes[2:end]
|
||||||
) where {T}
|
else
|
||||||
@assert radius >= 1
|
|
||||||
old = union!(OrderedSet([center]), [center * s for s in S])
|
|
||||||
sizes = [1, length(old)]
|
|
||||||
for _ in 2:radius
|
for _ in 2:radius
|
||||||
new = collect(
|
new = collect(
|
||||||
op(o, s) for o in @view(old.dict.keys[sizes[end-1]:end]) for s in S
|
op(o, s) for o in @view(ball[sizes[end-1]:end]) for s in S
|
||||||
)
|
)
|
||||||
union!(old, new)
|
append!(ball, new)
|
||||||
push!(sizes, length(old))
|
unique!(ball)
|
||||||
|
push!(sizes, length(ball))
|
||||||
end
|
end
|
||||||
return old.dict.keys, sizes[2:end]
|
|
||||||
end
|
end
|
||||||
|
return ball, sizes[2:end]
|
||||||
function wlmetric_ball_thr(
|
|
||||||
S::AbstractVector{T},
|
|
||||||
center::T = one(first(S));
|
|
||||||
radius = 2,
|
|
||||||
op = *,
|
|
||||||
) where {T}
|
|
||||||
@assert radius >= 1
|
|
||||||
old = union!([center], [center * s for s in S])
|
|
||||||
return _wlmetric_ball(S, old, radius, op, Folds.collect, Folds.unique)
|
|
||||||
end
|
end
|
||||||
|
# return wlmetric_ball_serial(S, center; radius = radius, op = op)
|
||||||
function _wlmetric_ball(S, old, radius, op, collect, unique)
|
|
||||||
sizes = [1, length(old)]
|
|
||||||
for _ in 2:radius
|
|
||||||
old = let old = old, S = S
|
|
||||||
new = collect(
|
|
||||||
(g = op(o, s);
|
|
||||||
normalform!(g);
|
|
||||||
hash(g);
|
|
||||||
g) for o in @view(old[sizes[end-1]:end]) for s in S
|
|
||||||
)
|
|
||||||
|
|
||||||
append!(old, new)
|
|
||||||
unique(old)
|
|
||||||
end
|
|
||||||
push!(sizes, length(old))
|
|
||||||
end
|
|
||||||
return old, sizes[2:end]
|
|
||||||
end
|
end
|
||||||
|
@ -5,14 +5,18 @@ using Groups
|
|||||||
|
|
||||||
function wl_ball(F; radius::Integer)
|
function wl_ball(F; radius::Integer)
|
||||||
g, state = iterate(F)
|
g, state = iterate(F)
|
||||||
while length(word(g)) <= radius
|
sizes = Int[]
|
||||||
|
while length(sizes) ≤ radius
|
||||||
res = iterate(F, state)
|
res = iterate(F, state)
|
||||||
isnothing(res) && break
|
isnothing(res) && break
|
||||||
g, state = res
|
g, state = res
|
||||||
|
if length(word(g)) > length(sizes)
|
||||||
|
push!(sizes, length(state.seen) - 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elts = collect(state.seen)
|
elts = collect(state.seen)
|
||||||
elts = resize!(elts, length(elts)-1)
|
resize!(elts, sizes[end] - 1)
|
||||||
return elts
|
return elts, sizes[2:end]
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "Benchmarks" begin
|
@testset "Benchmarks" begin
|
||||||
@ -25,19 +29,14 @@ end
|
|||||||
let G = FN
|
let G = FN
|
||||||
S = unique([gens(G); inv.(gens(G))])
|
S = unique([gens(G); inv.(gens(G))])
|
||||||
|
|
||||||
sizes1 = last(Groups.wlmetric_ball(S, radius=R, threading=false))
|
sizes1 = last(Groups.wlmetric_ball(S; radius = R))
|
||||||
sizes2 = last(Groups.wlmetric_ball(S, radius=R, threading=true))
|
sizes2 = last(wl_ball(G; radius = R))
|
||||||
|
|
||||||
l = length(wl_ball(G, radius=R))
|
|
||||||
|
|
||||||
@test sizes1 == sizes2
|
@test sizes1 == sizes2
|
||||||
@test last(sizes1) == l
|
|
||||||
|
|
||||||
@info "Ball of radius $R in $(parent(first(S)))" sizes = sizes1
|
@info "Ball of radius $R in $(parent(first(S)))" sizes = sizes1
|
||||||
@info "serial"
|
@info "serial"
|
||||||
@time Groups.wlmetric_ball(S, radius=R, threading=false)
|
@time Groups.wlmetric_ball(S, radius = R)
|
||||||
@info "threaded"
|
|
||||||
@time Groups.wlmetric_ball(S, radius=R, threading=true)
|
|
||||||
@info "iteration"
|
@info "iteration"
|
||||||
@time wl_ball(G, radius = R)
|
@time wl_ball(G, radius = R)
|
||||||
end
|
end
|
||||||
@ -51,19 +50,14 @@ end
|
|||||||
let G = SAutFN
|
let G = SAutFN
|
||||||
S = unique([gens(G); inv.(gens(G))])
|
S = unique([gens(G); inv.(gens(G))])
|
||||||
|
|
||||||
sizes1 = last(Groups.wlmetric_ball(S, radius=R, threading=false))
|
sizes1 = last(Groups.wlmetric_ball(S; radius = R))
|
||||||
sizes2 = last(Groups.wlmetric_ball(S, radius=R, threading=true))
|
sizes2 = last(wl_ball(G; radius = R))
|
||||||
|
|
||||||
l = length(wl_ball(G, radius=R))
|
|
||||||
|
|
||||||
@test sizes1 == sizes2
|
@test sizes1 == sizes2
|
||||||
@test last(sizes1) == l
|
|
||||||
|
|
||||||
@info "Ball of radius $R in $(parent(first(S)))" sizes = sizes1
|
@info "Ball of radius $R in $(parent(first(S)))" sizes = sizes1
|
||||||
@info "serial"
|
@info "serial"
|
||||||
@time Groups.wlmetric_ball(S, radius=R, threading=false)
|
@time Groups.wlmetric_ball(S, radius = R)
|
||||||
@info "threaded"
|
|
||||||
@time Groups.wlmetric_ball(S, radius=R, threading=true)
|
|
||||||
@info "iteration"
|
@info "iteration"
|
||||||
@time wl_ball(G, radius = R)
|
@time wl_ball(G, radius = R)
|
||||||
end
|
end
|
||||||
|
@ -22,8 +22,6 @@ using Groups.MatrixGroups
|
|||||||
S = unique([S; inv.(S)])
|
S = unique([S; inv.(S)])
|
||||||
_, sizes = Groups.wlmetric_ball(S; radius = 4)
|
_, 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)
|
|
||||||
@test sizes == [7, 33, 141, 561]
|
|
||||||
|
|
||||||
Logging.with_logger(Logging.NullLogger()) do
|
Logging.with_logger(Logging.NullLogger()) do
|
||||||
@testset "GroupsCore conformance" begin
|
@testset "GroupsCore conformance" begin
|
||||||
@ -35,9 +33,9 @@ using Groups.MatrixGroups
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
x = w * inv(w) * r
|
x = w * inv(SL3Z(word(w)[end:end])) * r
|
||||||
|
|
||||||
@test length(word(x)) == 5
|
@test length(word(x)) == length(word(r))
|
||||||
@test size(x) == (3, 3)
|
@test size(x) == (3, 3)
|
||||||
@test eltype(x) == Int8
|
@test eltype(x) == Int8
|
||||||
|
|
||||||
@ -65,10 +63,10 @@ using Groups.MatrixGroups
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
x = gens(Sp6, 1)
|
x = gens(Sp6, 1) * gens(Sp6, 2)^2
|
||||||
x *= inv(x) * gens(Sp6, 2)
|
x *= inv(gens(Sp6, 2)^2) * gens(Sp6, 3)
|
||||||
|
|
||||||
@test length(word(x)) == 3
|
@test length(word(x)) == 2
|
||||||
@test size(x) == (6, 6)
|
@test size(x) == (6, 6)
|
||||||
@test eltype(x) == Int8
|
@test eltype(x) == Int8
|
||||||
|
|
||||||
@ -80,7 +78,7 @@ using Groups.MatrixGroups
|
|||||||
@test contains(sprint(show, MIME"text/plain"(), x), "∈ Sp{6,Int8}")
|
@test contains(sprint(show, MIME"text/plain"(), x), "∈ Sp{6,Int8}")
|
||||||
@test sprint(print, x) isa String
|
@test sprint(print, x) isa String
|
||||||
|
|
||||||
@test length(word(x)) == 1
|
@test length(word(x)) == 2
|
||||||
|
|
||||||
for g in gens(Sp6)
|
for g in gens(Sp6)
|
||||||
@test MatrixGroups.issymplectic(MatrixGroups.matrix(g))
|
@test MatrixGroups.issymplectic(MatrixGroups.matrix(g))
|
||||||
@ -101,10 +99,10 @@ using Groups.MatrixGroups
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
x = gens(G, 1)
|
x = gens(G, 1) * gens(G, 2)^3
|
||||||
x *= inv(x) * gens(G, 2)
|
x *= gens(G, 2)^-3
|
||||||
|
|
||||||
@test length(word(x)) == 3
|
@test length(word(x)) == 1
|
||||||
@test size(x) == (6, 6)
|
@test size(x) == (6, 6)
|
||||||
@test eltype(x) == Int16
|
@test eltype(x) == Int16
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user