From 7f810ca65ef87a135d3b8d05ab505182884490a1 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 13:06:21 +0100 Subject: [PATCH 01/26] make simplify_perms delete all (id)s --- src/automorphism_groups.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/automorphism_groups.jl b/src/automorphism_groups.jl index 51d2a48..6078840 100644 --- a/src/automorphism_groups.jl +++ b/src/automorphism_groups.jl @@ -100,5 +100,6 @@ function simplify_perms!(W::AutWord) end end end + deleteat!(W.symbols, find(x -> x.pow == 0, W.symbols)) return reduced end From ea9b9402a222b9c686f578cea753805f0a722c43 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 13:09:49 +0100 Subject: [PATCH 02/26] Tests for the specific example of Aut(F_4) --- test/runtests.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index a35dbff..e87b1a5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -120,4 +120,30 @@ end @test a*b == b*a @test a^3 * b^3 == one(a) end + @testset "specific Aut(𝔽₄) tests" begin + N = 4 + import Combinatorics.nthperm + SymmetricGroup(n) = [nthperm(collect(1:n), k) for k in 1:factorial(n)] + indexing = [[i,j] for i in 1:N for j in 1:N if i≠j] + + σs = [symmetric_AutSymbol(perm) for perm in SymmetricGroup(N)[2:end]]; + ϱs = [rmul_AutSymbol(i,j) for (i,j) in indexing] + λs = [lmul_AutSymbol(i,j) for (i,j) in indexing] + ɛs = [flip_AutSymbol(i) for i in 1:N]; + + S = vcat(ϱs, λs, σs, ɛs) + S = vcat(S, [inv(s) for s in S]) + @test isa(S, Vector{AutSymbol}) + @test length(S) == 102 + @test length(unique(S)) == 75 + S₁ = [GWord(s) for s in unique(S)] + @test isa(S₁, Vector{AutWord}) + p = prod(S₁) + @test length(p) == 75 + @test Group.simplify_perms!(p) == false + @test length(p) == 53 + @test Group.join_free_symbols!(p) == true + + + end end From 0d36b96c49a8cb30218f183c6ed87cb9ef9e5b28 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 13:17:33 +0100 Subject: [PATCH 03/26] amend tests for Aut(F_4) --- test/runtests.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index e87b1a5..12aa844 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -80,6 +80,7 @@ end @test (t*s*t^-1)^10 == t*s^10*t^-1 @test (t*s*t^-1)^-10 == t*s^-10*t^-1 end +end @testset "Automorphisms" begin @testset "AutSymbol" begin @test_throws MethodError AutSymbol("a") @@ -140,9 +141,9 @@ end @test isa(S₁, Vector{AutWord}) p = prod(S₁) @test length(p) == 75 - @test Group.simplify_perms!(p) == false + @test Groups.simplify_perms!(p) == false @test length(p) == 53 - @test Group.join_free_symbols!(p) == true + @test Groups.join_free_symbols!(p) == true end From 4b6651b728b1c0f17adf3e2422ca708758b5e460 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 13:44:20 +0100 Subject: [PATCH 04/26] Clone git version of Permutations.jl --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c189118..b7f0e75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,9 @@ notifications: email: false # uncomment the following lines to override the default test script #script: -# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi -# - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' + - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi + - julia -e 'Pkg.clone("https://github.com/scheinerman/Permutations.jl.git")' + - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' after_success: # push coverage results to Coveralls - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' From 20014aacde4d4469f65662ad2f85e61972add017 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 13:44:20 +0100 Subject: [PATCH 05/26] Clone git version of Permutations.jl --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c189118..3b5aa33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,9 @@ notifications: email: false # uncomment the following lines to override the default test script #script: -# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi -# - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' + - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi + - julia -e 'Pkg.clone("https://github.com/scheinerman/Permutations.jl.git")' + - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' after_success: # push coverage results to Coveralls - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' From 2f543eff458e238b78fd2ee7eb7566a03f5d8d08 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 13:57:03 +0100 Subject: [PATCH 06/26] tabs? 2 spaces? --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3b5aa33..139b44c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,9 @@ notifications: email: false # uncomment the following lines to override the default test script #script: - - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - - julia -e 'Pkg.clone("https://github.com/scheinerman/Permutations.jl.git")' - - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' + - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi + - julia -e 'Pkg.clone("https://github.com/scheinerman/Permutations.jl.git")' + - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' after_success: # push coverage results to Coveralls - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' From ec9dc214fb27e41e078c35ff7a4488f90d1ec5c6 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 14:12:16 +0100 Subject: [PATCH 07/26] uncomment script: --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 139b44c..d22df25 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ julia: notifications: email: false # uncomment the following lines to override the default test script -#script: +script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - julia -e 'Pkg.clone("https://github.com/scheinerman/Permutations.jl.git")' - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' @@ -18,3 +18,4 @@ after_success: - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' # push coverage results to Codecov - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())' +`` From 184a934fa34befcc6e7a61d08274ba45bb7c6d10 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 14:13:36 +0100 Subject: [PATCH 08/26] delete random characters at the end of file --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d22df25..d4efa83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,4 +18,3 @@ after_success: - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' # push coverage results to Codecov - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())' -`` From f65a709db91ace744d3d66baf4edf1e737b4aea6 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 14:18:29 +0100 Subject: [PATCH 09/26] REQUIRE Combinatorics --- REQUIRE | 1 + 1 file changed, 1 insertion(+) diff --git a/REQUIRE b/REQUIRE index 9a19caf..fee6ae7 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,2 +1,3 @@ julia 0.5 Permutations +Combinatorics From 143c7669ff83548df0bd5b63024ed804a058bdf1 Mon Sep 17 00:00:00 2001 From: kalmar Date: Tue, 24 Jan 2017 14:25:59 +0100 Subject: [PATCH 10/26] add travis status --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e97b3e9..9e070e8 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ # Groups +[![Build Status](https://travis-ci.org/abulak/Groups.jl.svg?branch=master)](https://travis-ci.org/abulak/Groups.jl) From c7e3c0b403f46f33f7f1568f4122383b3d68415a Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 10:57:48 +0100 Subject: [PATCH 11/26] 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 12/26] 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 13/26] 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 885854896f8d9b39ebcd5c08c7ae0f985215a8cb Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 12:18:01 +0100 Subject: [PATCH 14/26] =?UTF-8?q?fix=20conversion=20GSymbol=20=E2=86=92=20?= =?UTF-8?q?GWord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Groups.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Groups.jl b/src/Groups.jl index 97b7a41..3a41e29 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -1,6 +1,6 @@ module Groups -import Base: length, ==, hash, show +import Base: length, ==, hash, show, convert import Base: one, inv, reduce, *, ^ export GSymbol, GWord @@ -42,6 +42,7 @@ type GWord{T<:GSymbol} <: Word end GWord{T<:GSymbol}(s::T) = GWord{T}([s]) +convert{T<:GSymbol, W<:Word}(::Type{W}, s::T) = GWord{T}(s) IDWord{T<:GSymbol}(::Type{T}) = GWord(one(T)) IDWord{T<:GSymbol}(W::GWord{T}) = IDWord(T) From 7d5973b11c81c765b564079cbd21a1fee17ca7d6 Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 12:18:18 +0100 Subject: [PATCH 15/26] tests of the conversion --- test/runtests.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 12aa844..51fa668 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -40,6 +40,10 @@ end @test isa(Groups.GWord(s), Groups.GWord) @test isa(Groups.GWord(s), FGWord) @test isa(FGWord(s), Groups.GWord) + @test isa(convert(FGWord, s), GWord) + @test isa(convert(FGWord, s), FGWord) + @test isa(Vector{FGWord}([s,t]), Vector{FGWord}) + @test Vector{GWord{FGSymbol}}([s,t]) == Vector{FGWord}([s,t]) @test isa(s*s, FGWord) @test s*s == s^2 @test t*s ≠ s*t From de4d91a56acc52928fb13bd2fe00e9ecca287399 Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 15:40:50 +0100 Subject: [PATCH 16/26] Never override hash(::T) -- always hash(::T, ::UInt) --- src/Groups.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Groups.jl b/src/Groups.jl index 3a41e29..119e4aa 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -96,7 +96,10 @@ end freegroup_reduce(W::GWord) = freegroup_reduce!(deepcopy(W)) -hash{T}(W::GWord{T}) = (W.modified && freegroup_reduce!(W); W.savedhash) +function hash{T}(W::GWord{T}, h::UInt) + W.modified && freegroup_reduce!(W) + return W.savedhash) + h +end function (==){T}(W::GWord{T}, Z::GWord{T}) W.modified && freegroup_reduce!(W) # reduce clears the flag and recalculate the hash From 45e6eb47eaf121d49d8487aac33dd99105964eda Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 15:57:25 +0100 Subject: [PATCH 17/26] delete superfluous ")" --- src/Groups.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Groups.jl b/src/Groups.jl index 119e4aa..3ba24c6 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -98,7 +98,7 @@ freegroup_reduce(W::GWord) = freegroup_reduce!(deepcopy(W)) function hash{T}(W::GWord{T}, h::UInt) W.modified && freegroup_reduce!(W) - return W.savedhash) + h + return W.savedhash + h end function (==){T}(W::GWord{T}, Z::GWord{T}) From 2bbe1a6b61be2a33526768137735ccd1013a2828 Mon Sep 17 00:00:00 2001 From: kalmar Date: Wed, 25 Jan 2017 15:57:42 +0100 Subject: [PATCH 18/26] add tests for hash --- test/runtests.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 51fa668..ff9dcd3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -47,6 +47,8 @@ end @test isa(s*s, FGWord) @test s*s == s^2 @test t*s ≠ s*t + @test Vector{GWord}([s,t]) == [s^2*s^-1, t] + @test hash([t^1,s^1]) == hash([t^2*inv(t),s*inv(s)*s]) end @testset "eltary functions" begin @test length(FGWord(s)) == 1 @@ -60,6 +62,7 @@ end @test isa(one(w), FGWord) @test inv(s*t) == t^-1*s^-1 @test inv(w) == s*t^-1*s^-1 + end @testset "reductions" begin From 9914871adb36134f71e5f72790bbca5f1a4184f7 Mon Sep 17 00:00:00 2001 From: kalmar Date: Thu, 26 Jan 2017 10:43:26 +0100 Subject: [PATCH 19/26] fast_finish && allow_failures on nightly --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index d4efa83..34dc7ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,11 @@ os: julia: - release - nightly +matrix: + fast_finish: true + allow_failures: + julia: nightly + notifications: email: false # uncomment the following lines to override the default test script From aa9bba617a30098d286510539ec5551e5bfd77a6 Mon Sep 17 00:00:00 2001 From: kalmar Date: Thu, 26 Jan 2017 12:48:32 +0100 Subject: [PATCH 20/26] 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 21/26] 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 22/26] 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 23/26] 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 24/26] 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") From 3ca4563439e595e3b43939b3496f07fb86060ee6 Mon Sep 17 00:00:00 2001 From: kalmar Date: Fri, 27 Jan 2017 12:46:55 +0100 Subject: [PATCH 25/26] Make AutSymbol and AutWord callable via fmap and imap --- src/automorphism_groups.jl | 71 ++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/src/automorphism_groups.jl b/src/automorphism_groups.jl index 6078840..25ee5a1 100644 --- a/src/automorphism_groups.jl +++ b/src/automorphism_groups.jl @@ -7,19 +7,31 @@ immutable AutSymbol <: GSymbol gen::String pow::Int ex::Expr + fmap::Function + imap::Function +end + +function (f::AutSymbol){T}(v::Vector{GWord{T}}) + if f.pow > 0 + map = f.fmap + else + map = f.imap + end + for i in 1:abs(f.pow) + v::Vector{GWord{T}} = map(v) + end + return v end (==)(s::AutSymbol, t::AutSymbol) = s.gen == t.gen && s.pow == t.pow hash(s::AutSymbol, h::UInt) = hash(s.gen, hash(s.pow, hash(:AutSymbol, h))) -IdSymbol(::Type{AutSymbol}) = AutSymbol("(id)", 0, :(IdAutomorphism(N))) +IdSymbol(::Type{AutSymbol}) = AutSymbol("(id)", 0, :(Id(N)), v -> Vector{GWord}(v), v -> Vector{GWord}(v)) function change_pow(s::AutSymbol, n::Int) - if n == 0 return one(s) end - symbol = s.ex.args[1] if symbol == :ɛ return flip_AutSymbol(s.ex.args[2], pow=n) @@ -29,29 +41,58 @@ function change_pow(s::AutSymbol, n::Int) return rmul_AutSymbol(s.ex.args[2], s.ex.args[3], pow=n) elseif symbol == :λ return lmul_AutSymbol(s.ex.args[2], s.ex.args[3], pow=n) - elseif symbol == :IdAutomorphism + elseif symbol == :Id return s else warn("Changing an unknown type of symbol! $s") - return AutSymbol(s.gen, n, s.ex) + return AutSymbol(s.gen, n, s.ex, s.fmap, s.imap) end end inv(f::AutSymbol) = change_pow(f, -f.pow) +function ϱ(i,j) + # @assert i ≠ j + return v -> [(k!=i ? GWord(v[k]) : v[i]*v[j]) for k in eachindex(v)] +end + +function ϱ_inv(i,j) + # @assert i ≠ j + return v -> [(k!=i ? GWord(v[k]) : v[i]*v[j]^-1) for k in eachindex(v)] +end + + +function λ(i,j) + # @assert i ≠ j + return v -> ([(k!=i ? GWord(v[k]) : v[j]*v[i]) for k in eachindex(v)]) +end + +function λ_inv(i,j) + # @assert i ≠ j + return v -> ([(k!=i ? GWord(v[k]) : v[j]^-1*v[i]) for k in eachindex(v)]) +end + + +ɛ(i) = v -> [(k!=i ? GWord(v[k]) : v[k]^-1) for k in eachindex(v)] + +function σ(perm) + # @assert sort(perm) == collect(1:length(perm)) + return v -> [GWord(v[perm[k]]) for k in eachindex(v)] +end + function rmul_AutSymbol(i,j; pow::Int=1) gen = string('ϱ',Char(8320+i), Char(8320+j)...) - return AutSymbol(gen, pow, :(ϱ($i,$j))) + return AutSymbol(gen, pow, :(ϱ($i,$j)), ϱ(i,j), ϱ_inv(i,j)) end function lmul_AutSymbol(i,j; pow::Int=1) gen = string('λ',Char(8320+i), Char(8320+j)...) - return AutSymbol(gen, pow, :(λ($i,$j))) + return AutSymbol(gen, pow, :(λ($i,$j)), λ(i,j), λ_inv(i,j)) end function flip_AutSymbol(j; pow::Int=1) gen = string('ɛ', Char(8320 + j)) - return AutSymbol(gen, (2+ pow%2)%2, :(ɛ($j))) + return AutSymbol(gen, (2+ pow%2)%2, :(ɛ($j)), ɛ(j), ɛ(j)) end function symmetric_AutSymbol(perm::Vector{Int}; pow::Int=1) @@ -59,11 +100,12 @@ function symmetric_AutSymbol(perm::Vector{Int}; pow::Int=1) ord = order(perm) pow = pow % ord perm = perm^pow - if array(perm) == collect(1:length(perm)) + p = array(perm) + if p == collect(1:length(p)) return one(AutSymbol) else - gen = string('σ', [Char(8320 + i) for i in array(perm)]...) - return AutSymbol(gen, 1, :(σ($(array(perm))))) + gen = string('σ', [Char(8320 + i) for i in p]...) + return AutSymbol(gen, 1, :(σ($p)), σ(p), σ(array(inv(perm)))) end end @@ -77,6 +119,13 @@ end typealias AutWord GWord{AutSymbol} +function (F::AutWord)(v) + for f in F.symbols + v = f(v) + end + return v +end + convert(::Type{AutWord}, s::AutSymbol) = GWord(s) function simplify_perms!(W::AutWord) From 9755b9365c19d249a1434897d10140665742106e Mon Sep 17 00:00:00 2001 From: kalmar Date: Fri, 27 Jan 2017 13:04:52 +0100 Subject: [PATCH 26/26] fix basic tests for construction of automorphisms --- test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 54a4dcc..8573a5b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -113,7 +113,7 @@ end @testset "AutSymbol" begin @test_throws MethodError AutSymbol("a") @test_throws MethodError AutSymbol("a", 1) - f = AutSymbol("a", 1, :(a(0))) + f = AutSymbol("a", 1, :(a(0)), v -> v, v -> v) @test isa(f, GSymbol) @test isa(f, AutSymbol) @test isa(symmetric_AutSymbol([1,2,3,4]), AutSymbol) @@ -123,7 +123,7 @@ end end @testset "AutWords" begin - f = AutSymbol("a", 1, :(a(0))) + f = AutSymbol("a", 1, :(a(0)), v -> v, v -> v) @test isa(GWord(f), GWord) @test isa(GWord(f), AutWord) @test isa(AutWord(f), AutWord)