Getting at the Solution

It is often the case with CLP that there is more than one way to do something. This is a consequence of CLP's mixed heritage as a child of OSL and a cousin of OSI. Finding the status of a model exemplifies this situation.

The OSI way to check for optimality is to call model.isProvenOptimal(). Also available are isProvenPrimalInfeasible(), isProvenDualInfeasible(), isPrimalObjectiveLimitReached(), isDualObjectiveLimitReached(), isIterationLimitReached() or the feared isAbandoned(). Should one prefer the OSL way of doing things, model.status() returns as it would in OSL, so 0 means optimal, 1 means primal infeasible etc.

Similarly, to pick up the solution values, one could inhabit the virtuous world of OSI, or the not-quite-so-virtuous world of OSL and "pure" CLP. By this it is meant that const and non-const forms of arrays are used, respectively. It is easier to deal with the non-const versions, so most of the elaborate algorithms in CLP and its Samples use them.

Table 2.1.  Methods for getting solution information

Purpose OSI-style (virtuous) CLP-style (less virtuous)
Primal column solution const double * getColSolution() double * primalColumnSolution()
Dual row solution const double * getRowPrice() double * dualColumnSolution()
Primal row solution const double * getRowActivity() double * primalRowSolution()
Dual row solution const double * getReducedCost() double * dualColumnSolution()
Number of rows in model int getNumRows() int numberRows()
Number of columns in model int getNumCols() int numberColumns()

The reader may have noted a preference for "number" over "num" and "column" over "col". This may be a reaction to when one of the authors was young and 5 or 6 letters was the maximum in FORTRAN for any name or to early days with OSL when seven characters were allowed but the first three had to be "ekk"!

Using the above-listed functions, our initial example might be continued as follows:

Example 2.2.  Possible extension of minimum.cpp

    
  int numberRows = model.numberRows();
  double * rowPrimal = model.primalRowSolution();
  double * rowDual = model.dualRowSolution();

  int iRow;

  for (iRow=0;iRow<numberRows;iRow++) 	
    printf("Row %d, primal %g, dual %g\n",iRow,
	rowPrimal[iRow],rowDual[iRow]);
	
  int numberColumns = model.numberColumns();
  double * columnPrimal = model.primalColumnSolution();
  double * columnDual = model.dualColumnSolution();

  int iColumn;

  for (iColumn=0;iColumn<numberColumns;iColumn++) 	
    printf("Column %d, primal %g, dual %g\n",iColumn,
	columnPrimal[iColumn],columnDual[iColumn]);
  
  

This code sample would pretty-print information about the model's primal and dual solutions. How to additionally print row and column names is illustrated in the defaults.cpp file in the "Samples" directory (the Samples are properly addressed in Chapter 4, More Samples ). This sample is also useful as it explicitly performs default actions (e.g. it sets the primal feasiblility tolerance value to the default value).

The remainder of this chapter will show more of the basic CLP tasks a user might wish to perform. Apart from presolve we will only be looking at actions which can be performed when including the single header file COIN/Clp/include/ClpSimplex.hpp.