Skip to content

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]