[Coin-discuss] OsiSimplexInterface implementation for CPLEX (files are now attached)

Mikhail Nediak msnediak at rutcor.rutgers.edu
Thu Jul 11 12:53:29 EDT 2002


Dear COIN Community,

Some time ago we have promised to release a pivot-based simplex interface 
extensions to OSI. We now post a preliminary version of such interface
and its implementation for CPLEX. The following files are attached:

* OsiSimplexInterface.h -- an abstract class that defines all the methods
of the extended interface

* OsiCpxSimplexInterface.h -- a declaration of the OsiCpxSimplexInterface 
class which is a descendant of both OsiCpxSolverInterface and 
OsiSimplexInterface. We currently define setBasisStatus() and 
getBasisStatus() methods in addition to already available setWarmStart()
and getWarmStart(). They can probably be reimplemented in terms of
OsiWarmStartBasis. It is desirable, however, to make resize() operation
of OsiWarmStartBasis more efficient, since its current implementation 
reallocates and copies memory in each call.

* OsiCpxSimplexInterface.cpp -- an implementation of 
OsiCpxSimplexInterface. To compile this, the getEnvironmentPtr() 
function of OsiCpxSolverInterface class has to be a protected method 
(now it is defined as private). Some methods 
were quite thoroughly tested in our pivot-based MIP heuristic, others
may still require more work (those marked by //TEST). 
A dualPivotResult() method does not work since we do not completely
understand CPXdratio() function (suggestions are VERY welcomed).
Another issue is that we had to set full pricing to ensure that
reduced costs do get updated in the pivots forced by CPXpivot().
Suggestions on how this can be done some other way are welcomed.

This implementation was tested with CPLEX 7.x. We do not know if it
can work with previous versions or whether it will still work with new 
releases of CPLEX. The problem is that many functions that we had to use
are considered "undocumented" by ILOG and may simply disappear or change
in the future.

We welcome any comments and suggestions. Our hope is that this type of
functionality may be incorporated into the interface of the open source 
simplex solver which is currently under development in the COIN community, 
as well as into interfaces of (at least some of) other solvers. Having 
this type of functionality in the interface is important both for 
implementations of pivot-based heuristics, and for the cut generation
methods which use simplex tableau information.

Best regards,
Jonathan Eckstein
Mikhail Nediak


-------------- next part --------------
#ifndef OSI_SIMPLEX_INTERFACE
#define OSI_SIMPLEX_INTERFACE

#include <string>
#include <vector>

#include "OsiCollections.hpp"
#include "OsiPackedVectorBase.hpp"

#include "OsiSolverParameters.hpp"

class OsiPackedMatrix;

class OsiSimplexInterface {
 public:
  /**@name Simplex interface methods (abstract)*/
  //@{

  ///Set presolve status
  virtual void setPresolve(bool on) = 0;

  ///Enables normal operation of subsequent functions.
  ///This method is supposed to ensure that all typical things (like
  ///reduced costs, etc.) are updated when individual pivots are executed
  ///and can be queried by other methods
  virtual void enableSimplexInterface() = 0;

  ///Undo whatever setting changes the above method had to make
  virtual void disableSimplexInterface() = 0;

  ///Returns true if a basis is available
  virtual bool basisIsAvailable() = 0;

  ///The following two methods may be replaced by the
  ///methods using OsiWarmStartBasis if:
  ///1. OsiWarmStartBasis resize operation is implemented
  ///   more efficiently and
  ///2. It is ensured that effects on the solver are the same

  ///Returns a basis status of the structural/artificial variables
  virtual void getBasisStatus(int* cstat, int* rstat) = 0;

  ///Set the status of structural/artificial variables
  virtual int setBasisStatus(const int* cstat, const int* rstat) = 0;

  ///Perform a pivot by substituting a colOut for colIn in the basis. 
  ///The status of the leaving variable is given in statOut 
  virtual int pivot(int colIn, int colOut, int outStatus) = 0;

  ///Obtain a result of the primal pivot 
  ///Outputs: colOut -- leaving column, outStatus -- its status,
  ///t -- step size, and, if dx!=NULL, *dx -- primal ray direction.
  ///Inputs: colIn -- entering column, sign -- direction of its change (+/-1).
  ///Both for colIn and colOut, artificial variables are index by
  ///the negative of the row index minus 1.
  ///Return code (for now): 0 -- leaving variable found, 
  /// -1 -- everything else.
  ///Clearly, more informative set of return values is required
  virtual int primalPivotResult(int colIn, int sign, 
				int& colOut, int& outStatus, 
				double& t, OsiPackedVector* dx) = 0;

  ///Obtain a result of the dual pivot (similar to the previous method)
  ///Differences: entering variable and a sign of its change are now
  ///the outputs, the leaving variable and its statuts -- the inputs
  ///If dx!=NULL, then *dx contains dual ray
  ///Return code: same
  virtual int dualPivotResult(int& colIn, int& sign, 
			      int colOut, int outStatus, 
			      double& t, OsiPackedVector* dx) = 0;

  ///Get the reduced gradient for the cost vector c
  virtual void getReducedGradient(double* z, const double * c) = 0;

  ///Set a new objective, while keeping the old basis
  virtual void setObjective(double* c) = 0;

  ///Get a row of the tableau
  virtual void getBInvARow(int row, double* z) = 0;

  ///Get a row of the basis inverse
  virtual void getBInvRow(int row, double* z) = 0;

  ///Get a column of the tableau
  virtual void getBInvACol(int col, double* vec) = 0;
  //virtual void getBInvACol(int col, OsiPackedVector& vec) = 0;

  ///Get a column of the basis inverse
  virtual void getBInvCol(int col, double* vec) = 0;
  //virtual void getBInvCol(int col, OsiPackedVector& vec) = 0;

  ///Get basic indices (order of indices corresponds to the
  ///order of elements in a vector retured by getBInvACol() and
  ///getBInvCol()).
  virtual void getBasics(int* index) = 0;

  ///Get a row index, corresponding to the basic variable i,
  ///return -1 if this variable is not basic
  virtual int basicColToRow(int i) = 0;
  //@}

};

#endif
-------------- next part --------------
#ifndef OSI_CPX_SIMPLEX_INTERFACE
#define OSI_CPX_SIMPLEX_INTERFACE

#include <string>
#include <vector>

#include "OsiCpxSolverInterface.hpp"
#include "CoinError.hpp"
#include "CoinHelperFunctions.hpp"
#include "OsiWarmStartBasis.hpp"
#include "OsiPackedVector.hpp"

#include "OsiSimplexInterface.h"

class OsiCpxSimplexInterface : public OsiSimplexInterface, 
			       virtual public OsiCpxSolverInterface 
{
 protected:

  void getTableauColumn(int col, OsiPackedVector& vec);

 public:

  /**@name Constructors and destructors */
  //@{
  /// Default Constructor
  OsiCpxSimplexInterface(); 
      
  /// Clone
  virtual OsiSolverInterface * clone() const;
 
  /// Copy constructor 
  OsiCpxSimplexInterface (const OsiCpxSimplexInterface &);
  
  /// Assignment operator 
  OsiCpxSimplexInterface &
    operator=(const OsiCpxSimplexInterface& rhs);
  
  /// Destructor 
  virtual ~OsiCpxSimplexInterface ();
  //@}

  /**@name Simplex interface implementation */
  //@{
  ///Sets the presolve status
  void setPresolve(bool on);
  ///Get solution status
  int getSolStatus();

  ///Enables normal operation of subsequent functions
  virtual void enableSimplexInterface();

  ///Undo the effects of above method
  virtual void disableSimplexInterface();

  ///Returns true if the basis is available
  virtual bool basisIsAvailable();

  ///Returns a basis status of the structural/artificial variables
  virtual void getBasisStatus(int* cstat, int* rstat);

  virtual int setBasisStatus(const int* cstat, const int* rstat);

  ///Perform a pivot by substituting a colOut for colIn in the basis. 
  ///The status of the leaving variable is given in statOut 
  virtual int pivot(int colIn, int colOut, int outStatus);

  virtual int primalPivotResult(int colIn, int sign, 
				int& colOut, int& outStatus, 
				double& t, OsiPackedVector* dx);

  virtual int dualPivotResult(int& colIn, int& sign, 
			      int colOut, int outStatus, 
			      double& t, OsiPackedVector* dx);

  virtual void getReducedGradient(double* z, const double * c);
  virtual void setObjective(double* c);
  virtual void getBInvARow(int row, double* z);
  virtual void getBInvRow(int row, double* z);
  virtual void getBInvACol(int col, double* vec);
  //virtual void getBInvACol(int col, OsiPackedVector& vec);
  virtual void getBInvCol(int col, double* vec);
  //virtual void getBInvCol(int col, OsiPackedVector& vec);
  virtual void getBasics(int* index);
  virtual int basicColToRow(int i);
  //@}

};

#endif


-------------- next part --------------
#include "OsiCpxSimplexInterface.h"

//-----------------------------------------------------------------------------
OsiCpxSimplexInterface::OsiCpxSimplexInterface()
  : OsiCpxSolverInterface()
{}
      
//-----------------------------------------------------------------------------
OsiSolverInterface * OsiCpxSimplexInterface::clone() const
{
  return (new OsiCpxSimplexInterface(*this));
}

 
//-----------------------------------------------------------------------------
OsiCpxSimplexInterface::OsiCpxSimplexInterface (const OsiCpxSimplexInterface & rhs)
  : OsiCpxSolverInterface(rhs)
{
}
  
//-----------------------------------------------------------------------------
OsiCpxSimplexInterface &
OsiCpxSimplexInterface::operator=(const OsiCpxSimplexInterface& rhs)
{
  if (this != &rhs) {
    OsiCpxSolverInterface::operator=(rhs);
  }
  return *this;
}

//-----------------------------------------------------------------------------
OsiCpxSimplexInterface::~OsiCpxSimplexInterface ()
{
}

//#############################################################################
// OsiSimplexInterface implementation
//#############################################################################
void OsiCpxSimplexInterface::setPresolve(bool on)
{
  int err;
  if ( on )
    err = CPXsetintparam (getEnvironmentPtr(), 
			  CPX_PARAM_PREIND, CPX_ON);
  else
    err = CPXsetintparam (getEnvironmentPtr(), 
			  CPX_PARAM_PREIND, CPX_OFF);
  if ( err ) 
    throw CoinError("Failure in CPXsetintparam", 
		    "setPresolve", "OsiCpxSimplexInterface");
}

int OsiCpxSimplexInterface::getSolStatus()
{
  return CPXgetstat (getEnvironmentPtr(),
		     getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ));
}

