GurobiSolver¶
A class for interfacing with gurobi to solve LPs
Methods¶
add_constraints(lp_problem, model)
staticmethod
¶
Add the constraints in a Flipy LpProblem to a gurobi model
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lp_problem |
LpProblem |
The Flipy object to grab the constraints from |
required |
model |
Model |
The gurobi model to add the constraints to |
required |
Source code in flipy/solvers/gurobi_solver.py
@staticmethod
def add_constraints(lp_problem: LpProblem, model: gurobipy.Model) -> None:
""" Add the constraints in a Flipy LpProblem to a gurobi model
Parameters
----------
lp_problem:
The Flipy object to grab the constraints from
model:
The gurobi model to add the constraints to
"""
for name, constraint in lp_problem.lp_constraints.items():
lhs_expr = [(coef, var.solver_var) for var, coef in constraint.lhs.expr.items()]
if constraint.slack:
lhs_expr += [((-1 if constraint.sense == 'leq' else 1), constraint.slack_variable.solver_var)]
lhs_expr = gurobipy.LinExpr(lhs_expr)
lhs_expr.addConstant(constraint.lhs.const)
rhs_expr = gurobipy.LinExpr([(coef, var.solver_var) for var, coef in constraint.rhs.expr.items()])
rhs_expr.addConstant(constraint.rhs.const)
if constraint.sense.lower() == 'leq':
relation = gurobipy.GRB.LESS_EQUAL
elif constraint.sense.lower() == 'geq':
relation = gurobipy.GRB.GREATER_EQUAL
else:
relation = gurobipy.GRB.EQUAL
constraint.solver_constraint = model.addConstr(lhs_expr, relation, rhs_expr, name)
model.update()
add_slack_variables(self, lp_problem, model)
¶
Add the slack variables in a Flipy LpProblem to a gurobi model
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lp_problem |
LpProblem |
The Flipy object to grab the constraints from |
required |
model |
Model |
The gurobi model to add the constraints to |
required |
Source code in flipy/solvers/gurobi_solver.py
def add_slack_variables(self, lp_problem: LpProblem, model: gurobipy.Model) -> None:
""" Add the slack variables in a Flipy LpProblem to a gurobi model
Parameters
----------
lp_problem:
The Flipy object to grab the constraints from
model:
The gurobi model to add the constraints to
"""
for _, constraint in lp_problem.lp_constraints.items():
if constraint.slack:
self.add_variable(constraint.slack_variable,
(-1 if lp_problem.lp_objective.sense == Maximize else 1) * constraint.slack_penalty,
model)
add_variable(var, obj_coef, model)
staticmethod
¶
Add a variable to the LP
Parameters:
Name | Type | Description | Default |
---|---|---|---|
var |
LpVariable |
The linear variable to add |
required |
obj_coef |
Union[int, float] |
The coefficient of the linear variable in the objective |
required |
model |
Model |
The gurobi model to add the variable to |
required |
Source code in flipy/solvers/gurobi_solver.py
@staticmethod
def add_variable(var: LpVariable, obj_coef: Numeric, model: gurobipy.Model) -> None:
""" Add a variable to the LP
Parameters
----------
var:
The linear variable to add
obj_coef:
The coefficient of the linear variable in the objective
model:
The gurobi model to add the variable to
"""
low_bound = var.low_bound
if low_bound is None:
low_bound = -gurobipy.GRB.INFINITY
up_bound = var.up_bound
if up_bound is None:
up_bound = gurobipy.GRB.INFINITY
if var.var_type == VarType.Continuous:
var_type = gurobipy.GRB.CONTINUOUS
else:
var_type = gurobipy.GRB.INTEGER
var.solver_var = model.addVar(low_bound, up_bound, vtype=var_type, obj=obj_coef, name=var.name)
add_variables(self, lp_variables, model)
¶
Add the variables in a Flipy LpProblem to a gurobi model
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lp_variables |
List[flipy.lp_variable.LpVariable] |
The Flipy object to grab the variables from |
required |
model |
Model |
The gurobi model to add the variables to |
required |
Source code in flipy/solvers/gurobi_solver.py
def add_variables(self, lp_variables: List[LpVariable], model: gurobipy.Model) -> None:
""" Add the variables in a Flipy LpProblem to a gurobi model
Parameters
----------
lp_variables:
The Flipy object to grab the variables from
model:
The gurobi model to add the variables to
"""
for var in lp_variables:
self.add_variable(var, var.obj_coeff, model)
model.update()
retrieve_values(lp_problem, lp_variables, model)
staticmethod
¶
Extract the value of variables from the gurobi model and set them into the Flipy objects
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lp_problem |
LpProblem |
The Flipy object into which the variable values will be set |
required |
lp_variables |
List[flipy.lp_variable.LpVariable] |
A list of LpVariables of the problem |
required |
model |
Model |
The gurobi model to grab the variable values from |
required |
Source code in flipy/solvers/gurobi_solver.py
@staticmethod
def retrieve_values(lp_problem: LpProblem, lp_variables: List[LpVariable], model: gurobipy.Model) -> None:
""" Extract the value of variables from the gurobi model and set them into the Flipy objects
Parameters
----------
lp_problem:
The Flipy object into which the variable values will be set
lp_variables:
A list of LpVariables of the problem
model:
The gurobi model to grab the variable values from
"""
try:
var_name_to_values = dict(
zip(
model.getAttr(gurobipy.GRB.Attr.VarName, model.getVars()),
model.getAttr(gurobipy.GRB.Attr.X, model.getVars())))
for var in lp_variables:
var.set_value(var_name_to_values[var.name])
for constraint in lp_problem.lp_constraints.values():
if constraint.slack:
constraint.slack_variable.set_value(var_name_to_values[constraint.slack_variable.name])
except (gurobipy.GurobiError, AttributeError):
pass
solve(self, lp_problem)
¶
Form and solve the LP, set the variables to their solution values.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lp_problem |
LpProblem |
The LP to solve |
required |
Exceptions:
Type | Description |
---|---|
Exception |
Raised when lp_problem is not an instance of LpProblem |
Returns:
Type | Description |
---|---|
SolutionStatus |
The status of the solution |
Source code in flipy/solvers/gurobi_solver.py
def solve(self, lp_problem: LpProblem) -> SolutionStatus:
""" Form and solve the LP, set the variables to their solution values.
Raises
------
Exception
Raised when lp_problem is not an instance of LpProblem
Parameters
----------
lp_problem:
The LP to solve
Returns
-------
flipy.SolutionStatus
The status of the solution
"""
model = gurobipy.Model(lp_problem.name)
model.setParam('MIPGap', self.mip_gap)
if self.timeout is not None:
model.setParam('TimeLimit', self.timeout)
if lp_problem.lp_objective and lp_problem.lp_objective.sense == Maximize:
model.setAttr("ModelSense", -1)
if not isinstance(lp_problem, LpProblem):
raise Exception('%s is not an LpProblem' % lp_problem)
if lp_problem.lp_objective.sense == Maximize:
model.setAttr("ModelSense", -1)
variables = list(lp_problem.lp_variables.values())
self.add_slack_variables(lp_problem, model)
self.add_variables(variables, model)
self.add_constraints(lp_problem, model)
model.optimize()
self.retrieve_values(lp_problem, variables, model)
return self.STATUS_MAPPING[model.Status]