Decision Optimization

Decision Optimization

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

 View Only
  • 1.  Problem solving LP within user cut callback

    Posted Thu March 21, 2019 10:44 AM

    Originally posted by: BrunoAsiv


    Hi,

     

    I have a user cut callback in which I create a LP. When I solve this LP, some of the variables take values that are outside the bounds I have set for them: they have negative values even though they are supposed to be >= 0.

     

    I have tested their bounds with getLB() just before and after solving the problem and the bounds seem to be in place. I check the variable values right after solving the problem so I don't think it's possible for them to be changed from their optimal solution values. Also, when I use cplex "interactively" to read the .lp file which I export right before solving the problem in my c++ code, I get a solution where the variables do respect their bounds. The problem described in the .lp file matches the theoretical formulation I'm aiming for.

     

    Any ideas on what could be the cause of this problem?

     

    Here is a condensed version of my usercut callback code up to where I solve the LP. I have removed the irrelevant parts:


     

    ILOUSERCUTCALLBACK4(UserCutCallback2, IloModel, model_cb, IloNumVarArray, var_cb, IloBoolVarArray, bool_var_cb, adjacency_list_t, adjacency_list5)
    {
    
        IloEnv masterEnv = getEnv();
    
        IloEnv env_uccb;
        IloModel model_uccb(env_uccb);
        IloObjective objec_uccb = IloMinimize(env_uccb);
        IloNumVarArray var_gamma_uccb(env_uccb);
        IloNumVarArray var_gamma_y_uccb(env_uccb);
        IloNumVarArray var_gamma_1y_uccb(env_uccb);
        IloNumVarArray var_theta_uccb(env_uccb);
        IloRangeArray con_1_uccb(env_uccb);
        IloRangeArray con_2_uccb(env_uccb);
        IloRangeArray con_3_uccb(env_uccb);
    
        for(int i = 0; i < number_of_y; i++)
        {
            stringstream sss;
            sss << "gamma_" << i;
            var_gamma_uccb.add(IloNumVar(env_uccb, 0.0, IloInfinity));
            var_gamma_uccb[i].setName(sss.str().c_str());
            
            sss.str(std::string());
            sss << "gamma_Y_" << i;
            var_gamma_y_uccb.add(IloNumVar(env_uccb, 0.0, IloInfinity));
            var_gamma_y_uccb[i].setName(sss.str().c_str());
            
            sss.str(std::string());
            sss << "gamma_1-Y_" << i;
            var_gamma_1y_uccb.add(IloNumVar(env_uccb, 0.0, IloInfinity));
            var_gamma_1y_uccb[i].setName(sss.str().c_str());
        }
    
        for(int i = 0; i < number_of_nodes; i++)
        {
            stringstream sss;
            sss << "theta_" << i;
            var_theta_uccb.add(IloNumVar(env_uccb));
            var_theta_uccb[i].setName(sss.str().c_str());
        }
        
        
    
        for(int mg = 0; mg < number_of_y; mg++)
        {
            objec_uccb.setLinearCoef(var_gamma_y_uccb[mg], getValue(bool_var_cb[mg]));
            objec_uccb.setLinearCoef(var_gamma_1y_uccb[mg], (1 - getValue(bool_var_cb[mg])));
        }
        model_uccb.add(objec_uccb);
    
        for( int b = 0; b < links.size(); b++ )
                {
                    
                    //building the benders subproblem dual (1)
                    IloExpr expa(env_uccb);                                                                                        //building part of constraints group #1
                    cout << "orii: " << links[b][0] << "   dest: " << links[b][1] << "\n";
                    expa += (1) * var_theta_uccb[links[b][0] - 1];                                                                //add theta i
                    expa += (-1) * var_theta_uccb[links[b][1] - 1];                                                                //add theta j
                    con_1_uccb.add(expa >= -(omega * adjacency_list5[link_order[b][0]][link_order[b][1]].weight2));                //add rht (base utility * omega)
                    expa.end();
                                    
                    
                }
    
        for ( int mg = 0; mg < number_of_y; mg++)
                {
                    
                    //building the benders subproblem dual (2)
                    cout << "This res is on arc: " << whys[mg][0] << "\n";
                    IloExpr expa(env_uccb);                                                                            //building constraints group #2
                    expa += (1) * var_gamma_uccb[mg];                                                                //add gamma
                    expa += (1) * var_gamma_y_uccb[mg];                                                                //add gamma y
                    expa += (-1) * var_gamma_1y_uccb[mg];                                                            //add gamma 1 - y
                    con_2_uccb.add(expa >= bigeps[mg][d]);
                    expa.end();
    
                    
                                                                                                                    //completing constraints group #1
                    con_1_uccb[whys[mg][0]].setLinearCoef(var_gamma_uccb[mg], -1);                                    //add gamma
                    con_1_uccb[whys[mg][0]].setLinearCoef(var_gamma_1y_uccb[mg], 1);                                //add gamma 1 - y
                    
                    
                    model_uccb.add(con_1_uccb);                                                                        //add con 1 to model
                    model_uccb.add(con_2_uccb);                                                                        //add con 2 to model
                    
                }
    
            if(odpairs[f][(d+1) * 2] > 0)
                    {
                        
                        //building the benders subproblem dual (3)
                        cout << "    od pair: " << f << endl << endl;
                        cout << "ori: " << odpairs[f][0] << "   desti: " << odpairs[f][1] << "\n";
                        
    
                        objec_uccb.setLinearCoef(var_theta_uccb[odpairs[f][1] - 1], (-1));
                        
                        
                        
                        IloExpr expa(env_uccb);
                        expa += (1) * var_theta_uccb[odpairs[f][0] - 1];
                        con_3_uccb.add(expa == 0);
                        expa.end();
                        
                        
                        
                        model_uccb.add(con_3_uccb);
                        
                        
                        IloCplex cplex_uccb(model_uccb);
                        
                        std::stringstream p_name;
                        
                        
                        nb_iter2++;
                        p_name << "uccb_prob_" << usercut_call_back_counter - 1 << "_" << nb_iter2 << ".lp";
                      
                        cplex_uccb.exportModel(p_name.str().c_str());
                        
                        float obj_value = 0;
                                           
                        
                        for(int i = 0; i < number_of_y; i++)
                        {
                            cout << var_gamma_uccb[i].getLB() << "\n";
                            cout <<  var_gamma_y_uccb[i].getLB() << "\n";
                            cout << var_gamma_1y_uccb[i].getLB() << "\n";
                        }
                        
                        if(1 == 1)                                                                                            //change to proper check later
                        {
                            // Optimize the problem and obtain solution.
                            if ( !cplex_uccb.solve() ) {
                                env_uccb.error() << "Failed to optimize UCCB" << endl;
                                throw(-1);
                            }
                            
                            obj_value = cplex_uccb.getObjValue();
                            
                            cout << "\n\nprint out of gammas\n\n";
                            cout << "gamma        gamma y         gamma 1-y\n";
                            
                            for( int vv = 0; vv < number_of_y; vv++)
                            {
                                cout << cplex_uccb.getValue(var_gamma_uccb[vv]) << "      " << getValue(var_gamma_y_uccb[vv]) << "      " << getValue(var_gamma_1y_uccb[vv]) << "\n";
                            }
                            cout << "\n\n";
                        }
    

    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Problem solving LP within user cut callback

    Posted Thu March 21, 2019 12:57 PM

    What exactly are those negative values? Could it be that you just get slightly negative values like -1e-10 or so? That would probably roundoff errors due to finite precision arithmetic.


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: Problem solving LP within user cut callback

    Posted Thu March 21, 2019 03:04 PM

    Originally posted by: BrunoAsiv


    Here's an example:

    This corresponds to the output of lines 144-147 in my code sample.

     

    gamma        gamma y         gamma 1-y
    0                      -27.7424      -56.4527
    0                     -30.9848      -27.7424
    0                     -15.6212      -30.9848
    0                      66.1477            20
    0                      33.0739      66.1477
    0                          40                -0

     

    I can provide the associated instance in .lp format if needed.

     

    edit: I found the reason; I had to use cplex_uccb.getValue(...) instead of simply getValue(). I find it strange that simply calling getValue(...) returns a (seemingly random) value at all though...

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: Problem solving LP within user cut callback

    Posted Fri March 22, 2019 02:20 AM

    getValue() calls this->getValue(), hence it returns the variable values for the current node (the one for which the callback was invoked). It is strange that this worked since the variables you are querying are not part of that model ...


    #CPLEXOptimizers
    #DecisionOptimization