void OsiCpxSimplexInterface::enableSimplexInterface()
{
  //There may be a problem here since this method affect the CPLEX
  //environment, i.e. all problem instances

  //Make sure that advanced start information is used
  int err = CPXsetintparam (getEnvironmentPtr(), CPX_PARAM_ADVIND, CPX_ON);
  if ( err ) 
    throw CoinError("Failure in CPXsetintparam", 
		    "enableSimplexInterface", "OsiCpxSimplexInterface");
   
  //Set full pricing (we have discovered that 
  //otherwise the reduced costs do not get properly updated).
  //Suggestions on how to ensure proper updates in some more efficient
  //way are very welcomed.
  err = CPXsetintparam (getEnvironmentPtr(), CPX_PARAM_PPRIIND, CPX_PPRIIND_FULL);
  if ( err ) 
    throw CoinError("Failure in CPXsetintparam", 
		    "enableSimplexInterface", "OsiCpxSimplexInterface");
}

void OsiCpxSimplexInterface::disableSimplexInterface()
{
  //Not yet implemented. The same problems as above.
  throw CoinError("Method is not yet implemented", 
				  "enableSimplexInterface", "OsiCpxSimplexInterface");
}

bool OsiCpxSimplexInterface::basisIsAvailable()
{
  int *rs = new int[getNumRows()];
  int err = CPXgetbase(getEnvironmentPtr(),
		       getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ),
		       NULL, rs);
  delete[] rs;
  return err == 0;
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::getBasisStatus(int* cstat, int* rstat)
{
  int err = CPXgetbase(getEnvironmentPtr(),
		       getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
		       cstat, rstat);

  if (err == 0) {
    int i, n = getNumCols(), m = getNumRows();

    for (i = 0; i < m; i++) {
      switch( rstat[i] ) {
      case CPX_BASIC:
	rstat[i] = OsiWarmStartBasis::basic;
	break;
      case CPX_AT_LOWER:
	rstat[i] = OsiWarmStartBasis::atLowerBound;
	break;
      case CPX_AT_UPPER:
	rstat[i] = OsiWarmStartBasis::atUpperBound;
	break;
      default:  // unknown row status: throw exception?
	break;
      }
    }

    for( i = 0; i < n; i++ ) {
      switch( cstat[i] ) {
      case CPX_BASIC:
	cstat[i] = OsiWarmStartBasis::basic;
	break;
      case CPX_AT_LOWER:
	cstat[i] = OsiWarmStartBasis::atLowerBound;
	break;
      case CPX_AT_UPPER:
	cstat[i] = OsiWarmStartBasis::atUpperBound;
	break;
      case CPX_FREE_SUPER:
	cstat[i] = OsiWarmStartBasis::isFree;
	break;
      default:  // unknown column status: throw exception?
	break;
      }
    }
  }
}

