mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2025-01-04 20:30:29 +01:00
add FPGroups.jl file
This commit is contained in:
parent
ab31d8fca1
commit
f395af242b
188
src/FPGroups.jl
Normal file
188
src/FPGroups.jl
Normal file
@ -0,0 +1,188 @@
|
||||
###############################################################################
|
||||
#
|
||||
# FPSymbol/FPGroupElem/FPGroup definition
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
immutable FPSymbol <: GSymbol
|
||||
str::String
|
||||
pow::Int
|
||||
end
|
||||
|
||||
typealias FPGroupElem = GWord{FPSymbol}
|
||||
|
||||
type FPGroup <: AbstractFPGroup
|
||||
gens::Vector{FPSymbol}
|
||||
rels::Dict{FPGroupElem, FPGroupElem}
|
||||
|
||||
function FPGroup{T<:GSymbol}(gens::Vector{T}, rels::Dict{FPGroupElem, FPGroupElem})
|
||||
G = new(gens)
|
||||
G.rels = Dict(G(k) => G(v) for (k,v) in rels)
|
||||
return G
|
||||
end
|
||||
end
|
||||
|
||||
export FPGroupElem, FPGroup
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Type and parent object methods
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
parent_type(::Type{FPGroupElem}) = FPGroup
|
||||
|
||||
elem_type(::FPGroup) = FPGroupElem
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# FPSymbol constructors
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
FPSymbol(s::String) = FPSymbol(s,1)
|
||||
|
||||
convert(::Type{FPSymbol}, s::FreeSymbol) = FPSymbol(s.str, s.pow)
|
||||
|
||||
FPGroup(gens::Vector{FPSymbol}) = FPGroup(gens, Dict{FPGroupElem, FPGroupElem}())
|
||||
|
||||
FPGroup(a::Vector{String}) = FPGroup([FPSymbol(i) for i in a])
|
||||
|
||||
FPGroup(n::Int, symbol::String="f") = FPGroup(["$symbol$i" for i in 1:n])
|
||||
FPGroup(H::FreeGroup) = FPGroup([FPSymbol(s) for s in H.gens])
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Parent object call overloads
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
function (G::FPGroup)()
|
||||
id = FPGroupElem(FPSymbol("", 0))
|
||||
id.parent = G
|
||||
return id
|
||||
end
|
||||
|
||||
function (G::FPGroup)(w::GWord)
|
||||
if length(w) == 0
|
||||
return G()
|
||||
end
|
||||
|
||||
if eltype(w.symbols) == FreeSymbol
|
||||
w = FPGroupElem(w.symbols)
|
||||
end
|
||||
|
||||
if eltype(w.symbols) == FPSymbol
|
||||
for s in w.symbols
|
||||
i = findfirst(g -> g.str == s.str, G.gens)
|
||||
i == 0 && throw("Symbol $s does not belong to $G.")
|
||||
s.pow % G.gens[i].pow == 0 || throw("Symbol $s doesn't belong to $G.")
|
||||
end
|
||||
end
|
||||
w.parent = G
|
||||
return reduce!(w)
|
||||
end
|
||||
|
||||
(G::FPGroup)(s::FPSymbol) = G(FPGroupElem(s))
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Basic manipulation
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
hash(s::FPSymbol, h::UInt) = hash(s.str, hash(s.pow, hash(FPSymbol, h)))
|
||||
|
||||
change_pow(s::FPSymbol, n::Int) = FPSymbol(s.str, n)
|
||||
|
||||
length(s::FPSymbol) = abs(s.pow)
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# String I/O
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
function show(io::IO, G::FPGroup)
|
||||
print(io, "FPgroup on $(length(G.gens)) generators: ")
|
||||
print(io, "⟨ ", join(G.gens, ", "), " | ", join(G.rels, ", "), " ⟩.")
|
||||
end
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Comparison
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
function (==)(s::FPSymbol, t::FPSymbol)
|
||||
isone(s) && isone(t) && return true
|
||||
s.str == t.str || return false
|
||||
s.pow == t.pow || return false
|
||||
return true
|
||||
end
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inversion
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
inv(s::FPSymbol) = change_pow(s, -s.pow)
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Binary operations
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
(*)(W::FPGroupElem, Z::FPGroupElem) = r_multiply(W, Z.symbols)
|
||||
(*)(W::FPGroupElem, s::FPSymbol) = r_multiply(W, [s])
|
||||
(*)(s::FPSymbol, W::FPGroupElem) = l_multiply(W, [s])
|
||||
|
||||
function reduce!(W::FPGroupElem)
|
||||
if length(W) < 2
|
||||
deleteat!(W.symbols, find(x -> x.pow == 0, W.symbols))
|
||||
else
|
||||
reduced = false
|
||||
while !reduced
|
||||
reduced = free_reduce!(W) || replace_all!(W, parent(W).rels)
|
||||
end
|
||||
end
|
||||
|
||||
W.savedhash = hash(W.symbols, hash(typeof(W)))
|
||||
W.modified = false
|
||||
return W
|
||||
end
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Misc
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
function add_rels!(G::FPGroup, newrels::Dict{FPGroupElem,FPGroupElem})
|
||||
for w in keys(newrels)
|
||||
if !(w in keys(G.rels))
|
||||
G.rels[w] = G(newrels[w])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function /(G::FPGroup, newrels::Vector{FPGroupElem})
|
||||
for r in rels
|
||||
parent(r) == G || throw("Can not form quotient group: $r is not an element of $G")
|
||||
end
|
||||
H = deepcopy(G)
|
||||
newrels = Dict(H(r) => H() for r in newrels)
|
||||
add_rels!(H, newrels)
|
||||
return H
|
||||
end
|
||||
|
||||
function /(G::FreeGroup, rels::Vector{FreeGroupElem})
|
||||
for r in rels
|
||||
parent(r) == G || throw("Can not form quotient group: $r is not an element of $G")
|
||||
end
|
||||
H = FPGroup(G)
|
||||
H.rels = Dict(H(rel) => H() for rel in unique(rels))
|
||||
return H
|
||||
end
|
Loading…
Reference in New Issue
Block a user