71 lines
2.0 KiB
Python
71 lines
2.0 KiB
Python
import gurobipy as gp
|
|
import numpy
|
|
|
|
class ILPopt():
|
|
"""
|
|
An integer linear programming (ILP) solver based on GUROBI
|
|
"""
|
|
|
|
def __init__(self, num_vars, obj, constrs=[]):
|
|
"""
|
|
Params:
|
|
- num_val: # of variables
|
|
- obj: tuple ("x[0] + 2 * x[1] - 4 * x[2]", "min/max")
|
|
- constr: list of tuples (expr, op, val)
|
|
- e.g. [("2 * x[0] - 3 * x[1]**2 + 6 * x[2]", ">=", "32"), ...]
|
|
- variables should only be x[0], x[1], ..., x[num_val - 1]
|
|
"""
|
|
self.model = gp.Model()
|
|
self.num_vars = num_vars
|
|
self.obj = obj
|
|
self.constrs = constrs
|
|
|
|
def optimize(self):
|
|
|
|
x = self.model.addVars(self.num_vars, vtype=gp.GRB.INTEGER) # Integers
|
|
self.vars = x
|
|
|
|
# Set objective
|
|
if self.obj[1] == "min":
|
|
self.model.setObjective(eval(self.obj[0]), gp.GRB.MINIMIZE)
|
|
elif self.obj[1] == "max":
|
|
self.model.setObjective(eval(self.obj[0]), gp.GRB.MAXIMIZE)
|
|
else:
|
|
raise Exception("obj[1] should be among 'max' and 'min'")
|
|
|
|
# Set constraints
|
|
for constr in self.constrs:
|
|
if constr[1] == ">":
|
|
self.model.addConstr(eval(constr[0]) > eval(constr[2]))
|
|
elif constr[1] == ">=":
|
|
self.model.addConstr(eval(constr[0]) >= eval(constr[2]))
|
|
elif constr[1] == "<":
|
|
self.model.addConstr(eval(constr[0]) < eval(constr[2]))
|
|
elif constr[1] == "<=":
|
|
self.model.addConstr(eval(constr[0]) <= eval(constr[2]))
|
|
else:
|
|
raise Exception("The constraint operator should be among '>', '>=', '<', '<='")
|
|
|
|
self.model.optimize()
|
|
|
|
def print_result(self):
|
|
print("############## Summarize Results ###############")
|
|
print(f"Optimal objective value: {self.model.objVal}")
|
|
print("Solution values:")
|
|
for i in range(self.num_vars):
|
|
print(f"x[{i}]={self.vars[i].X}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|