//-----------------------------------------------------------------------------
int OsiCpxSimplexInterface::setBasisStatus(const int* cstat, const int* rstat)
{
  int i, n = getNumCols(), m = getNumRows();
  int* cs = new int[n];
  int* rs = new int[m];

  for( i = 0; i < m; ++i ) {
    switch( rstat[i] ) {
    case OsiWarmStartBasis::basic:
      rs[i] = CPX_BASIC;
      break;
    case OsiWarmStartBasis::atLowerBound:
      rs[i] = CPX_AT_LOWER;
      break;
    case OsiWarmStartBasis::atUpperBound:
      rs[i] = CPX_AT_UPPER;
      break;
    default:  // unknown row status: throw exception?
      break;
    }
  }

  for( i = 0; i < n; ++i ) {
    switch( cstat[i] ) {
    case OsiWarmStartBasis::basic:
      cs[i] = CPX_BASIC;
      break;
    case OsiWarmStartBasis::atLowerBound:
      cs[i] = CPX_AT_LOWER;
      break;
    case OsiWarmStartBasis::atUpperBound:
      cs[i] = CPX_AT_UPPER;
      break;
    case OsiWarmStartBasis::isFree:
      cs[i] = CPX_FREE_SUPER;
      break;
    default:  // unknown row status: throw exception?
      break;
    }
  }

  int err = CPXcopybase( getEnvironmentPtr(), 
			 getLpPtr(OsiCpxSolverInterface::FREECACHED_RESULTS),
			 cs, rs );
  delete[] cs;
  delete[] rs;
  //*FIXME*: Is more detailed diagnostics needed?
  if (err != 0) return -1;

  int itLimit;
  err = CPXgetintparam ( getEnvironmentPtr(), CPX_PARAM_ITLIM, &itLimit);
  if (err != 0) 
    throw CoinError( "failure in CPXgetintparam", 
		     "setObjective", "OsiCpxSolverInterface" );

  err = CPXsetintparam ( getEnvironmentPtr(), CPX_PARAM_ITLIM, 0);
  if (err != 0)
    throw CoinError( "failure in CPXsetintparam", 
		     "setObjective", "OsiCpxSolverInterface" );

  err = CPXprimopt ( getEnvironmentPtr(), 
		     getLpPtr(OsiCpxSolverInterface::FREECACHED_RESULTS));
  if (err != 0)
    throw CoinError( "failure in CPXprimopt", 
		     "setObjective", "OsiCpxSolverInterface" );

  err = CPXsetintparam ( getEnvironmentPtr(), CPX_PARAM_ITLIM, itLimit);
  if (err != 0)
    throw CoinError( "failure in CPXsetintparam", 
		     "setObjective", "OsiCpxSolverInterface" );
  return 0;
}

