mirror of
https://github.com/kalmarek/PropertyT.jl.git
synced 2024-11-23 16:20:28 +01:00
add orbit-related code
This commit is contained in:
parent
e21f97f541
commit
77121c32eb
206
src/OrbitDecomposition.jl
Normal file
206
src/OrbitDecomposition.jl
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
push!(LOAD_PATH, "./")
|
||||||
|
|
||||||
|
using Nemo
|
||||||
|
using Groups
|
||||||
|
|
||||||
|
using GroupRings
|
||||||
|
using PropertyT
|
||||||
|
|
||||||
|
import Nemo.elements
|
||||||
|
|
||||||
|
using JLD
|
||||||
|
|
||||||
|
include("Projections.jl")
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Iterator protocol for Nemo.FinField
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
type FFEltsIter{T<:Nemo.FinField}
|
||||||
|
all::Int
|
||||||
|
field::T
|
||||||
|
|
||||||
|
function FFEltsIter(F::T)
|
||||||
|
return new(Int(characteristic(F)^degree(F)), F)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
FFEltsIter{T<:Nemo.FinField}(F::T) = FFEltsIter{T}(F)
|
||||||
|
|
||||||
|
import Base: start, next, done, eltype, length
|
||||||
|
|
||||||
|
Base.start(A::FFEltsIter) = (zero(A.field), 0)
|
||||||
|
Base.next(A::FFEltsIter, state) = next_ffelem(state...)
|
||||||
|
Base.done(A::FFEltsIter, state) = state[2] >= A.all
|
||||||
|
Base.eltype(::Type{FFEltsIter}) = elem_type(A.field)
|
||||||
|
Base.length(A::FFEltsIter) = A.all
|
||||||
|
|
||||||
|
function next_ffelem(f::Nemo.FinFieldElem, c::Int)
|
||||||
|
if c == 0
|
||||||
|
return (f, (f, 1))
|
||||||
|
elseif c == 1
|
||||||
|
f = one(parent(f))
|
||||||
|
return (f, (f, 2))
|
||||||
|
else
|
||||||
|
f = gen(parent(f))*f
|
||||||
|
return (f, (f, c+1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
import Nemo.elements
|
||||||
|
elements(F::Nemo.FinField) = FFEltsIter(F)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Orbit stuff
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
function orbit_decomposition(G::Nemo.Group, E::Vector, rdict=GroupRings.reverse_dict(E))
|
||||||
|
|
||||||
|
elts = collect(elements(G))
|
||||||
|
|
||||||
|
tovisit = trues(E);
|
||||||
|
orbits = Vector{Vector{Int}}()
|
||||||
|
|
||||||
|
for i in 1:endof(E)
|
||||||
|
if tovisit[i]
|
||||||
|
orbit = Vector{Int}()
|
||||||
|
a = E[i]
|
||||||
|
for g in elts
|
||||||
|
idx = rdict[g(a)]
|
||||||
|
tovisit[idx] = false
|
||||||
|
push!(orbit,idx)
|
||||||
|
end
|
||||||
|
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{Vector{Int64}}}, n)
|
||||||
|
result = spzeros(n,n)
|
||||||
|
for cnstr in constraints
|
||||||
|
for p in cnstr
|
||||||
|
result[p[2], p[1]] += 1.0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 1/length(constraints)*result
|
||||||
|
end
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Matrix- and C*-representations
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
function matrix_repr(g::GroupElem, 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 matrix_reps{T<:GroupElem}(G::Nemo.Group, S::Vector{T}, AutS::Nemo.Group, radius::Int)
|
||||||
|
Id = (isa(G, Nemo.Ring) ? one(G) : G())
|
||||||
|
E2, _ = Groups.generate_balls(S, Id, radius=radius)
|
||||||
|
Edict = GroupRings.reverse_dict(E2)
|
||||||
|
|
||||||
|
mreps = Dict(g=>matrix_repr(g, E2, Edict) for g in elements(AutS))
|
||||||
|
return mreps
|
||||||
|
end
|
||||||
|
|
||||||
|
function reconstruct_sol(mreps::Dict, Us::Vector, Ps::Vector, dims::Vector)
|
||||||
|
recP = zeros(size(Us[1],1), size(Us[1],1))
|
||||||
|
|
||||||
|
for g in keys(mreps)
|
||||||
|
for π in 1:endof(Us)
|
||||||
|
recP .+= dims[π] .* mreps[g]*transform(Us[π]', Ps[π])*mreps[inv(g)]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
recP .*= 1/length(collect(keys(mreps)))
|
||||||
|
|
||||||
|
return recP
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cstar_repr(x::GroupRingElem, mreps)
|
||||||
|
k = collect(keys(mreps))[1]
|
||||||
|
res = zeros(size(mreps[k])...)
|
||||||
|
|
||||||
|
for g in parent(x).basis
|
||||||
|
res .+= x[g]*mreps[g]
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
function orthSVD(M::AbstractMatrix)
|
||||||
|
M = full(M)
|
||||||
|
fact = svdfact(M)
|
||||||
|
singv = fact[:S]
|
||||||
|
M_rank = sum(singv .> maximum(size(M))*eps(eltype(singv)))
|
||||||
|
return fact[:U][:,1:M_rank]
|
||||||
|
end
|
||||||
|
|
||||||
|
function compute_orbit_data{T<:GroupElem}(logger, name::String, G::Nemo.Group, S::Vector{T}, AutS; radius=2)
|
||||||
|
isdir(name) || mkdir(name)
|
||||||
|
|
||||||
|
info(logger, "Generating ball of radius $(2*radius)")
|
||||||
|
|
||||||
|
# TODO: Fix that by multiple dispatch?
|
||||||
|
Id = (isa(G, Nemo.Ring) ? one(G) : G())
|
||||||
|
|
||||||
|
@time E4, sizes = Groups.generate_balls(S, Id, radius=2*radius);
|
||||||
|
info(logger, "Balls of sizes $sizes.")
|
||||||
|
info(logger, "Reverse dict")
|
||||||
|
@time E_dict = GroupRings.reverse_dict(E4)
|
||||||
|
|
||||||
|
info(logger, "Product matrix")
|
||||||
|
@time pm = GroupRings.create_pm(E4, E_dict, sizes[radius], twisted=true)
|
||||||
|
RG = GroupRing(G, E4, E_dict, pm)
|
||||||
|
Δ = PropertyT.splaplacian(RG, S)
|
||||||
|
@assert GroupRings.augmentation(Δ) == 0
|
||||||
|
save(joinpath(name, "delta.jld"), "Δ", Δ.coeffs)
|
||||||
|
save(joinpath(name, "pm.jld"), "pm", pm)
|
||||||
|
|
||||||
|
info(logger, "Decomposing E into orbits of $(AutS)")
|
||||||
|
@time orbs = orbit_decomposition(AutS, E4, E_dict)
|
||||||
|
@assert sum(length(o) for o in orbs) == length(E4)
|
||||||
|
save(joinpath(name, "orbits.jld"), "orbits", orbs)
|
||||||
|
|
||||||
|
info(logger, "Action matrices")
|
||||||
|
E2 = E4[1:sizes[radius]]
|
||||||
|
@time AutS_mreps = Dict(g=>matrix_repr(g, E2, E_dict) for g in elements(AutS))
|
||||||
|
|
||||||
|
info(logger, "Projections")
|
||||||
|
@time AutS_mps = rankOne_projections(AutS);
|
||||||
|
|
||||||
|
@time π_E_projections = [Cstar_repr(p, AutS_mreps) for p in AutS_mps]
|
||||||
|
|
||||||
|
info(logger, "Uπs...")
|
||||||
|
@time Uπs = orthSVD.(π_E_projections)
|
||||||
|
|
||||||
|
multiplicities = size.(Uπs,2)
|
||||||
|
info(logger, "multiplicities = $multiplicities")
|
||||||
|
dimensions = [Int(p[AutS()]*Int(order(AutS))) for p in AutS_mps];
|
||||||
|
info(logger, "dimensions = $dimensions")
|
||||||
|
@assert dot(multiplicities, dimensions) == sizes[radius]
|
||||||
|
|
||||||
|
save(joinpath(name, "U_pis.jld"), "Uπs", Uπs, "dims", dimensions)
|
||||||
|
return 0
|
||||||
|
end
|
135
src/Projections.jl
Normal file
135
src/Projections.jl
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
using DirectProducts
|
||||||
|
using WreathProducts
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Characters of PermutationGroup
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Character of DirectProducts
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
function epsilon(i, g::DirectProducts.DirectProductGroupElem)
|
||||||
|
return reduce(*, 1, ((-1)^isone(g.elts[j]) for j in 1:i))
|
||||||
|
end
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Projections
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
function central_projection(RG::GroupRing, char::Function, T::Type=Rational{Int})
|
||||||
|
result = RG(T)
|
||||||
|
for g in RG.basis
|
||||||
|
result[g] = char(inv(g))
|
||||||
|
end
|
||||||
|
return convert(T, char(RG.group())//Int(order(RG.group))*result)
|
||||||
|
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
|
234
src/oPropertyT.jl
Normal file
234
src/oPropertyT.jl
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
using JLD
|
||||||
|
using JuMP
|
||||||
|
using SCS
|
||||||
|
|
||||||
|
using GroupRings
|
||||||
|
using PropertyT
|
||||||
|
|
||||||
|
using ValidatedNumerics
|
||||||
|
using ArgParse
|
||||||
|
|
||||||
|
import Nemo: Group, GroupElem
|
||||||
|
|
||||||
|
immutable Settings
|
||||||
|
name::String
|
||||||
|
N::Int
|
||||||
|
G::Group
|
||||||
|
S::Vector
|
||||||
|
AutS::Group
|
||||||
|
radius::Int
|
||||||
|
solver::SCSSolver
|
||||||
|
upper_bound::Float64
|
||||||
|
tol::Float64
|
||||||
|
end
|
||||||
|
|
||||||
|
immutable OrbitData
|
||||||
|
name::String
|
||||||
|
Us::Vector
|
||||||
|
Ps::Vector{Array{JuMP.Variable,2}}
|
||||||
|
cnstr::Vector
|
||||||
|
laplacian::Vector
|
||||||
|
laplacianSq::Vector
|
||||||
|
dims::Vector{Int}
|
||||||
|
end
|
||||||
|
|
||||||
|
include("OrbitDecomposition.jl")
|
||||||
|
|
||||||
|
function sparsify{T}(U::Array{T}, eps=eps(T))
|
||||||
|
n = rank(U)
|
||||||
|
W = deepcopy(U)
|
||||||
|
W[abs.(W) .< eps] = zero(T)
|
||||||
|
if rank(W) != n
|
||||||
|
warn("Sparsification would decrease the rank!")
|
||||||
|
W = U
|
||||||
|
end
|
||||||
|
W = sparse(W)
|
||||||
|
dropzeros!(W)
|
||||||
|
return W
|
||||||
|
end
|
||||||
|
|
||||||
|
function sparsify!{T}(U::SparseMatrixCSC{T}, eps=eps(T))
|
||||||
|
U[abs.(U) .< eps] = zero(T)
|
||||||
|
dropzeros!(U)
|
||||||
|
return U
|
||||||
|
end
|
||||||
|
|
||||||
|
sparsify{T}(U::SparseMatrixCSC{T}, eps=eps(T)) = sparsify!(deepcopy(U), eps)
|
||||||
|
|
||||||
|
function init_model(Uπs)
|
||||||
|
m = JuMP.Model();
|
||||||
|
l = size(Uπs,1)
|
||||||
|
P = Vector{Array{JuMP.Variable,2}}(l)
|
||||||
|
|
||||||
|
for k in 1:l
|
||||||
|
s = size(Uπs[k],2)
|
||||||
|
P[k] = JuMP.@variable(m, [i=1:s, j=1:s])
|
||||||
|
JuMP.@SDconstraint(m, P[k] >= 0.0)
|
||||||
|
end
|
||||||
|
|
||||||
|
JuMP.@variable(m, λ >= 0.0)
|
||||||
|
JuMP.@objective(m, Max, λ)
|
||||||
|
return m, P
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_OrbitData(name::String)
|
||||||
|
splap = load(joinpath(name, "delta.jld"), "Δ");
|
||||||
|
pm = load(joinpath(name, "pm.jld"), "pm");
|
||||||
|
cnstr = PropertyT.constraints_from_pm(pm);
|
||||||
|
splap² = GroupRings.mul(splap, splap, pm);
|
||||||
|
|
||||||
|
Uπs = load(joinpath(name, "U_pis.jld"), "Uπs");
|
||||||
|
# Uπs = sparsify.(Uπs);
|
||||||
|
#dimensions of the corresponding πs:
|
||||||
|
dims = load(joinpath(name, "U_pis.jld"), "dims")
|
||||||
|
|
||||||
|
m, P = init_model(Uπs);
|
||||||
|
|
||||||
|
orbits = load(joinpath(name, "orbits.jld"), "orbits");
|
||||||
|
n = size(Uπs[1],1)
|
||||||
|
orb_spcnstrm = [orbit_constraint(cnstr[collect(orb)], n) for orb in orbits]
|
||||||
|
orb_splap = orbit_spvector(splap, orbits)
|
||||||
|
orb_splap² = orbit_spvector(splap², orbits)
|
||||||
|
|
||||||
|
orbData = OrbitData(name, Uπs, P, orb_spcnstrm, orb_splap, orb_splap², dims);
|
||||||
|
|
||||||
|
# orbData = OrbitData(name, Uπs, P, orb_spcnstrm, splap, splap², dims);
|
||||||
|
|
||||||
|
return m, orbData
|
||||||
|
end
|
||||||
|
|
||||||
|
function transform(U::AbstractArray, V::AbstractArray; sparse=false)
|
||||||
|
w = U'*V*U
|
||||||
|
sparse && sparsify!(w)
|
||||||
|
return w
|
||||||
|
end
|
||||||
|
|
||||||
|
A(data::OrbitData, π, t) = data.dims[π]*transform(data.Us[π], data.cnstr[t])
|
||||||
|
|
||||||
|
function constrLHS(m::JuMP.Model, data::OrbitData, t)
|
||||||
|
l = endof(data.Us)
|
||||||
|
lhs = @expression(m, sum(vecdot(A(data, π, t), data.Ps[π]) for π in 1:l))
|
||||||
|
return lhs
|
||||||
|
end
|
||||||
|
|
||||||
|
function addconstraints!(m::JuMP.Model, data::OrbitData, l::Int=length(data.laplacian); var::Symbol = :λ)
|
||||||
|
λ = m[var]
|
||||||
|
# orbits = load(joinpath(data.name, "orbits.jld"), "orbits");
|
||||||
|
# locate(t, orb=orbits) = findfirst(x->t in x, orb)
|
||||||
|
for t in 1:l
|
||||||
|
# lhs = constrLHS(m, data, locate(t))
|
||||||
|
lhs = constrLHS(m, data, t)
|
||||||
|
|
||||||
|
d, d² = data.laplacian[t], data.laplacianSq[t]
|
||||||
|
if lhs == zero(lhs)
|
||||||
|
if d == 0 && d² == 0
|
||||||
|
info("Detected empty constraint")
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
warn("Adding unsatisfiable constraint!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
JuMP.@constraint(m, lhs == d² - λ*d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function create_SDP_problem(name::String; upper_bound=Inf)
|
||||||
|
info(PropertyT.logger, "Loading orbit data....")
|
||||||
|
t = @timed SDP_problem, orb_data = init_OrbitData(name);
|
||||||
|
info(PropertyT.logger, PropertyT.timed_msg(t))
|
||||||
|
|
||||||
|
if upper_bound < Inf
|
||||||
|
λ = JuMP.getvariable(SDP_problem, :λ)
|
||||||
|
JuMP.@constraint(SDP_problem, λ <= upper_bound)
|
||||||
|
end
|
||||||
|
|
||||||
|
info(PropertyT.logger, "Adding constraints... ")
|
||||||
|
t = @timed addconstraints!(SDP_problem, orb_data)
|
||||||
|
info(PropertyT.logger, PropertyT.timed_msg(t))
|
||||||
|
|
||||||
|
return SDP_problem, orb_data
|
||||||
|
end
|
||||||
|
|
||||||
|
function λandP(m::JuMP.Model, data::OrbitData)
|
||||||
|
varλ = m[:λ]
|
||||||
|
varP = data.Ps
|
||||||
|
λ, Ps = PropertyT.λandP(data.name, m, varλ, varP)
|
||||||
|
return λ, Ps
|
||||||
|
end
|
||||||
|
|
||||||
|
function λandP(m::JuMP.Model, data::OrbitData, sett::Settings)
|
||||||
|
info(PropertyT.logger, "Solving SDP problem...")
|
||||||
|
λ, Ps = λandP(m, data)
|
||||||
|
|
||||||
|
info(PropertyT.logger, "Reconstructing P...")
|
||||||
|
mreps = matrix_reps(sett.G, sett.S, sett.AutS, sett.radius)
|
||||||
|
|
||||||
|
recP = reconstruct_sol(mreps, data.Us, Ps, data.dims)
|
||||||
|
|
||||||
|
fname = PropertyT.λSDPfilenames(data.name)[2]
|
||||||
|
save(fname, "origP", Ps, "P", recP)
|
||||||
|
return λ, recP
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_orbit_data(logger, sett::Settings; radius=2)
|
||||||
|
|
||||||
|
ex(fname) = isfile(joinpath(sett.name, fname))
|
||||||
|
|
||||||
|
files_exists = ex.(["delta.jld", "pm.jld", "U_pis.jld", "orbits.jld"])
|
||||||
|
|
||||||
|
if !all(files_exists)
|
||||||
|
compute_orbit_data(logger, sett.name, sett.G, sett.S, sett.AutS, radius=radius)
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function orbit_check_propertyT(logger, sett::Settings)
|
||||||
|
|
||||||
|
init_orbit_data(logger, sett, radius=sett.radius)
|
||||||
|
|
||||||
|
Δ = PropertyT.ΔandSDPconstraints(sett.name, sett.G)[1]
|
||||||
|
|
||||||
|
fnames = PropertyT.λSDPfilenames(sett.name)
|
||||||
|
|
||||||
|
if all(isfile.(fnames))
|
||||||
|
λ, P = PropertyT.λandP(sett.name)
|
||||||
|
else
|
||||||
|
info(logger, "Creating SDP problem...")
|
||||||
|
SDP_problem, orb_data = create_SDP_problem(sett.name, upper_bound=sett.upper_bound)
|
||||||
|
JuMP.setsolver(SDP_problem, sett.solver)
|
||||||
|
|
||||||
|
λ, P = λandP(SDP_problem, orb_data, sett)
|
||||||
|
end
|
||||||
|
|
||||||
|
info(logger, "λ = $λ")
|
||||||
|
info(logger, "sum(P) = $(sum(P))")
|
||||||
|
info(logger, "maximum(P) = $(maximum(P))")
|
||||||
|
info(logger, "minimum(P) = $(minimum(P))")
|
||||||
|
|
||||||
|
if λ > 0
|
||||||
|
|
||||||
|
isapprox(eigvals(P), abs(eigvals(P)), atol=sett.tol) ||
|
||||||
|
warn("The solution matrix doesn't seem to be positive definite!")
|
||||||
|
# @assert P == Symmetric(P)
|
||||||
|
Q = real(sqrtm(Symmetric(P)))
|
||||||
|
|
||||||
|
sgap = PropertyT.check_distance_to_positive_cone(Δ, λ, Q, 2*sett.radius, tol=sett.tol, rational=false)
|
||||||
|
if isa(sgap, Interval)
|
||||||
|
sgap = sgap.lo
|
||||||
|
end
|
||||||
|
if sgap > 0
|
||||||
|
info(logger, "λ ≥ $(Float64(trunc(sgap,12)))")
|
||||||
|
Kazhdan_κ = PropertyT.Kazhdan_from_sgap(sgap, length(sett.S))
|
||||||
|
Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12))
|
||||||
|
info(logger, "κ($(sett.name), S) ≥ $Kazhdan_κ: Group HAS property (T)!")
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
sgap = Float64(trunc(sgap, 12))
|
||||||
|
info(logger, "λ($(sett.name), S) ≥ $sgap: Group may NOT HAVE property (T)!")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
info(logger, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)")
|
||||||
|
return false
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user