PropertyT.jl/src/OrbitDecomposition.jl

162 lines
4.5 KiB
Julia
Raw Normal View History

2017-06-22 14:12:35 +02:00
include("Projections.jl")
###############################################################################
#
# Orbit stuff
#
###############################################################################
2018-07-31 10:21:54 +02:00
function orbit_decomposition(G::Group, E::Vector, rdict=GroupRings.reverse_dict(E))
2017-06-22 14:12:35 +02:00
elts = collect(elements(G))
tovisit = trues(E);
orbits = Vector{Vector{Int}}()
orbit = zeros(Int, length(elts))
2017-06-22 14:12:35 +02:00
for i in 1:endof(E)
if tovisit[i]
g = E[i]
Threads.@threads for j in 1:length(elts)
orbit[j] = rdict[elts[j](g)]
2017-06-22 14:12:35 +02:00
end
2017-08-27 18:32:19 +02:00
tovisit[orbit] = false
2017-06-22 14:12:35 +02:00
push!(orbits, unique(orbit))
end
end
return orbits
end
function orbit_spvector(vect::AbstractVector, orbits)
orb_vector = spzeros(length(orbits))
for (i,o) in enumerate(orbits)
k = vect[collect(o)]
val = k[1]
@assert all(k .== val)
orb_vector[i] = val
end
return orb_vector
end
function orbit_constraint(constraints::Vector{Vector{Int}}, n)
2017-06-22 14:12:35 +02:00
result = spzeros(n,n)
for cnstr in constraints
result[cnstr] += 1.0/length(constraints)
2017-06-22 14:12:35 +02:00
end
return result
2017-06-22 14:12:35 +02:00
end
###############################################################################
#
2017-11-08 09:28:04 +01:00
# Matrix-, Permutation- and C*-representations
2017-06-22 14:12:35 +02:00
#
###############################################################################
2017-11-08 09:28:04 +01:00
function matrix_repr(p::perm)
N = parent(p).n
return sparse(1:N, p.d, [1.0 for _ in 1:N])
2017-06-22 14:12:35 +02:00
end
2018-01-26 13:20:56 +01:00
function matrix_reps(preps::Dict{T,perm{I}}) where {T<:GroupElem, I<:Integer}
2017-11-08 09:28:04 +01:00
kk = collect(keys(preps))
mreps = Vector{SparseMatrixCSC{Float64, Int}}(length(kk))
Threads.@threads for i in 1:length(kk)
mreps[i] = matrix_repr(preps[kk[i]])
end
return Dict(kk[i] => mreps[i] for i in 1:length(kk))
2017-06-22 14:12:35 +02:00
end
2017-11-08 09:28:04 +01:00
function perm_repr(g::GroupElem, E::Vector, E_dict)
2018-01-01 14:06:33 +01:00
p = Vector{Int}(length(E))
for (i,elt) in enumerate(E)
p[i] = E_dict[g(elt)]
end
return p
2017-08-27 18:35:35 +02:00
end
2017-11-08 09:28:04 +01:00
function perm_reps(G::Group, E::Vector, E_rdict=GroupRings.reverse_dict(E))
2018-01-01 14:06:33 +01:00
elts = collect(elements(G))
l = length(elts)
2018-07-31 10:21:54 +02:00
preps = Vector{perm}(l)
2017-08-27 18:35:35 +02:00
2018-07-31 10:21:54 +02:00
permG = PermutationGroup(length(E))
2017-08-27 18:35:35 +02:00
2018-01-01 14:06:33 +01:00
Threads.@threads for i in 1:l
preps[i] = permG(PropertyT.perm_repr(elts[i], E, E_rdict), false)
2018-01-01 14:06:33 +01:00
end
2017-08-27 18:35:35 +02:00
2018-01-01 14:06:33 +01:00
return Dict(elts[i]=>preps[i] for i in 1:l)
2017-08-27 18:35:35 +02:00
end
2017-11-08 09:56:28 +01:00
function perm_reps(S::Vector, autS::Group, radius::Int)
2018-01-01 14:06:33 +01:00
E, _ = Groups.generate_balls(S, radius=radius)
return perm_reps(autS, E)
2017-08-27 18:35:35 +02:00
end
2017-08-03 11:35:34 +02:00
function reconstruct_sol(preps::Dict{T, S}, Us::Vector, Ps::Vector, dims::Vector) where {T<:GroupElem, S<:perm}
2018-01-01 14:06:33 +01:00
l = length(Us)
transfP = [dims[π].*Us[π]*Ps[π]*Us[π]' for π in 1:l]
tmp = [zeros(Float64, size(first(transfP))) for _ in 1:l]
perms = collect(keys(preps))
@inbounds Threads.@threads for π in 1:l
for p in perms
BLAS.axpy!(1.0, view(transfP[π], preps[p].d, preps[p].d), tmp[π])
end
end
recP = 1/length(perms) .* sum(tmp)
for i in eachindex(recP)
if abs(recP[i]) .< eps(eltype(recP))*100
recP[i] = zero(eltype(recP))
end
end
2018-01-01 14:06:33 +01:00
return recP
2017-06-22 14:12:35 +02:00
end
2017-10-03 14:46:05 +02:00
function Cstar_repr(x::GroupRingElem{T}, mreps::Dict) where {T}
2018-01-01 14:06:33 +01:00
return sum(x[i].*mreps[parent(x).basis[i]] for i in findn(x.coeffs))
2017-06-22 14:12:35 +02:00
end
2018-08-20 03:58:09 +02:00
function orthSVD(M::AbstractMatrix{T}) where {T<:AbstractFloat}
2018-01-01 14:06:33 +01:00
M = full(M)
fact = svdfact(M)
M_rank = sum(fact[:S] .> maximum(size(M))*eps(T))
return fact[:U][:,1:M_rank]
2017-06-22 14:12:35 +02:00
end
function compute_orbit_data(name::String, RG::GroupRing, autS::Group)
2018-01-01 14:06:33 +01:00
2018-08-19 20:05:45 +02:00
info("Decomposing E into orbits of $(autS)")
@time orbs = orbit_decomposition(autS, RG.basis, RG.basis_dict)
@assert sum(length(o) for o in orbs) == length(RG.basis)
2018-08-19 20:05:45 +02:00
info("E consists of $(length(orbs)) orbits!")
2018-01-01 14:06:33 +01:00
2018-08-19 20:05:45 +02:00
info("Action matrices")
@time preps = perm_reps(autS, RG.basis[1:size(RG.pm,1)], RG.basis_dict)
mreps = matrix_reps(preps)
2018-01-01 14:06:33 +01:00
2018-08-19 20:05:45 +02:00
info("Projections")
@time autS_mps = Projections.rankOne_projections(GroupRing(autS));
2018-01-01 14:06:33 +01:00
@time π_E_projections = [Cstar_repr(p, mreps) for p in autS_mps]
2018-01-01 14:06:33 +01:00
2018-08-19 20:05:45 +02:00
info("Uπs...")
@time Uπs = orthSVD.(π_E_projections)
2018-01-01 14:06:33 +01:00
multiplicities = size.(Uπs,2)
2018-08-19 20:05:45 +02:00
info("multiplicities = $multiplicities")
2018-01-01 14:06:33 +01:00
dimensions = [Int(p[autS()]*Int(order(autS))) for p in autS_mps];
2018-08-19 20:05:45 +02:00
info("dimensions = $dimensions")
@assert dot(multiplicities, dimensions) == size(RG.pm,1)
2018-01-01 14:06:33 +01:00
save(filename(name, :orbits), "orbits", orbs)
save_preps(filename(name, :preps), preps)
save(filename(name, :Uπs), "Uπs", Uπs, "dims", dimensions)
2018-01-01 14:06:33 +01:00
return 0
2017-06-22 14:12:35 +02:00
end