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.
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).