Forum Discussion
FICO
5 years agoCommunity Manager
Bug report: addVariable() has quadratic time complexity on QCQP's
Hi,
I'm using the Python API of Xpress and I noticed that addVariable() has quadratic time complexity when the problem is a QCQP. This code here demonstrates the issue:
import timeit
def create_qcqp(size):
import xpress as xp
p = xp.problem()
for i in range(size):
v = xp.var(name=f"v{i}")
w = xp.var(name=f"w{i}")
p.addVariable(v, w)
p.addConstraint(v ** 2 + w ** 2 <= 0) # make problem a QCQP
print(f"{'NUM_VARS':>10}: {'TIME':>10}")
for size in [2000 * (2 ** i) for i in range(10)]:
runtime = timeit.timeit(lambda: create_qcqp(size), number=1)
print(f"{size:>10,}: {runtime:>10.3f}")The output is:
NUM_VARS: TIME
2,000: 0.056
4,000: 0.103
8,000: 0.285
16,000: 0.844
32,000: 3.634
64,000: 29.386
128,000: 164.903Clearly, the run-time grows quadratically (or maybe even cubic) with the number of variable. I suppose this is a bug, since I expect the time to grow linearly, since I'm only adding independent variables which are not linked by any constraints.
The problem exists for QCQP only, for the following LP
import timeit
def create_lp(size):
import xpress as xp
p = xp.problem()
for i in range(size):
v = xp.var(name=f"v{i}")
w = xp.var(name=f"w{i}")
p.addVariable(v, w)
p.addConstraint(v + w <= 0)
print(f"{'NUM_VARS':>10}: {'TIME':>10}")
for size in [2000 * (2 ** i) for i in range(10)]:
runtime = timeit.timeit(lambda: create_lp(size), number=1)
print(f"{size:>10,}: {runtime:>10.3f}")the output is
NUM_VARS: TIME
2,000: 0.045
4,000: 0.073
8,000: 0.109
16,000: 0.215
32,000: 0.438
64,000: 0.896
128,000: 1.801
256,000: 3.620
512,000: 7.302
1,024,000: 15.110which is fine as the runtime grows linear with the problem size.
A line-by-line profiler shows that addVariable is the problem:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 @profile
4 def func():
5 1 1.0 1.0 0.0 size = 64000
6
7 1 230.0 230.0 0.0 p = xp.problem()
8 64001 49543.0 0.8 0.2 for i in range(size):
9 64000 216261.0 3.4 0.7 v = xp.var(name=f"v{i}")
10 64000 83085.0 1.3 0.3 w = xp.var(name=f"w{i}")
11 64000 27572217.0 430.8 94.0 p.addVariable(v, w)
12 64000 1409492.0 22.0 4.8 p.addConstraint(v ** 2 + w ** 2 <= 0)
3 Replies
- FICOCommunity Manager
Thanks Michaja. It is a performance issue that is due to the extra overhead we need in order to link variables with quadratic constraints---it is indeed within the getVariable() call that most of the time is spent. We will fix this issue in a future release, but please note that for efficiency it would be far better to aggregate both the generation of variables and the insertion of constraints, as in the following code:
def create_qcqp(size): import xpress as xp p = xp.problem() x = [[xp.var(name=f"v{i}"), xp.var(name=f"w{i}")] for i in range(size)] p.addVariable(x) p.addConstraint(x[i][0]**2 + x[i][1]**2 <= 0 for i in range(size))These are the times I get using your script with the modified function above (on a decent laptop):
2,000: 0.020 4,000: 0.039 8,000: 0.077 16,000: 0.152 32,000: 0.301 64,000: 0.619 128,000: 1.271 256,000: 2.700 512,000: 5.643 1,024,000: 11.469 - FICOCommunity Manager
Thanks for the reply!
Manually aggregating variables and constraints is very cumbersome, if the problem is complicated and distributed over dozens of source files (which it is in my case). Great if the addVariable function can be fixed to have constant-time overhead, so that aggregation is not that critical.
For the time being I will wrap the Xpress problem class and do the aggregation in the wrapper, so that I don't have to change all my existing code.
- FICOCommunity Manager
Hi, it's understandable that some modifications can't be made in bulk, so your workaround is for now ideal.
Related Content
Related Content
Quadratic Optimization
Hello! I have the following problem: I want to minimize a least square problem with restrictions using quadratic module from xpress MP. The model has the following form: F:=sum(i in 1..N) (y(i)-...14 years agoPlace FICO® Xpress Optimization ForumFICO® Xpress Optimization Forum1 unread comment1 unread0Views0likes1CommentMixed-Integer Quadratically-Constrained Programming (MIQCP)
Hello, I would like to solve a MIQCP problem in Xpress Python Interface, but I cannot find the online document prescribing the noticeble points need to be pay attention prior to solving such type of...7 years agoPlace FICO® Xpress Optimization ForumFICO® Xpress Optimization Forum4 unread comments4 unread0Views0likes4CommentsIs it possible to disable the implicit factor of 0.5 in the optimization objectives quadratic part?
Through trial and error, I figured out, that the XPress optimizer is using an implicit factor of 0.5 in the quadratic part of the optimization objective (which doesn't show up in the mps dumps btw.) ...3 years agoPlace FICO® Xpress Optimization ForumFICO® Xpress Optimization Forum4 unread comments4 unread0Views0likes4Comments