diff --git a/src/Projections.jl b/src/Projections.jl index ccd207d..00d5e43 100644 --- a/src/Projections.jl +++ b/src/Projections.jl @@ -61,49 +61,75 @@ function central_projection(RG::GroupRing, chi::AbstractCharacter, return result end -function rankOne_projections(G::PermutationGroup, T::Type=Rational{Int}) - RG = GroupRing(G) - cprojs = [central_projection(RG, χ, T) for χ in (PermCharacter(λ) for λ in Partitions(G.n))] +function idempotents(RG::GroupRing{PermGroup}, T::Type=Rational{Int}) + if RG.group.n == 1 + return GroupRingElem{T}[one(RG,T)] + elseif RG.group.n == 2 + Id = one(RG,T) + transp = convert(T, RG(RG.group([2,1]))) + return GroupRingElem{T}[1//2*(Id + transp), 1//2*(Id - transp)] - if G.n == 1 || G.n == 2 - return cprojs - elseif G.n == 3 - p = 1//2*(one(RG, T) - RG(G([2,1,3]), T)) - rankone_projs = [ - cprojs[1], # alternating - p*cprojs[2], # regular - cprojs[3] # trivial - ] - elseif G.n == 4 - p⁺ = 1//2*(one(RG, T) + RG(G([2,1,3,4]), T)) - p⁻ = 1//2*(one(RG, T) - RG(G([2,1,3,4]), T)) - rankone_projs = [ - cprojs[1], # alternating - p⁺*cprojs[2], # alt_regular - p⁻*cprojs[3], # regular - p⁻*cprojs[4], # via projection to S₃ - cprojs[5] # trivial - ] - elseif G.n == 5 - p⁺ = 1//2*(one(RG, T) + RG(G([2,1,3,4,5]), T)) - p⁻ = 1//2*(one(RG, T) - RG(G([2,1,3,4,5]), T)) + end + projs = Vector{Vector{perm}}() + for l in 2:RG.group.n + u = RG.group([circshift([i for i in 1:l], -1); [i for i in l+1:RG.group.n]]) + i = 0 + while (l-1)*i <= RG.group.n + v = RG.group(circshift(collect(1:RG.group.n), i)) + k = inv(v)*u*v + push!(projs, generateGroup([k], RG.group.n)) + i += 1 + end + end - q⁺ = 1//2*(one(RG, T) + RG(G([1,2,4,3,5]), T)) - q⁻ = 1//2*(one(RG, T) - RG(G([1,2,4,3,5]), T)) + idems = Vector{GroupRingElem{T}}() + for p in projs + append!(idems, [RG(p, T), RG(p, T, alt=true)]) + end - rankone_projs = [ - cprojs[1], # alternating - p⁺*cprojs[2], # alt_regular - p⁺*q⁺*cprojs[3], # ψ - p⁺*q⁺*cprojs[4], # alt_ϱ - p⁻*cprojs[5], # regular - p⁻*q⁻*cprojs[6], # ϱ - cprojs[7] # trivial - ] - else - throw("Rank-one projections for $G unknown!") + return unique(idems) +end + +function rankOne_projection{S}(chi::PropertyT.PermCharacter, idems::Vector{GroupRingElem{S}}) + + RG = parent(first(idems)) + + ids = [[one(RG, S)]; idems] + + for (i,j,k) in Base.product(ids, ids, ids) + if chi(i) == zero(S) || chi(j) == zero(S) || chi(k) == zero(S) + continue + end + elt = i*j*k + elt^2 == elt || continue + if chi(elt) == one(S) + return elt + # return (i,j,k) + end end - return rankone_projs + throw("Couldn't find rank-one projection for $chi") +end + +function minimalprojections(G::PermutationGroup, T::Type=Rational{Int}) + if G.n == 1 + return [(one(GroupRing(G), T), one(GroupRing(G), T))] + elseif G.n < 8 + RG = GroupRing(G, fastm=true) + else + RG = GroupRing(G, fastm=false) + end + + RGidems = idempotents(RG, T) + chars = [PropertyT.PermCharacter(p) for p in Partitions(G.n)] + + return [ + (rankOne_projection(chi, RGidems), PropertyT.central_projection(RG, chi)) + for chi in chars] +end + +function rankOne_projections(G::PermutationGroup, T::Type=Rational{Int}) + mps = minimalprojections(G, T) + return [idem*cproj for (idem, cproj) in mps] end function rankOne_projections(BN::WreathProduct, T::Type=Rational{Int}) @@ -137,3 +163,53 @@ function rankOne_projections(BN::WreathProduct, T::Type=Rational{Int}) return all_projs end + +############################################################################## +# +# General Groups Misc +# +############################################################################## + +doc""" + products(X::Vector{GroupElem}, Y::Vector{GroupElem}, op=*) +> Returns a vector of all possible products (or `op(x,y)`), where $x\in X$ and +> $y\in Y$ are group elements. You may specify which operation is used when +> forming 'products' by adding `op` (which is `*` by default). +""" +function products{T<:GroupElem}(X::AbstractVector{T}, Y::AbstractVector{T}, op=*) + result = Vector{T}() + seen = Set{T}() + for x in X + for y in Y + z = op(x,y) + if !in(z, seen) + push!(seen, z) + push!(result, z) + end + end + end + return result +end + +doc""" + generateGroup(gens::Vector{GroupElem}, r=2, Id=parent(first(gens))(), op=*) +> Produces all elements of a group generated by elements in `gens` in ball of +> radius `r` (word-length metric induced by `gens`). +> If `r(=2)` is specified the procedure will terminate after generating ball +> of radius `r` in the word-length metric induced by `gens`. +> The identity element `Id` and binary operation function `op` can be supplied +> to e.g. take advantage of additive group structure. +""" +function generateGroup{T<:GroupElem}(gens::Vector{T}, r=2, Id::T=parent(first(gens))(), op=*) + n = 0 + R = 1 + elts = gens + gens = [Id; gens] + while n ≠ length(elts) && R < r + # @show elts + R += 1 + n = length(elts) + elts = products(elts, gens, op) + end + return elts +end