diff --git a/src/PropertyT.jl b/src/PropertyT.jl index aa0036e..bea4df1 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -21,31 +21,36 @@ import MathProgBase.SolverInterface.AbstractMathProgSolver struct Symmetrize end struct Naive end -mutable struct Settings{Gr<:Group, GEl<:GroupElem, Sol<:AbstractMathProgSolver} +struct Settings{T} where T<:Union{Symmetrize, Naive} name::String - G::Gr - S::Vector{GEl} + + G::Group + S::Vector{GroupElem} radius::Int - solver::Sol + solver::AbstractMathProgSolver upper_bound::Float64 tol::Float64 warmstart::Bool autS::Group - function Settings(name, G::Gr, S::Vector{GEl}, r::Int, - sol::Sol, ub, tol, ws) where {Gr, GEl, Sol} - return new{Gr, GEl, Sol}(name, G, S, r, sol, ub, tol, ws) + function Settings(name::String, + G::Group, S::Vector{GEl}, r::Int, + sol::Sol, ub, tol, ws) where + {GEl<:GroupElem, Sol<:AbstractMathProgSolver} + return new{Naive}(name, G, S, r, sol, ub, tol, ws) end - function Settings(name, G::Gr, S::Vector{GEl}, r::Int, - sol::Sol, ub, tol, ws, autS) where {Gr, GEl, Sol} - return new{Gr, GEl, Sol}(name, G, S, r, sol, ub, tol, ws, autS) + function Settings(name::String, + G::Group, S::Vector{GEl}, r::Int, + sol::Sol, ub, tol, ws, autS) where {Gr, GEl, Sol} + return new{Symmetrize}(name, G, S, r, sol, ub, tol, ws, autS) end end -prefix(s::Settings) = s.name +prefix(s::Settings{Naive}) = s.name +prefix(s::Settings{Symmetrize}) = "o"*s.name suffix(s::Settings) = "$(s.upper_bound)" prepath(s::Settings) = prefix(s) fullpath(s::Settings) = joinpath(prefix(s), suffix(s)) @@ -72,57 +77,53 @@ filename(prefix, s::Symbol) = filename(prefix, Val{s}) end end -for T in [:Naive, :Symmetrize] - @eval begin - function check_property_T(::Type{$T}, sett::Settings) +function check_property_T(sett::Settings{$T}) - if exists(filename(prepath(sett),:pm)) && - exists(filename(prepath(sett),:Δ)) - # cached - Δ = loadLaplacian(prepath(sett), parent(sett.S[1])) - else - # compute - Δ = computeLaplacian(sett.S, sett.radius) - save(filename(prepath(sett), :pm), "pm", parent(Δ).pm) - save(filename(prepath(sett), :Δ), "Δ", Δ.coeffs) - end + if exists(filename(prepath(sett),:pm)) && + exists(filename(prepath(sett),:Δ)) + # cached + Δ = loadLaplacian(prepath(sett), parent(sett.S[1])) + else + # compute + Δ = computeLaplacian(sett.S, sett.radius) + save(filename(prepath(sett), :pm), "pm", parent(Δ).pm) + save(filename(prepath(sett), :Δ), "Δ", Δ.coeffs) + end - files_exist = exists(filename(fullpath(sett), :λ)) && - exists(filename(fullpath(sett), :P)) + files_exist = exists(filename(fullpath(sett), :λ)) && + exists(filename(fullpath(sett), :P)) - if !sett.warmstart && files_exist - λ, P = loadλandP(fullpath(sett)) - else - warmfile = filename(fullpath(sett), :warm) - if sett.warmstart && exists(warmfile) - ws = load(warmfile, "warmstart") - else - ws = nothing - end + if !sett.warmstart && files_exist + λ, P = loadλandP(fullpath(sett)) + else + warmfile = filename(fullpath(sett), :warm) + if sett.warmstart && exists(warmfile) + ws = load(warmfile, "warmstart") + else + ws = nothing + end - λ, P, ws = computeλandP($T, Δ, sett, - solverlog=filename(fullpath(sett), :solverlog)) - saveλandP(fullpath(sett), λ, P, ws) + λ, P, ws = computeλandP(sett, Δ, + solverlog=filename(fullpath(sett), :solverlog)) + saveλandP(fullpath(sett), λ, P, ws) - if λ < 0 - warn("Solver did not produce a valid solution!") - end - end - - info("λ = $λ") - info("sum(P) = $(sum(P))") - info("maximum(P) = $(maximum(P))") - info("minimum(P) = $(minimum(P))") - - isapprox(eigvals(P), abs.(eigvals(P)), atol=sett.tol) || - warn("The solution matrix doesn't seem to be positive definite!") - - @time Q = real(sqrtm((P+P')/2)) - sgap = distance_to_cone(Δ, λ, Q, wlen=2*sett.radius) - - return interpret_results(sett, sgap) + if λ < 0 + warn("Solver did not produce a valid solution!") end end + + info("λ = $λ") + info("sum(P) = $(sum(P))") + info("maximum(P) = $(maximum(P))") + info("minimum(P) = $(minimum(P))") + + isapprox(eigvals(P), abs.(eigvals(P)), atol=sett.tol) || + warn("The solution matrix doesn't seem to be positive definite!") + + @time Q = real(sqrtm((P+P')/2)) + sgap = distance_to_cone(Δ, λ, Q, wlen=2*sett.radius) + + return interpret_results(sett, sgap) end Kazhdan(λ::Number, N::Integer) = sqrt(2*λ/N) diff --git a/src/laplacians.jl b/src/laplacians.jl index 313e83a..ff7e238 100644 --- a/src/laplacians.jl +++ b/src/laplacians.jl @@ -62,7 +62,8 @@ end # ############################################################################### -function computeλandP(::Type{Naive}, Δ::GroupRingElem, sett::Settings, ws=nothing; solverlog=tempname()*".log") +function computeλandP(sett::Settings{Naive}, + Δ::GroupRingElem, ws=nothing; solverlog=tempname()*".log") info("Creating SDP problem...") SDP_problem, varλ, varP = SOS_problem(Δ^2, Δ, upper_bound=sett.upper_bound) JuMP.setsolver(SDP_problem, sett.solver) @@ -73,7 +74,8 @@ function computeλandP(::Type{Naive}, Δ::GroupRingElem, sett::Settings, ws=noth return λ, P, ws end -function computeλandP(::Type{Symmetrize}, Δ::GroupRingElem, sett::Settings, ws=nothing; solverlog=tempname()*".log") +function computeλandP(sett::Settings{Symmetrize}, + Δ::GroupRingElem, ws=nothing; solverlog=tempname()*".log") pdir = prepath(sett) files_exist = exists(filename(pdir,:Uπs)) && exists(filename(pdir,:orbits)) && exists(filename(pdir,:preps))