Skip to content

Commit c009cfc

Browse files
committed
Add benchmark against linopy and cvxpy
1 parent 2b7f928 commit c009cfc

File tree

2 files changed

+126
-20
lines changed

2 files changed

+126
-20
lines changed

bench/bench_linopy_cvxpy.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import time
2+
from numpy import arange
3+
import numpy as np
4+
import pandas as pd
5+
6+
from linopy import Model
7+
8+
import pyoptinterface as poi
9+
from pyoptinterface import gurobi
10+
11+
import cvxpy
12+
13+
14+
def create_linopy_model(N):
15+
m = Model()
16+
x = m.add_variables(coords=[arange(N), arange(N)])
17+
y = m.add_variables(coords=[arange(N), arange(N)])
18+
m.add_constraints(x - y >= arange(N))
19+
m.add_constraints(x + y >= 0)
20+
m.add_objective((2 * x).sum() + y.sum())
21+
return m
22+
23+
24+
def create_cvxpy_model(N):
25+
x = cvxpy.Variable((N, N))
26+
y = cvxpy.Variable((N, N))
27+
constraints = []
28+
for i in range(N):
29+
constraints.append(x[:, i] - y[:, i] >= np.arange(N))
30+
constraints.append(x + y >= 0)
31+
objective = cvxpy.Minimize(2 * cvxpy.sum(x) + cvxpy.sum(y))
32+
return cvxpy.Problem(objective, constraints)
33+
34+
35+
def create_poi_model(N):
36+
m = gurobi.Model()
37+
x = m.add_variables(range(N), range(N))
38+
y = m.add_variables(range(N), range(N))
39+
for i in range(N):
40+
for j in range(N):
41+
m.add_linear_constraint(x[i, j] - y[i, j], poi.Geq, i)
42+
m.add_linear_constraint(x[i, j] + y[i, j], poi.Geq, 0)
43+
expr = poi.ExprBuilder()
44+
poi.quicksum_(expr, x, lambda x: 2 * x)
45+
poi.quicksum_(expr, y)
46+
m.set_objective(expr)
47+
return m
48+
49+
50+
def bench(N):
51+
results = {}
52+
53+
t0 = time.time()
54+
model = create_poi_model(N)
55+
model.optimize()
56+
t1 = time.time()
57+
results["n_variables"] = 2 * N * N
58+
results["poi"] = t1 - t0
59+
60+
t0 = time.time()
61+
model = create_linopy_model(N)
62+
model.solve(solver_name="gurobi", io_api="direct")
63+
t1 = time.time()
64+
results["linopy"] = t1 - t0
65+
66+
t0 = time.time()
67+
model = create_cvxpy_model(N)
68+
model.solve(solver=cvxpy.GUROBI)
69+
t1 = time.time()
70+
results["cvxpy"] = t1 - t0
71+
72+
return results
73+
74+
75+
def main():
76+
Ns = range(100, 501, 100)
77+
results = []
78+
for N in Ns:
79+
results.append(bench(N))
80+
# create a DataFrame
81+
df = pd.DataFrame(results, index=Ns)
82+
83+
# show result
84+
print(df)
85+
86+
87+
if __name__ == "__main__":
88+
main()

