在回调(CPXcutcallbackadd)中添加用户剪切后,如何编写问题表述(CPXwriteprob)?

时间:2019-01-29 15:16:29

标签: c++ cplex

我正在尝试在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;
}

1 个答案:

答案 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上找到与您类似的另一个问题。