0

I'm solving a LP with CPLEX using the Java API. I build my model with the methods provided (like cplex.numVar(col, lb, ub) and cplex.addLe()) After optimization is done, I'm interested in reading the simplex tableau of the final iteration (to be precise: not only the duals and reduced costs but also the coefficients inside the tableau).

I tried to access the IloLPMatrix object cplex.LPMatrix(), but this only returns an empty matrix. I'm interested in the "filled" matrix associated to the problem I just solved.

So, how can I read the simplex tableau?

halfer
  • 19,824
  • 17
  • 99
  • 186

2 Answers2

0

In CPLEX_Studio128\cplex\examples\src\java you could have a look at the example LPex1.java.

halfer
  • 19,824
  • 17
  • 99
  • 186
Alex Fleischer
  • 9,276
  • 2
  • 12
  • 15
0

The short answer is that you cannot access the simplex tableau with the Concert (Java/.NET/C++) APIs. You can access this advanced feature with the C Callable Library and Python APIs, though. For example, see CPXXbinvarow and examining the simplex tableau in the Python API.

Now, to clear up your possible confusion with what IloLPMatrix does, consider the following (mostly cribbed from this thread on the official IBM developerWorks forum).

If you add constraints to the model with cplex.addLe() then you can use rangeIterator to access them (and possibly conversionIterator, SOS1Iterator, SO2Iterator). Note that when you use rangeIterator you have to figure out the runtime type of an expression before you can get at the coefficients. For example:

for (Iterator it = cplex.rangeIterator(); it.hasNext(); /* nothing */) {
   IloRange range = (IloRange)it.next();
   IloNumExpr expr = range.getExpr(); // Cannot get the coefficients of expr directly :-(
   if (expr instanceof IloLinearNumExpr) {
      IloLinearNumExpr linExpr = (IloLinearNumExpr)expr;
      for (IloLinearNumExprIterator jt = linExpr.linearIterator(); jt.hasNext(); /* nothing */) {
          IloNumVar var = jt.nextNumVar();
          double coef = jt.getValue();
          ...
       }
   }
   else if (expr instance of ...) {
      ...
   }
}

On the other hand, if you build your model with an IloLPMatrix, then you can access it with LPMatrixIterator. When you call cplex.LPMatrix it "Creates and returns an empty LP matrix object." You then have to fill it and add it to the model. Alternately, you can use addLPMatrix to create and add it in one step (you still need to populate it).

For example:

// Create a matrix in which we setup the model.
IloLPMatrix matrix = cplex.LPMatrix();

// Create variables.
IloNumVar x = cplex.numVar();
IloNumVar y = cplex.numVar();
matrix.addCols(new IloNumVar[]{ x, y });

// Create constraint x + y <= 2.
IloLinearNumExpr lhs = cplex.linearNumExpr();
lhs.addTerm(x, 1.0);
lhs.addTerm(y, 1.0);
matrix.addRow(cplex.le(lhs, 2.0));

// When all constraints are setup add the matrix to the model.
cplex.add(matrix);

Note that you can only add linear constraints when using an IloLPMatrix.

Whether you use the first method to build your model and rangeIterator to access it, or the second method and LPMatrixIterator, is a matter of taste and possibly some performance trade-offs; you'd have to experiment with both approaches.

rkersh
  • 4,447
  • 2
  • 22
  • 31
  • Thank you very much for your answer! I (falsely) expected `clpex.getLPMatrix()` to return a matrix for the current model... Though, I still have some questions... Using your first code-snippet, can I access any other information than the _original_ coefficients? (This won't help, since I already know them) Do you know, why it's not possible to access the simplex tableau? I would assume, this is a common use case... – Markus Seizinger Jul 04 '18 at 06:40
  • The techniques in the code snippets are there to access the original coefficients. Indeed, it is not very useful unless you are reading in a model, etc., where you did not build it in the first place. – rkersh Jul 05 '18 at 16:00
  • As the documentation for `CPXXbinvarow` indicates, it is considered an "advanced routine". If you search for "tableau" on the official [IBM developerWorks forum](https://www.ibm.com/developerworks/community/forums/html/forum?id=11111111-0000-0000-0000-000000002059) you'll see that it is not something that comes up very often. Surely, if there were greater demand for this functionality it would have been in the product long ago. – rkersh Jul 05 '18 at 16:00