-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Explore PytOptInferface for writing matrix over native C API #271
Comments
Thanks for your attention! @pz-max |
I made a minimal example here to build the model described in link. On my computer, the output is:
I am afraid that using PyOptInterface will not accelerate linopy because PyOptInterface does not have shortcut to create variables or constraints in bulk. I haven't profiled the code to find the time-consuming step, do you have any clues? |
@metab0t We would be keen to explore possibilities. Would you be free for a 30-minute exchange with @FabianHofmann (linopy maintainer) and me? If yes, could you ping me per email: max.parzen(at)openenergytransition.org with few time suggestions that are EU friendly? :) |
@pz-max I have sent you an email for arrangement of time. Have you received it? |
So this has potential of abstracting things in io module of linopy (where magic of translating linopy model into solver specific one happens)? |
After profiling, I think that the bottleneck is in the import time
from numpy import arange
from linopy import Model
import pyoptinterface as poi
from pyoptinterface import gurobi
def access_matrix(m):
M = m.matrices
vlabels = M.vlabels
names = "x" + vlabels.astype(str).astype(object)
vtypes = M.vtypes
lb = M.lb
ub = M.ub
if m.is_quadratic:
Q = M.Q
c = M.c
A = M.A
clabels = M.clabels
sense = M.sense
b = M.b
names = "c" + clabels.astype(str).astype(object)
def create_model(N):
m = Model()
x = m.add_variables(coords=[arange(N), arange(N)])
y = m.add_variables(coords=[arange(N), arange(N)])
m.add_constraints(x - y >= arange(N))
m.add_constraints(x + y >= 0)
m.add_objective((x * x).sum() + y.sum())
return m
def create_poi_model(N):
m = gurobi.Model()
x = m.add_variables(range(N), range(N))
y = m.add_variables(range(N), range(N))
for i in range(N):
for j in range(N):
m.add_linear_constraint(x[i, j] - y[i, j], poi.Geq, i)
m.add_linear_constraint(x[i, j] + y[i, j], poi.Geq, 0)
expr = poi.ExprBuilder()
poi.quicksum_(expr, x, lambda x: 2 * x)
poi.quicksum_(expr, y)
m.set_objective(expr)
return m
N = 1000
t0 = time.time()
model = create_model(N)
t1 = time.time()
print('Time to create linopy model:', t1 - t0)
t0 = time.time()
access_matrix(model)
t1 = time.time()
print('Time to access matrices:', t1 - t0)
t0 = time.time()
raw_model = model.to_gurobipy()
t1 = time.time()
print('Time to convert to gurobipy model:', t1 - t0)
t0 = time.time()
raw_model = create_poi_model(N)
t1 = time.time()
print('Time to create poi model:', t1 - t0) The output:
More than half of the time is spent on constructing the matrix. The time spent on gurobipy (14.52 - 8.10 = 6.42s) is quite close to the time to build model in POI, so it is unlikely to be reduced significantly. It also reflects the performance of POI where the sequential construction of POI is only slightly slower than the bulk construction with addMVar/addMConstr of gurobipy. |
Summary of exchange:
|
@pz-max @FabianHofmann
In fact, the bottleneck is in the step 1. Gurobipy has done a good job in step 2 and swapping it with POI will not have significant influence on the performance even if POI implements adding variables/constraints in bulk. What do you think about it? |
See also some related discussion in #207 |
Background
Linopy either constructs a big matrix itself and stores it in a standardized file format such as the “LP” or the “MPS” file format or writes the matrix through direct Python solver interfaces. Linopy uses xarray and, therefore, has good memory and speed performance in creating the matrix/lp files. The syntax is also easier to read compared to Jump.
PyOptInterface was just released now (April 2024) by @metab0t and its benchmark shows that the speed in constructing the matrix is comparable to Jump.
Explore
Can we use PyOptInterface within Linopy to speed up the matrix construction?
The text was updated successfully, but these errors were encountered: