mirror of
https://github.com/kalmarek/PropertyT.jl.git
synced 2024-09-18 09:38:00 +02:00
126 lines
3.9 KiB
Julia
126 lines
3.9 KiB
Julia
###############################################################################
|
|
#
|
|
# Laplacians
|
|
#
|
|
###############################################################################
|
|
|
|
function spLaplacian(RG::GroupRing, S, T::Type=Float64)
|
|
result = RG(T)
|
|
result[RG.group()] = T(length(S))
|
|
for s in S
|
|
result[s] -= one(T)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function spLaplacian(RG::GroupRing{R}, S, T::Type=Float64) where {R<:Ring}
|
|
result = RG(T)
|
|
result[one(RG.group)] = T(length(S))
|
|
for s in S
|
|
result[s] -= one(T)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function computeLaplacian(S::Vector{E}, radius) where E<:AbstractAlgebra.RingElem
|
|
R = parent(first(S))
|
|
return computeLaplacian(S, one(R), radius)
|
|
end
|
|
|
|
function computeLaplacian(S::Vector{E}, radius) where E<:AbstractAlgebra.GroupElem
|
|
G = parent(first(S))
|
|
return computeLaplacian(S, G(), radius)
|
|
end
|
|
|
|
function computeLaplacian(S, Id, radius)
|
|
info("Generating metric ball of radius $radius...")
|
|
@time E_R, sizes = Groups.generate_balls(S, Id, radius=2radius)
|
|
info("Generated balls of sizes $sizes.")
|
|
|
|
info("Creating product matrix...")
|
|
@time pm = GroupRings.create_pm(E_R, GroupRings.reverse_dict(E_R), sizes[radius]; twisted=true)
|
|
|
|
RG = GroupRing(parent(Id), E_R, pm)
|
|
Δ = spLaplacian(RG, S)
|
|
return Δ
|
|
end
|
|
|
|
function loadLaplacian(name::String, G::Group)
|
|
if exists(filename(name, :Δ)) && exists(filename(name, :pm))
|
|
info("Loading precomputed Δ...")
|
|
RG = GroupRing(G, load(filename(name, :pm), "pm"))
|
|
Δ = GroupRingElem(load(filename(name, :Δ), "Δ")[:, 1], RG)
|
|
else
|
|
throw("You need to precompute $(filename(name, :pm)) and $(filename(name, :Δ)) to load it!")
|
|
end
|
|
return Δ
|
|
end
|
|
|
|
###############################################################################
|
|
#
|
|
# λandP
|
|
#
|
|
###############################################################################
|
|
|
|
function computeλandP(::Type{Naive}, Δ::GroupRingElem, sett::Settings, 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)
|
|
info(Base.repr(SDP_problem))
|
|
|
|
@time λ, P, ws = solve_logged(SDP_problem, varλ, varP, ws, solverlog=solverlog)
|
|
|
|
return λ, P, ws
|
|
end
|
|
|
|
function computeλandP(::Type{Symmetrize}, Δ::GroupRingElem, sett::Settings, ws=nothing; solverlog=tempname()*".log")
|
|
pdir = prepath(sett)
|
|
|
|
files_exist = exists(filename(pdir,:Uπs)) && exists(filename(pdir,:orbits)) && exists(filename(pdir,:preps))
|
|
|
|
if files_exist
|
|
orbit_data = load_OrbitData(sett)
|
|
else
|
|
isdefined(parent(Δ), :basis) || throw("You need to define basis of Group Ring to compute orbit decomposition!")
|
|
orbit_data = compute_OrbitData(parent(Δ), sett.autS)
|
|
save_OrbitData(sett, orbit_data)
|
|
end
|
|
orbit_data = decimate(orbit_data)
|
|
|
|
info("Creating SDP problem...")
|
|
|
|
SDP_problem, varλ, varP = SOS_problem(Δ^2, Δ, orbit_data, upper_bound=sett.upper_bound)
|
|
JuMP.setsolver(SDP_problem, sett.solver)
|
|
info(Base.repr(SDP_problem))
|
|
|
|
@time λ, P, ws = solve_logged(SDP_problem, varλ, varP, ws, solverlog=solverlog)
|
|
|
|
fname = filename(fullpath(sett), :P)
|
|
save(joinpath(dirname(fname), "orig_"*basename(fname)), "origP", P)
|
|
|
|
info("Reconstructing P...")
|
|
@time recP = reconstruct(P, orbit_data)
|
|
|
|
return λ, recP, ws
|
|
end
|
|
|
|
function saveλandP(name, λ, P, ws)
|
|
save(filename(name, :λ), "λ", λ)
|
|
save(filename(name, :P), "P", P)
|
|
save(filename(name, :warm), "warmstart", ws)
|
|
end
|
|
|
|
function loadλandP(name::String)
|
|
λ_fname = filename(name, :λ)
|
|
P_fname = filename(name, :P)
|
|
|
|
if exists(λ_fname) && exists(P_fname)
|
|
info("Loading precomputed λ, P...")
|
|
λ = load(λ_fname, "λ")
|
|
P = load(P_fname, "P")
|
|
else
|
|
throw("You need to precompute $λ_fname and $P_fname to load it!")
|
|
end
|
|
return λ, P
|
|
end
|