From 12f2ff92a710d07547a1119cbed2eb0e017b70ed Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Fri, 14 Oct 2022 14:05:01 +0200 Subject: [PATCH] update README --- README.md | 112 +++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 79523ed..b2fc191 100644 --- a/README.md +++ b/README.md @@ -10,25 +10,25 @@ The package implements `AbstractFPGroup` with three concrete types: `FreeGroup`, julia> using Groups, GroupsCore julia> A = Alphabet([:a, :A, :b, :B, :c, :C], [2, 1, 4, 3, 6, 5]) -Alphabet of Symbol: - 1. :a = (:A)⁻¹ - 2. :A = (:a)⁻¹ - 3. :b = (:B)⁻¹ - 4. :B = (:b)⁻¹ - 5. :c = (:C)⁻¹ - 6. :C = (:c)⁻¹ +Alphabet of Symbol + 1. a (inverse of: A) + 2. A (inverse of: a) + 3. b (inverse of: B) + 4. B (inverse of: b) + 5. c (inverse of: C) + 6. C (inverse of: c) julia> F = FreeGroup(A) free group on 3 generators julia> a,b,c = gens(F) -3-element Vector{FPGroupElement{FreeGroup{Symbol}, KnuthBendix.Word{UInt8}}}: +3-element Vector{FPGroupElement{FreeGroup{Symbol, KnuthBendix.LenLex{Symbol}}, …}}: a b c julia> a*inv(a) -(empty word) +(id) julia> (a*b)^2 a*b*a*b @@ -40,65 +40,75 @@ julia> x = a*b; y = inv(b)*a; julia> x*y a^2 - ``` + +## FPGroup Let's create a quotient of the free group above: ```julia -julia> ε = one(F); - -julia> G = FPGroup(F, [a^2 => ε, b^3=> ε, (a*b)^7=>ε, (a*b*a*inv(b))^6 => ε, commutator(a, c) => ε, commutator(b, c) => ε ]) -┌ Warning: Maximum number of rules (100) reached. The rewriting system may not be confluent. -│ You may retry `knuthbendix` with a larger `maxrules` kwarg. -└ @ KnuthBendix ~/.julia/packages/KnuthBendix/i93Np/src/kbs.jl:6 -⟨a, b, c | a^2 => (empty word), b^3 => (empty word), a*b*a*b*a*b*a*b*a*b*a*b*a*b => (empty word), a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B => (empty word), A*C*a*c => (empty word), B*C*b*c => (empty word)⟩ +julia> ε = one(F) +(id) +julia> G = FPGroup(F, [a^2 => ε, b^3=> ε, (a*b)^7=>ε, (a*b*a*inv(b))^6 => ε, commutator(a, c) => ε, commutator(b, c) => ε ], max_rules=100) +┌ Warning: Maximum number of rules (100) reached. +│ The rewriting system may not be confluent. +│ You may retry `knuthbendix` with a larger `max_rules` kwarg. +└ @ KnuthBendix ~/.julia/packages/KnuthBendix/6ME1b/src/knuthbendix_base.jl:8 +Finitely presented group generated by: + { a b c }, +subject to relations: + a^2 => (id) + b^3 => (id) + a*b*a*b*a*b*a*b*a*b*a*b*a*b => (id) + a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B => (id) + A*C*a*c => (id) + B*C*b*c => (id) ``` -As you can see from the warning, the Knuth-Bendix procedure has not completed successfully. This means that we only are able to approximate the word problem in `G`, i.e. if the equality (`==`) of two group elements may return `false` even if group elements are equal. Let us try with a larger maximal number of rules in the underlying rewriting system. +As you can see from the warning, the Knuth-Bendix procedure has not completed successfully. This means that we only are able to **approximate the word problem** in `G`, i.e. if the equality (`==`) of two group elements may return `false` even if group elements are equal. Let us try with a larger maximal number of rules in the underlying rewriting system. ```julia -julia> G = FPGroup(F, [a^2 => ε, b^3=> ε, (a*b)^7=>ε, (a*b*a*inv(b))^6 => ε, commutator(a, c) => ε, commutator(b, c) => ε ], maxrules=500) -⟨a, b, c | a^2 => (empty word), b^3 => (empty word), a*b*a*b*a*b*a*b*a*b*a*b*a*b => (empty word), a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B => (empty word), A*C*a*c => (empty word), B*C*b*c => (empty word)⟩ +julia> G = FPGroup(F, [a^2 => ε, b^3=> ε, (a*b)^7=>ε, (a*b*a*inv(b))^6 => ε, commutator(a, c) => ε, commutator(b, c) => ε ], max_rules=500) +Finitely presented group generated by: + { a b c }, +subject to relations: + a^2 => (id) + b^3 => (id) + a*b*a*b*a*b*a*b*a*b*a*b*a*b => (id) + a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B*a*b*a*B => (id) + A*C*a*c => (id) + B*C*b*c => (id) ``` -This time there was no warning, i.e. Knuth-Bendix completion was successful and we may treat the equality (`==`) as true mathematical equality. Note that `G` is the direct product of `ℤ = ⟨ c ⟩` and a quotient of van Dyck `(2,3,7)`-group. Let's create a random word and reduce it as an element of `G`. +This time there was no warning, i.e. Knuth-Bendix completion was successful and we may treat the equality (`==`) as the **true mathematical equality**. Note that `G` is the direct product of `ℤ = ⟨ c ⟩` and a quotient of van Dyck `(2,3,7)`-group. Let's create a random word and reduce it as an element of `G`. ```julia -julia> using Random; Random.seed!(1); w = Groups.Word(rand(1:length(A), 16)) -KnuthBendix.Word{UInt16}: 4·6·1·1·1·6·5·1·5·2·3·6·2·4·2·6 +julia> using Random; Random.seed!(1); w = Groups.Word(rand(1:length(A), 16)); -julia> F(w) # freely reduced w -B*C*a^4*c*A*b*C*A*B*A*C +julia> length(w), w # word of itself +(16, 1·3·5·4·6·2·5·5·5·2·4·3·2·1·4·4) -julia> G(w) # w as an element of G -B*a*b*a*B*a*C^2 +julia> f = F(w) # freely reduced w +a*b*c*B*C*A*c^3*A*B^2 -julia> F(w) # freely reduced w -B*C*a^4*c*A*b*C*A*B*A*C +julia> length(word(f)), word(f) # the underlying word in F +(12, 1·3·5·4·6·2·5·5·5·2·4·4) -julia> word(ans) # the underlying word in A -KnuthBendix.Word{UInt8}: 4·6·1·1·1·1·5·2·3·6·2·4·2·6 - -julia> G(w) # w as an element of G -B*a*b*a*B*a*C^2 - -julia> word(ans) # the underlying word in A -KnuthBendix.Word{UInt8}: 4·1·3·1·4·1·6·6 +julia> g = G(w) # w as an element of G +a*b*c^3 +julia> length(word(g)), word(g) # the underlying word in G +(5, 1·3·5·5·5) ``` As we can see the underlying words change according to where they are reduced. -Note that a word `w` (of type `Word <: AbstractWord`) is just a sequence of numbers -- pointers to letters of an `Alphabet`. Without the alphabet `w` has no meaning. +Note that a word `w` (of type `Word <: AbstractWord`) is just a sequence of numbers -- indices of letters of an `Alphabet`. Without the alphabet `w` has no intrinsic meaning. -### Automorphism Groups +## Automorphism Groups -Relatively complete is the support for the automorphisms of free groups, as given by Gersten presentation: +Relatively complete is the support for the automorphisms of free groups generated by transvections (or Nielsen generators): ```julia -julia> saut = SpecialAutomorphismGroup(F, maxrules=100) -┌ Warning: Maximum number of rules (100) reached. The rewriting system may not be confluent. -│ You may retry `knuthbendix` with a larger `maxrules` kwarg. -└ @ KnuthBendix ~/.julia/packages/KnuthBendix/i93Np/src/kbs.jl:6 +julia> saut = SpecialAutomorphismGroup(F, max_rules=1000) automorphism group of free group on 3 generators julia> S = gens(saut) -12-element Vector{Automorphism{FreeGroup{Symbol},…}}: +12-element Vector{Automorphism{FreeGroup{Symbol, KnuthBendix.LenLex{Symbol}}, …}}: ϱ₁.₂ ϱ₁.₃ ϱ₂.₁ @@ -114,17 +124,15 @@ julia> S = gens(saut) julia> x, y, z = S[1], S[12], S[6]; -julia> f = x*y*inv(z) -ϱ₁.₂*λ₃.₂*ϱ₃.₂^-1 +julia> f = x*y*inv(z); -julia> g = inv(z)*y*x -ϱ₃.₂^-1*ϱ₁.₂*λ₃.₂ +julia> g = inv(z)*y*x; julia> word(f), word(g) -(KnuthBendix.Word{UInt8}: 1·12·18, KnuthBendix.Word{UInt8}: 18·1·12) +(1·23·12, 12·23·1) ``` -Even though Knuth-Bendix did not finish successfully in automorphism groups we have another ace in our sleeve to solve the word problem: evaluation. +Even though there is no known finite, confluent rewriting system for automorphism groupsof the free group (so Knuth-Bendix did not finish successfully) we have another ace in our sleeve to solve the word problem: evaluation. Lets have a look at the images of generators under those automorphisms: ```julia julia> evaluate(f) # or to be more verbose... @@ -147,7 +155,7 @@ This is what is happening behind the scenes: 2. if resulting words are equal `true` is returned 3. if they are not equal `Groups.equality_data` is computed for each argument (here: the images of generators) and the result of comparison is returned. -Moreover we try to amortize the cost of computing those images. That is a hash of `equality_daata` is lazily stored in each group element and used as needed. Essentially only if `true` is returned, but comparison of words returns `false` recomputation of images is needed (to guard against hash collisions). +Moreover we try to amortize the cost of computing those images. That is a hash of `equality_daata` is lazily stored in each group element and used as needed. Essentially only if `true` is returned, but comparison of words returns `false` recomputation of images is needed (to guard against hash collisions). ---- This package was developed for computations in [1712.07167](https://arxiv.org/abs/1712.07167) and in [1812.03456](https://arxiv.org/abs/1812.03456). If you happen to use this package please cite either of them.