diff --git a/src/AutGroup.jl b/src/AutGroup.jl index 3499ec7..1c9206a 100644 --- a/src/AutGroup.jl +++ b/src/AutGroup.jl @@ -1,8 +1,9 @@ +export Automorphism, AutGroup, Aut, SAut + ############################################################################### # # AutSymbol/ AutGroup / Automorphism # -############################################################################### struct RTransvect i::Int8 @@ -30,70 +31,6 @@ struct AutSymbol <: GSymbol fn::Union{LTransvect, RTransvect, PermAut, FlipAut, Identity} end -mutable struct AutGroup{N} <: AbstractFPGroup - objectGroup::FreeGroup - gens::Vector{AutSymbol} -end - -mutable struct Automorphism{N} <: GWord{AutSymbol} - symbols::Vector{AutSymbol} - modified::Bool - savedhash::UInt - parent::AutGroup{N} - - function Automorphism{N}(f::Vector{AutSymbol}) where {N} - return new{N}(f, true, zero(UInt)) - end -end - -export Automorphism, AutGroup, Aut, SAut - -############################################################################### -# -# Type and parent object methods -# -############################################################################### - -elem_type(::Type{AutGroup{N}}) where N = Automorphism{N} - -parent_type(::Automorphism{N}) where N = AutGroup{N} - -############################################################################### -# -# AutSymbol defining functions -# -############################################################################### - -function (ϱ::RTransvect)(v, pow::Integer=1) - append!(v[ϱ.i], v[ϱ.j]^pow) - freereduce!(v[ϱ.i]) - return v -end - -function (λ::LTransvect)(v, pow::Integer=1) - prepend!(v[λ.i], v[λ.j]^pow) - freereduce!(v[λ.i]) - return v -end - -function (σ::PermAut)(v, pow::Integer=1) - w = deepcopy(v) - s = (σ.perm^pow).d - @inbounds for k in eachindex(v) - v[k].symbols = w[s[k]].symbols - end - return v -end - -function (ɛ::FlipAut)(v, pow::Integer=1) - @inbounds if isodd(pow) - v[ɛ.i].symbols = inv(v[ɛ.i]).symbols - end - return v -end - -(::Identity)(v, pow::Integer=1) = v - # taken from ValidatedNumerics, under under the MIT "Expat" License: # https://github.com/JuliaIntervals/ValidatedNumerics.jl/blob/master/LICENSE.md function subscriptify(n::Integer) @@ -135,26 +72,54 @@ function AutSymbol(p::Generic.Perm, pow::Integer=1) return id_autsymbol() end -function AutSymbol(a::Vector{<:Integer}, pow=1) - return AutSymbol(Generic.Perm(convert(Vector{Int8}, a)), pow) -end +ϱ(i::Integer, j::Integer, pow::Integer=1) = transvection_R(i, j, pow) +λ(i::Integer, j::Integer, pow::Integer=1) = transvection_L(i, j, pow) +ε(i::Integer, pow::Integer=1) = flip(i, pow) +σ(v::Generic.Perm, pow::Integer=1) = AutSymbol(v, pow) -ϱ(i::Integer, j::Integer, pow::Integer=1) = transvection_R(i, j, pow=pow) -λ(i::Integer, j::Integer, pow::Integer=1) = transvection_L(i, j, pow=pow) -ε(i::Integer, pow::Integer=1) = flip(i, pow=pow) -σ(v, pow=1) = AutSymbol(v, pow=pow) - -function domain(G::AutGroup{N}) where N - F = G.objectGroup - gg = gens(F) - return ntuple(i->gg[i], N) +function change_pow(s::AutSymbol, n::Integer) + if n == zero(n) + return id_autsymbol() + end + symbol = s.fn + if symbol isa FlipAut + return flip(symbol.i, n) + elseif symbol isa PermAut + return AutSymbol(symbol.perm, n) + elseif symbol isa RTransvect + return transvection_R(symbol.i, symbol.j, n) + elseif symbol isa LTransvect + return transvection_L(symbol.i, symbol.j, n) + elseif symbol isa Identity + return s + else + throw(DomainError("Unknown type of AutSymbol: $s")) + end end ############################################################################### # -# AutGroup / Automorphism constructors +# AutGroup / Automorphism # -############################################################################### + +mutable struct AutGroup{N} <: AbstractFPGroup + objectGroup::FreeGroup + gens::Vector{AutSymbol} +end + +mutable struct Automorphism{N} <: GWord{AutSymbol} + symbols::Vector{AutSymbol} + modified::Bool + savedhash::UInt + parent::AutGroup{N} + + function Automorphism{N}(f::Vector{AutSymbol}) where {N} + return new{N}(f, true, zero(UInt)) + end +end + +elem_type(::Type{AutGroup{N}}) where N = Automorphism{N} +parent_type(::Type{Automorphism{N}}) where N = AutGroup{N} function AutGroup(G::FreeGroup; special=false) S = AutSymbol[] @@ -163,14 +128,14 @@ function AutGroup(G::FreeGroup; special=false) indexing = [[i,j] for i in 1:n for j in 1:n if i≠j] - rmuls = [transvection_R(i,j) for (i,j) in indexing] - lmuls = [transvection_L(i,j) for (i,j) in indexing] + rmuls = [ϱ(i,j) for (i,j) in indexing] + lmuls = [λ(i,j) for (i,j) in indexing] append!(S, [rmuls; lmuls]) if !special - flips = [flip(i) for i in 1:n] - syms = [AutSymbol(p) for p in SymmetricGroup(Int8(n))][2:end] + flips = [ε(i) for i in 1:n] + syms = [σ(p) for p in SymmetricGroup(Int8(n))][2:end] append!(S, [flips; syms]) end @@ -180,64 +145,86 @@ end Aut(G::Group) = AutGroup(G) SAut(G::Group) = AutGroup(G, special=true) -############################################################################### -# -# Types call overloads -# -############################################################################### - Automorphism{N}(s::AutSymbol) where N = Automorphism{N}(AutSymbol[s]) function (G::AutGroup{N})(f::AutSymbol) where N g = Automorphism{N}([f]) - g.parent = G + setparent!(g, G) return g end -function (G::AutGroup{N})(g::Automorphism{N}) where N - g.parent = G - return g +(G::AutGroup{N})(g::Automorphism{N}) where N = (setparent!(g, G); g) + +############################################################################### +# +# AutSymbol defining functions && evaluation +# NOTE: all automorphisms operate on a tuple of FreeWords INPLACE! +# + +function (ϱ::RTransvect)(v, pow::Integer=1) + append!(v[ϱ.i], v[ϱ.j]^pow) + freereduce!(v[ϱ.i]) + return v end +function (λ::LTransvect)(v, pow::Integer=1) + prepend!(v[λ.i], v[λ.j]^pow) + freereduce!(v[λ.i]) + return v +end + +function (σ::PermAut)(v, pow::Integer=1) + w = deepcopy(v) + s = (σ.perm^pow).d + @inbounds for k in eachindex(v) + v[k].symbols = w[s[k]].symbols + end + return v +end + +function (ɛ::FlipAut)(v, pow::Integer=1) + @inbounds if isodd(pow) + v[ɛ.i].symbols = inv(v[ɛ.i]).symbols + end + return v +end + +(::Identity)(v, pow::Integer=1) = v + ############################################################################### # # Functional call overloads for evaluation of AutSymbol and Automorphism # -############################################################################### (s::AutSymbol)(v::NTuple{N, T}) where {N, T} = s.fn(v, s.pow)::NTuple{N, T} function (f::Automorphism{N})(v::NTuple{N, T}) where {N, T} for s in syllables(f) v = s(v)::NTuple{N, T} - # if iszero(i % 3) - # freereduce!.(v) - # end end - # return freereduce!.(v) return v end +function domain(G::AutGroup{N}) where N + F = G.objectGroup + return ntuple(i->F(F.gens[i]), N) +end + evaluate(f::Automorphism) = f(domain(parent(f))) ############################################################################### # -# Comparison +# hashing && equality # -############################################################################### - -const HASHINGCONST = 0x7d28276b01874b19 # hash(Automorphism) - -hash(s::AutSymbol, h::UInt) = hash(s.id, hash(s.pow, hash(AutSymbol, h))) function hash_internal(g::Automorphism, images = freereduce!.(evaluate(g)), - h::UInt = HASHINGCONST) + h::UInt = 0x7d28276b01874b19) # hash(Automorphism) return hash(images, hash(parent(g), h)) end function compute_images(g::Automorphism) images = reduce!.(evaluate(g)) - g.savedhash = hash_internal(g, images) + savehash!(g, hash_internal(g, images)) unsetmodified!(g) return images end @@ -268,37 +255,10 @@ function (==)(g::Automorphism{N}, h::Automorphism{N}) where N return img == imh end -############################################################################### -# -# Basic manipulation -# -############################################################################### - -function change_pow(s::AutSymbol, n::Integer) - if n == zero(n) - return id_autsymbol() - end - symbol = s.fn - if symbol isa FlipAut - return flip(symbol.i, n) - elseif symbol isa PermAut - return AutSymbol(symbol.perm, n) - elseif symbol isa RTransvect - return transvection_R(symbol.i, symbol.j, n) - elseif symbol isa LTransvect - return transvection_L(symbol.i, symbol.j, n) - elseif symbol isa Identity - return s - else - throw(DomainError("Unknown type of AutSymbol: $s")) - end -end - ############################################################################### # # String I/O # -############################################################################### function show(io::IO, G::AutGroup) print(io, "Automorphism Group of $(G.objectGroup)\n") @@ -307,21 +267,8 @@ end ############################################################################### # -# Binary operators +# Reduction # -############################################################################### - -############################################################################### -# -# Inversion -# -############################################################################### - -############################################################################### -# -# Misc -# -############################################################################### getperm(s::AutSymbol) = s.fn.perm^s.pow