dimanche 23 décembre 2018

Set global incumbent solution at arbitrary moment in time

We are using CPLEX 12.8 to solve an MIP, and in parallel, we have a heuristic that solves the same problem. The currently best solution obtained by the heuristic is stored in a global variable (g_bestSolHeuristic and g_bestObjHeuristic) that is also accessible by the CPLEX implementation.

At the moment, we use the heuristic callback (see code at the bottom of this question) provided by CPLEX to check whether the heuristic has found a solution better than the current best integer solution known to CPLEX. If so, then we feed this solution to CPLEX with the "setBounds, solve, setSolution" paradigm.

However, the problem is that the solution given by the heuristic is globally feasible but might not be feasible in the current node from which the heuristic callback is called. In that case, the heuristic callback tries at every node to provide a new solution (which will be rejected) until a node is reached in which the solution is also locally feasible. For most instances this is not really an issue, however, sometimes this causes the heuristic callback to take up to 50% of the total runtime (which is not accepted by any sane person).

Is there a better way to feed the new solution (that is guaranteed to be globally feasible) to CPLEX?

ILOHEURISTICCALLBACK1(CALLBACK_HEUR, ModelA &, model)
{
try
{
  // Only provide new solution if better than current best incumbent

  if (g_bestObjHeuristic >= getIncumbentObjValue())
    return;

  // Transform g_bestSolHeuristic into CPLEX variables

  IloNumArray vals    = IloNumArray(model.d_env);
  IloNumVarArray vars = IloNumVarArray(model.d_env);

  for (int i = 0; i != model.d_nNodes; ++i)
  {
    for (int j = 0; j != model.d_nNodes; ++j)
    {
      int const value = g_bestSolHeuristic[i][j]._a;

      if (value != 1)
        continue;

      vals.add(value);
      vars.add(model.d_x[i][j]);
    }
  }

  // Feed the solution to CPLEX
  setBounds(vars, vals, vals);

  if (not solve())
    cout << "\n--\n-- New heuristic solution (" << g_bestObjHeuristic << " vs " << getIncumbentObjValue() << ") is not accepted (ModelA::heuristicCallback)\n--\n";

  else
    setSolution(vars, vals, g_bestObjHeuristic);

  vals.end();
  vars.end();
}

catch (IloException e)
{
 cout << e << endl;
}

}

Aucun commentaire:

Enregistrer un commentaire