Search code examples
mathematical-optimizationlinear-programminggurobimixed-integer-programming

How to add a rounding constraint which takes floor value of 2 floats decision variable - Gurobi


Is there a way to introduce a rounding constraint, something on the following lines : v = floor(x * y), where x, y are continuous decision variables and v is an integer decision variable. Essentially want to cast multiplication of continuous decision variable to integer. I am using Gurobi solver.


Solution

  • Above can be achieved by adding following inequality constraints:

    v <= x*y <= v + 1
    

    With help of above inequalities, v would be rounded down to the value of x*y. This would work perfectly if x*y is a float, however, if x*y is an integer say, 6, then v could be either be 5 or 6. To avoid such cases, one could introduce a small constant tolerance e > 0 and apply it to one of the inequalities.

    Below is a short code snippet to demonstrate the above reasoning:

    import gurobipy as gp
    from gurobipy import GRB
    
    m = gp.Model()
    
    x = m.addVar(vtype = GRB.CONTINUOUS, ub = 5)
    y = m.addVar(vtype = GRB.CONTINUOUS, ub = 8)
    
    int_var = m.addVar(vtype = GRB.INTEGER)
    
    # fix x, y to some float values.
    # x*y = 27.8695, so int_var should = 27, post solve 
    m.addConstr(x == 4.01)
    m.addConstr(y == 6.95)
    
    e = 0.00001
    
    m.addConstr(x*y >= int_var - e)
    m.addConstr(x*y <= int_var + 1 - e)
    
    # dummy objective, since x and y are already fixed
    m.setObjective(x*y, sense = GRB.MAXIMIZE)
    
    m.optimize()
    

    Indeed, int_var resolves to 27 which is the floor of x*y = 27.8695. If you take x*y=24, the int_var will resolve to 24 (which is expected behaviour, per small tolerance e taken above.