//-----------------------------------------------------------------------------
int OsiCpxSimplexInterface::pivot(int colIn, int colOut, int outStatus)
{
  switch (outStatus) {
  case OsiWarmStartBasis::atLowerBound:
    outStatus = CPX_AT_LOWER;
    break;
  case OsiWarmStartBasis::atUpperBound:
    outStatus = CPX_AT_UPPER;
    break;
  case OsiWarmStartBasis::isFree:
    outStatus = CPX_FREE_SUPER;
    break;
  default:  
    return -1;
    break;
  }

  int err = CPXpivot( getEnvironmentPtr(), 
		      getLpPtr(OsiCpxSolverInterface::FREECACHED_RESULTS),
		      colIn, colOut, outStatus);
  if (err == 0) 
    return 0;
  else {
    flush(cout << " Error in CPXpivot() " << err);
    return -1;
  }
}

void OsiCpxSimplexInterface::getTableauColumn(int col, OsiPackedVector& vec)
{
  int m = getNumRows();
  int* head = new int[m];
  double* y = new double[m];

  int err = CPXgetbhead (getEnvironmentPtr(),
			 getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
			 head, y);
  if ( err != 0 ) {
    delete[] head;
    delete[] y;
    throw CoinError("failure in CPXgetbhead", "primalPivotResult",
		    "OsiCpxSimplexInterface");
  }

  if (col >= 0) {
    //col is a structural variable
    err = CPXbinvacol (getEnvironmentPtr(),
		       getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
		       col, y);
  } else {
    //col is artificial variable
    err = CPXbinvcol (getEnvironmentPtr(),
		      getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
		      -col-1, y);
  }
  if ( err != 0 ) {
    delete[] head;
    delete[] y;
    throw CoinError("failure in CPXbinvacol", "primalPivotResult",
		    "OsiCpxSimplexInterface");
  }
	
  vec.assignVector(m, head, y, false);
}

