Topic
  • 5 replies
  • Latest Post - ‏2011-05-03T09:23:42Z by SystemAdmin
gangulo
gangulo
34 Posts

Pinned topic Branching on semi-continuous variables

‏2011-04-18T20:14:33Z |
Hi,

I'm working in a problem with semi-continuous variables. I noticed that CPLEX adds indicator variables/constraints to enforce semi-continuity. Is there any way to override CPLEX's branching decisions using a branch callback in this case? I wrote one, but whenever CPLEX suggests to branch on a variable, it is an indicator variable having an out-of-range index, so I cannot do anything with it. Even the function CPXgetcallbackindicatorinfo doesn't give me any information other than the number of indicators in the presolved problem (I cannot get detailed information about the implications).
Any suggestions?
Thanks!!
Updated on 2011-05-03T09:23:42Z at 2011-05-03T09:23:42Z by SystemAdmin
  • SystemAdmin
    SystemAdmin
    7929 Posts

    Re: Branching on semi-continuous variables

    ‏2011-04-19T10:45:33Z  
    Which API are you using? If you are using an object-oriented API like C++ or Java, then you cannot access the presolved model, and thus, you do not have access to the internally generated binary variables to enforce semi-continuity.

    If you work with the C API, then you need to make sure that the MIPCBREDLP parameter is set to 1 (i.e., that your callbacks work on the presolved model).

    Alternatively, you can just model the semi-continuous variables as pairs of continuous and binary variables yourself. There is no magic in the CPLEX automatic reformulation, so doing it yourself should not cost performance. And if you do it yourself, you can of course branch on the binary variable as you like.

    Tobias
  • gangulo
    gangulo
    34 Posts

    Re: Branching on semi-continuous variables

    ‏2011-04-19T18:58:40Z  
    Which API are you using? If you are using an object-oriented API like C++ or Java, then you cannot access the presolved model, and thus, you do not have access to the internally generated binary variables to enforce semi-continuity.

    If you work with the C API, then you need to make sure that the MIPCBREDLP parameter is set to 1 (i.e., that your callbacks work on the presolved model).

    Alternatively, you can just model the semi-continuous variables as pairs of continuous and binary variables yourself. There is no magic in the CPLEX automatic reformulation, so doing it yourself should not cost performance. And if you do it yourself, you can of course branch on the binary variable as you like.

    Tobias
    In this problem the semi-continuous variables are unbounded from above, so I can model them using a big-M formulation. However, what I wanted to do was just to keep track of the branching decisions that CPLEX makes at each node by adding a node handle to each child without modifying CPLEX's decisions, and then fathom a node when a given criteria is met.
    I'm using the C API, but I had CPX_PARAM_MIPCBREDLP set to 0. I will try setting this parameter to 1.
    Thanks!!
  • gangulo
    gangulo
    34 Posts

    Re: Branching on semi-continuous variables

    ‏2011-04-19T22:46:21Z  
    • gangulo
    • ‏2011-04-19T18:58:40Z
    In this problem the semi-continuous variables are unbounded from above, so I can model them using a big-M formulation. However, what I wanted to do was just to keep track of the branching decisions that CPLEX makes at each node by adding a node handle to each child without modifying CPLEX's decisions, and then fathom a node when a given criteria is met.
    I'm using the C API, but I had CPX_PARAM_MIPCBREDLP set to 0. I will try setting this parameter to 1.
    Thanks!!
    Tobias,

    I set CPX_PARAM_MIPCBREDLP to 1, but the function CPXgetcallbackindicatorinfo is not giving me any info (just the number of indicators). This is part of my branch callback

    status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, 0, CPX_CALLBACK_INFO_IC_NUM , &numindic);
     
            for(int i = 0; i < numindic; i++)
            {
                    status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLYING_VAR , &implying);
                    status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLIED_VAR, &implied);
                    status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_SENSE, &sense);
                    status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_RHS, &rhs);
                    status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IS_FEASIBLE, &isfeas);
     
                    cout << "x" << implying << " -> x" << implied << sense << rhs << endl;
            }
    


    There is no problem getting numindic, but the first and second lines inside the loop are crashing, and the remaining lines give me nothing. Is there any issue with the code, with some other parameter, or is it just impossible to access this information?

    By the way, inside the branch callback, is there any way to get the seqnum of the nodes that CPLEX would create by default? This would actually solve my problem.

    Thanks again,

    Gustavo
    Updated on 2014-03-25T01:07:49Z at 2014-03-25T01:07:49Z by iron-man
  • SystemAdmin
    SystemAdmin
    7929 Posts

    Re: Branching on semi-continuous variables

    ‏2011-05-03T08:47:21Z  
    • gangulo
    • ‏2011-04-19T22:46:21Z
    Tobias,

    I set CPX_PARAM_MIPCBREDLP to 1, but the function CPXgetcallbackindicatorinfo is not giving me any info (just the number of indicators). This is part of my branch callback

    <pre class="java dw" data-editor-lang="java" data-pbcklang="java" dir="ltr">status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, 0, CPX_CALLBACK_INFO_IC_NUM , &numindic); for(int i = 0; i < numindic; i++) { status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLYING_VAR , &implying); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLIED_VAR, &implied); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_SENSE, &sense); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_RHS, &rhs); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IS_FEASIBLE, &isfeas); cout << "x" << implying << " -> x" << implied << sense << rhs << endl; } </pre>

    There is no problem getting numindic, but the first and second lines inside the loop are crashing, and the remaining lines give me nothing. Is there any issue with the code, with some other parameter, or is it just impossible to access this information?

    By the way, inside the branch callback, is there any way to get the seqnum of the nodes that CPLEX would create by default? This would actually solve my problem.

    Thanks again,

    Gustavo
    Wow. This is a really long standing bug. CPXgetcallbackindicatorinfo() with CPX_CALLBACK_INFO_IC_IMPLYING_VAR and CPX_CALLBACK_INFO_IC_IMPLIED_VAR never worked since the introduction of the method in 2005.

    The next release will contain a fix for this bug.

    What happens due to the bug is that your 'implying' and 'implied' variables just stay unassigned. Unfortunately, there is no work-around with the current version.

    What do you mean with "the first and second lines inside the loop are crashing"? In our code I do not see anything that could make the code crash. Just, as I said, that the return value is not assigned.

    Btw: you are correctly catching the status of each CPX method call. But why aren't you checking it against zero? I would suggest to change your code to something like this:

    status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, 0, CPX_CALLBACK_INFO_IC_NUM , &numindic);
       if ( status ) goto TERMINATE;
     
       for(int i = 0; i < numindic; i++)
       {
          status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLYING_VAR , &implying);
          if ( status ) goto TERMINATE;
     
          status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLIED_VAR, &implied);
          if ( status ) goto TERMINATE;
     
          status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_SENSE, &sense);
          if ( status ) goto TERMINATE;
     
          status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_RHS, &rhs);
          if ( status ) goto TERMINATE;
     
          status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IS_FEASIBLE, &isfeas);
          if ( status ) goto TERMINATE;
     
          cout << "x" << implying << " -> x" << implied << sense << rhs << endl;
       }
     
    TERMINATE:
     
       if ( status ) {
          char err[1024];
          CPXgeterrorstring(env, status, err);
          cout << err << endl;
       }
    
    Updated on 2014-03-25T01:08:28Z at 2014-03-25T01:08:28Z by iron-man
  • SystemAdmin
    SystemAdmin
    7929 Posts

    Re: Branching on semi-continuous variables

    ‏2011-05-03T09:23:42Z  
    • gangulo
    • ‏2011-04-19T22:46:21Z
    Tobias,

    I set CPX_PARAM_MIPCBREDLP to 1, but the function CPXgetcallbackindicatorinfo is not giving me any info (just the number of indicators). This is part of my branch callback

    <pre class="java dw" data-editor-lang="java" data-pbcklang="java" dir="ltr">status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, 0, CPX_CALLBACK_INFO_IC_NUM , &numindic); for(int i = 0; i < numindic; i++) { status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLYING_VAR , &implying); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IMPLIED_VAR, &implied); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_SENSE, &sense); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_RHS, &rhs); status = CPXgetcallbackindicatorinfo(env, cbdata, wherefrom, i, CPX_CALLBACK_INFO_IC_IS_FEASIBLE, &isfeas); cout << "x" << implying << " -> x" << implied << sense << rhs << endl; } </pre>

    There is no problem getting numindic, but the first and second lines inside the loop are crashing, and the remaining lines give me nothing. Is there any issue with the code, with some other parameter, or is it just impossible to access this information?

    By the way, inside the branch callback, is there any way to get the seqnum of the nodes that CPLEX would create by default? This would actually solve my problem.

    Thanks again,

    Gustavo
    I have to correct myself: Daniel just saw the reason why there was a segmentation fault with the combination of MIPCBREDLP = 1 and querying the two indicator infos.

    Will be fixed in the next release.