docs/source/benchmark.md

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,50 @@ All code to run the benchmarks is available at [https://github.com/metab0t/PyOpt
88
:widths: auto
99
:align: center
1010

11-
| Model | Variables | C++ | PyOptInterface | JuMP | gurobipy | Pyomo |
12-
|----------|-----------|-----|----------------|------|----------|-------|
13-
| fac-25 | 67651 | 0.2 | 0.2 | 0.2 | 1.2 | 4.1 |
14-
| fac-50 | 520301 | 0.8 | 1.2 | 1.8 | 9.7 | 32.7 |
15-
| fac-75 | 1732951 | 2.7 | 4.1 | 6.6 | 32.5 | 119.3 |
16-
| fac-100 | 4080601 | 6.3 | 10.0 | 17.8 | 79.1 | 286.3 |
17-
| lqcp-500 | 251501 | 0.9 | 1.5 | 1.3 | 6.3 | 23.8 |
18-
| lqcp-1000| 1003001 | 3.7 | 6.0 | 6.1 | 26.7 | 106.6 |
19-
| lqcp-1500| 2254501 | 8.3 | 14.0 | 17.7 | 61.8 | 234.0 |
20-
| lqcp-2000| 4006001 | 14.5| 24.9 | 38.3 | 106.9 | 444.1 |
11+
| Model | Variables | C++ | PyOptInterface | JuMP | gurobipy | Pyomo |
12+
| --------- | --------- | ---- | -------------- | ---- | -------- | ----- |
13+
| fac-25 | 67651 | 0.2 | 0.2 | 0.2 | 1.2 | 4.1 |
14+
| fac-50 | 520301 | 0.8 | 1.2 | 1.8 | 9.7 | 32.7 |
15+
| fac-75 | 1732951 | 2.7 | 4.1 | 6.6 | 32.5 | 119.3 |
16+
| fac-100 | 4080601 | 6.3 | 10.0 | 17.8 | 79.1 | 286.3 |
17+
| lqcp-500 | 251501 | 0.9 | 1.5 | 1.3 | 6.3 | 23.8 |
18+
| lqcp-1000 | 1003001 | 3.7 | 6.0 | 6.1 | 26.7 | 106.6 |
19+
| lqcp-1500 | 2254501 | 8.3 | 14.0 | 17.7 | 61.8 | 234.0 |
20+
| lqcp-2000 | 4006001 | 14.5 | 24.9 | 38.3 | 106.9 | 444.1 |
2121

2222
:::
2323

2424
:::{table} Time (second) to generate model and pass it to COPT optimizer.
2525
:widths: auto
2626
:align: center
2727

28-
| Model | Variables | C++ | PyOptInterface | JuMP | coptpy | Pyomo |
29-
|----------|-----------|-----|----------------|------|--------|-------|
30-
| fac-25 | 67651 | 0.3 | 0.2 | 0.3 | 0.6 | 4.1 |
31-
| fac-50 | 520301 | 2.2 | 1.5 | 2.7 | 5.4 | 32.8 |
32-
| fac-75 | 1732951 | 8.1 | 6.6 | 10.2 | 20.3 | 117.4 |
33-
| fac-100 | 4080601 | 22.4| 23.4 | 30.3 | 58.0 | 284.0 |
34-
| lqcp-500 | 251501 | 3.8 | 3.1 | 3.0 | 6.6 | 26.4 |
35-
| lqcp-1000| 1003001 | 16.0| 15.5 | 13.9 | 28.1 | 112.1 |
36-
| lqcp-1500| 2254501 | 37.6| 32.4 | 33.7 | 64.6 | 249.3 |
37-
| lqcp-2000| 4006001 | 68.2| 60.3 | 66.2 | 118.4 | 502.4 |
28+
| Model | Variables | C++ | PyOptInterface | JuMP | coptpy | Pyomo |
29+
| --------- | --------- | ---- | -------------- | ---- | ------ | ----- |
30+
| fac-25 | 67651 | 0.3 | 0.2 | 0.3 | 0.6 | 4.1 |
31+
| fac-50 | 520301 | 2.2 | 1.5 | 2.7 | 5.4 | 32.8 |
32+
| fac-75 | 1732951 | 8.1 | 6.6 | 10.2 | 20.3 | 117.4 |
33+
| fac-100 | 4080601 | 22.4 | 23.4 | 30.3 | 58.0 | 284.0 |
34+
| lqcp-500 | 251501 | 3.8 | 3.1 | 3.0 | 6.6 | 26.4 |
35+
| lqcp-1000 | 1003001 | 16.0 | 15.5 | 13.9 | 28.1 | 112.1 |
36+
| lqcp-1500 | 2254501 | 37.6 | 32.4 | 33.7 | 64.6 | 249.3 |
37+
| lqcp-2000 | 4006001 | 68.2 | 60.3 | 66.2 | 118.4 | 502.4 |
3838

3939
:::
40+
41+
Recently, there are a lot of requests to test the performance of PyOptInterface compared with [linopy]([https://gith](https://github.com/PyPSA/linopy) and [cvxpy](https://github.com/cvxpy/cvxpy), so we prepare a [benchmark](https://github.com/metab0t/PyOptInterface/blob/master/bench/bench_linopy_cvxpy.py).
42+
43+
This is the result of benchmark, where the performance of PyOptInterface exceeds linopy and cvxpy significantly.
44+
45+
:::{table} Time (second) to generate and solve a linear programming model with Gurobi optimizer.
46+
:widths: auto
47+
:align: center
48+
49+
| N | Variables | PyOptInterface | linopy | cvxpy |
50+
| --- | --------- | -------------- | -------- | --------- |
51+
| 100 | 20000 | 0.112849 | 0.422408 | 0.373407 |
52+
| 200 | 80000 | 0.294830 | 1.118702 | 1.575949 |
53+
| 300 | 180000 | 0.710237 | 2.462809 | 4.038862 |
54+
| 400 | 320000 | 1.256276 | 4.535225 | 8.687895 |
55+
| 500 | 500000 | 2.189127 | 8.243707 | 18.941519 |
56+
57+
:::

0 commit comments

Comments
 (0)