GRBCallback#
-
class GRBCallback#
Gurobi回调类。这是一个抽象类。要实现一个回调,你应该创建这个类的一个子类并实现一个
callback()
方法。如果你在调用GRBModel::setCallback
之前将这个子类的对象传递给方法GRBModel::optimize
或GRBModel::computeIIS
,该类的callback()
方法将会被定期调用。根据回调被调用的位置,你可以获取关于优化进度的各种信息。请注意,此类包含一个受保护的int成员变量:
where
。您可以从callback()
方法中查询此变量 以确定回调是从哪里调用的。Gurobi回调函数可以用于监控优化的进度以及修改Gurobi优化器的行为。一个简单的用户回调函数可能会调用
GRBCallback::getIntInfo
或GRBCallback::getDoubleInfo
方法来生成自定义显示,或者可能提前终止优化(使用GRBCallback::abort
)或继续到计算的下一个阶段(使用GRBCallback::proceed
)。更复杂的MIP回调可能会使用GRBCallback::getNodeRel
或GRBCallback::getSolution
从当前节点的解决方案中检索值,然后使用GRBCallback::addCut
或GRBCallback::addLazy
添加约束以切断该解决方案,或者使用GRBCallback::setSolution
导入从该解决方案构建的启发式解决方案。对于多目标问题,您可以使用GRBCallback::stopOneMultiObj
来中断多目标MIP问题中某个优化步骤的优化过程,而不会停止分层优化过程。在使用多线程求解模型时,用户回调只会从单个线程调用,因此您无需担心回调的线程安全性。
一些参数是回调可设置的。这些参数可以在回调调用中使用
GRBCallback::set
方法进行修改。您可以查看callback_c++.cpp示例,了解如何使用Gurobi回调的详细信息。
-
GRBCallback GRBCallback()#
回调构造函数。
- Returns:
一个回调对象。
-
void addCut(const GRBLinExpr &lhsExpr, char sense, double rhsVal)#
在回调函数中向MIP模型添加切割平面。 请注意,此方法只能在
where
成员变量等于GRB_CB_MIPNODE
时调用(有关更多信息,请参阅回调代码部分)。切割平面可以在分支切割树的任何节点添加。 然而,应该谨慎添加,因为它们会增加在每个节点求解的松弛模型的大小,并可能显著降低节点处理速度。
切割平面通常用于切断当前的松弛解。要检索当前节点的松弛解,您应该首先调用
getNodeRel
。在添加自己的切割时,您应考虑将参数预粉碎设置为值1。此设置会关闭一些预求解缩减,这些缩减有时会阻止您的切割应用于预求解模型(这会导致您的切割被静默忽略)。
请注意,通过此方法添加的切割平面必须是真正的切割平面——它们可以切断连续解,但不能切断尊重模型原始约束的整数解。忽略此限制将导致错误的解。
- Parameters:
lhsExpr – 新切割平面的左侧表达式。
sense – 新切割平面的方向(
GRB_LESS_EQUAL
,GRB_EQUAL
,或GRB_GREATER_EQUAL
)。rhsVal – 新切割平面的右侧值。
-
void addCut(GRBTempConstr &tc)#
在回调函数中向MIP模型添加切割平面。 请注意,此方法只能在
where
成员变量等于GRB_CB_MIPNODE
时调用(更多信息请参见回调代码部分)。切割平面可以在分支切割树的任何节点添加。 然而,应该谨慎添加,因为它们会增加在每个节点求解的松弛模型的大小,并可能显著降低节点处理速度。
切割平面通常用于切断当前的松弛解。要检索当前节点的松弛解,您应首先调用
getNodeRel
。在添加自己的切割时,您应考虑将参数预粉碎设置为值1。此设置会关闭一些预求解缩减,这些缩减有时会阻止您的切割应用于预求解模型(这会导致您的切割被静默忽略)。
请注意,通过此方法添加的切割平面必须是真正的切割平面——它们可以切断连续解,但不能切断尊重模型原始约束的整数解。忽略此限制将导致错误的解。
- Parameters:
tc – 临时约束对象,使用重载的比较运算符创建。有关更多信息,请参见
GRBTempConstr
。
-
void addLazy(const GRBLinExpr &lhsExpr, char sense, double rhsVal)#
在回调函数中向MIP模型添加一个惰性约束。 请注意,此方法只能在
where
成员变量等于GRB_CB_MIPNODE
或GRB_CB_MIPSOL
时调用(更多信息请参见回调代码部分)。惰性约束通常用于当MIP模型的完整约束集太大而无法显式表示时。通过仅包含在分支切割搜索期间找到的解决方案实际违反的约束,有时可以在仅添加完整约束集的一小部分的情况下找到经过验证的最优解。
通常,您会通过首先查询当前节点解决方案(通过从
GRB_CB_MIPSOL
回调中调用getSolution
,或从GRB_CB_MIPNODE
回调中调用getNodeRel
),然后调用addLazy()
来添加一个约束以切断该解决方案。Gurobi保证您将有机会切断任何原本会被视为可行的解决方案。MIP解决方案可能在MIP节点之外生成。因此,当回调函数中的
where
值等于GRB_CB_MIPNODE
时,生成惰性约束是可选的。为了避免这种情况,我们建议始终检查where
值是否等于GRB_CB_MIPSOL
。您的回调函数应准备好切断违反任何惰性约束的解决方案,包括那些已经添加的约束。节点解决方案通常会尊重先前添加的惰性约束,但并非总是如此。
请注意,如果您想使用惰性约束,必须设置LazyConstraints参数。
- Parameters:
lhsExpr – 新惰性约束的左侧表达式。
sense – 新惰性约束的意义(
GRB_LESS_EQUAL
,GRB_EQUAL
,或GRB_GREATER_EQUAL
)。rhsVal – 新惰性约束的右侧值。
-
void addLazy(GRBTempConstr &tc)#
从回调函数内向MIP模型添加一个惰性约束。 请注意,此方法只能在
where
成员变量等于GRB_CB_MIPNODE
或GRB_CB_MIPSOL
时调用(更多信息请参见回调代码部分)。惰性约束通常用于当MIP模型的完整约束集太大而无法显式表示时。通过仅包含在分支切割搜索期间找到的解决方案实际违反的约束,有时可以在仅添加完整约束集的一小部分的情况下找到经过验证的最优解。
通常,您会通过首先查询当前节点解决方案(通过从
getSolution
调用GRB_CB_MIPSOL
回调,或从getNodeRel
调用GRB_CB_MIPNODE
回调),然后调用addLazy()
来添加一个约束以切断该解决方案。Gurobi保证您将有机会切断任何原本会被视为可行的解决方案。MIP解决方案可能在MIP节点之外生成。因此,当回调函数中的
where
值等于GRB_CB_MIPNODE
时,生成惰性约束是可选的。为了避免这种情况,我们建议始终检查where
值是否等于GRB_CB_MIPSOL
。您的回调函数应准备好切断违反任何惰性约束的解决方案,包括那些已经添加的约束。节点解决方案通常会尊重先前添加的惰性约束,但并非总是如此。
请注意,如果您想使用惰性约束,必须设置LazyConstraints参数。
- Parameters:
tc – 临时约束对象,使用重载的比较运算符创建。有关更多信息,请参见
GRBTempConstr
。
-
double getDoubleInfo(int what)#
请求双值回调信息。可用信息取决于
where
成员的值。有关where
可能的值以及可以查询的不同where
值的双值信息,请参阅回调部分。- Parameters:
what – 请求的信息(请参考Gurobi的回调代码列表以获取可能的值)。
- Returns:
请求的回调信息的价值。
-
int getIntInfo(int what)#
请求整数值的回调信息。可用的信息取决于
where
成员的值。有关where
可能的值以及可以为不同where
值查询的整数值信息,请参阅回调部分。- Parameters:
what – 请求的信息(请参考Gurobi的回调代码列表以获取可能的值)。
- Returns:
请求的回调信息的价值。
-
double getNodeRel(GRBVar v)#
从当前节点的节点松弛解中检索一个值。 仅在
where
成员变量等于GRB_CB_MIPNODE
,且GRB_CB_MIPNODE_STATUS
等于GRB_OPTIMAL
时可用(更多信息请参见回调代码 部分)。请注意,在节点处检索到的松弛解不一定对用户模型是可行的。
- Parameters:
v – 需要获取值的变量。
- Returns:
当前节点中指定变量在节点松弛中的值。
-
double *getNodeRel(const GRBVar *xvars, int len)#
从当前节点的节点松弛解中检索值。 仅在
where
成员变量等于GRB_CB_MIPNODE
,且GRB_CB_MIPNODE_STATUS
等于GRB_OPTIMAL
时可用(更多信息请参见回调代码 部分)。请注意,在节点处检索到的松弛解不一定对用户模型是可行的。
- Parameters:
xvars – 所需值的变量列表。
len – 列表中变量的数量。
- Returns:
当前节点中指定变量的节点松弛值。请注意,结果是堆分配的,必须由用户返回到堆中。
-
double getSolution(GRBVar v)#
从当前解向量中检索值。仅当
where
成员变量等于GRB_CB_MIPSOL
或GRB_CB_MULTIOBJ
时可用。- Parameters:
v – 需要获取值的变量。
- Returns:
当前解向量中指定变量的值。
-
double *getSolution(const GRBVar *xvars, int len)#
从当前解向量中检索值。仅当
where
成员变量等于GRB_CB_MIPSOL
或GRB_CB_MULTIOBJ
时可用。- Parameters:
xvars – 所需值的变量列表。
len – 列表中变量的数量。
- Returns:
当前解决方案中指定变量的值。 请注意,结果是堆分配的,必须由用户返回到堆。
-
string getStringInfo(int what)#
请求字符串值的回调信息。可用的信息取决于
where
成员的值。有关where
可能的值以及可以为不同where
值查询的字符串值信息,请参阅回调部分。- Parameters:
what – 请求的信息(请参考Gurobi的回调代码列表以获取可能的值)。
- Returns:
请求的回调信息的价值。
-
void proceed()#
生成一个请求以继续计算的下一个阶段。请注意,该请求仅在算法的几个阶段被接受,并且不会立即执行。
在当前Gurobi版本中,此回调允许您从NoRel启发式算法过渡到标准MIP搜索。您可以使用回调中的
MIP_PHASE
、MIPNODE_PHASE
或MIPSOL_PHASE
查询来确定当前算法阶段。
-
void set(GRB_DoubleParam param, double newvalue)#
允许在确定性回调期间修改可设置的回调双值参数。
也就是说,当
where
的值为GRB_CB_PRESOLVED
、GRB_CB_SIMPLEX
、GRB_CB_MIP
、GRB_CB_MIPSOL
、GRB_CB_MIPNODE
、GRB_CB_BARRIER
或GRB_CB_MULTIOBJ
时(更多信息请参见 回调代码部分)在远程服务器的情况下,从回调函数内部更改参数可能不会立即生效。
- Parameters:
param – 正在修改的参数。
newvalue – 参数所需的新值。
-
void set(GRB_IntParam param, int newvalue)#
允许在确定性回调期间修改可设置的回调整数值参数。
也就是说,当
where
的值为GRB_CB_PRESOLVED
、GRB_CB_SIMPLEX
、GRB_CB_MIP
、GRB_CB_MIPSOL
、GRB_CB_MIPNODE
、GRB_CB_BARRIER
或GRB_CB_MULTIOBJ
时(更多信息请参见 回调代码部分)在远程服务器的情况下,从回调函数内部更改参数可能不会立即生效。
- Parameters:
param – 正在修改的参数。
newvalue – 参数所需的新值。
-
void set(GRB_StringParam param, string newvalue)#
允许在确定性回调期间修改可设置的回调字符串值参数。
也就是说,当
where
的值为GRB_CB_PRESOLVED
、GRB_CB_SIMPLEX
、GRB_CB_MIP
、GRB_CB_MIPSOL
、GRB_CB_MIPNODE
、GRB_CB_BARRIER
或GRB_CB_MULTIOBJ
时(更多信息请参见 回调代码部分)在远程服务器的情况下,从回调函数内部更改参数可能不会立即生效。
- Parameters:
param – 正在修改的参数。
newvalue – 参数所需的新值。
-
void setSolution(GRBVar v, double val)#
导入启发式解决方案的解决方案值。仅在
where
成员变量等于GRB_CB_MIP
、GRB_CB_MIPNODE
或GRB_CB_MIPSOL
时可用(更多信息请参见回调代码部分)。当您从回调中指定启发式解决方案时,变量最初会取未定义的值。您应该使用此方法来指定变量值。您可以从一次回调调用中多次调用
setSolution
来为多组变量指定值。回调之后,如果已为任何变量指定了值,Gurobi优化器将尝试从指定的值计算出一个可行的解决方案,可能会为值未定义的变量填充值。您还可以选择在回调函数中调用useSolution
,以尝试立即从指定的值计算出一个可行的解决方案。在计算服务器环境中,出于性能考虑,通过
setSolution
发送的解决方案不一定立即由计算服务器处理。它们可能在客户端回调发送后稍晚一些出现在求解过程中。在极端情况下,甚至可能计算服务器优化作业在用户解决方案处理之前就终止了。- Parameters:
v – 正在设置其值的变量。
val – 新解决方案中变量的值。
-
void setSolution(const GRBVar *xvars, const double *sol, int len)#
导入启发式解决方案的解决方案值。仅在
where
成员变量等于GRB_CB_MIP
、GRB_CB_MIPNODE
或GRB_CB_MIPSOL
时可用(更多信息请参见回调代码部分)。当您从回调中指定启发式解决方案时,变量最初会取未定义的值。您应该使用此方法来指定变量值。您可以从一次回调调用中多次调用
setSolution
来为多组变量指定值。回调之后,如果已为任何变量指定了值,Gurobi优化器将尝试从指定的值计算可行解,可能会为值未定义的变量填充值。您还可以选择在回调函数中调用useSolution
,以尝试立即从指定的值计算可行解。在计算服务器环境中,出于性能考虑,通过
setSolution
发送的解决方案不一定立即由计算服务器处理。它们可能在客户端回调发送后稍晚一些出现在求解过程中。在极端情况下,甚至可能计算服务器优化作业在用户解决方案处理之前就终止了。- Parameters:
xvars – 正在设置其值的变量。
sol – 新解中变量的值。
len – 变量的数量。
-
void stopOneMultiObj(int objcnt)#
在多目标MIP问题中,中断其中一个优化步骤的优化过程,而不停止分层优化过程。仅适用于多目标MIP模型,并且当where成员变量不等于GRB_CB_MULTIOBJ时(有关更多信息,请参阅回调代码部分)。
通常,您会通过查询最后完成的多目标优化步骤的数量来停止多目标优化步骤,并使用该数量来停止当前步骤并继续下一个层次目标(如果有的话),如下例所示:
#include <ctime> class mycallback: public GDBCallback { public: int objcnt = 0; time_t starttime = time(); protected: void callback () { if (where == GRB_CB_MULTIOBJ) { /* get current objective number */ objcnt = getIntInfo(GRB_CB_MULTIOBJ_OBJCNT); /* reset start time to current time */ starttime = time(); } else if (time() - startime > BIG || /* takes too long or good enough */) { /* stop only this optimization step */ stopOneMultiObj(objcnt); } } }
您应该参考 多目标部分,了解如何指定多个目标函数并控制它们之间的权衡。
- Parameters:
objnum – 多目标优化步骤的编号,用于中断。对于本地运行的进程,此参数可以具有特殊值-1,表示停止当前步骤。
-
double useSolution()#
一旦你使用
setSolution
导入了解决方案值, 你可以选择在GRB_CB_MIPNODE
回调中调用useSolution
, 以立即使用这些值尝试计算启发式解决方案。 或者,你可以在GRB_CB_MIP
或GRB_CB_MIPSOL
回调中调用useSolution
, 这将存储解决方案,直到可以在内部处理。- Returns:
从您的解决方案值中获得的解决方案的目标值。如果未找到改进的解决方案或从回调中调用了该方法而不是
GRB_CB_MIPNODE
,则它等于GRB_INFINITY
,因为在这些上下文中,解决方案是存储而不是立即处理的。
-
GRBCallback GRBCallback()#