Hello,

I'm having troubles understanding how to get the values of the incumbent solution in a heuristic callback and I would be very grateful if someone could help me. It's been troubling me for hours and I see no way to solve the problem on my own. I suspect it has a simple solution, probably related to basic cplex usage.

To illustrate my problem I took the example of a heuristic callback given in iloadmipex2.cpp (C++ implementation). I receive the error message "Concert exception caught: The referenced IloExtractable has not been extracted by the IloAlgorithm", but I "know" that the variables are in the model as without the callback the code works fine. Please take a look at the (pseudo) code below. For simplicity I omit the function that reads input data from my file (can provide it if needed).

//THIS IS THE EXAMPLE GIVEN IN iloadmipex2.cpp
// I changed the parameter from IloNumVarArray to IloBoolVarArray
ILOHEURISTICCALLBACK1(Rounddown, IloBoolVarArray, vars) {
   IntegerFeasibilityArray feas;
   IloNumArray             obj;
   IloNumArray             x;
   try {
      feas = IntegerFeasibilityArray(getEnv());
      obj  = IloNumArray(getEnv());
      x    = IloNumArray(getEnv());
      getFeasibilities(feas, vars); //HERE IS WHERE THE EXCEPTION/ERROR IS THROWN
      getObjCoefs     (obj , vars);
      getValues       (x   , vars);

      IloNum objval = getObjValue();
      IloInt cols   = vars.getSize();
      for (IloInt j = 0; j < cols; j++) {
         // Set the fractional variable to zero and update the objective value
         if ( feas[j] == Infeasible ) {
            objval -= x[j] * obj[j];
            x[j] = 0.0;
         }
      }
      setSolution(vars, x, objval);
   }
   catch (...) {
      feas.end();
      obj.end();
      x.end();
      throw;
   }
   feas.end();
   obj.end();
   x.end();
}

//MY CODE STARTS HERE
int main(){
    IloEnv env;
    try{    
            IloModel model(env);
        IloBoolVarArray X(env, pd._n_sets+1);

                //read the data via my method - not important for the problem
        problem_description pd = readInstance("benchmarks\\scp4x\\scp41.txt");

                //build the model - I think this is not so important
        for(int i = 0; i < pd._n_variables; i++){
            IloBoolExpr exp(env);
            for(unsigned int j = 0; j < pd._cover_info[i].size(); j++){
                exp += X[pd._cover_info[i][j]];
            }
            model.add(exp >= k);
        }

        IloIntExpr obj(env);
        for(int i = 0; i < pd._n_sets; i++){
            obj += X[i+1];          
        }
        model.add(IloMinimize(env, obj));

        IloCplex cplex(model);
                //IF I COMMENT OUT THIS cplex.use LINE IT WORKS AS EXPECTED
        cplex.use(Rounddown(env, X));

        cplex.setParam(IloCplex::Threads, 1);
        cplex.setParam(IloCplex::MIPSearch, 1); //use traditional branch and cut

        cplex.solve();

        cout << "Objective value: " << cplex.getObjValue() << endl;

        for(int i = 1; i <= pd._n_sets; i++){
            cout << i << ": " << cplex.getValue(X[i]) << endl;
        }
        env.end();
        system("pause");
    }
    catch (IloException& e) {
      cerr << "Concert exception caught: " << e << endl;
   }
   catch (...) {
      cerr << "Unknown exception caught" << endl;
   }
    return 0;
}

Even if I create a global pointer to X, and pass it in the callback, it still reports an error. Perhaps it has something to do with the fact that cplex does preprocessing, but still without the callback it works as expected. It is very puzzling for me. I would very much appreciate your help.

asked 28 Sep '16, 18:04

Emir's gravatar image

Emir
157
accept rate: 0%

edited 28 Sep '16, 18:13


Defining the X vector in the main routine is not enough. Unless every X[i] appears in at least one constraint, or the objective function, you're in trouble. If X[j] is never used, it won't be extracted -- but it will be in the argument passed to the callback, causing the line that throws the exception to look for feasibility info on it.

If the model is not too big, you can export it to a .lp file (human readable) and then see if you can find a reference to each and every X[i]. Alternatively, you can just add a loop that executes model.add(X[j]) for each j. This works in the Java API, convincing CPLEX to extract even variables that do not appear in the model, so it should work in the C++ API. Of course, the feasibility, objective coefficients and values will be meaningless.

link

answered 28 Sep '16, 18:49

Paul%20Rubin's gravatar image

Paul Rubin ♦♦
14.6k412
accept rate: 19%

Thank you for your quick reply! You might be right, since now I realize that X[0] is not used in the model. I missed that. Sadly I cannot check this now, but will do si first thing tomorrow.

(28 Sep '16, 18:58) Emir

Indeed, it seems that you were correct. As I stated above, the issue was that I allocated one more element in the array X then I really needed.

Thank you for your help. I really appreciate it.

(29 Sep '16, 11:24) Emir
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×191
×30
×21
×10
×2

Asked: 28 Sep '16, 18:04

Seen: 1,162 times

Last updated: 29 Sep '16, 11:24

OR-Exchange! Your site for questions, answers, and announcements about operations research.