我正在尝试在cplex回调函数中添加用户剪切。为了检查这些剪切,添加剪切后我写了一个lp文件。但是,在lp文件中没有用户剪切。
根据this forum thread(网址:www.ibm.com/developerworks/community/forums/html/topic?id=82b92bee-4ac7-41dd-b1fc-606eae3514f3),剪切应该以'u开头'。
我代码的相关部分(基于示例文件bendersatsp.c):
int CPXPUBLIC benders_solver::benders_callback(CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle, int *useraction_p)
{
int status = 0;
int do_separate = 0;
USER_CBHANDLE *user_cbhandle = (USER_CBHANDLE *)cbhandle;
int purgeable;
*useraction_p = CPX_CALLBACK_DEFAULT;
/* Decide if we want to separate cuts, depending on the parameter wherefrom */
switch (wherefrom) {
case CPX_CALLBACK_MIP_CUT_FEAS: // 115
do_separate = 1;
break;
case CPX_CALLBACK_MIP_CUT_LAST: // 114: indicates that CPLEX is done adding cuts and the user has a last chance to add cuts
do_separate = 1;
break;
case CPX_CALLBACK_MIP_CUT_LOOP: // 106: The callback was called from the cut loop CPLEX executes at each node.
do_separate = 0;
break;
default:
fprintf(stderr, "Unexpected value of wherefrom: %d\n", wherefrom);
do_separate = 0;
}
if (!do_separate) goto TERMINATE;
/* Get the current x solution */
status = CPXgetcallbacknodex(env, cbdata, wherefrom, user_cbhandle->x, 0, user_cbhandle->num_x_cols - 1);
if (status) {
fprintf(stderr, "Error in CPXgetcallbacknodex: status = %d\n", status);
goto TERMINATE;
}
CPXCLPptr lp_p;
status = CPXgetcallbacklp(env, cbdata, wherefrom, &lp_p); // store master problem to lp_p
changeSub_d(user_cbhandle, user_cbhandle->subenv, user_cbhandle->subproblem_d);
/* Solve the worker LP and look for a violated cut */
CPXsetintparam(user_cbhandle->subenv, CPX_PARAM_PREIND, 0);
int optstatus = CPXlpopt(user_cbhandle->subenv, user_cbhandle->subproblem_d);
worker_lp_sol_stat = CPXgetstat(user_cbhandle->subenv, user_cbhandle->subproblem_d);
/* Make cut */
int matind[21000] = { 0 };
double matval[21000] = { 0 };
double rhs[1];
char sense[1];
int nbnz{ 0 };
status = addBendersCut(user_cbhandle, worker_lp_sol_stat, env, lp_p, cbdata, wherefrom);
int purgeable = CPX_USECUT_FORCE;
status = CPXcutcallbackadd(env, cbdata, wherefrom, nbnz, rhs[0], sense[0], matind, matval, purgeable);
status = CPXwriteprob(masterenv, masterproblem, "cback.lp", "LP");
/* Tell CPLEX that cuts have been created */
if (status)
goto TERMINATE;
*useraction_p = CPX_CALLBACK_SET;
TERMINATE:
/* If an error has been encountered, we fail */
if (status) *useraction_p = CPX_CALLBACK_FAIL;
return status;
} /* END benders_callback */
bool benders_solver::startSolve()
{
loadGeneralData(sol);
// Initialize the CPLEX environment
masterenv = CPXopenCPLEX(&status);
subenv = CPXopenCPLEX(&status);
loadMasterProblem();
loadSubProblem();
USER_CBHANDLE user_cbhandle;
int separate_fractional_solutions = 1;
/* Init the cut callback data structure */
status = init_user_cbhandle(&user_cbhandle, separate_fractional_solutions);
/* Let MIP callbacks work on the original model */
status = CPXsetintparam(env, CPXPARAM_MIP_Strategy_CallbackReducedLP, CPX_OFF);
status = CPXsetintparam(env, CPX_PARAM_PRELINEAR, 0);
status = CPXsetintparam(env, CPX_PARAM_MIPCBREDLP, 0);
status = CPXsetintparam(env, CPXPARAM_Threads, 1);
/* Turn on traditional search for use with control callbacks */
status = CPXsetintparam(env, CPXPARAM_MIP_Strategy_Search, CPX_MIPSEARCH_TRADITIONAL);
if (user_cbhandle->separate_fractional_solutions) {
status = CPXsetusercutcallbackfunc(env, benders_callback, user_cbhandle);
}
/* Optimize the problem and obtain solution status */
status = CPXsetintparam(masterenv, CPX_PARAM_PREIND, 0);
status = CPXsetdblparam(masterenv, CPX_PARAM_TILIM, 300);
status = CPXsetstrparam(masterenv, CPXPARAM_WorkDir, "c:/cplex/");
status = CPXsetintparam(masterenv, CPXPARAM_MIP_Strategy_File, 2);
status = CPXsetdblparam(masterenv, CPXPARAM_WorkMem, 6000);
status = CPXsetintparam(masterenv, CPX_PARAM_MEMORYEMPHASIS, 1);
status = CPXmipopt(masterenv, masterproblem);
status = CPXsetlogfile(masterenv, NULL);
return true;
}
答案 0 :(得分:1)
编写LP时,看起来好像您正在使用原始模型对象(即masterproblem
):
status = CPXwriteprob(masterenv, masterproblem, "cback.lp", "LP");
相反,您将需要使用节点LP,如下所示:
CPXLPptr _lp;
status = CPXgetcallbacknodelp(env, cbdata, wherefrom, &_lp);
CPXwriteprob(env, _lp, "cback.lp", "LP");
正如您在论坛帖子中提到的那样,链接到:
CPXcutcallbackadd()函数不使用任何参数来提供名称。 在cback.lp文件中,您添加的剪切的名称将以 以'u',后跟数字。这样就可以找到哪些行被剪切 由您添加的,但您无法轻松地将它们映射回事物 在您的代码中
值得一提(并澄清我在评论中提到的内容)的另一个小要点是,在回调之外,使用{时,您的剪切将不显示{1}}(即,不会导出在树搜索期间在回调中动态添加的所有剪切)。但是,如果您使用CPXaddusercuts在优化之前 添加用户剪切,则它们会。
可以在here上找到与您类似的另一个问题。