//-----------------------------------------------------------------------------
int OsiCpxSimplexInterface::primalPivotResult(int colIn, int sign, 
					      int& colOut, int& outStatus, 
					      double& t, OsiPackedVector* dx)
{
  if (sign != 1 && sign != -1) return -1;
  double downratio, upratio;
  int downleave, upleave;
  int downleavestatus, upleavestatus;
  int downstatus, upstatus;
  int err = CPXpratio(getEnvironmentPtr(),
		      getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
		      &colIn, 1, &downratio, &upratio,
		      &downleave, &upleave,
		      &downleavestatus, &upleavestatus,
		      &downstatus, &upstatus);
  
  if (err != 0) {
    flush(cout << "Warning: problems in CPXpratio()");
    //Throw exception?
    return -1;
  }
  if (sign == 1) {
    //*FIXME* Should ckeck for values like CPX_NO_VARIABLE and
    //CPXERR_BAD_PIVOT (anything else here?)
    if (upstatus != 0) {
      flush(cout << " upstatus=" << upstatus);
      return -1;
    }
    t = upratio;
    colOut = upleave;
    switch (upleavestatus) {
    case CPX_AT_LOWER:
      outStatus = OsiWarmStartBasis::atLowerBound;
      break;
    case CPX_AT_UPPER:
      outStatus = OsiWarmStartBasis::atUpperBound;
      break;
    default:
      //throw exception?
      flush(cout << " upleavestatus=" << upleavestatus);
      break;
    }
  } else {
    //*FIXME* Should ckeck for values like CPX_NO_VARIABLE and
    //CPXERR_BAD_PIVOT (anything else here?)
    if (downstatus != 0) {
      flush(cout << " downstatus=" << downstatus);
      return -1;
    }
    t = -downratio;
    colOut = downleave;
    switch (downleavestatus) {
    case CPX_AT_LOWER:
      outStatus = OsiWarmStartBasis::atLowerBound;
      break;
    case CPX_AT_UPPER:
      outStatus = OsiWarmStartBasis::atUpperBound;
      break;
    default:
      //throw exception?
      flush(cout << " downleavestatus=" << downleavestatus);
      break;
    }
  }
  if (dx != NULL) {
	//*FIXME* more efficient implementaion is possible if we know what
	//internal buffers to access
    getTableauColumn(colIn, *dx);
  }
  return 0;
}

//-----------------------------------------------------------------------------
void testCPXdratio(CPXENVptr env, CPXLPptr lp, int n, int m)
{
  int goodlen = n + m;
  int* goodlist = new int[goodlen];
  int i;
  for (i = 0; i < goodlen; i++) {
    goodlist[i] = i - m;
    cout << " " << goodlist[i];
  }
  cout << endl;
  int *downenter = new  int[goodlen];
  int *upenter = new int[goodlen];
  int *downstatus = new int[goodlen];
  int *upstatus = new int[goodlen];
  double *downratio = new double[goodlen];
  double *upratio = new double[goodlen];
  for (i = 0; i < goodlen; i++) {
    cout << " " << goodlist[i];
  }
  cout << endl;
  int err = CPXdratio(env, lp, goodlist, goodlen, 
		      downratio, upratio, downenter, upenter,
		      downstatus, upstatus);
  for (i = 0; i < goodlen; i++) {
    cout << i << " " << goodlist[i] << " "
	 << downratio[i] << " " << downenter[i] << " " << downstatus[i] << " "
	 << upratio[i] << " " << upenter[i] << " " << upstatus[i] << endl;
  }
  delete[] goodlist;
  delete[] downenter;
  delete[] upenter;
  delete[] downstatus;
  delete[] upstatus;
  delete[] downratio;
  delete[] upratio;
}

