I solved an IP problem in PySCIPOpt and also solved the same problem in Julia and found the solution time was strikingly different. Julia solved the problem in 25 secs using Cbc while PySCIPOpt took 198 seconds using the inbuilt solver. While running the code line by line I found that most of the time was spent in the problem formulation part in PySCIPOpt compared to actually solving it. I was wondering if this is something expected or if there are some methods of making this more efficient (or comparable to Julia performance).
Edit: Below is the formulation I have.
model=Model("Route_Selection")
start_time=time.clock()
x={}
for j in range(J):
x[j]=model.addVar(vtype = 'B', name = 'x (%s)' %j)
y={}
for i in range(I):
y[i]=model.addVar(vtype='C', name = 'y (%s)' %i)
model.setObjective(quicksum(C[j]*x[j] for j in range(J))+ M* quicksum(y[i] for i in range(I)), "minimize")
for i in range(I):
model.addCons(quicksum(A_mat[i,j]*x[j] for j in range(J))+y[i] ==1, name='coverage of (%s)' %i)
model.addCons(quicksum(x[j] for j in range(J))<= N, name = 'vehicle constraint')
model.optimize()
print (time.clock()-start_time, "seconds")
It turns out exploiting the sparsity of matrix A makes the model build much faster. The following edit to the code made it run much faster.
model=Model("Route_Selection")
start_time=time.clock()
x={}
for j in range(J):
x[j]=model.addVar(vtype = 'B', name = 'x (%s)' %j)
y={}
for i in range(I):
y[i]=model.addVar(vtype='C', name = 'y (%s)' %i)
model.setObjective(quicksum(C[j]*x[j] for j in range(J))+ M* quicksum(y[i] for i in range(I)), "minimize")
from scipy.sparse import csr_matrix #added line 1
B=csr_matrix(A_mat) #added line 2
for i in range(I):
start=B.indptr[i] #added line 3
end=B.indptr[i+1] #added line 4
model.addCons(quicksum(x[j] for j in B.indices[start:end])+y[i] ==1, name='coverage of (%s)' %i) #edited line 5
model.addCons(quicksum(x[j] for j in range(J))<= N, name = 'vehicle constraint')
model.optimize()
print (time.clock()-start_time, "seconds")
Added: Here is the Julia code for the reference. The solving time comparison is about 17secs for PySCIPOpt and about 22 secs for Julia.
tic()
Routing=Model(solver=CbcSolver(logLevel=0))
#Variables
@variable(Routing, X[j=1:J], Bin)
@variable(Routing, Y[i=1:I], Bin)
#Objective
@objective(Routing, Min, sum(C[j]*X[j] for j=1:J)+sum(M*Y[i] for i=1:I))
#Constraints
A=sparse(A_mat)
@constraint(Routing, consRef[i=1:I], sum(A[i,j]*X[j] for j=1:J)+Y[i]==1)
@constraint(Routing, sum(X[j] for j=1:J)<=N)
solve(Routing)
toc()