-->

CPLEX - Error in accessing solution C++

2019-08-17 00:58发布

问题:

I have a problem in accessing the solution of a LP problem.

This is the output of CPLEX after calling cplex.solve();

 CPXPARAM_MIP_Strategy_CallbackReducedLP          0
 Found incumbent of value 0.000000 after 0.00 sec. (0.70 ticks)
 Tried aggregator 1 time.
 MIP Presolve eliminated 570 rows and 3 columns.
 MIP Presolve modified 88 coefficients.
 Reduced MIP has 390 rows, 29291 columns, and 76482 nonzeros.
 Reduced MIP has 29291 binaries, 0 generals, 0 SOSs, and 0 indicators.
 Presolve time = 0.06 sec. (49.60 ticks)
 Tried aggregator 1 time.
 Reduced MIP has 390 rows, 29291 columns, and 76482 nonzeros.
 Reduced MIP has 29291 binaries, 0 generals, 0 SOSs, and 0 indicators.
 Presolve time = 0.04 sec. (31.47 ticks)
 Probing time = 0.02 sec. (1.36 ticks)
 MIP emphasis: balance optimality and feasibility.
 MIP search method: dynamic search.
 Parallel mode: deterministic, using up to 8 threads.
 Root relaxation solution time = 0.03 sec. (17.59 ticks)

    Nodes                                         Cuts/
Node  Left     Objective  IInf  Best Integer    Best Bound    ItCnt     Gap

*     0+    0                            0.0000     -395.1814              --- 
*     0+    0                         -291.2283     -395.1814            35.69%
*     0     0      integral     0     -372.2283     -372.2283      201    0.00%
 Elapsed time = 0.21 sec. (131.64 ticks, tree = 0.00 MB, solutions = 3)

 Root node processing (before b&c):
   Real time             =    0.21 sec. (133.18 ticks)
 Parallel b&c, 8 threads:
   Real time             =    0.00 sec. (0.00 ticks)
   Sync time (average)   =    0.00 sec.
   Wait time (average)   =    0.00 sec.
                      ------------
 Total (root+branch&cut) =    0.21 sec. (133.18 ticks)

However when I call cplex.getValues(values, variables); the program gives a SIGABRT signal throwing the following exception:

libc++abi.dylib: terminating with uncaught exception of type IloAlgorithm::NotExtractedException

This is my code. What I'm doing wrong?

std::vector<links_t> links(pointsA.size()*pointsB.size());

std::unordered_map<int, std::vector<std::size_t> > point2DToLinks;

for(std::size_t i=0; i<pointsA.size(); ++i){

  for(std::size_t j=0; j<pointsB.size(); ++j){

    std::size_t index = (i*pointsA.size()) + j;

    links[index].from = i;
    links[index].to   = j;

    links[index].value = cv::norm(pointsA[i] - pointsB[j]);

    point2DToLinks[pointsA[i].point2D[0]->id].push_back(index);
    point2DToLinks[pointsA[i].point2D[1]->id].push_back(index);
    point2DToLinks[pointsA[i].point2D[2]->id].push_back(index);

    point2DToLinks[pointsB[j].point2D[0]->id].push_back(index);
    point2DToLinks[pointsB[j].point2D[1]->id].push_back(index);
    point2DToLinks[pointsB[j].point2D[2]->id].push_back(index);

  }

}

std::size_t size = links.size() + point2DToLinks.size();

IloEnv environment;

IloNumArray coefficients(environment, size);

for(std::size_t i=0; i<links.size(); ++i)    coefficients[i] = links[i].value;
for(std::size_t i=links.size(); i<size; ++i) coefficients[i] = -lambda;

IloNumVarArray variables(environment, size, 0, 1, IloNumVar::Bool);

IloObjective objective(environment, 0.0, IloObjective::Minimize);

objective.setLinearCoefs(variables, coefficients);

IloRangeArray constrains = IloRangeArray(environment);

std::size_t counter = 0;

for(auto point=point2DToLinks.begin(); point!=point2DToLinks.end(); point++){

  IloExpr expression(environment);

  const std::vector<std::size_t> & inLinks = point->second;

  for(std::size_t j=0; j<inLinks.size(); j++) expression += variables[inLinks[j]];

  expression -= variables[links.size() + counter];

  constrains.add(IloRange(environment, 0, expression));

  expression.end();

  ++counter;

}

IloModel model(environment);

model.add(objective);
model.add(constrains);

IloCplex cplex(model);

cplex.solve();

if(cplex.getStatus() != IloAlgorithm::Optimal){
  fprintf(stderr, "error: cplex terminate with an error.\n");
  abort();
}

IloNumArray values(environment, size);

cplex.getValues(values, variables);

for(std::size_t i=0; i<links.size(); ++i)
  if(values[i] > 0) pairs.push_back(links[i]);

environment.end();

回答1:

This is an error that happens if you ask CPLEX for the value of a variable that CPLEX does not have in its model. When you build the model, it is not enough to just declare and define the variable for it to be included in the model. It also has to be part of one of the constraints or the objective in the model. Any variable that you declare/define that is NOT included in one of the constraints or the objective will therefore not be in the set of variables that gets extracted into the inner workings of CPLEX. There are two obvious things that you can do to resolve this.

First you can try to get the variable values inside a loop over the variables, and test whether each is actually in the cplex model - I think is is something like cplex.isExtracted(var). Do something simple like print a message when you come across a variable that is not extracted, telling you which variable is causing the problem.

Secondly you can export the model from CPLEX as an LP format file and check it manually. This is a very useful way to see what is actually in your model rather than what you think is in your model.



标签: c++ cplex