int OsiCpxSimplexInterface::dualPivotResult(int& colIn, int& sign, 
					    int colOut, int outStatus, 
					    double& t, OsiPackedVector* dx)
{
  //This function is currently not implemented due to our limited 
  //understanding of CPXdratio()
  throw CoinError("Operation not implemented", "dualPivotResult",
				  "OsiCpxSimplexInterface");
  /*
  // *TEST*
  double downratio, upratio;
  int downenter, upenter;
  int downstatus, upstatus;
  int err = CPXdratio(getEnvironmentPtr(),
		      getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
		      &colOut, 1, &downratio, &upratio,
		      &downenter, &upenter,
		      &downstatus, &upstatus);
  testCPXdratio(getEnvironmentPtr(),
		getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ),
		getNumCols(), getNumRows());

  cout << "CPXdratio for colOut=" << colOut << ": " << err << endl;
  cout << upratio << " " << upenter << " " << upstatus << endl;
  cout << downratio << " " << downenter << " " << downstatus << endl;
  //flush(cout << "?");
  
  if (err != 0) {
    flush(cout << "Warning: problems in CPXdratio()");
    //Throw exception?
    return -1;
  }
  switch (outStatus) {
  case OsiWarmStartBasis::atUpperBound:
    // *FIXME* Should ckeck for values like CPX_NO_VARIABLE and
    //CPXERR_BAD_PIVOT (anything else here?)
    if (upstatus != 0) return -1;
    t = upratio;
    colIn = upenter;
    sign = +1;
    break;
  case OsiWarmStartBasis::atLowerBound:
    // *FIXME* Should ckeck for values like CPX_NO_VARIABLE and
    //CPXERR_BAD_PIVOT (anything else here?)
    if (downstatus != 0) return -1;
    t = -downratio;
    colIn = downenter;
    sign = -1;
  default:
    // cases of OsiWarmStartBasis::isFree and OsiWarmStartBasis::basic
    // *FIXME* What is a proper treatment of isFree case (it should 
    // not really happen)
    return -1;
  }

  if (dx != NULL) 
    getTableauColumn(colIn, *dx);

  return 0;
  */
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::getReducedGradient(double* z, const double * c)
{
  int i, m = getNumRows(), n = getNumCols();
  int* head = new int[m];
  double* y = new double[n];
  int err = CPXgetbhead (getEnvironmentPtr(),
			 getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
			 head, y);
  if ( err != 0 ) {
    delete[] head;
    delete[] y;
    throw CoinError("failure in CPXgetbhead", "getReducedGradient",
		    "OsiCpxSimplexInterface");
  }

  for (i = 0; i < m; i++) {
    if (head[i] < 0) y[i] = 0.0;
    else y[i] = c[head[i]];
  }

  delete[] head;

  err = CPXbtran (getEnvironmentPtr(),
		  getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ),
		  y );

  if ( err != 0 ) {
    delete[] y;
    throw CoinError("failure in CPXbtran", "getReducedGradient",
		    "OsiCpxSimplexInterface");
  }

  err = CPXdjfrompi (getEnvironmentPtr(),
		     getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
		     y, z);
  //delete[] y; //BUG!

  if ( err != 0 ) {
    delete[] y;
    throw CoinError("failure in CPXdjfrompi", "getReducedGradient",
		    "OsiCpxSimplexInterface");
  }

  err = CPXgetobj (getEnvironmentPtr(),
		   getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
		   y, 0, n - 1);
  if ( err != 0 ) {
    delete[] y;
    throw CoinError("failure in CPXgetobj", "getReducedGradient",
		    "OsiCpxSimplexInterface");
  }
  for (i = 0; i < n; i++) {
    z[i] += c[i] - y[i];
  }
  delete[] y;
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::setObjective(double* c)
{
  int n = getNumCols(), m = getNumRows();
  int *rs = new int[m];
  int *cs = new int[n];
  int status = CPXgetbase(getEnvironmentPtr(),
			  getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL),
			  cs, rs);

  int *indices = new int[n];
  CoinIotaN(indices, n, 0);
  int err = CPXchgobj(getEnvironmentPtr(), 
		      getLpPtr( OsiCpxSolverInterface::FREECACHED_COLUMN ), 
		      n, indices, c);
  delete[] indices;
  if (err != 0) { 
    delete[] rs;
    delete[] cs;
    throw CoinError( "failure in CPXchgobj", 
		     "setObjective", "OsiCpxSolverInterface" );
  }

  if (status == 0) {
    err = CPXcopybase( getEnvironmentPtr(), 
		       getLpPtr(OsiCpxSolverInterface::FREECACHED_RESULTS),
		       cs, rs );
    delete[] cs;
    delete[] rs;
    if (err != 0) 
      throw CoinError( "failure in CPXcopybase", 
		       "setObjective", "OsiCpxSolverInterface" );

    int itLimit;
    err = CPXgetintparam ( getEnvironmentPtr(), CPX_PARAM_ITLIM, &itLimit);
    if (err != 0) 
      throw CoinError( "failure in CPXgetintparam", 
		       "setObjective", "OsiCpxSolverInterface" );

    err = CPXsetintparam ( getEnvironmentPtr(), CPX_PARAM_ITLIM, 0);
    if (err != 0)
      throw CoinError( "failure in CPXsetintparam", 
		       "setObjective", "OsiCpxSolverInterface" );

    err = CPXprimopt ( getEnvironmentPtr(), 
		       getLpPtr(OsiCpxSolverInterface::FREECACHED_RESULTS));
    if (err != 0)
      throw CoinError( "failure in CPXprimopt", 
		       "setObjective", "OsiCpxSolverInterface" );

    err = CPXsetintparam ( getEnvironmentPtr(), CPX_PARAM_ITLIM, itLimit);
    if (err != 0)
      throw CoinError( "failure in CPXsetintparam", 
		       "setObjective", "OsiCpxSolverInterface" );
  } else {
    delete[] cs;
    delete[] rs;
  }
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::getBInvARow(int row, double* z)
{
  //TEST
  int err = CPXbinvarow (getEnvironmentPtr(),
			 getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
			 row, z);
  if ( err != 0 ) {
    throw CoinError("failure in CPXbinvarow", "getBInvARow",
		    "OsiCpxSimplexInterface");
  }
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::getBInvRow(int row, double* z)
{
  //TEST
  int err = CPXbinvrow (getEnvironmentPtr(),
			getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
			row, z);
  if ( err != 0 ) {
    throw CoinError("failure in CPXbinvrow", "getBInvRow",
		    "OsiCpxSimplexInterface");
  }
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::getBInvACol(int col, double* vec)
{
  //TEST
  if (col >= 0 && col < getNumCols()) {
    //col is a structural variable
    int err = CPXbinvacol (getEnvironmentPtr(),
						   getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
						   col, vec);
	if ( err != 0 ) {
	  throw CoinError("failure in CPXbinvacol", "getBInvACol",
					  "OsiCpxSimplexInterface");
	}

  } else
    throw CoinError("invalid column index", "getBInvACol",
		    "OsiCpxSimplexInterface");
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::getBInvCol(int col, double* vec)
{
  //TEST
  if (col >= 0 && col < getNumRows()) {
    //col is artificial variable
    int err = CPXbinvcol (getEnvironmentPtr(),
						  getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
						  -col-1, vec);

	if ( err != 0 ) {
	  throw CoinError("failure in CPXbinvcol", "getBInvCol",
					  "OsiCpxSimplexInterface");
	}
  } else
    throw CoinError("invalid column index", "getBInvCol",
		    "OsiCpxSimplexInterface");
}

//-----------------------------------------------------------------------------
void OsiCpxSimplexInterface::getBasics(int* index)
{
  //TEST
  double* y = new double[getNumRows()];
  int err = CPXgetbhead (getEnvironmentPtr(),
			 getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ALL ), 
			 index, y);
  delete[] y;
  if ( err != 0 ) {
    throw CoinError("failure in CPXgetbhead", "getReducedGradient",
		    "OsiCpxSimplexInterface");
  }
}

//-----------------------------------------------------------------------------
int OsiCpxSimplexInterface::basicColToRow(int i)
{
  //TEST
  if (i < 0 || i >= getNumCols()) return -1;
  else {
    int err, row;
    err = CPXgetijrow( getEnvironmentPtr(), 
		       getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL),
		       -1, i, &row);
    return row; // row == -1 when err != 0
  }
}


More information about the Coin-discuss mailing list