Source code for pylp.problem

"""
Contains functionality for dealing with a linear programming model.
"""
from typing import Iterable
from collections import namedtuple

import pulp
from contexttimer import Timer

from pylp.constraint import Constraint
import warnings


if pulp.__version__ >= '2.1':
    import pulp.apis.cplex_api as cplex
    import pulp.apis.glpk_api as glpk
    import pulp.apis.choco_api as choco
    import pulp.apis.gurobi_api as gurobi
    import pulp.apis.coin_api as coin
else:
    import pulp.solvers as solvers
    warnings.warn('You are using pulp 2.0 or lower, pulp.apis.core has been changed to pulp.sovers automatically')

Status = namedtuple("Status", ["status", "time"])


[docs] def solve( *, objective=None, constraints: Iterable[Constraint] = None, minimize: bool = False, solver: str = "glpk", verbose: bool = False, options: list = None, solver_path: str = None, **kwargs, ) -> Status: """ Solve the linear programming problem. Args: objective: The objective function constraints: The collection of constraints minimize: True for minimizing; False for maximizing solver: The solver to use. Current supports 'glpk', 'theo-cluster' and 'cplex'. verbose: If True, output the results of the solver options list: add options to the (glpk) solver **kwargs: is used to set the cluster path Returns: A tuple of the status (eg: Optimal, Unbounded, etc.) and the elapsed time solver: theo-cluster This is a specific version of the code to do cluster submission. """ if minimize: sense = pulp.LpMinimize else: sense = pulp.LpMaximize problem = pulp.LpProblem(sense=sense) # Objective function is added first problem += objective.construct() if constraints: for constraint in constraints: problem += constraint.construct() if solver == "glpk": if solver_path!=None: solver = glpk.GLPK(msg=verbose, path=solver_path, options=options) else: print("solver_path is not set, going to default, without options") # This catches the error if glpk_path is not set solver = glpk.GLPK(msg=verbose) elif solver == "glpk-cluster": if solver_path!=None: solver = glpk.GLPK(msg=verbose, path=solver_path, options=options) else: print("solver_path is not set, going to default.") # This catches the error if glpk_path is not set solver = glpk.GLPK(msg=verbose, path="/home/theochri/ENV/bin/glpsol") elif solver == "cplex": solver = cplex.CPLEX(msg=verbose) elif solver == "gurobi": if solver_path!=None: solver = gurobi.GUROBI_CMD(msg=verbose,path=solver_path) else: solver = gurobi.GUROBI_CMD(msg=verbose) elif solver == "cbc": if solver_path!=None: solver = coin.PULP_CBC_CMD(msg=verbose,path=solver_path) else: solver = coin.PULP_CBC_CMD(msg=verbose) elif solver == "coin": if solver_path!=None: solver = coin.COIN_CMD(msg=verbose,path=solver_path) else: solver = coin.COIN_CMD(msg=verbose) elif solver == "choco": if solver_path!=None: solver = choco.PULP_CHOCO_CMD(msg=verbose,path=solver_path) else: solver = choco.PULP_CHOCO_CMD(msg=verbose) else: raise ValueError(f"Unsupported solver: {solver}") with Timer() as time: results = problem.solve(solver) status = pulp.LpStatus[results] return Status(status=status, time=time.elapsed)