Search code examples
or-toolsmixed-integer-programming

How to add indicator and SOS constraints in mathopt [Google OR-Tools]


I am struggling to add indicator and SOS constraints using mathopt library in or-tools. In the web-page it is mentioned that mathopt supports these specialised constraints, but I am not able to use them in my program. Below is a small dummy code, through which I want to use these constraints.

from ortools.math_opt.python import mathopt

model = mathopt.Model(name="MIP_model")
x_int = model.add_integer_variable(lb=0, ub=10, name="x_int")
x_sos_bool = model.add_binary_variable(name="x_sos_bool")
y_int = model.add_integer_variable(lb=0, ub=10, name="y_int")
y_sos_bool = model.add_binary_variable(name="y_sos_bool")
z_ind_bool = model.add_binary_variable(name="z_ind_bool")

model.add_linear_constraint(x_int + y_int <= 15)

# if z == 1 then x <= 5
# for now I have manually linearise like below.
big_M = 100
model.add_linear_constraint(z_ind_bool == 1)
model.add_linear_constraint(x_int - 5 <= big_M * (1 - z_ind_bool))

# x, y belongs to SOS 1 set
# again done manually like below
model.add_linear_constraint(x_sos_bool + y_sos_bool == 1)
model.add_linear_constraint(x_int - big_M * x_sos_bool <= 0)
model.add_linear_constraint(y_int - big_M * y_sos_bool <= 0)

model.maximize(x_int + y_int)

params = mathopt.SolveParameters(enable_output=True)
result = mathopt.solve(model, mathopt.SolverType.GSCIP, params=params)

print("x:", result.variable_values()[x_int]) # x_int: 0.0 (optimal sol)
print("y:", result.variable_values()[y_int]) # y_int: 10.0 (optimal sol)

Solution

  • They are supported in the C++ API but are not yet in the python API.

    If you really need to use this right now, you can try exporting your model to a protocol buffer:

    https://github.com/google/or-tools/blob/stable/ortools/math_opt/python/model.py#L1812

    Then adding the SOS constraint manually on the proto:

    https://github.com/google/or-tools/blob/stable/ortools/math_opt/model.proto#L295

    And then directly invoking solver.solve():

    https://github.com/google/or-tools/blob/stable/ortools/math_opt/python/solve.py#L77

    But I would not recommend this, it is brittle and likely to break on future changes to or-tools. Better to use big-M yourself, wait for the feature to arrive in Python MathOpt, or just use a different modeling library.