Decision Optimization

Decision Optimization

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


#Analytics
#DecisionOptimization
#DecisionOptimization
 View Only
  • 1.  Cut callback, Exception: Access violation

    Posted 02/22/12 08:54 AM

    Originally posted by: MatthiasWalter


    Dear Cplex community,

    I have a problem using a cut callback in a problem with binary variables (x[i][j], IloBoolVar).
    My system:
    Windows 7, 32 bit
    MS Visual Studio, C++
    Cplex 12.2

    As long as I use the user-cut pool via
    
    
    
    for(s=0; s < S; ++s)
    { ... MyUserCuts.add(expr >= rhsValue); ... 
    } cplex.addUserCuts(MyUserCuts);
    

    where expr is a sum of some binary variables x[i][[j] everything works fine.
    However, when I try to apply the same cuts using the macro ILOUSERCUTCALLBACK3 I get an error message from MS Visual Studio during execution (Exception: Access violation). I followed the example iloadmipex5.cpp and wrote:
    
    ILOUSERCUTCALLBACK3(CtCallback, IloExprArray, lhs, IloNumArray, rhs, IloNum, eps) 
    { IloInt IloIntNumCuts = lhs.getSize(); 
    
    for (IloInt i = 0; i < IloIntNumCuts ; i++) 
    { IloNum xrhs = rhs[i]; 
    
    if (xrhs < IloInfinity  &&  getValue(lhs[i]) < xrhs - eps)  
    { IloRange cut; 
    
    try 
    { cut = (lhs[i] >= xrhs); add(cut).end(); rhs[i] = IloInfinity; 
    } 
    
    catch (...) 
    { cut.end(); 
    
    throw; 
    } 
    } 
    } 
    }   
    
    void Instance::solve_MIP(...) ... IloExprArray lhs(env); IloNumArray rhs(env); 
    
    for(s=0; s < S; ++s)
    { IloExpr expr(env); 
    
    for(v=0; v < V; ++v)
    { 
    
    for(w=0; w < W; ++w)
    { expr += x[v][w]; 
    } 
    } lhs.add(expr); rhs.add(rhsValue); expr.end(); 
    } cplex.use(CtCallback(env, lhs, rhs, cplex.getParam(IloCplex::EpRHS)));
    

    The exception occurs when ILOUSERCUTCALLBACK3 is executed and lhs[i] is accessed. lhs.getSize() and rhs[i] return the expected values when ILOUSERCUTCALLBACK3 is executed. When lhs[i] is accessed in the member function Instance::solve_MIP no exception is thrown.
    In ILOUSERCUTCALLBACK3 the exception is thrown in the first loop execution (i = 0). All x[i][j] variables that are used to build the expression are extracted to the model.
    If I change the code to
    
    ... expr = x[0][0]; 
    } 
    } lhs.add(expr); ...
    

    then the exception occurs for i = lhs.getSize() - 1. If I omit this last loop iteration no exception is thrown.

    I have already tried different parameter settings with respect to IloCplex::MIPSearch, IloCplex::Reduce, IloCplex::PreLinear, IloCplex::PreInd and IloCplex::AggInd because I assumed that differences between the original model and the presolved model might cause the problem. But different settings did not help.

    I would be grateful for any advice.

    Kind regards
    Matthias Walter
    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Cut callback, Exception: Access violation

    Posted 02/22/12 10:14 AM

    Originally posted by: SystemAdmin


    You say that the exception occurs when lhs[i] is accessed. Which statement do you mean: 'getValue(lhs[i])' or 'lhs[i] >= xrhs'?
    Can you print out lhs[i] like this:
    std::cout << "lhs[" << i << "] (" + lhs.getSize() + "): " << lhs[i] << std::endl;
    

    at the beginning of the loop? Does this work or does this already throw the same exception? Does the printout look reasonable?
    Do you have a stack trace that you can show us? Did you define the NDEBUG macro when compiling your code? If so, does the problem persist if you undefine it?
    How many threads do you use? Did you change the number of threads explicitly or do you leave that at its default value?
    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: Cut callback, Exception: Access violation

    Posted 02/23/12 09:50 AM

    Originally posted by: MatthiasWalter


    Dear Daniel,

    thanks for the quick reply.
    The exception occurs for both 'getValue(lhs[i])' and 'lhs[i] >= xrhs' whatever I put first. I noticed that the exception even occurs outside of ILOUSERCUTCALLBACK3, i.e. in my function Instance::solve_MIP(...) where I build the IloExprArray lhs. When I try to print lhs like
    
    std::cout << 
    "lhs[" << i << 
    "] (" << lhs.getSize() << 
    "): " << lhs[i] << std::endl;
    

    only the getSize() part works. It returns the expected size of the array. lhs[i] causes an exception (access violation).

    In the following you will find the content of the call stack window of Microsoft Visual Studio (german language version). I am not sure if that is what you mean when you asked for the stack trace:

    Algorithms_MPSWAP_02.exe!IloControlCallbackManager::getValue() + 0x99 Bytes C++
    Algorithms_MPSWAP_02.exe!IloCplex::ControlCallbackI::getValue() + 0xd Bytes C++
    > Algorithms_MPSWAP_02.exe!CtCallbackI::main() Zeile 48 + 0x49 Bytes C++
    Algorithms_MPSWAP_02.exe!IloControlCallbackManager::call() + 0x30 Bytes C++
    Algorithms_MPSWAP_02.exe!IloCplexCallbackManager::call() + 0x4c Bytes C++
    Algorithms_MPSWAP_02.exe!_cutcallback@20() + 0xda Bytes C++
    cplex122.dll!10253222()
    http://Unten angegebene Rahmen sind möglicherweise nicht korrekt und/oder fehlen, keine Symbole geladen für cplex122.dll
    cplex122.dll!102cbc29()
    cplex122.dll!1025a3c2()
    cplex122.dll!1025cd12()
    cplex122.dll!10265baa()
    cplex122.dll!104f2780()
    cplex122.dll!100200cd()
    cplex122.dll!1027bef8()
    cplex122.dll!101eb11d()
    cplex122.dll!104f2dc3()
    cplex122.dll!101e927d()
    KernelBase.dll!75286cf2()
    cplex122.dll!101bd5b8()
    cplex122.dll!101e205e()
    cplex122.dll!101e4679()
    cplex122.dll!101e211e()
    cplex122.dll!101bd51d()
    cplex122.dll!1011e809()
    cplex122.dll!1011e816()
    Algorithms_MPSWAP_02.exe!IloCplexI::solve() + 0xd1 Bytes C++
    Algorithms_MPSWAP_02.exe!IloAlgorithm::solve() + 0x3d Bytes C++
    Algorithms_MPSWAP_02.exe!IloCplex::solve() Zeile 2804 + 0x2b Bytes C++
    Algorithms_MPSWAP_02.exe!Instance::solve_Standard_MIP_Cuts(int & cInst=1, std::basic_ofstream<char,std::char_traits<char> > & oFstreamOutputFile={...}, int & intTimeLim=15, int & intMaxNumProcedures=10, std::vector<std::vector<bool,std::allocator<bool> >,std::allocator<std::vector<bool,std::allocator<bool> > > > * xStartSol=http://...()) Zeile 680 + 0xb Bytes C++
    Algorithms_MPSWAP_02.exe!main(int argc=1, char * * argv=0x00862420) Zeile 155 C++
    Algorithms_MPSWAP_02.exe!__tmainCRTStartup() Zeile 266 + 0x12 Bytes C
    kernel32.dll!77011114()
    ntdll.dll!76edb299()
    ntdll.dll!76edb26c()

    The line
    > Algorithms_MPSWAP_02.exe!CtCallbackI::main() Zeile 48 + 0x49 Bytes C++
    refers to line 48 in my code, that is
    
    
    
    if (xrhs < IloInfinity  &&  getValue(lhs[i]) < xrhs - eps)  
    {
    

    where the exception occurs (it is the first time lhs[i] is encountered during execution).

    I am not sure if I defined/how to define the NDEBUG macro. In the project properties > C/C++ > Preprocessor > Preprocessor definitions the entry reads as follows:
    WIN32;NDEBUG;_CONSOLE;IL_STD
    If I delete NDEBUG from that list, the exception does also occur.

    I have the parameter specifying the number of threads at default (just like the other parameters). Log then says:
    >>MIP search method: traditional branch-and-cut.
    >>Parallel mode: none, using 1 thread.
    Though, if I set IloCplex::Threads to 2 (my maximum number of threads) log reads as:
    >>MIP search method: traditional branch-and-cut.
    >>Parallel mode: opportunistic, using up to 2 threads.
    In both cases the exception occurs.

    When I use the following code where I build the left-hand-side expression within the cut callback function everything works fine.
    
    ILOUSERCUTCALLBACK5(CtCallback, IloArray<IloBoolVarArray>, x, IloArray<IloNumArray>, rhs, Instance*, Inst, int&, intUserCut1Counter,  IloNum, eps)
    { 
    //Variable for the right-hand-side value IloNum xrhs; 
    
    for(
    
    int s = 0; s < Inst->S; ++s)
    { xrhs = rhs[s][…]; 
    
    if (xrhs < IloInfinity)
    { 
    //Variable to store the value of the left-hand-side of the cut IloNum lhs; lhs = 0; IloExpr expr(getEnv()); 
    
    for(v=0; v < V; ++v)
    { 
    
    for(w=0; w < W; ++w)
    { lhs += getValue(x[v][w]); expr += x[v][w]; 
    } 
    } 
    //If the solution is not feasible ... 
    
    if(lhs < xrhs - eps)
    { IloRange cut; 
    //... add the cut  
    
    try 
    { cut = (expr >= xrhs); add(cut); cut.end(); rhs[s][...] = IloInfinity; ++intUserCut1Counter; 
    //cout << endl << "User cut 1 applied." << endl; 
    } 
    
    catch (...) 
    { cut.end(); 
    
    throw; 
    } 
    } 
    } 
    } 
    }
    

    There I pass the vector x of decision variables via
    
    cplex.use(CtCallback(env, x, IloNumArrayCutRhs, this, intUserCut1Counter, cplex.getParam(IloCplex::EpRHS)));
    


    I hope this helps to let you identify the problem.

    Kind regards
    Matthias Walter
    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: Cut callback, Exception: Access violation

    Posted 02/23/12 11:25 AM

    Originally posted by: SystemAdmin


    Yes, this is exactly the information I was asking for. Since I am German as well I have no trouble reading it :-)
    Do I understand correctly that printing lhs[i] already fails in your function Instance::solve_MIP(...), even before you call IloCplex::solve()? If that is the case then we should try to track down why this happens.
    Is it possible that some of the IloNumVar instances you add to the expression are not initialized properly?
    Can you iterate manually over the expression like this:
    for (IloExpr::LinearIterator it = lhs[i].getLinearIterator(); it.ok(); ++it) {
      IloNumVar v = it.getNumVar();
      std::cerr << "v = " << v << std::endl;
    }
    

    Does this work or does this cause an exception as well? Does the printout look reasonable for all variables?
    By the way, do you call any end() function before you try to print out the expression? If so, does the problem persist if you do not call end()?
    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: Cut callback, Exception: Access violation

    Posted 02/23/12 11:29 AM

    Originally posted by: SystemAdmin


    I think the problem is the 'expr.end()' at the end of this loop:
    for(s=0; s < S; ++s){
       IloExpr expr(env);
       for(v=0; v < V; ++v){
          for(w=0; w < W; ++w){
             expr += x[v][w];
          }
       }
       lhs.add(expr);
       rhs.add(rhsValue);
       expr.end();
    }
    

    IloExprArray::add() does not create a deep copy of its argument, so you must not end() it. Does removing this call to IloExpr::end() fix the problem?
    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: Cut callback, Exception: Access violation

    Posted 02/24/12 04:29 AM

    Originally posted by: MatthiasWalter


    Yes, that’s the solution. If I do not call expr.end() no exception will occur. Now, I can access lhs[i] and the printout for
    for(int i = 0; i < lhs.getSize(); ++i){
                            cout << endl << lhs[i] << endl;
                    }
    

    is alright (eg. for i=0 it reads

    IloIntVar(1)[0..1] + IloIntVar(6)[0..1] + IloIntVar(11)[0..1] + IloIntVar(16)[0..1] + IloIntVar(26)[0..1] + IloIntVar(40)[0..1]).

    Thanks a lot for your help.

    Best regards
    Matthias Walter
    #CPLEXOptimizers
    #DecisionOptimization