0

I need some way to cap the sum of integer variables to be 1 at max in a python cvxpy optimization task constraint.

What i do not want is to force the sum of the variables to be 1, I just need a function to cap the result of sum(x) to be 1 at max to use it in a constraint. What i want to model is a constraint like:

y[i] >= if sum(x) >= 1 then 1 else 0

y is a boolean variable and x need to be integer variables. I can't seem to find a solution to this problem. I have tried using the min and cvxpy.minimal functions

y[i] >= min(sum(x), 1)

and

y[i] >= cvxpy.minimal(sum(x), x[test])

where x[test] is always 1 per constraint, but both methods do not work. The first gives an error, because strict inequalities are not allowed and the second gives an error, that the constraint violates DCP.

The only thing i have found to be working is a little "hack" where I multiply the sum by 0.001 (the sum will never be larger than 1000 and therefore the result is always between 0 and 1)

y[i] >= sum(x) * 0.001

but this somehow completely breaks the solver and even problems with only a few constraints and variables (500, 100) seem to run endlessly. (30+ min still no solution) The maximum amount of variables with this "hack" are < 100 with a runtime of a few minutes, which is really unacceptable

____UPDATE for more clarification:

I want to have X Amount of Product Y and i know how much seller Z has in stock for Product Y. I also need to take into account shipping costs for each seller (fixed amount of 1) This problem is described very easily like this:

             Product1  Product2  Product3
seller1 has  3         4         5
seller2 has  0         1         10

wanted order 2         1         7

which equates to the problem (ignoring constraints x1 >= 0 for simplicity)

min 1*x1 + 1*x2 + 1*x3 + 1*x4 + 0.9*x5 + 0.95*x6 + y1 + y2
s.t. 
     x1 <= 3
     x2 <= 4
     x3 <= 5
     x4 <= 0
     x5 <= 1
     x6 <= 10
     x1 + x4 >= 2
     x2 + x5 >= 1
     x3 + x6 >= 7
     y1 >= if x1 + x2 + x3 > 0 then 1 else 0
     y2 >= if x4 + x5 + x6 > 0 then 1 else 0
Vlad de Elstyr
  • 83
  • 1
  • 2
  • 6

1 Answers1

0

If performance is bad, consider using a better MIP solver. CVXPY supports different solvers (some good, some are only useful for toy problems).

Secondly, it may be better to operate on the individual variables x[i,j] (say) than on the sum (this is called dis-aggregation). I.e.

y[i] = 0 => x[i,j] = 0 

or

x[i,j] <= 100*y[i] 

Of course we assume that we minimize y[i] (otherwise we would need to use a bidirectional implication).

So in your updated model we have:

y1 >= if x1 + x2 + x3 > 0 then 1 else 0

This can be modeled in disaggregated form as:

x1 <= 100*y1
x2 <= 100*y1
x3 <= 100*y1

or aggregated:

x1+x2+x3 <= 100*y1

Depending on the solver, the disaggregated version may work better (some advanced solvers recognize the aggregation structure).

From a modeling point of view, I would probably use y[i] and x[i,j] as variables. That is a bit more logical (to me).

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39
  • I have tried your inital post by adding another set of variables "b", but that did not work. It seems that multiplying with constants is too much for the solver :( To your most recent post: I want to minimize sum(x * prices) + sum(y). Basically wat i want to achieve with the constraint in my post is to add shipping costs (Variable y) => If I have one or more products from one seller (sum([x[1] + x[2]) + x[3] > 0) for example, than y[i] needs to be 1 (fixed shipping cost) I have clarified my initial post and added an example to make it more clear. – Vlad de Elstyr Dec 05 '19 at 11:43