Changeset 472


Ignore:
Timestamp:
Oct 11, 2004 5:25:44 PM (15 years ago)
Author:
forrest
Message:

Allow for startFinish and tableau stuff

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/ClpModel.cpp

    r471 r472  
    5656  numberIterations_(0),
    5757  solveType_(0),
     58  whatsChanged_(0),
    5859  problemStatus_(-1),
    5960  secondaryStatus_(0),
     
    129130  delete eventHandler_;
    130131  eventHandler_=NULL;
     132  whatsChanged_=0;
    131133}
    132134//#############################################################################
     
    208210  delete [] rowObjective_;
    209211  rowObjective_=ClpCopyOfArray(rowObjective,numberRows_);
     212  whatsChanged_=0;
    210213}
    211214void
     
    313316#endif
    314317  objective()[elementIndex] = elementValue;
     318  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    315319}
    316320/* Set a single row lower bound<br>
     
    321325    elementValue=-COIN_DBL_MAX;
    322326  rowLower_[elementIndex] = elementValue;
     327  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    323328}
    324329     
     
    330335    elementValue=COIN_DBL_MAX;
    331336  rowUpper_[elementIndex] = elementValue;
     337  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    332338}
    333339   
     
    343349  rowLower_[elementIndex] = lower;
    344350  rowUpper_[elementIndex] = upper;
     351  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    345352}
    346353void ClpModel::setRowSetBounds(const int* indexFirst,
     
    353360  double * lower = rowLower_;
    354361  double * upper = rowUpper_;
     362  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    355363  while (indexFirst != indexLast) {
    356364    const int iRow=*indexFirst++;
     
    384392    elementValue=-COIN_DBL_MAX;
    385393  columnLower_[elementIndex] = elementValue;
     394  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    386395}
    387396     
     
    400409    elementValue=COIN_DBL_MAX;
    401410  columnUpper_[elementIndex] = elementValue;
     411  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    402412}
    403413
     
    420430  columnUpper_[elementIndex] = upper;
    421431  assert (upper>=lower);
     432  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    422433}
    423434void ClpModel::setColumnSetBounds(const int* indexFirst,
     
    427438  double * lower = columnLower_;
    428439  double * upper = columnUpper_;
     440  whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
    429441#ifndef NDEBUG
    430442  int n = numberColumns_;
     
    523535  numberIterations_ = rhs.numberIterations_;
    524536  solveType_ = rhs.solveType_;
     537  whatsChanged_ = rhs.whatsChanged_;
    525538  problemStatus_ = rhs.problemStatus_;
    526539  secondaryStatus_ = rhs.secondaryStatus_;
     
    823836{
    824837  delete matrix_;
     838  whatsChanged_ = 0;
    825839  CoinPackedMatrix matrix2;
    826840  matrix_=new ClpPackedMatrix(matrix2);
     
    830844ClpModel::resize (int newNumberRows, int newNumberColumns)
    831845{
     846  if (newNumberRows==numberRows_&&
     847      newNumberColumns==numberColumns_)
     848    return; // nothing to do
     849  whatsChanged_ = 0;
    832850  rowActivity_ = resizeDouble(rowActivity_,numberRows_,
    833851                              newNumberRows,0.0,true);
     
    913931ClpModel::deleteRows(int number, const int * which)
    914932{
     933  if (!number)
     934    return; // nothing to do
     935  whatsChanged_ &= ~(1+2+4+8+16+32); // all except columns changed
    915936  int newSize=0;
    916937  rowActivity_ = deleteDouble(rowActivity_,numberRows_,
     
    9811002ClpModel::deleteColumns(int number, const int * which)
    9821003{
     1004  if (!number)
     1005    return; // nothing to do
     1006  whatsChanged_ &= ~(1+2+4+8+64+128+256); // all except rows changed
    9831007  int newSize=0;
    9841008  columnActivity_ = deleteDouble(columnActivity_,numberColumns_,
     
    10681092  // Create a list of CoinPackedVectors
    10691093  if (number) {
     1094    whatsChanged_ &= ~(1+2+8+16+32); // all except columns changed
    10701095    CoinPackedVectorBase ** rows=
    10711096      new CoinPackedVectorBase * [number];
     
    10981123  // Create a list of CoinPackedVectors
    10991124  if (number) {
     1125    whatsChanged_ &= ~(1+2+8+16+32); // all except columns changed
    11001126    CoinPackedVectorBase ** rows=
    11011127      new CoinPackedVectorBase * [number];
     
    11251151  if (!number)
    11261152    return;
     1153  whatsChanged_ &= ~(1+2+8+16+32); // all except columns changed
    11271154  int numberRowsNow = numberRows_;
    11281155  resize(numberRowsNow+number,numberColumns_);
     
    11761203  // Create a list of CoinPackedVectors
    11771204  if (number) {
     1205    whatsChanged_ &= ~(1+2+4+64+128+256); // all except rows changed
    11781206    CoinPackedVectorBase ** columns=
    11791207      new CoinPackedVectorBase * [number];
     
    12081236  // Create a list of CoinPackedVectors
    12091237  if (number) {
     1238    whatsChanged_ &= ~(1+2+4+64+128+256); // all except rows changed
    12101239    CoinPackedVectorBase ** columns=
    12111240      new CoinPackedVectorBase * [number];
     
    12371266  if (!number)
    12381267    return;
     1268  whatsChanged_ &= ~(1+2+4+64+128+256); // all except rows changed
    12391269  int numberColumnsNow = numberColumns_;
    12401270  resize(numberRows_,numberColumnsNow+number);
     
    12941324  int numberRows = numberRows_;
    12951325  int iRow;
     1326  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    12961327  if (rowLower) {
    12971328    for (iRow = 0; iRow < numberRows; iRow++) {
     
    13111342ClpModel::chgRowUpper(const double * rowUpper)
    13121343{
     1344  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    13131345  int numberRows = numberRows_;
    13141346  int iRow;
     
    13301362ClpModel::chgColumnLower(const double * columnLower)
    13311363{
     1364  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    13321365  int numberColumns = numberColumns_;
    13331366  int iColumn;
     
    13491382ClpModel::chgColumnUpper(const double * columnUpper)
    13501383{
     1384  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    13511385  int numberColumns = numberColumns_;
    13521386  int iColumn;
     
    13681402ClpModel::chgObjCoefficients(const double * objIn)
    13691403{
     1404  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    13701405  double * obj = objective();
    13711406  int numberColumns = numberColumns_;
     
    16401675                              const int * column, const double * element)
    16411676{
     1677  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    16421678  assert (numberColumns==numberColumns_);
    16431679  assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
     
    16531689ClpModel::loadQuadraticObjective (  const CoinPackedMatrix& matrix)
    16541690{
     1691  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    16551692  assert (matrix.getNumCols()==numberColumns_);
    16561693  assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
     
    16681705ClpModel::deleteQuadraticObjective()
    16691706{
     1707  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    16701708  ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
    16711709  if (obj)
     
    16751713ClpModel::setObjective(ClpObjective * objective)
    16761714{
     1715  whatsChanged_ = 0; // Use ClpSimplex stuff to keep
    16771716  delete objective_;
    16781717  objective_=objective->clone();
     
    17201759    delete matrix_;
    17211760  matrix_=matrix;
     1761  whatsChanged_ = 0; // Too big a change
    17221762}
    17231763// Subproblem constructor
     
    17541794  numberIterations_ = rhs->numberIterations_;
    17551795  solveType_ = rhs->solveType_;
     1796  whatsChanged_ = 0; // Too big a change
    17561797  problemStatus_ = rhs->problemStatus_;
    17571798  secondaryStatus_ = rhs->secondaryStatus_;
  • trunk/ClpSimplex.cpp

    r468 r472  
    23602360  }
    23612361  // do scaling if needed
    2362   if (scalingFlag_>0&&!rowScale_) {
     2362  if (scalingFlag_>0&&!rowScale_&&(what&16)!=0) {
    23632363    if (matrix_->scale(this))
    23642364      scalingFlag_=-scalingFlag_; // not scaled after all
     
    28442844  // scaling may have been turned off
    28452845  scalingFlag_ = abs(scalingFlag_);
    2846   if(getRidOfFactorizationData>=0)
     2846  if(getRidOfFactorizationData>0)
    28472847    gutsOfDelete(getRidOfFactorizationData+1);
    28482848  // get rid of data
     
    33813381#include "ClpSimplexDual.hpp"
    33823382#include "ClpSimplexPrimal.hpp"
    3383 int ClpSimplex::dual (int ifValuesPass )
     3383int ClpSimplex::dual (int ifValuesPass , int startFinishOptions)
    33843384{
    33853385  int saveQuadraticActivated = objective_->activated();
     
    33963396      As far as I can see this is perfectly safe.
    33973397  */
    3398   int returnCode = ((ClpSimplexDual *) this)->dual(ifValuesPass);
     3398  int returnCode = ((ClpSimplexDual *) this)->dual(ifValuesPass, startFinishOptions);
    33993399  if (problemStatus_==10) {
    34003400    //printf("Cleaning up with primal\n");
     
    34693469#include "ClpQuadraticObjective.hpp"
    34703470// primal
    3471 int ClpSimplex::primal (int ifValuesPass )
     3471int ClpSimplex::primal (int ifValuesPass , int startFinishOptions)
    34723472{
    34733473  // See if nonlinear
     
    34863486      As far as I can see this is perfectly safe.
    34873487  */
    3488   int returnCode = ((ClpSimplexPrimal *) this)->primal(ifValuesPass);
     3488  int returnCode = ((ClpSimplexPrimal *) this)->primal(ifValuesPass,startFinishOptions);
    34893489  if (problemStatus_==10) {
    34903490    //printf("Cleaning up with dual\n");
     
    46734673{
    46744674  // put in standard form
    4675   createRim(7+8+16);
     4675  createRim(7+8+16+32);
    46764676  dualTolerance_=dblParam_[ClpDualTolerance];
    46774677  primalTolerance_=dblParam_[ClpPrimalTolerance];
     
    53805380// Common bits of coding for dual and primal
    53815381int
    5382 ClpSimplex::startup(int ifValuesPass)
    5383 {
     5382ClpSimplex::startup(int ifValuesPass, int startFinishOptions)
     5383{
     5384  // Get rid of some arrays and empty factorization
     5385  int useFactorization=false;
     5386  if ((startFinishOptions&2)!=0)
     5387    useFactorization=true; // Keep factorization if possible
    53845388  // sanity check
    53855389  // bad if empty (trap here to avoid using bad matrix_)
     
    54065410  // put in standard form (and make row copy)
    54075411  // create modifiable copies of model rim and do optional scaling
    5408   bool goodMatrix=createRim(7+8+16,true);
     5412  bool goodMatrix=createRim(7+8+16+32,true);
    54095413
    54105414  if (goodMatrix) {
     
    54155419    // or we can just increment iBasic one by one
    54165420    // for now let ...iBasic give pivot row
    5417     factorization_->increasingRows(2);
    5418     // row activities have negative sign
    5419     factorization_->slackValue(-1.0);
    5420     factorization_->zeroTolerance(1.0e-13);
     5421    int saveThreshold = factorization_->denseThreshold();
     5422    if (!useFactorization||factorization_->numberRows()!=numberRows_) {
     5423      useFactorization = false;
     5424      factorization_->increasingRows(2);
     5425      // row activities have negative sign
     5426      factorization_->slackValue(-1.0);
     5427      factorization_->zeroTolerance(1.0e-13);
    54215428    // Switch off dense (unless special option set)
    5422     int saveThreshold = factorization_->denseThreshold();
    5423     factorization_->setDenseThreshold(0);
     5429      factorization_->setDenseThreshold(0);
     5430    }
    54245431    // If values pass then perturb (otherwise may be optimal so leave a bit)
    54255432    if (ifValuesPass) {
     
    54445451    int numberThrownOut = -1;
    54455452    int totalNumberThrownOut=0;
    5446     while(numberThrownOut) {
    5447       int status = internalFactorize(ifValuesPass ? 10 : 0);
    5448       if (status<0)
    5449         return 1; // some error
    5450       else
    5451         numberThrownOut = status;
    5452      
    5453       // for this we need clean basis so it is after factorize
    5454       if (!numberThrownOut)
    5455         numberThrownOut = gutsOfSolution(  NULL,NULL,
    5456                                          ifValuesPass!=0);
    5457       else
    5458         matrix_->rhsOffset(this,true); // redo rhs offset
    5459       totalNumberThrownOut+= numberThrownOut;
    5460      
    5461     }
    5462    
     5453    // see if we are re-using factorization
     5454    if (!useFactorization) {
     5455      while(numberThrownOut) {
     5456        int status = internalFactorize(ifValuesPass ? 10 : 0);
     5457        if (status<0)
     5458          return 1; // some error
     5459        else
     5460          numberThrownOut = status;
     5461       
     5462        // for this we need clean basis so it is after factorize
     5463        if (!numberThrownOut) {
     5464          // solution will be done again - skip if absolutely sure
     5465          if ((specialOptions_&512)==0)
     5466            numberThrownOut = gutsOfSolution(  NULL,NULL,
     5467                                               ifValuesPass!=0);
     5468        } else {
     5469          matrix_->rhsOffset(this,true); // redo rhs offset
     5470        }
     5471        totalNumberThrownOut+= numberThrownOut;
     5472       
     5473      }
     5474    } else {
     5475      // using previous factorization - we assume fine
     5476      // but we need to say not optimal
     5477      numberPrimalInfeasibilities_=1;
     5478      numberDualInfeasibilities_=1;
     5479    }
    54635480    if (totalNumberThrownOut)
    54645481      handler_->message(CLP_SINGULARITIES,messages_)
     
    54835500
    54845501void
    5485 ClpSimplex::finish()
     5502ClpSimplex::finish(int startFinishOptions)
    54865503{
    54875504  // Get rid of some arrays and empty factorization
    5488   deleteRim();
     5505  int getRidOfData=1;
     5506  if ((startFinishOptions&1)!=0) {
     5507    getRidOfData=0; // Keep stuff
     5508    // mark all as current
     5509    whatsChanged_ = 0xffff;
     5510  } else {
     5511    whatsChanged_=0;
     5512  }
     5513  deleteRim(getRidOfData);
    54895514  // Skip message if changing algorithms
    54905515  if (problemStatus_!=10) {
     
    55775602  // put back original costs and then check
    55785603  // also move to work arrays
    5579   createRim(4+32);
     5604  createRim(7+8+16+32);
    55805605  //memcpy(rowActivityWork_,rowActivity_,numberRows_*sizeof(double));
    55815606  //memcpy(columnActivityWork_,columnActivity_,numberColumns_*sizeof(double));
     
    64706495  eventHandler_->setSimplex(this);
    64716496}
     6497#ifndef NDEBUG
     6498// For errors to make sure print to screen
     6499// only called in debug mode
     6500static void indexError(int index,
     6501                        std::string methodName)
     6502{
     6503  std::cerr<<"Illegal index "<<index<<" in ClpSimplex::"<<methodName<<std::endl;
     6504  throw CoinError("Illegal index",methodName,"ClpSimplex");
     6505}
     6506#endif
     6507// These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal)
     6508//Get a row of the tableau (slack part in slack if not NULL)
     6509void
     6510ClpSimplex::getBInvARow(int row, double* z, double * slack)
     6511{
     6512#ifndef NDEBUG
     6513  int n = numberRows();
     6514  if (row<0||row>=n) {
     6515    indexError(row,"getBInvARow");
     6516  }
     6517#endif
     6518  if (!rowArray_[0]) {
     6519    printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
     6520    abort();
     6521  }
     6522  ClpFactorization * factorization = factorization_;
     6523  CoinIndexedVector * rowArray0 = rowArray(0);
     6524  CoinIndexedVector * rowArray1 = rowArray(1);
     6525  CoinIndexedVector * columnArray0 = columnArray(0);
     6526  CoinIndexedVector * columnArray1 = columnArray(1);
     6527  rowArray0->clear();
     6528  rowArray1->clear();
     6529  columnArray0->clear();
     6530  columnArray1->clear();
     6531  // put +1 in row
     6532  rowArray1->insert(row,1.0);
     6533  factorization->updateColumnTranspose(rowArray0,rowArray1);
     6534  // put row of tableau in rowArray1 and columnArray0
     6535  clpMatrix()->transposeTimes(this,1.0,
     6536                            rowArray1,columnArray1,columnArray0);
     6537  memcpy(z,columnArray0->denseVector(),
     6538         numberColumns()*sizeof(double));
     6539  if (slack) {
     6540    int n = numberRows();
     6541    double * array = rowArray1->denseVector();
     6542    for (int i=0;i<n;i++) {
     6543      // clp stores slacks as -1.0  (Does not seem to matter - basics should be 1.0)
     6544      slack[i] =  array[i];
     6545    }
     6546    //memcpy(slack,rowArray1->denseVector(),
     6547    //   numberRows()*sizeof(double));
     6548  }
     6549  // don't need to clear everything always, but doesn't cost
     6550  rowArray0->clear();
     6551  rowArray1->clear();
     6552  columnArray0->clear();
     6553  columnArray1->clear();
     6554}
     6555
     6556//Get a row of the basis inverse
     6557void
     6558ClpSimplex::getBInvRow(int row, double* z)
     6559
     6560{
     6561#ifndef NDEBUG
     6562  int n = numberRows();
     6563  if (row<0||row>=n) {
     6564    indexError(row,"getBInvRow");
     6565  }
     6566#endif
     6567  if (!rowArray_[0]) {
     6568    printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
     6569    abort();
     6570  }
     6571  ClpFactorization * factorization = factorization_;
     6572  CoinIndexedVector * rowArray0 = rowArray(0);
     6573  CoinIndexedVector * rowArray1 = rowArray(1);
     6574  rowArray0->clear();
     6575  rowArray1->clear();
     6576  // put +1 in row
     6577  rowArray1->insert(row,1.0);
     6578  factorization->updateColumnTranspose(rowArray0,rowArray1);
     6579  memcpy(z,rowArray1->denseVector(),numberRows()*sizeof(double));
     6580  rowArray1->clear();
     6581}
     6582
     6583//Get a column of the tableau
     6584void
     6585ClpSimplex::getBInvACol(int col, double* vec)
     6586{
     6587  if (!rowArray_[0]) {
     6588    printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
     6589    abort();
     6590  }
     6591  ClpFactorization * factorization = factorization_;
     6592  CoinIndexedVector * rowArray0 = rowArray(0);
     6593  CoinIndexedVector * rowArray1 = rowArray(1);
     6594  rowArray0->clear();
     6595  rowArray1->clear();
     6596  // get column of matrix
     6597#ifndef NDEBUG
     6598  int n = numberColumns();
     6599  if (col<0||col>=n) {
     6600    indexError(col,"getBInvACol");
     6601  }
     6602#endif
     6603  unpack(rowArray1,col);
     6604  factorization->updateColumn(rowArray0,rowArray1,false);
     6605  memcpy(vec,rowArray1->denseVector(),numberRows()*sizeof(double));
     6606  rowArray1->clear();
     6607}
     6608
     6609//Get a column of the basis inverse
     6610void
     6611ClpSimplex::getBInvCol(int col, double* vec)
     6612{
     6613  if (!rowArray_[0]) {
     6614    printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
     6615    abort();
     6616  }
     6617  ClpFactorization * factorization = factorization_;
     6618  CoinIndexedVector * rowArray0 = rowArray(0);
     6619  CoinIndexedVector * rowArray1 = rowArray(1);
     6620  rowArray0->clear();
     6621  rowArray1->clear();
     6622#ifndef NDEBUG
     6623  int n = numberRows();
     6624  if (col<0||col>=n) {
     6625    indexError(col,"getBInvCol");
     6626  }
     6627#endif
     6628  // put +1 in row
     6629  rowArray1->insert(col,1.0);
     6630  factorization->updateColumn(rowArray0,rowArray1,false);
     6631  memcpy(vec,rowArray1->denseVector(),numberRows()*sizeof(double));
     6632  rowArray1->clear();
     6633}
     6634
     6635/* Get basic indices (order of indices corresponds to the
     6636   order of elements in a vector retured by getBInvACol() and
     6637   getBInvCol()).
     6638*/
     6639void
     6640ClpSimplex::getBasics(int* index)
     6641{
     6642  if (!rowArray_[0]) {
     6643    printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
     6644    abort();
     6645  }
     6646  assert (index);
     6647  memcpy(index,pivotVariable(),
     6648         numberRows()*sizeof(int));
     6649}
     6650/* Set an objective function coefficient */
     6651void
     6652ClpSimplex::setObjectiveCoefficient( int elementIndex, double elementValue )
     6653{
     6654#ifndef NDEBUG
     6655  if (elementIndex<0||elementIndex>=numberColumns_) {
     6656    indexError(elementIndex,"setObjectiveCoefficient");
     6657  }
     6658#endif
     6659  if (objective()[elementIndex] != elementValue) {
     6660    objective()[elementIndex] = elementValue;
     6661    if ((whatsChanged_&1)!=0) {
     6662      // work arrays exist - update as well
     6663      whatsChanged_ &= ~64;
     6664      double direction = optimizationDirection_*objectiveScale_;
     6665      if (!rowScale_) {
     6666        objectiveWork_[elementIndex] = direction*elementValue;
     6667      } else {
     6668        objectiveWork_[elementIndex] = direction*elementValue
     6669          *columnScale_[elementIndex];
     6670      }
     6671    }
     6672  }
     6673}
     6674/* Set a single row lower bound<br>
     6675   Use -DBL_MAX for -infinity. */
     6676void
     6677ClpSimplex::setRowLower( int elementIndex, double elementValue ) {
     6678#ifndef NDEBUG
     6679  int n = numberRows_;
     6680  if (elementIndex<0||elementIndex>=n) {
     6681    indexError(elementIndex,"setRowLower");
     6682  }
     6683#endif
     6684  if (elementValue<-1.0e27)
     6685    elementValue=-COIN_DBL_MAX;
     6686  if (rowLower_[elementIndex] != elementValue) {
     6687    rowLower_[elementIndex] = elementValue;
     6688    if ((whatsChanged_&1)!=0) {
     6689      // work arrays exist - update as well
     6690      whatsChanged_ &= ~16;
     6691      if (rowLower_[elementIndex]==-COIN_DBL_MAX) {
     6692        rowLowerWork_[elementIndex] = -COIN_DBL_MAX;
     6693      } else if (!rowScale_) {
     6694        rowLowerWork_[elementIndex] = elementValue * rhsScale_;
     6695      } else {
     6696        rowLowerWork_[elementIndex] = elementValue * rhsScale_
     6697          * rowScale_[elementIndex];
     6698      }
     6699    }
     6700  }
     6701}
     6702     
     6703/* Set a single row upper bound<br>
     6704   Use DBL_MAX for infinity. */
     6705void
     6706ClpSimplex::setRowUpper( int elementIndex, double elementValue ) {
     6707#ifndef NDEBUG
     6708  int n = numberRows_;
     6709  if (elementIndex<0||elementIndex>=n) {
     6710    indexError(elementIndex,"setRowUpper");
     6711  }
     6712#endif
     6713  if (elementValue>1.0e27)
     6714    elementValue=COIN_DBL_MAX;
     6715  if (rowUpper_[elementIndex] != elementValue) {
     6716    rowUpper_[elementIndex] = elementValue;
     6717    if ((whatsChanged_&1)!=0) {
     6718      // work arrays exist - update as well
     6719      whatsChanged_ &= ~32;
     6720      if (rowUpper_[elementIndex]==COIN_DBL_MAX) {
     6721        rowUpperWork_[elementIndex] = COIN_DBL_MAX;
     6722      } else if (!rowScale_) {
     6723        rowUpperWork_[elementIndex] = elementValue * rhsScale_;
     6724      } else {
     6725        rowUpperWork_[elementIndex] = elementValue * rhsScale_
     6726          * rowScale_[elementIndex];
     6727      }
     6728    }
     6729  }
     6730}
     6731   
     6732/* Set a single row lower and upper bound */
     6733void
     6734ClpSimplex::setRowBounds( int elementIndex,
     6735              double lowerValue, double upperValue ) {
     6736#ifndef NDEBUG
     6737  int n = numberRows_;
     6738  if (elementIndex<0||elementIndex>=n) {
     6739    indexError(elementIndex,"setRowBounds");
     6740  }
     6741#endif
     6742  if (lowerValue<-1.0e27)
     6743    lowerValue=-COIN_DBL_MAX;
     6744  if (upperValue>1.0e27)
     6745    upperValue=COIN_DBL_MAX;
     6746  assert (upperValue>=lowerValue);
     6747  if (rowLower_[elementIndex] != lowerValue) {
     6748    rowLower_[elementIndex] = lowerValue;
     6749    if ((whatsChanged_&1)!=0) {
     6750      // work arrays exist - update as well
     6751      whatsChanged_ &= ~16;
     6752      if (rowLower_[elementIndex]==-COIN_DBL_MAX) {
     6753        rowLowerWork_[elementIndex] = -COIN_DBL_MAX;
     6754      } else if (!rowScale_) {
     6755        rowLowerWork_[elementIndex] = lowerValue * rhsScale_;
     6756      } else {
     6757        rowLowerWork_[elementIndex] = lowerValue * rhsScale_
     6758          * rowScale_[elementIndex];
     6759      }
     6760    }
     6761  }
     6762  if (rowUpper_[elementIndex] != upperValue) {
     6763    rowUpper_[elementIndex] = upperValue;
     6764    if ((whatsChanged_&1)!=0) {
     6765      // work arrays exist - update as well
     6766      whatsChanged_ &= ~32;
     6767      if (rowUpper_[elementIndex]==COIN_DBL_MAX) {
     6768        rowUpperWork_[elementIndex] = COIN_DBL_MAX;
     6769      } else if (!rowScale_) {
     6770        rowUpperWork_[elementIndex] = upperValue * rhsScale_;
     6771      } else {
     6772        rowUpperWork_[elementIndex] = upperValue * rhsScale_
     6773          * rowScale_[elementIndex];
     6774      }
     6775    }
     6776  }
     6777}
     6778void ClpSimplex::setRowSetBounds(const int* indexFirst,
     6779                                            const int* indexLast,
     6780                                            const double* boundList)
     6781{
     6782#ifndef NDEBUG
     6783  int n = numberRows_;
     6784#endif
     6785  int numberChanged=0;
     6786  const int * saveFirst=indexFirst;
     6787  while (indexFirst != indexLast) {
     6788    const int iRow=*indexFirst++;
     6789#ifndef NDEBUG
     6790    if (iRow<0||iRow>=n) {
     6791      indexError(iRow,"setRowSetBounds");
     6792    }
     6793#endif
     6794    double lowerValue = *boundList++;
     6795    double upperValue = *boundList++;
     6796    if (lowerValue<-1.0e27)
     6797      lowerValue=-COIN_DBL_MAX;
     6798    if (upperValue>1.0e27)
     6799      upperValue=COIN_DBL_MAX;
     6800    assert (upperValue>=lowerValue);
     6801    if (rowLower_[iRow] != lowerValue) {
     6802      rowLower_[iRow] = lowerValue;
     6803      whatsChanged_ &= ~16;
     6804      numberChanged++;
     6805    }
     6806    if (rowUpper_[iRow] != upperValue) {
     6807      rowUpper_[iRow] = upperValue;
     6808      whatsChanged_ &= ~32;
     6809      numberChanged++;
     6810    }
     6811  }
     6812  if (numberChanged&&(whatsChanged_&1)!=0) {
     6813    indexFirst = saveFirst;
     6814    while (indexFirst != indexLast) {
     6815      const int iRow=*indexFirst++;
     6816      if (rowLower_[iRow]==-COIN_DBL_MAX) {
     6817        rowLowerWork_[iRow] = -COIN_DBL_MAX;
     6818      } else if (!rowScale_) {
     6819        rowLowerWork_[iRow] = rowLower_[iRow] * rhsScale_;
     6820      } else {
     6821        rowLowerWork_[iRow] = rowLower_[iRow] * rhsScale_
     6822          * rowScale_[iRow];
     6823      }
     6824      if (rowUpper_[iRow]==COIN_DBL_MAX) {
     6825        rowUpperWork_[iRow] = COIN_DBL_MAX;
     6826      } else if (!rowScale_) {
     6827        rowUpperWork_[iRow] = rowUpper_[iRow] * rhsScale_;
     6828      } else {
     6829        rowUpperWork_[iRow] = rowUpper_[iRow] * rhsScale_
     6830          * rowScale_[iRow];
     6831      }
     6832    }
     6833  }
     6834}
     6835//-----------------------------------------------------------------------------
     6836/* Set a single column lower bound<br>
     6837   Use -DBL_MAX for -infinity. */
     6838void
     6839ClpSimplex::setColumnLower( int elementIndex, double elementValue )
     6840{
     6841#ifndef NDEBUG
     6842  int n = numberColumns_;
     6843  if (elementIndex<0||elementIndex>=n) {
     6844    indexError(elementIndex,"setColumnLower");
     6845  }
     6846#endif
     6847  if (elementValue<-1.0e27)
     6848    elementValue=-COIN_DBL_MAX;
     6849  if (columnLower_[elementIndex] != elementValue) {
     6850    columnLower_[elementIndex] = elementValue;
     6851    if ((whatsChanged_&1)!=0) {
     6852      // work arrays exist - update as well
     6853      whatsChanged_ &= ~128;
     6854      if (columnLower_[elementIndex]==-COIN_DBL_MAX) {
     6855        columnLowerWork_[elementIndex] = -COIN_DBL_MAX;
     6856      } else if (!columnScale_) {
     6857        columnLowerWork_[elementIndex] = elementValue * rhsScale_;
     6858      } else {
     6859        columnLowerWork_[elementIndex] = elementValue * rhsScale_
     6860          / columnScale_[elementIndex];
     6861      }
     6862    }
     6863  }
     6864}
     6865     
     6866/* Set a single column upper bound<br>
     6867   Use DBL_MAX for infinity. */
     6868void
     6869ClpSimplex::setColumnUpper( int elementIndex, double elementValue )
     6870{
     6871#ifndef NDEBUG
     6872  int n = numberColumns_;
     6873  if (elementIndex<0||elementIndex>=n) {
     6874    indexError(elementIndex,"setColumnUpper");
     6875  }
     6876#endif
     6877  if (elementValue>1.0e27)
     6878    elementValue=COIN_DBL_MAX;
     6879  if (columnUpper_[elementIndex] != elementValue) {
     6880    columnUpper_[elementIndex] = elementValue;
     6881    if ((whatsChanged_&1)!=0) {
     6882      // work arrays exist - update as well
     6883      whatsChanged_ &= ~256;
     6884      if (columnUpper_[elementIndex]==COIN_DBL_MAX) {
     6885        columnUpperWork_[elementIndex] = COIN_DBL_MAX;
     6886      } else if (!columnScale_) {
     6887        columnUpperWork_[elementIndex] = elementValue * rhsScale_;
     6888      } else {
     6889        columnUpperWork_[elementIndex] = elementValue * rhsScale_
     6890          / columnScale_[elementIndex];
     6891      }
     6892    }
     6893  }
     6894}
     6895
     6896/* Set a single column lower and upper bound */
     6897void
     6898ClpSimplex::setColumnBounds( int elementIndex,
     6899                                     double lowerValue, double upperValue )
     6900{
     6901#ifndef NDEBUG
     6902  int n = numberColumns_;
     6903  if (elementIndex<0||elementIndex>=n) {
     6904    indexError(elementIndex,"setColumnBounds");
     6905  }
     6906#endif
     6907  if (lowerValue<-1.0e27)
     6908    lowerValue=-COIN_DBL_MAX;
     6909  if (columnLower_[elementIndex] != lowerValue) {
     6910    columnLower_[elementIndex] = lowerValue;
     6911    if ((whatsChanged_&1)!=0) {
     6912      // work arrays exist - update as well
     6913      whatsChanged_ &= ~128;
     6914      if (columnLower_[elementIndex]==-COIN_DBL_MAX) {
     6915        columnLowerWork_[elementIndex] = -COIN_DBL_MAX;
     6916      } else if (!columnScale_) {
     6917        columnLowerWork_[elementIndex] = lowerValue * rhsScale_;
     6918      } else {
     6919        columnLowerWork_[elementIndex] = lowerValue * rhsScale_
     6920          / columnScale_[elementIndex];
     6921      }
     6922    }
     6923  }
     6924  if (upperValue>1.0e27)
     6925    upperValue=COIN_DBL_MAX;
     6926  assert (upperValue>=lowerValue);
     6927  if (columnUpper_[elementIndex] != upperValue) {
     6928    columnUpper_[elementIndex] = upperValue;
     6929    if ((whatsChanged_&1)!=0) {
     6930      // work arrays exist - update as well
     6931      whatsChanged_ &= ~256;
     6932      if (columnUpper_[elementIndex]==COIN_DBL_MAX) {
     6933        columnUpperWork_[elementIndex] = COIN_DBL_MAX;
     6934      } else if (!columnScale_) {
     6935        columnUpperWork_[elementIndex] = upperValue * rhsScale_;
     6936      } else {
     6937        columnUpperWork_[elementIndex] = upperValue * rhsScale_
     6938          / columnScale_[elementIndex];
     6939      }
     6940    }
     6941  }
     6942}
     6943void ClpSimplex::setColumnSetBounds(const int* indexFirst,
     6944                                            const int* indexLast,
     6945                                            const double* boundList)
     6946{
     6947#ifndef NDEBUG
     6948  int n = numberColumns_;
     6949#endif
     6950  int numberChanged=0;
     6951  const int * saveFirst=indexFirst;
     6952  while (indexFirst != indexLast) {
     6953    const int iColumn=*indexFirst++;
     6954#ifndef NDEBUG
     6955    if (iColumn<0||iColumn>=n) {
     6956      indexError(iColumn,"setColumnSetBounds");
     6957    }
     6958#endif
     6959    double lowerValue = *boundList++;
     6960    double upperValue = *boundList++;
     6961    if (lowerValue<-1.0e27)
     6962      lowerValue=-COIN_DBL_MAX;
     6963    if (upperValue>1.0e27)
     6964      upperValue=COIN_DBL_MAX;
     6965    assert (upperValue>=lowerValue);
     6966    if (columnLower_[iColumn] != lowerValue) {
     6967      columnLower_[iColumn] = lowerValue;
     6968      whatsChanged_ &= ~16;
     6969      numberChanged++;
     6970    }
     6971    if (columnUpper_[iColumn] != upperValue) {
     6972      columnUpper_[iColumn] = upperValue;
     6973      whatsChanged_ &= ~32;
     6974      numberChanged++;
     6975    }
     6976  }
     6977  if (numberChanged&&(whatsChanged_&1)!=0) {
     6978    indexFirst = saveFirst;
     6979    while (indexFirst != indexLast) {
     6980      const int iColumn=*indexFirst++;
     6981      if (columnLower_[iColumn]==-COIN_DBL_MAX) {
     6982        columnLowerWork_[iColumn] = -COIN_DBL_MAX;
     6983      } else if (!columnScale_) {
     6984        columnLowerWork_[iColumn] = columnLower_[iColumn] * rhsScale_;
     6985      } else {
     6986        columnLowerWork_[iColumn] = columnLower_[iColumn] * rhsScale_
     6987          / columnScale_[iColumn];
     6988      }
     6989      if (columnUpper_[iColumn]==COIN_DBL_MAX) {
     6990        columnUpperWork_[iColumn] = COIN_DBL_MAX;
     6991      } else if (!columnScale_) {
     6992        columnUpperWork_[iColumn] = columnUpper_[iColumn] * rhsScale_;
     6993      } else {
     6994        columnUpperWork_[iColumn] = columnUpper_[iColumn] * rhsScale_
     6995          / columnScale_[iColumn];
     6996      }
     6997    }
     6998  }
     6999}
  • trunk/ClpSimplexDual.cpp

    r471 r472  
    227227  // Do initial factorization
    228228  // If user asked for perturbation - do it
    229   if (!startup(0)) {
     229  if (!startup(0,startFinishOptions)) {
    230230    // looks okay
    231231    // Superbasic variables not allowed
     
    311311       
    312312    // This says whether to restore things etc
     313    // startup will have factorized so can skip
    313314    int factorType=0;
    314315    // Start check for cycles
     
    410411
    411412  // clean up
    412   if (!startFinishOptions)
    413     finish();
     413  finish(startFinishOptions);
    414414  delete [] saveDuals;
    415415
     
    36463646  // put in standard form (and make row copy)
    36473647  // create modifiable copies of model rim and do optional scaling
    3648   createRim(7+8+16,true);
     3648  createRim(7+8+16+32,true);
    36493649
    36503650  // change newLower and newUpper if scaled
  • trunk/ClpSimplexPrimal.cpp

    r464 r472  
    189189  int initialStatus=problemStatus_;
    190190  // initialize - maybe values pass and algorithm_ is +1
    191   if (!startup(ifValuesPass)) {
     191  if (!startup(ifValuesPass,startFinishOptions)) {
    192192   
    193193    // Set average theta
     
    422422  // clean up
    423423  unflag();
    424   if (!startFinishOptions)
    425     finish();
     424  finish(startFinishOptions);
    426425  restoreData(data);
    427426  return problemStatus_;
  • trunk/Test/unitTest.cpp

    r465 r472  
    631631    assert (fabs(valueDecrease[8]-2.95113)<1.0e-4);
    632632  }
     633  // Test binv etc
     634  {   
     635    /*
     636       Wolsey : Page 130
     637       max 4x1 -  x2
     638       7x1 - 2x2    <= 14
     639       x2    <= 3
     640       2x1 - 2x2    <= 3
     641       x1 in Z+, x2 >= 0
     642
     643       note slacks are -1 in Clp so signs may be different
     644    */
     645   
     646    int n_cols = 2;
     647    int n_rows = 3;
     648   
     649    double obj[2] = {-4.0, 1.0};
     650    double collb[2] = {0.0, 0.0};
     651    double colub[2] = {COIN_DBL_MAX, COIN_DBL_MAX};
     652    double rowlb[3] = {-COIN_DBL_MAX, -COIN_DBL_MAX, -COIN_DBL_MAX};
     653    double rowub[3] = {14.0, 3.0, 3.0};
     654   
     655    int rowIndices[5] =  {0,     2,    0,    1,    2};
     656    int colIndices[5] =  {0,     0,    1,    1,    1};
     657    double elements[5] = {7.0, 2.0, -2.0,  1.0, -2.0};
     658    CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5);
     659
     660    ClpSimplex model;
     661    model.loadProblem(M, collb, colub, obj, rowlb, rowub);
     662    // For now - without scaling
     663    model.scaling(0);
     664    model.dual(0,1); // keep factorization
     665   
     666    //check that the tableau matches wolsey (B-1 A)
     667    // slacks in second part of binvA
     668    double * binvA = (double*) malloc((n_cols+n_rows) * sizeof(double));
     669   
     670    printf("B-1 A");
     671    for(int i = 0; i < n_rows; i++){
     672      model.getBInvARow(i, binvA,binvA+n_cols);
     673      printf("\nrow: %d -> ",i);
     674      for(int j=0; j < n_cols+n_rows; j++){
     675        printf("%g, ", binvA[j]);
     676      }
     677    }
     678    printf("\n");
     679    free(binvA);
     680    // See if can re-use factorization
     681    model.primal(0,3); // keep factorization
     682    model.dual(0,2); // use factorization
     683    model.dual(0,2); // hopefully will not use factorization
     684  }
    633685  // test steepest edge
    634686  {   
  • trunk/include/ClpModel.hpp

    r470 r472  
    738738  /** Solve type - 1 simplex, 2 simplex interface, 3 Interior.*/
    739739  int solveType_;
     740  /** Whats changed since last solve.  This is a work in progress
     741      It is designed so careful people can make go faster.
     742      It is only used when startFinishOptions used in dual or primal.
     743      Bit 1 - number of rows/columns has not changed (so work arrays valid)
     744          2 - matrix has not changed
     745          4 - if matrix has changed only by adding rows
     746          8 - if matrix has changed only by adding columns
     747         16 - row lbs not changed
     748         32 - row ubs not changed
     749         64 - column objective not changed
     750        128 - column lbs not changed
     751        256 - column ubs not changed
     752              top bits may be used internally
     753  */
     754  unsigned int whatsChanged_;
    740755  /// Status of problem
    741756  int problemStatus_;
  • trunk/include/ClpSimplex.hpp

    r468 r472  
    171171  int initialPrimalSolve();
    172172  /** Dual algorithm - see ClpSimplexDual.hpp for method.
    173       ifValuesPass==2 just does values pass and then stops */
    174   int dual(int ifValuesPass=0);
     173      ifValuesPass==2 just does values pass and then stops.
     174
     175      startFinishOptions - bits
     176      1 - do not delete work areas and factorization at end
     177      2 - use old factorization if same number of rows
     178      4 - skip as much initialization of work areas as possible
     179          (based on whatsChanged in clpmodel.hpp) ** work in progress
     180      maybe other bits later
     181  */
     182  int dual(int ifValuesPass=0, int startFinishOptions=0);
    175183  /** Primal algorithm - see ClpSimplexPrimal.hpp for method.
    176       ifValuesPass==2 just does values pass and then stops */
    177   int primal(int ifValuesPass=0);
     184      ifValuesPass==2 just does values pass and then stops.
     185
     186      startFinishOptions - bits
     187      1 - do not delete work areas and factorization at end
     188      2 - use old factorization if same number of rows
     189      4 - skip as much initialization of work areas as possible
     190          (based on whatsChanged in clpmodel.hpp) ** work in progress
     191      maybe other bits later
     192  */
     193  int primal(int ifValuesPass=0, int startFinishOptions=0);
    178194  /** Solves nonlinear problem using SLP - may be used as crash
    179195      for other algorithms when number of iterations small.
     
    288304  int dualPivotResult();
    289305
    290   /** Common bits of coding for dual and primal.  Return s0 if okay,
     306  /** Common bits of coding for dual and primal.  Return 0 if okay,
    291307      1 if bad matrix, 2 if very bad factorization
    292   */
    293   int startup(int ifValuesPass);
    294   void finish();
     308
     309      startFinishOptions - bits
     310      1 - do not delete work areas and factorization at end
     311      2 - use old factorization if same number of rows
     312      4 - skip as much initialization of work areas as possible
     313          (based on whatsChanged in clpmodel.hpp) ** work in progress
     314      maybe other bits later
     315     
     316  */
     317  int startup(int ifValuesPass,int startFinishOptions=0);
     318  void finish(int startFinishOptions=0);
    295319 
    296320  /** Factorizes and returns true if optimal.  Used by user */
     
    808832      128 - Switch off all matrix sanity checks
    809833      256 - No row copy
     834      512 - Not values pass, solution guaranteed, skip as much as possible
    810835  */
    811836  inline unsigned int specialOptions() const
     
    814839  { specialOptions_=value;};
    815840  //@}
     841
     842  ///@name Basis handling
     843  // These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal)
     844  // *** At present only without scaling
     845  // *** Slacks havve -1.0 element (so == row activity) - take care
     846  ///Get a row of the tableau (slack part in slack if not NULL)
     847  void getBInvARow(int row, double* z, double * slack=NULL);
     848 
     849  ///Get a row of the basis inverse
     850  void getBInvRow(int row, double* z);
     851 
     852  ///Get a column of the tableau
     853  void getBInvACol(int col, double* vec);
     854 
     855  ///Get a column of the basis inverse
     856  void getBInvCol(int col, double* vec);
     857 
     858  /** Get basic indices (order of indices corresponds to the
     859      order of elements in a vector retured by getBInvACol() and
     860      getBInvCol()).
     861  */
     862  void getBasics(int* index);
     863 
     864  //@}
     865    //-------------------------------------------------------------------------
     866    /**@name Changing bounds on variables and constraints */
     867    //@{
     868       /** Set an objective function coefficient */
     869       void setObjectiveCoefficient( int elementIndex, double elementValue );
     870       /** Set an objective function coefficient */
     871       inline void setObjCoeff( int elementIndex, double elementValue )
     872       { setObjectiveCoefficient( elementIndex, elementValue);};
     873
     874      /** Set a single column lower bound<br>
     875          Use -DBL_MAX for -infinity. */
     876       void setColumnLower( int elementIndex, double elementValue );
     877     
     878      /** Set a single column upper bound<br>
     879          Use DBL_MAX for infinity. */
     880       void setColumnUpper( int elementIndex, double elementValue );
     881
     882      /** Set a single column lower and upper bound */
     883      void setColumnBounds( int elementIndex,
     884        double lower, double upper );
     885
     886      /** Set the bounds on a number of columns simultaneously<br>
     887          The default implementation just invokes setColLower() and
     888          setColUpper() over and over again.
     889          @param indexFirst,indexLast pointers to the beginning and after the
     890                 end of the array of the indices of the variables whose
     891                 <em>either</em> bound changes
     892          @param boundList the new lower/upper bound pairs for the variables
     893      */
     894      void setColumnSetBounds(const int* indexFirst,
     895                                   const int* indexLast,
     896                                   const double* boundList);
     897     
     898      /** Set a single column lower bound<br>
     899          Use -DBL_MAX for -infinity. */
     900       inline void setColLower( int elementIndex, double elementValue )
     901       { setColumnLower(elementIndex, elementValue);};
     902      /** Set a single column upper bound<br>
     903          Use DBL_MAX for infinity. */
     904       inline void setColUpper( int elementIndex, double elementValue )
     905       { setColumnUpper(elementIndex, elementValue);};
     906
     907      /** Set a single column lower and upper bound */
     908      inline void setColBounds( int elementIndex,
     909        double lower, double upper )
     910       { setColumnBounds(elementIndex, lower, upper);};
     911
     912      /** Set the bounds on a number of columns simultaneously<br>
     913          @param indexFirst,indexLast pointers to the beginning and after the
     914                 end of the array of the indices of the variables whose
     915                 <em>either</em> bound changes
     916          @param boundList the new lower/upper bound pairs for the variables
     917      */
     918      inline void setColSetBounds(const int* indexFirst,
     919                                   const int* indexLast,
     920                                   const double* boundList)
     921      { setColumnSetBounds(indexFirst, indexLast, boundList);};
     922     
     923      /** Set a single row lower bound<br>
     924          Use -DBL_MAX for -infinity. */
     925      void setRowLower( int elementIndex, double elementValue );
     926     
     927      /** Set a single row upper bound<br>
     928          Use DBL_MAX for infinity. */
     929      void setRowUpper( int elementIndex, double elementValue ) ;
     930   
     931      /** Set a single row lower and upper bound */
     932      void setRowBounds( int elementIndex,
     933                                 double lower, double upper ) ;
     934   
     935      /** Set the bounds on a number of rows simultaneously<br>
     936          @param indexFirst,indexLast pointers to the beginning and after the
     937                 end of the array of the indices of the constraints whose
     938                 <em>either</em> bound changes
     939          @param boundList the new lower/upper bound pairs for the constraints
     940      */
     941      void setRowSetBounds(const int* indexFirst,
     942                                   const int* indexLast,
     943                                   const double* boundList);
     944   
     945    //@}
    816946
    817947////////////////// data //////////////////
  • trunk/include/ClpSimplexDual.hpp

    r460 r472  
    112112     feasibility tolerance.
    113113
     114     for use of exotic parameter startFinishoptions see Clpsimplex.hpp
    114115  */
    115116
  • trunk/include/ClpSimplexPrimal.hpp

    r343 r472  
    109109     feasibility tolerance.
    110110
     111     for use of exotic parameter startFinishoptions see Clpsimplex.hpp
    111112  */
    112113
Note: See TracChangeset for help on using the changeset viewer.