Hi there JuMP-Crew
Given a symmetric matrix Q and the all ones matrix E and a set of vectors v_1,…,v_n called “Vertex_Set” and a set of two-tuples of these vectors (or rather their indices) called “Inclusion_Set”, I want to build the linear programming model
max z
subject to
Q-zE == S,
v_i’Sv_j >= 0, forall (i,j) in Inclusion_Set
S is a symmetric matrix variable
z is a scalar variable
This is a subproblem of an iterative algorithm (taken from An Adaptive Linear Approximation Algorithm for Copositive Programs – Optimization Online), where the Vertex_Set and Inclusion_set are updated in every iteration in a way so that the feasible region increases. I omit the details because they are not important to the question.
My problem is that much of the algorithm’s running time goes into the model creation. My implementation of the model building looks as follows
function Build_LP_Model( )
#1) Initialization and problem data-----------------------------------------------------------
# This would actually be function input, but I put it here for the sake
# of self-containment
n = 300
Q = randn(n,n)
Q = Q+Q'
E = ones(n,n)
Vertex_Set_Dict = Dict{Int64, @NamedTuple{vector::Vector{Float64}, parent1::Int64, parent2::Int64}}(
i => (
vector = LinearAlgebra.Diagonal(ones(n))[i,:],
parent1 = i,
parent2 = i
)
for i = 1:n
);
Inclusion_Set = [ (i,j) for i=1:n for j = i:n ]
#2) Construct Model-------------------------------------------------------------------
println("Constructing LP model")
@time begin
model = Model(Gurobi.Optimizer)
set_silent(model)
@variable(model, z)
@variable(model, S[i = 1:n, j = 1:n], Symmetric)
@objective(model, Max, z)
@constraint(model, Q-z*E == S)
println("Easy Part ends here ")
end
@time begin
Edge_con = Dict{Tuple{Int64, Int64},ConstraintRef}(
(i,j) => @constraint(
model,
Vertex_Set_Dict[i].vector'*S*Vertex_Set_Dict[j].vector >= 0
) for (i,j) in Inclusion_Set
)
println("Hard Part (Edge_con) ends here ")
end
return (model, Edge_con, S)
end
This will produce the output
Constructing LP model
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value ******
Academic license ***** - for non-commercial use only - registered to ******
Easy Part ends here
0.640964 seconds (2.30 M allocations: 159.583 MiB, 75.93% gc time, 8.38% compilation time)
Hard Part (Edge_con) ends here
43.991088 seconds (110.03 M allocations: 7.041 GiB, 2.21% gc
time)
(A JuMP Model
├ solver: Gurobi …
The problem is that building the inequality constraints takes almost a minute. Actually, solving the problem will take less than a fraction of a second. In the original paper, the authors have an implementation in C++ where the model building takes half a second (in 2009) for similarly sized problems (see Table 1 in the paper)
A couple of important notes:
- In every iteration there is an update on the Vertex_Set (only ever increases) and the Inclusion_Set (may lose and gain elements). Constraints will be added and deleted accordingly.
- Thus, it is important to keep track of the present constraints in what I call the Edge_Set_Dict.
- Data from the optimal solution as well as from all the sets mentioned above is used to update the respective sets, so all of it must be tracked as well.
My question is now the following
- Is there an obvious way in JuMP to speed up the model creation, in other words: Am I doing something stupid here?
- If there is no way to do it in JuMP, what would be an alternative in Julia and where can I read up on such an alternative?
Thank you for your help!