GroupsWithPropertyT/OrbitDecomposition.jl

307 lines
8.0 KiB
Julia
Raw Normal View History

push!(LOAD_PATH, "./")
using Nemo
using Groups
using WreathProducts
using GroupRings
import Nemo.elements
using JLD
using ProgressMeter
function products{T<:GroupElem}(X::AbstractVector{T}, Y::AbstractVector{T})
result = Vector{T}()
seen = Set{T}()
@showprogress for x in X
for y in Y
z = x*y
if !in(z, seen)
push!(seen, z)
push!(result, z)
end
end
end
return result
end
function generate_balls{T<:GroupElem}(S::Vector{T}, Id::T; radius=2)
sizes = Vector{Int}()
S = unshift!(S, Id)
B = [Id]
for i in 1:radius
B = products(B, S);
push!(sizes, length(B))
end
return B, sizes
end
function elements(F::Nemo.FqNmodFiniteField)
deg = Int(degree(F))
char = Int(characteristic(F))
z = (gen(F)^i for i in 0:deg-1)
crtsn_prd = Base.product([0:char-1 for i in 1:deg]...)
function _it()
for crt in crtsn_prd
g = sum([b*a for (a,b) in zip(z,crt)])
produce(g)
end
end
return Task(_it)
end
function AutFG_emb(A::AutGroup, g::WreathProductElem)
isa(A.objectGroup, FreeGroup) || throw("Not an Aut(FN)")
parent(g).P.n == length(A.objectGroup.gens) || throw("No natural action of $(parent(g)) on $A")
powers = [(elt == parent(elt)() ? 0: 1) for elt in g.n.elts]
elt = reduce(*, [A(Groups.flip_autsymbol(i))^pow for (i,pow) in enumerate(powers)])
Groups.r_multiply!(elt, [Groups.perm_autsymbol(g.p)])
return elt
end
function (g::WreathProductElem)(a::AutGroupElem)
g = AutFG_emb(parent(a),g)
return g*a*g^-1
end
function orbit_decomposition(G::Nemo.Group, E::Vector, rdict=GroupRings.reverse_dict(E))
elts = collect(elements(G))
tovisit = trues(E);
orbits = Vector{Set{Int}}()
@showprogress "Orbit decomposition... " for i in 1:endof(E)
if tovisit[i]
orbit = Set{Int}()
a = E[i]
for g in elts
idx = rdict[g(a)]
tovisit[idx] = false
push!(orbit,idx)
end
push!(orbits, orbit)
end
end
return orbits
end
function matrix_repr(g::WreathProductElem, E, E_dict)
rep_matrix = spzeros(Int, length(E), length(E))
for (i,e) in enumerate(E)
j = E_dict[g(e)]
rep_matrix[i,j] = 1
end
return rep_matrix
end
function action_mreps(G::Nemo.Group, E, E_dict)
result = @showprogress [matrix_repr(g, E, E_dict) for g in elements(G)]
return result
end
function chars(G::PermutationGroup)
permtype_unsorted(σ::Nemo.perm) = [length(c) for c in cycles(σ)]
permtype(σ::Nemo.perm) = sort(permtype_unsorted(σ))
χ_id(σ::Nemo.perm) = 1
χ_sgn(σ::Nemo.perm) = (-1)^parity(σ)
function χ_reg(σ::Nemo.perm)
fixed_points = countnz([(x == y? 1 : 0) for (x,y) in enumerate(σ.d)])
return fixed_points - 1
end
χ_regsgn(σ::Nemo.perm) = (-1)^parity(σ)*χ_reg(σ)
function χ_regviaS3(σ::Nemo.perm)
@assert parent(σ).n == 4
t = permtype(σ)
if t == [1,1,1,1]
result = 2
elseif t == [2,2]
result = 2
elseif t == [1,3]
result = -1
else
result = 0
end
return result
end
chars = [χ_id, χ_sgn, χ_regviaS3, χ_reg, χ_regsgn]
if G.n == 1
return chars[1:1]
elseif G.n == 2
return chars[1:2]
elseif G.n == 3
return [chars[1:2]..., chars[4]]
elseif G.n == 4
return chars[1:5]
else
throw("Characters for $G unknown!")
end
end
function epsilon(i, g::DirectProducts.DirectProductGroupElem)
return reduce(*, 1, ((-1)^isone(g.elts[j]) for j in 1:i))
end
import Base.convert
convert(::Type{Int}, x::Nemo.fmpz) = x.d
function central_projection(RG::GroupRing, char::Function, T::Type=Rational{Int})
result = RG(T)
for g in RG.basis
result[g] = char(g)
end
return convert(T, char(RG.group())//Int(order(RG.group))*result)
end
function Cstar_repr(x::GroupRingElem, matrix_reps)
res = zeros(matrix_reps[1])
for i in 1:length(parent(x).basis)
res += x.coeffs[i]*matrix_reps[i]
end
return res
end
function rankOne_projections(G::PermutationGroup, T::Type=Rational{Int})
RG = GroupRing(G)
projections = [central_projection(RG, χ, T) for χ in chars(G)]
if G.n == 1 || G.n == 2
return projections
elseif G.n == 3
rankone_projs = [
projections[1],
projections[2],
1//2*(one(RG) - RG(RG.group([2,1,3])))*projections[3]
]
return rankone_projs
elseif G.n == 4
rankone_projs = [
projections[1],
projections[2],
1//2*(one(RG) - RG(RG.group([2,1,3,4])))*projections[3],
1//2*(one(RG) - RG(RG.group([2,1,3,4])))*projections[4],
1//2*(one(RG) + RG(RG.group([2,1,3,4])))*projections[5]]
return rankone_projs
else
throw("Rank-one projections for $G unknown!")
end
end
function rankOne_projections(BN::WreathProducts.WreathProduct, T::Type=Rational{Int})
N = BN.P.n
# projections as elements of the group rings RSₙ
SNprojs_nc = [rankOne_projections(PermutationGroup(i), T) for i in 1:N]
# embedding into group ring of BN
RBN = GroupRing(BN)
RFFFF_projs = [central_projection(GroupRing(BN.N), g->epsilon(i,g), T)
for i in 0:BN.P.n]
Qs = [RBN(q, g -> BN(g)) for q in RFFFF_projs]
function incl(k::Int, g::perm, WP::WreathProduct=BN)
@assert length(g.d) + k <= WP.P.n
arr = [1:k; g.d .+ k; (length(g.d)+k+1):WP.P.n]
return WP(WP.P(arr))
end
all_projs=[Qs[1]*RBN(p, g-> incl(0,g)) for p in SNprojs_nc[N]]
for i in 1:N-1
Sk_first = [RBN(p, g->incl(0,g)) for p in SNprojs_nc[i]]
Sk_last = [RBN(p, g->incl(i,g)) for p in SNprojs_nc[N-i]]
append!(all_projs, [Qs[i+1]*p1*p2
for (p1,p2) in Base.product(Sk_first,Sk_last)])
end
append!(all_projs, [Qs[N+1]*RBN(p, g-> incl(0,g)) for p in SNprojs_nc[N]])
return all_projs
end
function orthSVD(M::AbstractMatrix)
M = full(M)
# matrixRank = rank(M)
fact = svdfact(M)
sings = fact[:S]
# @show sings[sings.>1e-14]
M_rank = sum(fact[:S] .> maximum(size(M))*eps(eltype(fact[:S])))
Ufactor = fact[:U]
return Ufactor[:,1:M_rank]
end
function Uπ_matrices(P_matrices; orth=orthSVD)
U_p_matrices = Vector{Array{Float64,2}}()
@showprogress "Computing Uπ mats..." for (i,p_mat) in enumerate(P_matrices)
U_p = orth(p_mat)
push!(U_p_matrices, U_p)
end
return U_p_matrices
end
function main(N::Int)
name = "test"
# SOutF$(N)_E4
isdir(name) || mkdir(name)
SOutFN = AutGroup(FreeGroup(N), special=true, outer=true)
S = generators(SOutFN);
S = [S; [inv(s) for s in S]]
@show S
info("Generating ball of radius 4")
@time E4, sizes = generate_balls(S, SOutFN(), radius=4);
info("Reverse dict")
@time E_dict = GroupRings.reverse_dict(E4)
BN = WreathProduct(Nemo.FiniteField(2,1, "a")[1], PermutationGroup(N))
if !isfile(joinpath(name, "orbits.jld"))
info("Decomposing E into orbits of B$(N)")
@time orbs = orbit_decomposition(BN, E4, E_dict)
@assert sum(length(o) for o in orbs) == length(E4)
save(joinpath(name, "orbits.jld"), "orbits", orbs)
end
info("Action matrices")
pm = GroupRings.create_pm(E4, E_dict, sizes[2], twisted=true)
RSOutFN = GroupRing(SOutFN, E4, E_dict, pm)
PropertyT.splaplacian(RSOutFN, S)
E2 = E4[1:sizes[2]]
@time BNactionE_mreps = action_mreps(BN, E2, E_dict)
save(joinpath(name, "matrix_reps.jld"), "matrix_reps", BNactionE_mreps)
info("Projections")
@time BN_mps = rankOne_projections(BN);
@time π_E_projections = @showprogress [Cstar_repr(p, BNactionE_mreps) for p in BN_mps]
info("Uπs...")
@time Uπs = Uπ_matrices(π_E_projections);
@show multiplicities = [size(U,2) for U in Uπs];
@show dimensions = [Int(p[BN()]*Int(order(BN))) for p in BN_mps];
@assert dot(multiplicities, dimensions) == sizes[2]
save(joinpath(name, "U_pis.jld"), "Uπs", Uπs, "dims", dimensions)
end
@time main(4)