Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.

 View Only
  • 1.  How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Mon December 14, 2015 11:47 PM

    Originally posted by: AdamWang


    Hello,

    I am solving an mip problem by the branch and cut algorithm through cplex c++ interface. I defined a lazy constraint callback to help add the inequalities (cuts) generated from separation to the current explored node. It is known that cplex will add the user-defined cuts to current node and reoptimize, this process iterates until no more cuts are generated and then cplex head to node branching process. I wonder is it possible in cplex to set the maximum number of user-defined cuts that can be added to the current node, that is, for current node, to set the maximum number of times that cplex calls the lazy constraint callback written by me. In this way, if cplex exceeds the maximum allowed iteration times , it will head to branching process even though there are still some possible cuts that can be added. Thanks. 


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Wed December 16, 2015 09:57 AM

    Since you seem to be mixing terminology let us first clarify: are you talking about user cuts or lazy constraints here? See here to learn about the differences between the two.


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Wed December 16, 2015 09:05 PM

    Originally posted by: AdamWang


    Sorry that  I misunderstand the definitions of lazy and user cut. Actually here I say the user cuts, because the user cut callback can be called several times for one node. So I wonder whether I can set the maximum number of call times on the user cut callback for each node. Thanks.


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Thu December 17, 2015 01:37 AM

    There is no parameter to limit the number of user defined cuts added from a user cut callback.

    However, in your callback code you can easily count the number of cuts added so far yourself and stop after you reach a certain limit. Functions that may come in handy when implementing this include

    • getNodeId() -- returns the id of the current node. Use this to check whether the callback is invoked for the same node or for another node
    • setNodeData() -- store data in a node. The data is preserved across multiple invocations of a callback. You can use this to store in a node the number of cuts already separated at this node.
    • getNodeData() -- get the data set via getNodeData()

    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Tue December 13, 2016 08:43 AM

    Originally posted by: pegonzalez


    Dear Daniel,

    I tried to follow your idea, but unfortunately I've failed. 

    First of all I tried to create a global variable to store the current NodeId. Following that thought, verifing if Cur_Node == getNodeId() would tell me whether or not I am at the same node. The first problem I encountered is how to define my Cur_Node, since I can neither create it as NodeID type,  nor cast getNodeId() to int.

    Supposing that problem can be solved, I went with something like that:

     

    int Cur_Node = 0; //Global
    int cuts_per_node = 0; //Global

    ILOUSERCUTCALLBACK2(CortesClique, ProblemInstance& , p, IloNumVarMatrix, y)
     {
        inicio:
        if(Cur_Node == getNodeNumber(getNodeId()) ){

            if(cuts_per_node<11){
                graph_t* G = graph_new(p.NbNode_Proib);

                for (unsigned int i = 0; i < p.NPOINTS; ++i)
                {
                    for(unsigned int r = 0; r < p.point[i].NumRadii ; ++r){
                        G->weights[p.mapIRToNode[make_pair(i,r)]] = getValue(y[i][r]);
                    }
                }

                for(int i = 0; i<p.NbNode_Proib-1; ++i){
                    for(int j = i+1; j<p.NbNode_Proib; ++j){
                        if(p.DIST[p.mapNodeToIR[i].first][p.mapNodeToIR[j].first] < (p.RADII[p.mapNodeToIR[i].second] + p.RADII[p.mapNodeToIR[j].second] - p.ALPHA[p.mapNodeToIR[i].second][p.mapNodeToIR[j].second])){
                            GRAPH_ADD_EDGE(G,i,j);
                        }
                    }
                }

                MaxWeightCliqueHeur CU(G);

                vector<int> Sol = CU.FindMaxWeightClique();


                double clique = CU.GetWeight(Sol);

                IloExpr Clique(getEnv());

                if(clique >= 1){
                    for(vector<int>::iterator it=Sol.begin(); it != Sol.end(); ++it){
                        Clique+=y[p.mapNodeToIR[*it].first][p.mapNodeToIR[*it].second];
                    }
                    add(Clique<=1);
                    cuts_per_node++;
                }
            }
        }else{
           Cur_Node = getNodeNumber(getNodeId())    ;
            cuts_per_node = 0;
            goto inicio;
        }

    }

     

    Can you help me make that work ?

     

    Best regards.

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Tue December 13, 2016 03:33 PM

    Here is a small code snippet that illustrates how to use node user data to keep track of the number of cuts at a search tree node. I think this is better/simpler code than using the NodeId to keep track of the current node.

    /** A simple struct that keeps track of the number of cuts added at
     * a particular search tree node.
     */
    struct CutCount : public IloCplex::MIPCallbackI::NodeData {
       int added;
       CutCount() : added(0) {}
    };
    
    ILOUSERCUTCALLBACK2(CortesClique, ProblemInstance& , p, IloNumVarMatrix, y) {
       // Get this node's user data. It is either nil or an instance of CutCount.
       NodeData *data = getNodeData();
       CutCount *cutCount;
    
       if ( !data ) {
          // This is the first time we are invoked at this node. Create a new
          // instance of CutCount to count the number of cuts added at this node.
          // Then register this new instance as the current node's user data.
          cutCount = new CutCount();
          setNodeData(cutCount);
       }
       else {
          // Not the first time we are invoked at this node.
          cutCount = dynamic_cast<CutCount *>(data);
       }
    
       // Now add the separation code. You can use cutCount->added to check
       // how many cuts were added at the current node and also update that
       // field.
       if ( cutCount->added < 11 ) {
          // Less than 11 cuts added so far. Separate and add a new one.
          IloRange r;
          // Populate the cut here.
          // ...
          // Add the cut and increment cut counter for current node.
          add(r).end();
          cutCount->added++;
       }
    }
    

    If you want to stick with using NodeId, then you can use the field NodeId::_id which is an integer type and gives the unique node id. This info can be obtained from the ilocplex.h header file:

        struct NodeId {
          CPXLONG _id;
          int operator==(const NodeId& nodeid) const {
             return ( nodeid._id == _id);
          }

          int operator!=(const NodeId& nodeid) const {
             return ( nodeid._id != _id);
          }
        };


    #CPLEXOptimizers
    #DecisionOptimization


  • 7.  Re: How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Thu December 12, 2019 01:08 PM

    Originally posted by: lbr33


    Dear Daniel,

     

    Besides setting the maximum number of cuts that can be added to the current node via userCut, I want to control in which node(only the ones that are in an specifc depth of the branch-and-bound tree) the separation of this cut are allowed

    I manage to do it separately.
    To set a maximum number of cuts, I use the code that you had posted before.
    To choose the depth of the nodes I use the approach below:
    

    ILONODECALLBACK0(nodecallback) {
       IloInt64 nextNode = 0;
       Depth *depth = new Depth(getDepth(nextNode));
       NodeData *old = setNodeData(nextNode, depth); // Replace node data in nextNode
       if ( old )  delete old;                       // Delete old node data (if there was any)
    }

    Depth const* const d = (Depth *)getNodeData();
    IloInt depth = d ? d->depth : 0;

    if (depth % 5 == 0 ){
      //separate the node

    }

     

    However, how can I impose the two constraints at the same time?

     

    Thank you!

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 8.  Re: How to set maximum number of user-defined cuts added to a node in branch and cut

    Posted Fri December 13, 2019 06:59 AM

    As of the just released version 12.10 you can query the depth of a node from the cut callback directly, see https://www.ibm.com/developerworks/community/forums/html/topic?id=745cdcec-ae7e-4354-b9d9-9683f9aff74b

    If you want to stick with older versions, then I think you are already there: You use ann ILOUSERCUTCALLBACK and an ILONODECALLBACK. Then in the cut callback you just add your code at the beginning:

    Depth const* const d = (Depth *)getNodeData();
    IloInt depth = d ? d->depth : 0;

    if (depth % 5 != 0 ){
     return;

    }


    #CPLEXOptimizers
    #DecisionOptimization