2020 if 'GUROBI_HOME' in environ :
2121 if platform .lower ().startswith ('win' ):
2222 libfile = glob (os .path .join (os .environ ['GUROBI_HOME' ],
23- 'bin\gurobi[0-9][0-9].dll' ))
23+ 'bin\\ gurobi[0-9][0-9].dll' ))
2424 else :
2525 libfile = glob (os .path .join (os .environ ['GUROBI_HOME' ],
2626 'lib/libgurobi[0-9][0-9].*' ))
27-
27+
2828 if libfile :
2929 lib_path = libfile [0 ]
3030
249249GRBgetstrattr = grblib .GRBgetstrattr
250250GRBsetstrattr = grblib .GRBsetstrattr
251251
252+ GRB_CB_MIPSOL = 4
253+ GRB_CB_MIPNODE = 5
252254
253255GRB_CB_PRE_COLDEL = 1000
254256GRB_CB_PRE_ROWDEL = 1001
@@ -390,7 +392,6 @@ def add_var(self,
390392 def add_cut (self , lin_expr : LinExpr ):
391393 # int GRBcbcut(void *cbdata, int cutlen, const int *cutind, const double *cutval, char cutsense, double cutrhs);
392394 # int GRBcbcut(void *cbdata, int cutlen, const int *cutind, const double *cutval, char cutsense, double cutrhs);
393-
394395
395396 return
396397
@@ -498,9 +499,12 @@ def callback(p_model: CData,
498499 obj_bound , obj_best ))
499500 log .append ((sec , (obj_bound , obj_best )))
500501
501- # adding cuts
502- if where == 5 : # MIPNODE == 5
503- if self .model .cuts_generator :
502+ # adding cuts or lazy constraints
503+ if self .model .cuts_generator :
504+ if where == GRB_CB_MIPNODE or \
505+ (where == GRB_CB_MIPSOL and
506+ hasattr (self .model .cuts_generator , 'lazy_constraints' ) and
507+ self .model .cuts_generator .lazy_constraints ):
504508 mgc = ModelGurobiCB (p_model , p_cbdata , where )
505509 self .model .cuts_generator .generate_cuts (mgc )
506510
@@ -538,6 +542,12 @@ def callback(p_model: CData,
538542 self .model .store_search_progress_log :
539543 GRBsetcallbackfunc (self ._model , callback , ffi .NULL )
540544
545+ if (self .model .cuts_generator is not None and
546+ hasattr (self .model .cuts_generator , 'lazy_constraints' ) and
547+ self .model .cuts_generator .lazy_constraints ) or \
548+ self .model .lazy_constrs_generator is not None :
549+ self .set_int_param ("LazyConstraints" , 1 )
550+
541551 if self .__threads >= 1 :
542552 self .set_int_param ("Threads" , self .__threads )
543553
@@ -1141,15 +1151,16 @@ def __init__(self, model: Model, grb_model: CData = ffi.NULL,
11411151 self ._obj_value = INF
11421152 self ._best_bound = INF
11431153 self ._status = OptimizationStatus .LOADED
1154+ self ._where = where
11441155
11451156 # pre-allocate temporary space to query names
11461157 self .__name_space = ffi .new ("char[{}]" .format (MAX_NAME_SIZE ))
11471158 # in cut generation
11481159 self .__name_spacec = ffi .new ("char[{}]" .format (MAX_NAME_SIZE ))
11491160
11501161 self .__relaxed = False
1151- if where == 5 :
1152- gstatus = ffi . new ( 'int *' )
1162+ gstatus = ffi . new ( 'int *' )
1163+ if where == 5 : # GRB_CB_MIPNODE
11531164 res = GRBcbget (cb_data , where , GRB_CB_MIPNODE_STATUS , gstatus )
11541165 if res != 0 :
11551166 raise Exception ('Error getting status' )
@@ -1168,6 +1179,21 @@ def __init__(self, model: Model, grb_model: CData = ffi.NULL,
11681179 raise Exception ('Error getting fractional solution' )
11691180 else :
11701181 self ._cb_sol = ffi .NULL
1182+ elif where == 4 : # GRB_CB_MIPSOL
1183+ self ._status = OptimizationStatus .FEASIBLE
1184+ ires = ffi .new ('int *' )
1185+ st = GRBgetintattr (grb_model , 'NumVars' .encode ('utf-8' ), ires )
1186+ if st != 0 :
1187+ raise Exception ('Could not query number of variables in Gurobi \
1188+ callback' )
1189+ ncols = ires [0 ]
1190+
1191+ self ._cb_sol = \
1192+ ffi .new ('double[{}]' .format (ncols ))
1193+ res = GRBcbget (cb_data , where , GRB_CB_MIPSOL_SOL , self ._cb_sol )
1194+ if res != 0 :
1195+ raise Exception ('Error getting integer solution in gurobi \
1196+ callback' )
11711197 else :
11721198 self ._cb_sol = ffi .NULL
11731199
@@ -1182,7 +1208,10 @@ def add_cut(self, cut: LinExpr):
11821208 sense = cut .sense .encode ("utf-8" )
11831209 rhs = - cut .const
11841210
1185- GRBcbcut (self ._cb_data , numnz , cind , cval , sense , rhs )
1211+ if self ._where == GRB_CB_MIPNODE :
1212+ GRBcbcut (self ._cb_data , numnz , cind , cval , sense , rhs )
1213+ elif self ._where == GRB_CB_MIPSOL :
1214+ GRBcblazy (self ._cb_data , numnz , cind , cval , sense , rhs )
11861215
11871216 def get_status (self ):
11881217 return self ._status
0 commit comments