mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-12-25 02:05:30 +01:00
add Homomorphisms
This commit is contained in:
parent
cb933c3f87
commit
dd6588f018
@ -9,15 +9,17 @@ import Random
|
|||||||
|
|
||||||
import OrderedCollections: OrderedSet
|
import OrderedCollections: OrderedSet
|
||||||
|
|
||||||
export Alphabet, AutomorphismGroup, FreeGroup, FreeGroup, FPGroup, FPGroupElement, SpecialAutomorphismGroup
|
|
||||||
export MatrixGroups
|
export MatrixGroups
|
||||||
|
|
||||||
|
export Alphabet, AutomorphismGroup, FreeGroup, FreeGroup, FPGroup, FPGroupElement, SpecialAutomorphismGroup, Homomorphism
|
||||||
|
|
||||||
export alphabet, evaluate, word, gens
|
export alphabet, evaluate, word, gens
|
||||||
|
|
||||||
include("types.jl")
|
include("types.jl")
|
||||||
include("hashing.jl")
|
include("hashing.jl")
|
||||||
include("normalform.jl")
|
include("normalform.jl")
|
||||||
include("autgroups.jl")
|
include("autgroups.jl")
|
||||||
|
include("homomorphisms.jl")
|
||||||
|
|
||||||
include("aut_groups/sautFn.jl")
|
include("aut_groups/sautFn.jl")
|
||||||
include("aut_groups/mcg.jl")
|
include("aut_groups/mcg.jl")
|
||||||
@ -25,5 +27,7 @@ include("aut_groups/mcg.jl")
|
|||||||
include("matrix_groups/MatrixGroups.jl")
|
include("matrix_groups/MatrixGroups.jl")
|
||||||
using .MatrixGroups
|
using .MatrixGroups
|
||||||
|
|
||||||
|
include("abelianize.jl")
|
||||||
|
|
||||||
include("wl_ball.jl")
|
include("wl_ball.jl")
|
||||||
end # of module Groups
|
end # of module Groups
|
||||||
|
23
src/abelianize.jl
Normal file
23
src/abelianize.jl
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
function _abelianize(
|
||||||
|
i::Integer,
|
||||||
|
source::AutomorphismGroup{<:FreeGroup},
|
||||||
|
target::MatrixGroups.SpecialLinearGroup{N, T}) where {N, T}
|
||||||
|
n = ngens(object(source))
|
||||||
|
@assert n == N
|
||||||
|
aut = alphabet(source)[i]
|
||||||
|
if aut isa Transvection
|
||||||
|
# we change (i,j) to (j, i) to be consistent with the action:
|
||||||
|
# Automorphisms act on the right which corresponds to action on
|
||||||
|
# the columns in the matrix case
|
||||||
|
eij = MatrixGroups.ElementaryMatrix{N}(
|
||||||
|
aut.j,
|
||||||
|
aut.i,
|
||||||
|
ifelse(aut.inv, -one(T), one(T))
|
||||||
|
)
|
||||||
|
k = alphabet(target)[eij]
|
||||||
|
return word_type(target)([k])
|
||||||
|
else
|
||||||
|
throw("unexpected automorphism symbol: $(typeof(aut))")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
114
src/homomorphisms.jl
Normal file
114
src/homomorphisms.jl
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
"""
|
||||||
|
Homomorphism(f, G::AbstractFPGroup, H::AbstractFPGroup[, check=true])
|
||||||
|
Struct representing homomorphism map from `G` to `H` given by map `f`.
|
||||||
|
|
||||||
|
To define `h = Homomorphism(f, G, H)` function (or just callable) `f` must
|
||||||
|
implement method `f(i::Integer, source, target)::AbstractWord` with the
|
||||||
|
following meaning. Suppose that word `w = Word([i])` consists of a single
|
||||||
|
letter in the `alphabet` of `source` (usually it means that in `G` it
|
||||||
|
represents a generator or its inverse). Then `f(i, G, H)` must return the
|
||||||
|
**word** representing the image in `H` of `G(w)` under the homomorphism.
|
||||||
|
|
||||||
|
In more mathematical terms it means that if `h(G(w)) == h`, then
|
||||||
|
`f(i, G, H) == word(h)`.
|
||||||
|
|
||||||
|
Images of both `AbstractWord`s and elements of `G` can be obtained by simply
|
||||||
|
calling `h(w)`, or `h(g)`.
|
||||||
|
|
||||||
|
If `check=true` then the correctness of the definition of `h` will be performed
|
||||||
|
when creating the homomorphism.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
`f(i, G, H)` must be implemented for all letters in the alphabet of `G`,
|
||||||
|
not only for those `i` which represent `gens(G)`. Function `f` will be
|
||||||
|
evaluated exactly once per letter of `alphabet(G)` and the results will be
|
||||||
|
cached.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
```julia
|
||||||
|
julia> F₂ = FreeGroup(2)
|
||||||
|
free group on 2 generators
|
||||||
|
|
||||||
|
julia> g,h = gens(F₂)
|
||||||
|
2-element Vector{FPGroupElement{FreeGroup{Symbol, KnuthBendix.LenLex{Symbol}}, …}}:
|
||||||
|
f1
|
||||||
|
f2
|
||||||
|
|
||||||
|
julia> ℤ² = FPGroup(F₂, [g*h => h*g])
|
||||||
|
Finitely presented group generated by:
|
||||||
|
{ f1 f2 },
|
||||||
|
subject to relations:
|
||||||
|
f1*f2 => f2*f1
|
||||||
|
|
||||||
|
julia> hom = Groups.Homomorphism(
|
||||||
|
(i, G, H) -> Groups.word_type(H)([i]),
|
||||||
|
F₂,
|
||||||
|
ℤ²
|
||||||
|
)
|
||||||
|
Homomorphism
|
||||||
|
from : free group on 2 generators
|
||||||
|
to : ⟨ f1 f2 |
|
||||||
|
f1*f2 => f2*f1 ⟩
|
||||||
|
|
||||||
|
julia> hom(g*h*inv(g))
|
||||||
|
f2
|
||||||
|
|
||||||
|
julia> hom(g*h*inv(g)) == hom(h)
|
||||||
|
true
|
||||||
|
```
|
||||||
|
|
||||||
|
"""
|
||||||
|
struct Homomorphism{Gr1, Gr2, I, W}
|
||||||
|
gens_images::Dict{I, W}
|
||||||
|
source::Gr1
|
||||||
|
target::Gr2
|
||||||
|
|
||||||
|
function Homomorphism(
|
||||||
|
f,
|
||||||
|
source::AbstractFPGroup,
|
||||||
|
target::AbstractFPGroup;
|
||||||
|
check=true
|
||||||
|
)
|
||||||
|
A = alphabet(source)
|
||||||
|
dct = Dict(i=>convert(word_type(target), f(i, source, target))
|
||||||
|
for i in 1:length(A))
|
||||||
|
I = eltype(word_type(source))
|
||||||
|
W = word_type(target)
|
||||||
|
hom = new{typeof(source), typeof(target), I, W}(dct, source, target)
|
||||||
|
|
||||||
|
if check
|
||||||
|
@assert hom(one(source)) == one(target)
|
||||||
|
for x in gens(source)
|
||||||
|
|
||||||
|
@assert hom(x^-1) == hom(x)^-1
|
||||||
|
|
||||||
|
for y in gens(source)
|
||||||
|
@assert hom(x*y) == hom(x)*hom(y)
|
||||||
|
@assert hom(x*y)^-1 == hom(y^-1)*hom(x^-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for (lhs, rhs) in relations(source)
|
||||||
|
relator = lhs*inv(alphabet(source), rhs)
|
||||||
|
im_r = hom.target(hom(relator))
|
||||||
|
@assert isone(im_r) "Map does not define a homomorphism: h($relator) = $(im_r) ≠ $(one(target))."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return hom
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function (h::Homomorphism)(w::AbstractWord)
|
||||||
|
result = one(word_type(h.target)) # Word
|
||||||
|
for l in w
|
||||||
|
append!(result, h.gens_images[l])
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function (h::Homomorphism)(g::AbstractFPGroupElement)
|
||||||
|
@assert parent(g) === h.source
|
||||||
|
w = h(word(g))
|
||||||
|
return h.target(w)
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.show(io::IO, h::Homomorphism) = print(io, "Homomorphism\n from : $(h.source)\n to : $(h.target)")
|
49
test/homomorphisms.jl
Normal file
49
test/homomorphisms.jl
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
function test_homomorphism(hom)
|
||||||
|
F = hom.source
|
||||||
|
@test isone(hom(one(F)))
|
||||||
|
@test all(inv(hom(g)) == hom(inv(g)) for g in gens(F))
|
||||||
|
@test all(isone(hom(g)*hom(inv(g))) for g in gens(F))
|
||||||
|
@test all(hom(g*h) == hom(g)*hom(h) for g in gens(F) for h in gens(F))
|
||||||
|
end
|
||||||
|
|
||||||
|
@testset "Homomorphisms" begin
|
||||||
|
|
||||||
|
F₂ = FreeGroup(2)
|
||||||
|
g,h = gens(F₂)
|
||||||
|
|
||||||
|
ℤ² = FPGroup(F₂, [g*h => h*g])
|
||||||
|
|
||||||
|
let hom = Groups.Homomorphism((i, G, H) -> Groups.word_type(H)([i]), F₂, ℤ²)
|
||||||
|
|
||||||
|
@test hom(word(g)) == word(g)
|
||||||
|
|
||||||
|
@test hom(word(g*h*inv(g))) == [1,3,2]
|
||||||
|
|
||||||
|
@test hom(g*h*inv(g)) == hom(h)
|
||||||
|
@test isone(hom(g*h*inv(g)*inv(h)))
|
||||||
|
|
||||||
|
@test contains(sprint(print, hom), "Homomorphism")
|
||||||
|
|
||||||
|
test_homomorphism(hom)
|
||||||
|
end
|
||||||
|
|
||||||
|
SAutF3 = SpecialAutomorphismGroup(FreeGroup(3))
|
||||||
|
SL3Z = MatrixGroups.SpecialLinearGroup{3}(Int8)
|
||||||
|
|
||||||
|
let hom = Groups.Homomorphism(
|
||||||
|
Groups._abelianize,
|
||||||
|
SAutF3,
|
||||||
|
SL3Z,
|
||||||
|
)
|
||||||
|
|
||||||
|
A = alphabet(SAutF3)
|
||||||
|
g = SAutF3([A[Groups.ϱ(1,2)]])
|
||||||
|
h = SAutF3([A[Groups.λ(1,2)]])^-1
|
||||||
|
|
||||||
|
@test !isone(g) && !isone(hom(g))
|
||||||
|
@test !isone(h) && !isone(hom(h))
|
||||||
|
@test !isone(g*h) && isone(hom(g*h))
|
||||||
|
|
||||||
|
test_homomorphism(hom)
|
||||||
|
end
|
||||||
|
end
|
@ -26,8 +26,10 @@ include(joinpath(pathof(GroupsCore), "..", "..", "test", "conformance_test.jl"))
|
|||||||
include("fp_groups.jl")
|
include("fp_groups.jl")
|
||||||
|
|
||||||
include("matrix_groups.jl")
|
include("matrix_groups.jl")
|
||||||
|
|
||||||
include("AutFn.jl")
|
include("AutFn.jl")
|
||||||
|
|
||||||
|
include("homomorphisms.jl")
|
||||||
|
|
||||||
include("AutSigma_41.jl")
|
include("AutSigma_41.jl")
|
||||||
include("AutSigma3.jl")
|
include("AutSigma3.jl")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user