3

I'm trying to force a variable to be an integer (integer constraint) using cvxpy in Python, but result keeps being a float:

from cvxpy import *

Fi = Int() 
Or = Int()

constr = [Fi <= 3000,
                 Or <= 3000,
                 Or >= 1000,
                 1.25*Or - Fi >= 0,
                 Fi >= 0,
                 Or >= 0]

obj= Maximize(50000*Fi + 25000*Or)

prob = Problem(obj, constr)
prob.solve()

print ("Status: ", prob.status)

print ("Fi: ", Fi.value)
print ("Or: ", Or.value)

print ("Obj: ", obj.value)

Result:

Status:  optimal
Fi:  2999.9999999
Or:  2999.99999989
Obj:  224999999.992

What can I do to force it?

I have tried too:

Fi = Variable() 
Or = Variable()

constr = [Fi <= 3000,
                 Or <= 3000,
                 Or >= 1000,
                 1.25*Or - Fi >= 0,
                 Fi >= 0,
                 Or >= 0,
                 Fi == Int(),
                 Or == Int()]

Fi and Or are variables. Not just numbers.

Aleharu
  • 170
  • 1
  • 9
  • @nico I have tried too `Fi=Variable()` and add constraint `Fi == Int()` and i'ts not duplicate. In that question they're not using cvxpy – Aleharu Apr 03 '17 at 21:37
  • On your constraint, 1.25*. How do you expect the result to be Int? http://www.cvxpy.org/en/latest/tutorial/intro/index.html – ADL Apr 03 '17 at 21:53
  • @ADL Fi can't be more than de 125% of Or. It doesn't imply that Fi has to be float – Aleharu Apr 03 '17 at 22:59
  • @Aleharu, I had the same problem (with many more variables)! I think cvxpy stores solutions as `numpy.matrix` variables to save space, which kind of casts every solutions as a float. I simply thresholded my output to cast as int: `np.matrix([0 if abs(el)<.99999 else 1 for el in x.value])` – Zach Siegel Jul 19 '17 at 16:22

1 Answers1

1

I had the same problem (with many more variables)! I think cvxpy stores solutions as numpy.matrix variables to save space, which kind of casts every solutions as a float. I simply thresholded my output to cast as int. This should work for you:

Fi_val = int(Fi.value)+(1 if (Fi.value - int(Fi.value)) >0.9 else 0)
Or_val =  int(Or.value)+(1 if (Or.value - int(Or.value)) >0.9 else 0)

There are better ways to get the fractional part of an integer x than x-int(x) (such as Math.modf(x) and numpy.modf(x)), but this requires no package imports.

Note that you can threshold at 0.9999999999 rather than just 0.9. The output of cvxpy seems to be an int up to almost the full precision of a numpy matrix float.

(If anyone can make this idea more precise, please do).

Zach Siegel
  • 330
  • 2
  • 9