2017-03-13 14:49:55 +01:00
|
|
|
using JuMP
|
|
|
|
import MathProgBase: AbstractMathProgSolver
|
|
|
|
|
2017-04-17 15:23:36 +02:00
|
|
|
function create_product_matrix{T}(basis::Vector{T}, limit; twisted=true)
|
2017-03-13 14:49:55 +01:00
|
|
|
product_matrix = zeros(Int, (limit,limit))
|
2017-03-26 16:22:51 +02:00
|
|
|
basis_dict = Dict{T, Int}(x => i
|
2017-03-13 14:49:55 +01:00
|
|
|
for (i,x) in enumerate(basis))
|
|
|
|
for i in 1:limit
|
2017-04-17 15:23:36 +02:00
|
|
|
if twisted
|
|
|
|
x = inv(basis[i])
|
|
|
|
else
|
|
|
|
x = basis[i]
|
|
|
|
end
|
2017-03-13 14:49:55 +01:00
|
|
|
for j in 1:limit
|
2017-04-17 15:23:36 +02:00
|
|
|
w = x*basis[j]
|
2017-03-13 14:49:55 +01:00
|
|
|
product_matrix[i,j] = basis_dict[w]
|
|
|
|
# index = findfirst(basis, w)
|
|
|
|
# index ≠ 0 || throw(ArgumentError("Product is not supported on basis: $w"))
|
|
|
|
# product_matrix[i,j] = index
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return product_matrix
|
|
|
|
end
|
|
|
|
|
2017-04-17 15:23:36 +02:00
|
|
|
create_product_matrix{T}(basis::Vector{T}; twisted=twisted) = create_product_matrix(basis, length(basis); twisted=twisted)
|
|
|
|
|
2017-03-13 14:49:55 +01:00
|
|
|
function constraints_from_pm(pm, total_length)
|
|
|
|
n = size(pm,1)
|
|
|
|
constraints = constraints = [Array{Int,1}[] for x in 1:total_length]
|
|
|
|
for j in 1:n
|
2017-03-14 16:42:04 +01:00
|
|
|
for i in 1:n
|
2017-03-13 14:49:55 +01:00
|
|
|
idx = pm[i,j]
|
|
|
|
push!(constraints[idx], [i,j])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return constraints
|
|
|
|
end
|
|
|
|
|
|
|
|
constraints_from_pm(pm) = constraints_from_pm(pm, maximum(pm))
|
|
|
|
|
|
|
|
function splaplacian_coeff(S, basis, n=length(basis))
|
|
|
|
result = spzeros(n)
|
|
|
|
result[1] = float(length(S))
|
|
|
|
for s in S
|
|
|
|
ind = findfirst(basis, s)
|
|
|
|
result[ind] += -1.0
|
|
|
|
end
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
|
|
|
|
function laplacian_coeff(S, basis)
|
|
|
|
return full(splaplacian_coeff(S,basis))
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2017-05-16 18:53:25 +02:00
|
|
|
function create_SDP_problem(matrix_constraints, Δ::GroupRingElem; upper_bound=Inf)
|
|
|
|
N = size(parent(Δ).pm, 1)
|
2017-03-17 16:27:01 +01:00
|
|
|
Δ² = Δ*Δ
|
2017-05-28 20:01:52 +02:00
|
|
|
@assert length(Δ.coeffs) == length(matrix_constraints)
|
2017-03-13 14:49:55 +01:00
|
|
|
m = JuMP.Model();
|
2017-04-01 15:21:57 +02:00
|
|
|
JuMP.@variable(m, P[1:N, 1:N], SDP)
|
|
|
|
JuMP.@SDconstraint(m, P >= 0)
|
|
|
|
JuMP.@constraint(m, sum(P[i] for i in eachindex(P)) == 0)
|
2017-03-20 21:41:12 +01:00
|
|
|
|
2017-03-13 14:49:55 +01:00
|
|
|
if upper_bound < Inf
|
2017-04-01 15:21:57 +02:00
|
|
|
JuMP.@variable(m, 0.0 <= λ <= upper_bound)
|
2017-03-20 21:41:12 +01:00
|
|
|
else
|
2017-04-01 15:21:57 +02:00
|
|
|
JuMP.@variable(m, λ >= 0)
|
2017-03-13 14:49:55 +01:00
|
|
|
end
|
|
|
|
|
2017-05-16 18:53:25 +02:00
|
|
|
for (pairs, δ², δ) in zip(matrix_constraints, Δ².coeffs, Δ.coeffs)
|
2017-04-01 15:21:57 +02:00
|
|
|
JuMP.@constraint(m, sum(P[i,j] for (i,j) in pairs) == δ² - λ*δ)
|
2017-03-13 14:49:55 +01:00
|
|
|
end
|
2017-03-20 21:41:12 +01:00
|
|
|
|
2017-04-01 15:21:57 +02:00
|
|
|
JuMP.@objective(m, Max, λ)
|
2017-03-20 21:41:12 +01:00
|
|
|
|
2017-03-13 14:49:55 +01:00
|
|
|
return m
|
|
|
|
end
|
|
|
|
|
|
|
|
function solve_SDP(SDP_problem, solver)
|
2017-03-16 09:35:32 +01:00
|
|
|
JuMP.setsolver(SDP_problem, solver)
|
2017-03-15 18:16:53 +01:00
|
|
|
info(logger, Base.repr(SDP_problem))
|
2017-03-13 14:49:55 +01:00
|
|
|
|
|
|
|
# @time MathProgBase.writeproblem(SDP_problem, "/tmp/SDP_problem")
|
2017-03-16 09:35:32 +01:00
|
|
|
out = STDOUT
|
2017-03-22 13:24:17 +01:00
|
|
|
|
|
|
|
# to change buffering mode of stdout to _IOLBF (line bufferin)
|
|
|
|
# see https://github.com/JuliaLang/julia/issues/8765
|
|
|
|
ccall((:printf, "libc"), Int, (Ptr{UInt8},), "\n");
|
|
|
|
|
2017-03-20 22:12:10 +01:00
|
|
|
o = redirect_stdout(solver_logger.handlers["solver_log"].io)
|
2017-03-16 09:35:32 +01:00
|
|
|
|
2017-03-17 16:32:20 +01:00
|
|
|
t = @timed solution_status = JuMP.solve(SDP_problem)
|
|
|
|
info(logger, timed_msg(t))
|
2017-03-16 15:37:52 +01:00
|
|
|
Base.Libc.flush_cstdio()
|
2017-03-16 09:35:32 +01:00
|
|
|
|
2017-03-16 15:37:52 +01:00
|
|
|
redirect_stdout(o)
|
2017-03-13 14:49:55 +01:00
|
|
|
|
|
|
|
if solution_status != :Optimal
|
2017-03-15 17:52:22 +01:00
|
|
|
warn(logger, "The solver did not solve the problem successfully!")
|
2017-03-13 14:49:55 +01:00
|
|
|
end
|
2017-03-15 17:51:13 +01:00
|
|
|
info(logger, solution_status)
|
2017-03-13 14:49:55 +01:00
|
|
|
|
2017-04-01 15:21:57 +02:00
|
|
|
λ = JuMP.getvalue(JuMP.getvariable(SDP_problem, :λ))
|
|
|
|
P = JuMP.getvalue(JuMP.getvariable(SDP_problem, :P))
|
|
|
|
return λ, P
|
2017-03-13 14:49:55 +01:00
|
|
|
end
|