From c7e3c0b403f46f33f7f1568f4122383b3d68415a Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 10:57:48 +0100 Subject: [PATCH 1/8] is_subsymbol function --- src/Groups.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Groups.jl b/src/Groups.jl index 97b7a41..6b5f11e 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -173,6 +173,9 @@ end (^)(x::GWord, n::Integer) = power_by_squaring(x,n) (^){T<:GSymbol}(x::T, n::Integer) = GWord(x)^n +is_subsymbol(s::GSymbol, t::GSymbol) = + s.gen == t.gen && (0 ≤ s.pow ≤ t.pow || 0 ≥ s.pow ≥ t.pow) + include("free_groups.jl") include("automorphism_groups.jl") From b0b129fd8b01a4ca34ef0e724815036321d05cb4 Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 11:30:46 +0100 Subject: [PATCH 2/8] findnext and findfirst for GWords --- src/Groups.jl | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Groups.jl b/src/Groups.jl index 6b5f11e..9952422 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -176,6 +176,29 @@ end is_subsymbol(s::GSymbol, t::GSymbol) = s.gen == t.gen && (0 ≤ s.pow ≤ t.pow || 0 ≥ s.pow ≥ t.pow) +function Base.findnext(W::GWord, Z::GWord, i::Integer) + + n = length(Z.symbols) + + @assert n > 1 + for (idx,a) in enumerate(W.symbols[i:end]) + + if idx + n - 1 > length(W.symbols) + break + end + first = is_subsymbol(Z.symbols[1],a) + if first + middle = W.symbols[i+idx:i-1+idx+n-2] == Z.symbols[2:end-1] + last = is_subsymbol(Z.symbols[end], W.symbols[i-1+idx+n-1]) + if middle && last + return i-1 + idx + end + end + end + return 0 +end + +Base.findfirst(W::GWord, Z::GWord) = findnext(W, Z, 1) include("free_groups.jl") include("automorphism_groups.jl") From 76ea736165ccb6469e94d52bf2afeef2f7c2c808 Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 11:32:12 +0100 Subject: [PATCH 3/8] replace! and replace_all! for GWords --- src/Groups.jl | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Groups.jl b/src/Groups.jl index 9952422..2271c8f 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -199,6 +199,36 @@ function Base.findnext(W::GWord, Z::GWord, i::Integer) end Base.findfirst(W::GWord, Z::GWord) = findnext(W, Z, 1) + +function replace!(W::GWord, index, toreplace::GWord, replacement::GWord; asserts=true) + n = length(toreplace.symbols) + if asserts + @assert is_subsymbol(toreplace.symbols[1], W.symbols[index]) + @assert W.symbols[index+1:index+n-2] == toreplace.symbols[2:end-1] + @assert is_subsymbol(toreplace.symbols[end], W.symbols[index+n-1]) + end + + first = W.symbols[index]*inv(toreplace.symbols[1]) + last = W.symbols[index+n-1]*inv(toreplace.symbols[end]) + replacement = first*replacement*last + splice!(W.symbols, index:index+n-1, replacement.symbols) + Groups.freegroup_reduce!(W) + return W +end + +function replace_all!{T}(W::GWord{T}, subst_dict::Dict{GWord{T}, GWord{T}}) + reduced = true + for toreplace in reverse!(sort!(collect(keys(subst_dict)))) + replacement = subst_dict[toreplace] + i = findfirst(W, toreplace) + while i ≠ 0 + replace!(W,i,toreplace, replacement) + i = findnext(W, toreplace, i-1) + end + end + return W +end + include("free_groups.jl") include("automorphism_groups.jl") From aa9bba617a30098d286510539ec5551e5bfd77a6 Mon Sep 17 00:00:00 2001 From: kalmar Date: Thu, 26 Jan 2017 12:48:32 +0100 Subject: [PATCH 4/8] findfirst and findnext reworked --- src/Groups.jl | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Groups.jl b/src/Groups.jl index 2271c8f..e99b4f3 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -2,6 +2,7 @@ module Groups import Base: length, ==, hash, show import Base: one, inv, reduce, *, ^ +import Base: findfirst, findnext export GSymbol, GWord @@ -176,29 +177,34 @@ end is_subsymbol(s::GSymbol, t::GSymbol) = s.gen == t.gen && (0 ≤ s.pow ≤ t.pow || 0 ≥ s.pow ≥ t.pow) -function Base.findnext(W::GWord, Z::GWord, i::Integer) - +function findfirst(W::GWord, Z::GWord) n = length(Z.symbols) @assert n > 1 - for (idx,a) in enumerate(W.symbols[i:end]) - + for (idx,a) in enumerate(W.symbols) if idx + n - 1 > length(W.symbols) break end first = is_subsymbol(Z.symbols[1],a) if first - middle = W.symbols[i+idx:i-1+idx+n-2] == Z.symbols[2:end-1] - last = is_subsymbol(Z.symbols[end], W.symbols[i-1+idx+n-1]) + middle = W.symbols[idx+1:idx+n-2] == Z.symbols[2:end-1] + last = is_subsymbol(Z.symbols[end], W.symbols[idx+n-1]) if middle && last - return i-1 + idx + return idx end end end return 0 end -Base.findfirst(W::GWord, Z::GWord) = findnext(W, Z, 1) +function findnext(W::GWord, Z::GWord, i::Integer) + t = findfirst(GWord{eltype(W.symbols)}(W.symbols[i:end]), Z) + if t > 0 + return t+i-1 + else + return 0 + end +end function replace!(W::GWord, index, toreplace::GWord, replacement::GWord; asserts=true) n = length(toreplace.symbols) From ebecf988ecd6f29e0404a9bf605a533692407149 Mon Sep 17 00:00:00 2001 From: kalmar Date: Thu, 26 Jan 2017 12:50:02 +0100 Subject: [PATCH 5/8] Sort keys in subst_dict by wordlength (in reverse) --- src/Groups.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Groups.jl b/src/Groups.jl index e99b4f3..0a4b434 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -223,8 +223,7 @@ function replace!(W::GWord, index, toreplace::GWord, replacement::GWord; asserts end function replace_all!{T}(W::GWord{T}, subst_dict::Dict{GWord{T}, GWord{T}}) - reduced = true - for toreplace in reverse!(sort!(collect(keys(subst_dict)))) + for toreplace in reverse!(sort!(collect(keys(subst_dict)),by=length)) replacement = subst_dict[toreplace] i = findfirst(W, toreplace) while i ≠ 0 From 986dc7748fe7a51592fa163bf30af621a19df208 Mon Sep 17 00:00:00 2001 From: kalmar Date: Thu, 26 Jan 2017 12:50:54 +0100 Subject: [PATCH 6/8] add replace and replace_all functions --- src/Groups.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Groups.jl b/src/Groups.jl index 0a4b434..ba1901f 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -222,6 +222,10 @@ function replace!(W::GWord, index, toreplace::GWord, replacement::GWord; asserts return W end +function replace(W::GWord, index, toreplace::GWord, replacement::GWord) + replace!(deepcopy(W), index, toreplace, replacement) +end + function replace_all!{T}(W::GWord{T}, subst_dict::Dict{GWord{T}, GWord{T}}) for toreplace in reverse!(sort!(collect(keys(subst_dict)),by=length)) replacement = subst_dict[toreplace] @@ -234,6 +238,8 @@ function replace_all!{T}(W::GWord{T}, subst_dict::Dict{GWord{T}, GWord{T}}) return W end +replace_all(W::GWord, subst_dict::Dict{GWord, GWord}) = replace_all!(deepcopy(W), subst_dict) + include("free_groups.jl") include("automorphism_groups.jl") From c2e1fa55f3eab49770b4c0c6efc5850c207c8b8c Mon Sep 17 00:00:00 2001 From: kalmar Date: Thu, 26 Jan 2017 12:51:48 +0100 Subject: [PATCH 7/8] arrays in julia start at 1 --- src/Groups.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Groups.jl b/src/Groups.jl index ba1901f..c01b624 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -232,7 +232,7 @@ function replace_all!{T}(W::GWord{T}, subst_dict::Dict{GWord{T}, GWord{T}}) i = findfirst(W, toreplace) while i ≠ 0 replace!(W,i,toreplace, replacement) - i = findnext(W, toreplace, i-1) + i = findnext(W, toreplace, i) end end return W From 6f27d39a837e1f526b49a0713fc1b689077674ef Mon Sep 17 00:00:00 2001 From: kalmar Date: Thu, 26 Jan 2017 12:52:24 +0100 Subject: [PATCH 8/8] tests of the replacement functions --- test/runtests.jl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 12aa844..3d87eda 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -80,7 +80,28 @@ end @test (t*s*t^-1)^10 == t*s^10*t^-1 @test (t*s*t^-1)^-10 == t*s^-10*t^-1 end + + @testset "replacements" begin + @test Groups.is_subsymbol(s, Groups.change_pow(s,2)) == true + @test Groups.is_subsymbol(s, Groups.change_pow(s,-2)) == false + @test Groups.is_subsymbol(t, Groups.change_pow(s,-2)) == false + @test Groups.is_subsymbol(inv(t), Groups.change_pow(t,-2)) == true + c = s*t*s^-1*t^-1 + @test findfirst(c, s^-1*t^-1) == 3 + @test findnext(c*s^-1, s^-1*t^-1,3) == 3 + @test findnext(c*s^-1*t^-1, s^-1*t^-1,4) == 5 + @test findfirst(c*t, c) == 0 + w = s*t*s^-1 + subst = Dict{FGWord, FGWord}(w => s^1, s*t^-1 => t^4) + @test Groups.replace(c, 1, s*t, one(FGWord)) == s^-1*t^-1 + + @test Groups.replace(c, 1, w, subst[w]) == s*t^-1 + @test Groups.replace(s*c*t^-1, 1, w, subst[w]) == s^2*t^-2 + @test Groups.replace(t*c*t, 2, w, subst[w]) == t*s + @test Groups.replace_all!(s*c*s*c*s, subst) == s*t^4*s*t^4*s + end end + @testset "Automorphisms" begin @testset "AutSymbol" begin @test_throws MethodError AutSymbol("a")