Modifying Solver Behavior - Callbacks#
-
int GRBcbcut(void *cbdata, int cutlen, const int *cutind, const double *cutval, char cutsense, double cutrhs)#
Add a new cutting plane to the MIP model from within a user callback routine. Note that this routine can only be called when the
where
value on the callback routine isGRB_CB_MIPNODE
(see the Callback Codes section for more information).Cutting planes can be added at any node of the branch-and-cut tree. Note that cuts should be added sparingly, since they increase the size of the relaxation model that is solved at each node and can significantly degrade node processing speed.
Cutting planes are typically used to cut off the current relaxation solution. To retrieve the relaxation solution at the current node, call
GRBcbget
withwhat = GRB_CB_MIPNODE_REL
.You should consider setting parameter PreCrush to value 1 when adding your own cuts. This setting shuts off a few presolve reductions that can sometimes prevent your cut from being applied to the presolved model (which would result in your cut being silently ignored).
One very important note: you should only add cuts that are implied by the constraints in your model. If you cut off an integer solution that is feasible according to the original model constraints, you are likely to obtain an incorrect solution to your MIP problem.
- Return value:
A non-zero return value indicates that a problem occurred while adding the cut. Refer to the Error Codes table for a list of possible return values. Details on the error can be obtained by calling
GRBgeterrormsg
.- Arguments:
cbdata – The
cbdata
argument that was passed into the user callback by the Gurobi optimizer. This argument must be passed unmodified from the user callback toGRBcbcut()
.cutlen – The number of non-zero coefficients in the new cutting plane.
cutind – Variable indices for non-zero values in the new cutting plane.
cutval – Numerical values for non-zero values in the new cutting plane.
cutsense – Sense for the new cutting plane. Options are
GRB_LESS_EQUAL
,GRB_EQUAL
, orGRB_GREATER_EQUAL
.cutrhs – Right-hand side value for the new cutting plane.
- Example:
if (where == GRB_CB_MIPNODE) { int cutind[] = {0, 1}; double cutval[] = {1.0, 1.0}; error = GRBcbcut(cbdata, 2, cutind, cutval, GRB_LESS_EQUAL, 1.0); if (error) return 0; }
-
int GRBcblazy(void *cbdata, int lazylen, const int *lazyind, const double *lazyval, char lazysense, double lazyrhs)#
Add a new lazy constraint to the MIP model from within a user callback routine. Note that this routine can only be called when the
where
value on the callback routine is eitherGRB_CB_MIPNODE
orGRB_CB_MIPSOL
(see the Callback Codes section for more information).Lazy constraints are typically used when the full set of constraints for a MIP model is too large to represent explicitly. By only including the constraints that are actually violated by solutions found during the branch-and-cut search, it is sometimes possible to find a proven optimal solution while only adding a fraction of the full set of constraints.
You would typically add a lazy constraint by querying the current node solution (by calling
GRBcbget
from aGRB_CB_MIPSOL
orGRB_CB_MIPNODE
callback, usingwhat=GRB_CB_MIPSOL_SOL
orwhat=GRB_CB_MIPNODE_REL
), and then callingGRBcblazy()
to add a constraint that cuts off the solution. Gurobi guarantees that you will have the opportunity to cut off any solutions that would otherwise be considered feasible.MIP solutions may be generated outside of a MIP node. Thus, generating lazy constraints is optional when the
where
value in the callback function equalsGRB_CB_MIPNODE
. To avoid this, we recommend to always check when thewhere
value equalsGRB_CB_MIPSOL
.Your callback should be prepared to cut off solutions that violate any of your lazy constraints, including those that have already been added. Node solutions will usually respect previously added lazy constraints, but not always.
Note that you must set the LazyConstraints parameter if you want to use lazy constraints.
- Return value:
A non-zero return value indicates that a problem occurred while adding the lazy constraint. Refer to the Error Codes table for a list of possible return values. Details on the error can be obtained by calling
GRBgeterrormsg
.- Arguments:
cbdata – The
cbdata
argument that was passed into the user callback by the Gurobi optimizer. This argument must be passed unmodified from the user callback toGRBcblazy()
.lazylen – The number of non-zero coefficients in the new lazy constraint.
lazyind – Variable indices for non-zero values in the new lazy constraint.
lazyval – Numerical values for non-zero values in the new lazy constraint.
lazysense – Sense for the new lazy constraint. Options are
GRB_LESS_EQUAL
,GRB_EQUAL
, orGRB_GREATER_EQUAL
.lazyrhs – Right-hand side value for the new lazy constraint.
- Example:
if (where == GRB_CB_MIPSOL) { int lazyind[] = {0, 1}; double lazyval[] = {1.0, 1.0}; error = GRBcblazy(cbdata, 2, lazyind, lazyval, GRB_LESS_EQUAL, 1.0); if (error) return 0; }
-
int GRBcbsolution(void *cbdata, const double *solution, double *objP)#
Provide a new feasible solution for a MIP model from within a user callback routine. Note that this routine can only be called when the
where
value on the callback routine isGRB_CB_MIP
,GRB_CB_MIPNODE
, orGRB_CB_MIPSOL
(see the Callback Codes section for more information).Heuristics solutions are typically built from the current relaxation solution. To retrieve the relaxation solution at the current node, call
GRBcbget
withwhat = GRB_CB_MIPNODE_REL
.When providing a solution, you can specify values for any subset of the variables in the model. To leave a variable value unspecified, set the variable to
GRB_UNDEFINED
in thesolution
vector. The Gurobi MIP solver will attempt to extend the specified partial solution to a complete solution.Note that this method is not supported in a Compute Server environment.
- Return value:
A non-zero return value indicates that a problem occurred while adding the new solution. Refer to the Error Codes table for a list of possible return values. Details on the error can be obtained by calling
GRBgeterrormsg
.- Arguments:
cbdata – The
cbdata
argument that was passed into the user callback by the Gurobi optimizer. This argument must be passed unmodified from the user callback toGRBcbsolution()
.solution – The solution vector. You must provide one entry for each variable in the model. Note that you can leave an entry unspecified by setting it to
GRB_UNDEFINED
. The Gurobi optimizer will attempt to find appropriate values for the unspecified variables.objP – Objective value for solution that results from this call. Returns
GRB_INFINITY
if no improved solution is found or the function has been called from a callback other thanGRB_CB_MIPNODE
.
- Example:
if (where == GRB_CB_MIPNODE) { error = GRBcbsolution(cbdata, solution, &obj); if (error) return 0; }
-
int GRBcbproceed(void *cbdata)#
Generate a request to proceed to the next phase of the computation. This routine can be called from any callback. Note that the request is only accepted in a few phases of the algorithm, and it won’t be acted upon immediately.
In the current Gurobi version, this callback allows you to proceed from the NoRel heuristic to the standard MIP search. You can determine the current algorithm phase using
MIP_PHASE
,MIPNODE_PHASE
, orMIPSOL_PHASE
queries from a callback.- Return value:
A non-zero return value indicates that a problem occurred while requesting to proceed. Refer to the Error Codes table for a list of possible return values. Details on the error can be obtained by calling
GRBgeterrormsg
.- Arguments:
cbdata – The
cbdata
argument that was passed into the user callback by the Gurobi optimizer. This argument must be passed unmodified from the user callback toGRBcbproceed()
.
- Example:
if (solution_objective < target_value) { GRBcbproceed(cbdata); }
-
int GRBcbstoponemultiobj(GRBmodel *model, void *cbdata, int objnum)#
Interrupt the optimization process of one of the optimization steps in a multi-objective MIP problem without stopping the hierarchical optimization process. Note that this routine can only be called for multi-objective MIP models and when the
where
value on the callback routine is not equal toGRB_CB_MULTIOBJ
(see the Callback Codes section for more information).You would typically stop a multi-objective optimization step by querying the last finished number of multi-objectives steps, and using that number to stop the current step and move on to the next hierarchical objective (if any) as shown in the following example:
#include <time.h> typedef struct { int objcnt; time_t starttime; } usrdata_t; int mycallback(GRBmodel *model, void *cbdata, int where, void *usrdata) { int error = 0; usrdata_t *ud = (usrdata_t*)usrdata; if (where == GRB_CB_MULTIOBJ) { /* get current objective number */ error = GRBcbget(cbdata, where, MULTIOBJ_OBJCNT, (void*)&ud->objcnt); if (error) goto QUIT; /* reset start time to current time */ ud->starttime = time(); } else if (time() - ud->starttime > BIG || /* takes too long or good enough */) { /* stop only this optimization step */ error = GRBcbstoponemultiobj(model, cbdata, ud->objcnt); if (error) goto QUIT; } QUIT: return error; }
You should refer to the section on Multiple Objectives for information on how to specify multiple objective functions and control the trade-off between them.
- Return value:
A non-zero return value indicates that a problem occurred while stopping the multi-objective step specified by objcnt. Refer to the Error Codes table for a list of possible return values. Details on the error can be obtained by calling
GRBgeterrormsg
.- Arguments:
model – The
model
argument that was passed into the user callback by the Gurobi optimizer. This argument must be passed unmodified from the user callback toGRBcbstoponemultiobj()
.cbdata – The
cbdata
argument that was passed into the user callback by the Gurobi optimizer. This argument must be passed unmodified from the user callback toGRBcbstoponemultiobj()
.objnum – The number of the multi-objective optimization step to interrupt. For processes running locally, this argument can have the special value -1, meaning to stop the current step.
-
void GRBterminate(GRBmodel *model)#
Generate a request to terminate the current optimization. This routine can be called at any time during an optimization (from a callback, from another thread, from an interrupt handler, etc.). Note that, in general, the request won’t be acted upon immediately.
When the optimization stops, the Status attribute will be equal to
GRB_INTERRUPTED
.- Arguments:
model – The model to terminate.
- Example:
if (time_to_quit) GRBterminate(model);