From d88a1da93f7af4de3739d3457d2bbd274cb6ced2 Mon Sep 17 00:00:00 2001 From: Cristiano Date: Tue, 18 Jun 2019 07:49:20 +0200 Subject: [PATCH 1/2] Set cbc to default solver I've come across a bug; on Linux (but I think it's multi os) I installed only mip and, when launching my script using it, I got a NameError: name 'ffi' is not defined. I searched where the problem was (line 264 of gurobi.py file, called in line 485 of model.py __init__), tried to fix it, but the problem was that in the first try except block ffi was initializated AFTER the raise of exception (going into the except block), causing the has_gurobi to be False and ffi to not exist in the workspace. TL;DR setting the solver_name to cbc (the one that comes included with installation btw) there isn't any problem and everything works --- mip/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mip/model.py b/mip/model.py index 004d122c..a2789aea 100644 --- a/mip/model.py +++ b/mip/model.py @@ -444,7 +444,7 @@ class Model: def __init__(self, name: str = "", sense: str = MINIMIZE, - solver_name: str = "", + solver_name: str = "cbc", solver=None): """Model constructor From 643641614400406daa898ba79d909df2b7a9cfef Mon Sep 17 00:00:00 2001 From: Crissal1995 Date: Tue, 18 Jun 2019 17:13:57 +0200 Subject: [PATCH 2/2] Moved has_gurobi into model, and gurobi.py now raise ImportError --- mip/gurobi.py | 118 +++++++++++++++++++++++++------------------------- mip/model.py | 11 +++-- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/mip/gurobi.py b/mip/gurobi.py index 898b9119..7724d0a9 100644 --- a/mip/gurobi.py +++ b/mip/gurobi.py @@ -31,18 +31,16 @@ grblib = ffi.dlopen(lib_path) print('gurobi version {}.{} found'.format(major_ver, minor_ver)) - has_gurobi = True except Exception: - has_gurobi = False + raise ImportError -if has_gurobi: - CData = ffi.CData - os_is_64_bit = maxsize > 2**32 - INF = float('inf') - MAX_NAME_SIZE = 512 # for variables and constraints +CData = ffi.CData +os_is_64_bit = maxsize > 2**32 +INF = float('inf') +MAX_NAME_SIZE = 512 # for variables and constraints - ffi.cdef(""" +ffi.cdef(""" typedef struct _GRBmodel GRBmodel; typedef struct _GRBenv GRBenv; @@ -179,47 +177,47 @@ int GRBdelconstrs (GRBmodel *model, int numdel, int *ind); """) - GRBloadenv = grblib.GRBloadenv - GRBnewmodel = grblib.GRBnewmodel - GRBfreeenv = grblib.GRBfreeenv - GRBfreemodel = grblib.GRBfreemodel - GRBaddvar = grblib.GRBaddvar - GRBaddconstr = grblib.GRBaddconstr - GRBoptimize = grblib.GRBoptimize - GRBgetvarbyname = grblib.GRBgetvarbyname - GRBsetdblattrarray = grblib.GRBsetdblattrarray - GRBsetcharattrlist = grblib.GRBsetcharattrlist - GRBsetdblattrlist = grblib.GRBsetdblattrlist - GRBwrite = grblib.GRBwrite - GRBreadmodel = grblib.GRBreadmodel - GRBgetconstrbyname = grblib.GRBgetconstrbyname - GRBupdatemodel = grblib.GRBupdatemodel - GRBgetcharattrelement = grblib.GRBgetcharattrelement - GRBgetconstrs = grblib.GRBgetconstrs - GRBgetdblattrelement = grblib.GRBgetdblattrelement - GRBgetvars = grblib.GRBgetvars - GRBsetcharattrelement = grblib.GRBsetcharattrelement - GRBsetdblattrelement = grblib.GRBsetdblattrelement - GRBsetintattr = grblib.GRBsetintattr - GRBsetdblattr = grblib.GRBsetdblattr - GRBgetintattr = grblib.GRBgetintattr - GRBgetintparam = grblib.GRBgetintparam - GRBsetintparam = grblib.GRBsetintparam - GRBgetdblattr = grblib.GRBgetdblattr - GRBsetdblparam = grblib.GRBsetdblparam - GRBgetdblparam = grblib.GRBgetdblparam - GRBgetstrattrelement = grblib.GRBgetstrattrelement - GRBcbget = grblib.GRBcbget - GRBcbsetparam = grblib.GRBcbsetparam - GRBcbsolution = grblib.GRBcbsolution - GRBcbcut = grblib.GRBcbcut - GRBcblazy = grblib.GRBcblazy - GRBsetcallbackfunc = grblib.GRBsetcallbackfunc - GRBdelvars = grblib.GRBdelvars - GRBdelconstrs = grblib.GRBdelconstrs - GRBgetenv = grblib.GRBgetenv - GRBgetstrattr = grblib.GRBgetstrattr - GRBsetstrattr = grblib.GRBsetstrattr +GRBloadenv = grblib.GRBloadenv +GRBnewmodel = grblib.GRBnewmodel +GRBfreeenv = grblib.GRBfreeenv +GRBfreemodel = grblib.GRBfreemodel +GRBaddvar = grblib.GRBaddvar +GRBaddconstr = grblib.GRBaddconstr +GRBoptimize = grblib.GRBoptimize +GRBgetvarbyname = grblib.GRBgetvarbyname +GRBsetdblattrarray = grblib.GRBsetdblattrarray +GRBsetcharattrlist = grblib.GRBsetcharattrlist +GRBsetdblattrlist = grblib.GRBsetdblattrlist +GRBwrite = grblib.GRBwrite +GRBreadmodel = grblib.GRBreadmodel +GRBgetconstrbyname = grblib.GRBgetconstrbyname +GRBupdatemodel = grblib.GRBupdatemodel +GRBgetcharattrelement = grblib.GRBgetcharattrelement +GRBgetconstrs = grblib.GRBgetconstrs +GRBgetdblattrelement = grblib.GRBgetdblattrelement +GRBgetvars = grblib.GRBgetvars +GRBsetcharattrelement = grblib.GRBsetcharattrelement +GRBsetdblattrelement = grblib.GRBsetdblattrelement +GRBsetintattr = grblib.GRBsetintattr +GRBsetdblattr = grblib.GRBsetdblattr +GRBgetintattr = grblib.GRBgetintattr +GRBgetintparam = grblib.GRBgetintparam +GRBsetintparam = grblib.GRBsetintparam +GRBgetdblattr = grblib.GRBgetdblattr +GRBsetdblparam = grblib.GRBsetdblparam +GRBgetdblparam = grblib.GRBgetdblparam +GRBgetstrattrelement = grblib.GRBgetstrattrelement +GRBcbget = grblib.GRBcbget +GRBcbsetparam = grblib.GRBcbsetparam +GRBcbsolution = grblib.GRBcbsolution +GRBcbcut = grblib.GRBcbcut +GRBcblazy = grblib.GRBcblazy +GRBsetcallbackfunc = grblib.GRBsetcallbackfunc +GRBdelvars = grblib.GRBdelvars +GRBdelconstrs = grblib.GRBdelconstrs +GRBgetenv = grblib.GRBgetenv +GRBgetstrattr = grblib.GRBgetstrattr +GRBsetstrattr = grblib.GRBsetstrattr GRB_CB_PRE_COLDEL = 1000 @@ -264,7 +262,7 @@ class SolverGurobi(Solver): def __init__(self, model: Model, name: str, sense: str, modelp: CData = - ffi.NULL): + ffi.NULL): """modelp should be informed if a model should not be created, but only allow access to an existing one""" super().__init__(model, name, sense) @@ -362,7 +360,7 @@ def add_var(self, def add_cut(self, lin_expr: LinExpr): # int GRBcbcut(void *cbdata, int cutlen, const int *cutind, const double *cutval, char cutsense, double cutrhs); # int GRBcbcut(void *cbdata, int cutlen, const int *cutind, const double *cutval, char cutsense, double cutrhs); - + return @@ -467,7 +465,7 @@ def callback(p_model: CData, difu = abs(obj_best - log[-1][1][1]) if difl >= 1e-6 or difu >= 1e-6: print('>>>>>>> {} {}'.format( - obj_bound, obj_best)) + obj_bound, obj_best)) log.append((sec, (obj_bound, obj_best))) # adding cuts @@ -507,7 +505,7 @@ def callback(p_model: CData, self.update() if self.model.cuts_generator is not None or \ - self.model.store_search_progress_log: + self.model.store_search_progress_log: GRBsetcallbackfunc(self._model, callback, ffi.NULL) if self.__threads >= 1: @@ -594,7 +592,7 @@ def set_objective_sense(self, sense: str): self.set_int_attr("ModelSense", 1) else: raise Exception("Unknown sense: {}, use {} or {}".format(sense, - MAXIMIZE, MINIMIZE)) + MAXIMIZE, MINIMIZE)) self.__updated = False def get_num_solutions(self) -> int: @@ -712,7 +710,7 @@ def read(self, file_path: str) -> None: self._model) if st != 0: raise Exception('Could not read model {}, check contents'.format( - file_path)) + file_path)) self._model = self._model[0] def num_cols(self) -> int: @@ -761,7 +759,7 @@ def constr_get_expr(self, constr: Constr) -> LinExpr: constr.idx, 1) if st != 0: raise Exception('Could not get info for constraint {}'.format( - constr.idx)) + constr.idx)) nz = nnz[0] # creating arrays to hold indices and coefficients @@ -782,12 +780,12 @@ def constr_get_expr(self, constr: Constr) -> LinExpr: constr.idx, c_sense) if st != 0: raise Exception('Could not query sense for constraint {}'.format( - constr.idx)) + constr.idx)) st = GRBgetdblattrelement(self._model, 'RHS'.encode('utf-8'), constr.idx, rhs) if st != 0: raise Exception('Could not query RHS for constraint {}'.format( - constr.idx)) + constr.idx)) ssense = c_sense[0].decode('utf-8') # translating sense @@ -963,7 +961,7 @@ def set_char_attr_element(self, name: str, index: int, value: str): if error != 0: raise Exception( 'Error setting gurobi char attr element {} index {} to value'. - format(name, index, value)) + format(name, index, value)) def get_dbl_attr_element(self, name: str, index: int) -> float: res = ffi.new('double *') @@ -980,7 +978,7 @@ def set_dbl_attr_element(self, name: str, index: int, value: float): if error != 0: raise Exception( "Error modifying dbl attribute {} for element {} to value {}". - format(name, index, value)) + format(name, index, value)) def set_int_attr(self, name: str, value: int): error = GRBsetintattr(self._model, name.encode('utf-8'), value) diff --git a/mip/model.py b/mip/model.py index a2789aea..701b9236 100644 --- a/mip/model.py +++ b/mip/model.py @@ -444,7 +444,7 @@ class Model: def __init__(self, name: str = "", sense: str = MINIMIZE, - solver_name: str = "cbc", + solver_name: str = "", solver=None): """Model constructor @@ -482,8 +482,13 @@ def __init__(self, name: str = "", self.solver = SolverCbc(self, name, sense) else: # checking which solvers are available - from mip import gurobi - if gurobi.has_gurobi: + try: + from mip import gurobi + has_gurobi = True + except ImportError: + has_gurobi = False + + if has_gurobi: from mip.gurobi import SolverGurobi self.solver = SolverGurobi(self, name, sense) self.solver_name = GUROBI