示例#1
0
文件: osiif.cpp 项目: lncosie/ogdf
void OsiIF::loadDummyRow(OsiSolverInterface* s2, const double* lbounds, const double* ubounds, const double* objectives)
{
	CoinPackedVector *coinrow = new CoinPackedVector();
	CoinPackedMatrix *matrix =  new CoinPackedMatrix(false,0,0);
	matrix->setDimensions(0, numCols_);
	ArrayBuffer<int> dummy(1,false);
	dummy.push(0);
	char *senses = new char[1];
	double *rhs = new double[1];
	double *ranges = new double[1];
	coinrow->insert(0, 1.);
	matrix->appendRow(*coinrow);
	senses[0] = 'E';
	rhs[0] = 1.;
	ranges[0] = 0.;

	lpSolverTime_.start();
	s2->loadProblem(*matrix, lbounds, ubounds, objectives, senses, rhs, ranges);
	lpSolverTime_.stop();
	_remRows(dummy);

	delete coinrow;
	delete matrix;
	freeChar(senses);
	freeDouble(rhs);
	freeDouble(ranges);

	return;
}
示例#2
0
/** Construct from a CoinPackedMatrix*/
TMat::TMat(const CoinPackedMatrix &M, MatrixStorageType T):
  iRow_(NULL), jCol_(NULL), value_(NULL), nnz_(M.getNumElements()),
  capacity_(M.getNumElements()), columnOrdering_(), rowOrdering_(),
  nonEmptyRows_(), nonEmptyCols_(){
  create(M);
  make_upper_triangular(T);
}
示例#3
0
/* Load in an problem by copying the arguments (the constraints on the
   rows are given by lower and upper bounds). If a pointer is NULL then the
   following values are the default:
   <ul>
   <li> <code>colub</code>: all columns have upper bound infinity
   <li> <code>collb</code>: all columns have lower bound 0 
   <li> <code>rowub</code>: all rows have upper bound infinity
   <li> <code>rowlb</code>: all rows have lower bound -infinity
   <li> <code>obj</code>: all variables have 0 objective coefficient
      </ul>
*/
void 
CoinSnapshot::loadProblem(const CoinPackedMatrix& matrix,
			  const double* collb, const double* colub,   
			  const double* obj,
			  const double* rowlb, const double* rowub,
			  bool makeRowCopy)
{
  // Keep scalars (apart from objective value etc)
  gutsOfDestructor(3+8);
  numRows_ = matrix.getNumRows();
  numCols_ = matrix.getNumCols();
  numElements_ = matrix.getNumElements();
  owned_.matrixByCol = 1;
  matrixByCol_ = new CoinPackedMatrix(matrix);
  if (makeRowCopy) {
    owned_.matrixByRow = 1;
    CoinPackedMatrix * matrixByRow = new CoinPackedMatrix(matrix);
    matrixByRow->reverseOrdering();
    matrixByRow_ = matrixByRow;
  }
  colLower_ = CoinCopyOfArray(collb,numCols_,0.0);
  colUpper_ = CoinCopyOfArray(colub,numCols_,infinity_);
  objCoefficients_ = CoinCopyOfArray(obj,numCols_,0.0);
  rowLower_ = CoinCopyOfArray(rowlb,numRows_,-infinity_);
  rowUpper_ = CoinCopyOfArray(rowub,numRows_,infinity_);
  // do rhs as well
  createRightHandSide();
}
示例#4
0
lpHook::lpHook(const double* clb, const double* cub, const double* obj,
               const double* rhs, const char* sense,
               const CoinPackedMatrix& mat)
{
     const int colnum = mat.getNumCols();
     const int rownum = mat.getNumRows();

     colupper_ = new double[colnum];
     collower_ = new double[colnum];
     objcoeffs_ = new double[colnum];
     rhs_ = new double[rownum];
     sense_ = new char[rownum];

     std::copy(clb, clb + colnum, collower_);
     std::copy(cub, cub + colnum, colupper_);
     std::copy(obj, obj + colnum, objcoeffs_);
     std::copy(rhs, rhs + rownum, rhs_);
     std::copy(sense, sense + rownum, sense_);

     if (mat.isColOrdered()) {
          colMatrix_.copyOf(mat);
          rowMatrix_.reverseOrderedCopyOf(mat);
     } else {
          rowMatrix_.copyOf(mat);
          colMatrix_.reverseOrderedCopyOf(mat);
     }
}
void
OsiVolSolverInterface::loadProblem(const CoinPackedMatrix& matrix,
				   const double* collb, const double* colub,
				   const double* obj,
				   const char* rowsen, const double* rowrhs,   
				   const double* rowrng)
{
   gutsOfDestructor_();
   const int rownum = matrix.getNumRows();
   const int colnum = matrix.getNumCols();

   if (matrix.isColOrdered()) {
      colMatrix_ = matrix;
      colMatrixCurrent_ = true;
      rowMatrixCurrent_ = false;
      maxNumcols_ = colMatrix_.getMaxMajorDim();
      maxNumrows_ = static_cast<int>((1+colMatrix_.getExtraGap()) *
				     colMatrix_.getMinorDim());
   } else {
      rowMatrix_ = matrix;
      rowMatrixCurrent_ = true;
      colMatrixCurrent_ = false;
      maxNumcols_ = static_cast<int>((1+rowMatrix_.getExtraGap()) *
				     rowMatrix_.getMinorDim());
      maxNumrows_ = rowMatrix_.getMaxMajorDim();
   }

   initFromRhsSenseRange(rownum, rowsen, rowrhs, rowrng);
   initFromClbCubObj(colnum, collb, colub, obj);
}
示例#6
0
// take columns of matrix and add each to arrays for matrix under construction
void addSubMatr (int *start, int *len, int *ind, double *el,
		 CoinPackedMatrix &A, 
		 CoinPackedVector &v, 
		 int &cur,
		 int &ncols,
		 int dispM, 
		 int dispVec, 
		 int finalrow) {

  const int 
    *aLe  = A.getVectorLengths (),
    *aIn  = A.getIndices  (),
    *vIn  = v.getIndices  (),
     aCol = A.getMajorDim ();

  int vNum = v.getNumElements ();

  const double 
    *aEl = A.getElements (),
    *vEl = v.getElements ();

  // add each column
  for (int i=0; i<aCol; i++, len++) {

    *start++ = cur;
    *len     = *aLe++;

    // matrix entries
    for (int j = 0; j < *len; j++) {
      *ind++ = dispM + *aIn++;
      *el++  = *aEl++;
    }

    cur += *len;

    // check if there is a corresponding rhs
    if (vNum && (*vIn == i)) {

      ++*len;
      cur++;
      *ind++ = dispVec;
      *el++  = *vEl;

      vIn++;
      vEl++;
      --vNum;
    }

    // normalization entry
    ++*len;
    cur++;
    *ind++ = finalrow;
    *el++  = 1.;

    ++ncols;
  }

  *start = cur;
}
示例#7
0
StochGenMatrix* sTreeImpl::createC() 
{
  //is this node a dead-end for this process?
  if(commWrkrs==MPI_COMM_NULL)
    return new StochGenDummyMatrix(m_id);

  StochGenMatrix* C = NULL;
  if (m_id==0) {
    CoinPackedMatrix Crow; 
    Crow.reverseOrderedCopyOf( in.getFirstStageConstraints() );

    // number of nz in the rows corresponding to ineq constraints
    int nnzD=countNNZ( Crow, 
		       in.getFirstStageRowLB(), 
		       in.getFirstStageRowUB(), 
		       ineq_comp());
    C = new StochGenMatrix( m_id, MZ, N, 
			    m_mz, 0,   0,    // C does not exist for the root
			    m_mz, m_nx, nnzD, // D is 1st stage ineq matrix
			    commWrkrs );
    extractRows( Crow,
		 in.getFirstStageRowLB(), in.getFirstStageRowUB(), ineq_comp(),
		 C->Bmat->krowM(), C->Bmat->jcolM(), C->Bmat->M() );
    //printf("  -- 1st stage mz=%lu nx=%lu nnzD=%d\n", m_mz, m_nx, nnzD);
  } else {
    int scen=m_id-1;
    CoinPackedMatrix Crow, Drow; 
    Crow.reverseOrderedCopyOf( in.getLinkingConstraints(scen) );
    Drow.reverseOrderedCopyOf( in.getSecondStageConstraints(scen) );

    int nnzC=countNNZ( Crow, in.getSecondStageRowLB(scen), 
		       in.getSecondStageRowUB(scen), ineq_comp() );
    int nnzD=countNNZ( Drow, in.getSecondStageRowLB(scen), 
		       in.getSecondStageRowUB(scen), ineq_comp() );

    C = new StochGenMatrix( m_id, MZ, N, 
			    m_mz, parent->m_nx, nnzC, 
			    m_mz, m_nx,         nnzD,
			    commWrkrs );
    //printf("  -- 2nd stage mz=%lu nx=%lu   1st stage nx=%lu     nnzC=%d nnzD=%d\n", m_mz, m_nx, parent->m_nx, nnzC, nnzD);
    extractRows( Crow,
		 in.getSecondStageRowLB(scen), 
		 in.getSecondStageRowUB(scen), 
		 ineq_comp(),
		 C->Amat->krowM(), C->Amat->jcolM(), C->Amat->M() );
    extractRows( Drow,
		 in.getSecondStageRowLB(scen), 
		 in.getSecondStageRowUB(scen), 
		 ineq_comp(),
		 C->Bmat->krowM(), C->Bmat->jcolM(), C->Bmat->M() );
  }
  
  for(size_t it=0; it<children.size(); it++) {
    StochGenMatrix* child = ((sTreeImpl*)children[it])->createC();
    C->AddChild(child);
  }
  return C;
}
示例#8
0
int
lpHook::compute_rc(const VOL_dvector& u, VOL_dvector& rc)
{
     rowMatrix_.transposeTimes(u.v, rc.v);
     const int psize = rowMatrix_.getNumCols();

     for (int i = 0; i < psize; ++i)
          rc[i] = objcoeffs_[i] - rc[i];
     return 0;
}
示例#9
0
// Create row-wise copy from MatrixByCol
void 
CoinSnapshot::createMatrixByRow()
{
  if (owned_.matrixByRow)
    delete matrixByRow_;
  assert (matrixByCol_);
  owned_.matrixByRow = 1;
  CoinPackedMatrix * matrixByRow = new CoinPackedMatrix(*matrixByCol_);
  matrixByRow->reverseOrdering();
  matrixByRow_ = matrixByRow;
}
示例#10
0
int
lpHook::solve_subproblem(const VOL_dvector& dual, const VOL_dvector& rc,
                         double& lcost, VOL_dvector& x, VOL_dvector& v,
                         double& pcost)
{
     int i;
     const int psize = x.size();
     const int dsize = v.size();

     // compute the lagrangean solution corresponding to the reduced costs
     for (i = 0; i < psize; ++i)
          x[i] = (rc[i] >= 0.0) ? collower_[i] : colupper_[i];

     // compute the lagrangean value (rhs*dual + primal*rc)
     lcost = 0;
     for (i = 0; i < dsize; ++i)
          lcost += rhs_[i] * dual[i];
     for (i = 0; i < psize; ++i)
          lcost += x[i] * rc[i];

     // compute the rhs - lhs
     colMatrix_.times(x.v, v.v);
     for (i = 0; i < dsize; ++i)
          v[i] = rhs_[i] - v[i];

     // compute the lagrangean primal objective
     pcost = 0;
     for (i = 0; i < psize; ++i)
          pcost += x[i] * objcoeffs_[i];

     return 0;
}
示例#11
0
int main () {
  // generate conic constraints
  CoinPackedMatrix * A = 0;
  CoinPackedVector * b = 0;
  CoinPackedVector * d = 0;
  double h = 0;
  generate_conic_constraint(A, b, d, h);
  A->dumpMatrix();
  // generate linear constraints
  CoinPackedMatrix * matrix = 0;
  double * col_lb = 0;
  double * col_ub = 0;
  double * obj = 0;
  double * row_lb = 0;
  double * row_ub = 0;
  generate_linear_constraints(matrix, col_lb, col_ub, obj, row_lb, row_ub);
  // create solver and load linear constraints
  OsiConicSolverInterface * solver = new ColaModel();
  // just add cols to the model
  solver->addCol(0, 0, 0, 0.0, solver->getInfinity(), 1.0, std::string("x1"));
  solver->addCol(0, 0, 0, 0.0, solver->getInfinity(), 0.0, std::string("x2"));
  solver->addCol(0, 0, 0, 0.0, solver->getInfinity(), 1.0, std::string("x3"));
  solver->addCol(0, 0, 0, 0.0, solver->getInfinity(), 0.0, std::string("x4"));
  //solver->loadProblem(*matrix, col_lb, NULL, obj, row_lb, row_ub);
  // add conic constraints
  solver->addConicConstraint(A, b, d, h);
  // todo(aykut) implement writing problem to mps files
  //solver->writeMps("ex");
  // solve problem
  solver->initialSolve();
  // print status
  std::cout << "is optimal: " << solver->isProvenOptimal() << std::endl;
  // print solution
  ColaModel * cm = dynamic_cast<ColaModel*>(solver);
  cm->print_stats();
  double const * sol = solver->getColSolution();
  for (int i=0; i<4; ++i) {
    std::cout << "x" << i << " " << sol[i] << std::endl;
  }
  delete A;
  delete b;
  delete d;
  delete matrix;
  delete solver;
  return 0;
}
bool
OsiTestSolverInterface::test_zero_one_minusone_(const CoinPackedMatrix& m) const
{
  const int vecnum = m.getMajorDim();
  const double* elem = m.getElements();
  const int* start = m.getVectorStarts();
  const int* length = m.getVectorLengths();
  int i, j;
  for (i = 0; i < vecnum; ++i) {
    for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
      const double val = elem[j];
      if (val != 1.0 && val != 0.0 && val != -1.0) {
	return false;
      }
    }
  }
  return true;
}
示例#13
0
   /** Equivalence.
       Two matrices are equivalent if they are both by rows or both by columns,
       they have the same dimensions, and each vector is equivalent. 
       In this method the FloatEqual function operator can be specified. 
   */
   template <class FloatEqual> bool 
   isEquivalent(const CoinPackedMatrix& rhs, const FloatEqual& eq) const
   {
      // Both must be column order or both row ordered and must be of same size
      if ((isColOrdered() ^ rhs.isColOrdered()) ||
	  (getNumCols() != rhs.getNumCols()) ||
	  (getNumRows() != rhs.getNumRows()) ||
	  (getNumElements() != rhs.getNumElements()))
	 return false;
     
      for (int i=getMajorDim()-1; i >= 0; --i) {
        CoinShallowPackedVector pv = getVector(i);
        CoinShallowPackedVector rhsPv = rhs.getVector(i);
        if ( !pv.isEquivalent(rhsPv,eq) )
          return false;
      }
      return true;
   }
示例#14
0
int main(int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("hello.mps", true);
     } else {
          status = model.readMps(argv[1], true);
     }
     if (status)
          exit(10);

     int numberColumns = model.numberColumns();
     int numberRows = model.numberRows();

     if (numberColumns > 80 || numberRows > 80) {
          printf("model too large\n");
          exit(11);
     }
     printf("This prints x wherever a non-zero element exists in the matrix.\n\n\n");

     char x[81];

     int iRow;
     // get row copy
     CoinPackedMatrix rowCopy = *model.matrix();
     rowCopy.reverseOrdering();
     const int * column = rowCopy.getIndices();
     const int * rowLength = rowCopy.getVectorLengths();
     const CoinBigIndex * rowStart = rowCopy.getVectorStarts();

     x[numberColumns] = '\0';
     for (iRow = 0; iRow < numberRows; iRow++) {
          memset(x, ' ', numberColumns);
          for (int k = rowStart[iRow]; k < rowStart[iRow] + rowLength[iRow]; k++) {
               int iColumn = column[k];
               x[iColumn] = 'x';
          }
          printf("%s\n", x);
     }
     printf("\n\n");
     return 0;
}
示例#15
0
void TMat::create(const CoinPackedMatrix &M){ 
  // Allocate arrays;
  iRow_ = new int[capacity_];
  jCol_ = new int[capacity_];
  value_ = new double[capacity_];

  int * iRow = iRow_;
  int * jCol = jCol_;
  if(!M.isColOrdered()){// Have to swap
    std::cout<<"Matrix is not col ordered"<<std::endl;
    iRow = jCol_;
    jCol = iRow_;
  }
  
  // Now we can safely assume that M is colorderd.
  int numcols = M.getMajorDim();
  const int * start = M.getVectorStarts();
  const int * length = M.getVectorLengths();
  const int * indice = M.getIndices();
  const double * value = M.getElements();
  int nnz = 0;
  for(int i = 0 ; i < numcols ; i++){
    int begin = start[i];
    int end = start[i] + length[i];
    for(int k = begin ; k < end ; k++){
      value_[nnz] = value[k];
      iRow[nnz] = indice[k];
      jCol[nnz++] = i;
    }
  }
  assert(nnz==nnz_);
}
示例#16
0
/* Modifies djs to allow for quadratic.
   returns quadratic offset */
CoinWorkDouble
ClpInterior::quadraticDjs(CoinWorkDouble * djRegion, const CoinWorkDouble * solution,
                          CoinWorkDouble scaleFactor)
{
     CoinWorkDouble quadraticOffset = 0.0;
#ifndef NO_RTTI
     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
#else
     ClpQuadraticObjective * quadraticObj = NULL;
     if (objective_->type() == 2)
          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
#endif
     if (quadraticObj) {
          CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
          const int * columnQuadratic = quadratic->getIndices();
          const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts();
          const int * columnQuadraticLength = quadratic->getVectorLengths();
          double * quadraticElement = quadratic->getMutableElements();
          int numberColumns = quadratic->getNumCols();
          for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
               CoinWorkDouble value = 0.0;
               for (CoinBigIndex j = columnQuadraticStart[iColumn];
                         j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                    int jColumn = columnQuadratic[j];
                    CoinWorkDouble valueJ = solution[jColumn];
                    CoinWorkDouble elementValue = quadraticElement[j];
                    //value += valueI*valueJ*elementValue;
                    value += valueJ * elementValue;
                    quadraticOffset += solution[iColumn] * valueJ * elementValue;
               }
               djRegion[iColumn] += scaleFactor * value;
          }
     }
     return quadraticOffset;
}
示例#17
0
 //TODO: ugh force both row/col format?
 void loadDataAndSolution(const CoinPackedMatrix & rowMatrix,
                          const CoinPackedMatrix & colMatrix,
                          const double           * collb, 
                          const double           * colub,   
                          const double           * obj,
                          const double           * rowlb, 
                          const double           * rowub,
                          const char             * colType,
                          const double           * primalSol,
                          const double             infinity){
    data_->setMatrixByRow(&rowMatrix);
    data_->setMatrixByCol(&colMatrix);      
    data_->setNrow(rowMatrix.getNumRows());
    data_->setNcol(rowMatrix.getNumCols());
    data_->setColLower(collb);
    data_->setColUpper(colub);
    data_->setRowLower(rowlb);
    data_->setRowUpper(rowub);
    data_->setObj(obj);
    data_->setColType(colType);
    data_->setPrimalSol(primalSol);
    data_->setInfinity(infinity);
    data_->initializeOtherData();
 }
/* Orders rows and saves pointer to model */
int
ClpCholeskyWssmpKKT::order(ClpInterior * model)
{
    int numberRowsModel = model->numberRows();
    int numberColumns = model->numberColumns();
    int numberTotal = numberColumns + numberRowsModel;
    numberRows_ = 2 * numberRowsModel + numberColumns;
    rowsDropped_ = new char [numberRows_];
    memset(rowsDropped_, 0, numberRows_);
    numberRowsDropped_ = 0;
    model_ = model;
    CoinPackedMatrix * quadratic = NULL;
    ClpQuadraticObjective * quadraticObj =
        (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject()));
    if (quadraticObj)
        quadratic = quadraticObj->quadraticObjective();
    int numberElements = model_->clpMatrix()->getNumElements();
    numberElements = numberElements + 2 * numberRowsModel + numberTotal;
    if (quadratic)
        numberElements += quadratic->getNumElements();
    // Space for starts
    choleskyStart_ = new CoinBigIndex[numberRows_+1];
    const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts();
    const int * columnLength = model_->clpMatrix()->getVectorLengths();
    const int * row = model_->clpMatrix()->getIndices();
    //const double * element = model_->clpMatrix()->getElements();
    // Now we have size - create arrays and fill in
    try {
        choleskyRow_ = new int [numberElements];
    } catch (...) {
        // no memory
        delete [] choleskyStart_;
        choleskyStart_ = NULL;
        return -1;
    }
    try {
        sparseFactor_ = new double[numberElements];
    } catch (...) {
        // no memory
        delete [] choleskyRow_;
        choleskyRow_ = NULL;
        delete [] choleskyStart_;
        choleskyStart_ = NULL;
        return -1;
    }
    int iRow, iColumn;

    sizeFactor_ = 0;
    // matrix
    if (!quadratic) {
        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
            choleskyStart_[iColumn] = sizeFactor_;
            choleskyRow_[sizeFactor_++] = iColumn;
            CoinBigIndex start = columnStart[iColumn];
            CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
            for (CoinBigIndex j = start; j < end; j++) {
                choleskyRow_[sizeFactor_++] = row[j] + numberTotal;
            }
        }
    } else {
        // Quadratic
        const int * columnQuadratic = quadratic->getIndices();
        const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts();
        const int * columnQuadraticLength = quadratic->getVectorLengths();
        //const double * quadraticElement = quadratic->getElements();
        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
            choleskyStart_[iColumn] = sizeFactor_;
            choleskyRow_[sizeFactor_++] = iColumn;
            for (CoinBigIndex j = columnQuadraticStart[iColumn];
                    j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                int jColumn = columnQuadratic[j];
                if (jColumn > iColumn)
                    choleskyRow_[sizeFactor_++] = jColumn;
            }
            CoinBigIndex start = columnStart[iColumn];
            CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
            for (CoinBigIndex j = start; j < end; j++) {
                choleskyRow_[sizeFactor_++] = row[j] + numberTotal;
            }
        }
    }
    // slacks
    for (; iColumn < numberTotal; iColumn++) {
        choleskyStart_[iColumn] = sizeFactor_;
        choleskyRow_[sizeFactor_++] = iColumn;
        choleskyRow_[sizeFactor_++] = iColumn - numberColumns + numberTotal;
    }
    // Transpose - nonzero diagonal (may regularize)
    for (iRow = 0; iRow < numberRowsModel; iRow++) {
        choleskyStart_[iRow+numberTotal] = sizeFactor_;
        // diagonal
        choleskyRow_[sizeFactor_++] = iRow + numberTotal;
    }
    choleskyStart_[numberRows_] = sizeFactor_;
    permuteInverse_ = new int [numberRows_];
    permute_ = new int[numberRows_];
    integerParameters_[0] = 0;
    int i0 = 0;
    int i1 = 1;
#ifndef USE_EKKWSSMP
    int i2 = 1;
    if (model->numberThreads() <= 0)
        i2 = 1;
    else
        i2 = model->numberThreads();
    F77_FUNC(wsetmaxthrds,WSETMAXTHRDS)(&i2);
#endif
    F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_,
                          NULL, permute_, permuteInverse_, 0, &numberRows_, &i1,
                          NULL, &i0, NULL, integerParameters_, doubleParameters_);
    integerParameters_[1] = 1; //order and symbolic
    integerParameters_[2] = 2;
    integerParameters_[3] = 0; //CSR
    integerParameters_[4] = 0; //C style
    integerParameters_[13] = 1; //reuse initial factorization space
    integerParameters_[15+0] = 1; //ordering
    integerParameters_[15+1] = 0;
    integerParameters_[15+2] = 1;
    integerParameters_[15+3] = 0;
    integerParameters_[15+4] = 1;
    doubleParameters_[10] = 1.0e-20;
    doubleParameters_[11] = 1.0e-15;
#if 1
    integerParameters_[1] = 2; //just symbolic
    for (int iRow = 0; iRow < numberRows_; iRow++) {
        permuteInverse_[iRow] = iRow;
        permute_[iRow] = iRow;
    }
#endif
    F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_,
                          NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1,
                          NULL, &i0, NULL, integerParameters_, doubleParameters_);
    //std::cout<<"Ordering and symbolic factorization took "<<doubleParameters_[0]<<std::endl;
    if (integerParameters_[63]) {
        std::cout << "wssmp returning error code of " << integerParameters_[63] << std::endl;
        return 1;
    }
    std::cout << integerParameters_[23] << " elements in sparse Cholesky" << std::endl;
    if (!integerParameters_[23]) {
        for (int iRow = 0; iRow < numberRows_; iRow++) {
            permuteInverse_[iRow] = iRow;
            permute_[iRow] = iRow;
        }
        std::cout << "wssmp says no elements - fully dense? - switching to dense" << std::endl;
        integerParameters_[1] = 2;
        integerParameters_[2] = 2;
        integerParameters_[7] = 1; // no permute
        F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_,
                              NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1,
                              NULL, &i0, NULL, integerParameters_, doubleParameters_);
        std::cout << integerParameters_[23] << " elements in dense Cholesky" << std::endl;
    }
    return 0;
}
OsiTestSolverInterface::OsiVolMatrixOneMinusOne_::
OsiVolMatrixOneMinusOne_(const CoinPackedMatrix& m) {
  const int major = m.getMajorDim();
  const double* elem = m.getElements();
  const int* ind = m.getIndices();
  const int* start = m.getVectorStarts();
  const int* length = m.getVectorLengths();

  majorDim_ = major;
  minorDim_ = m.getMinorDim();

  plusSize_ = 0;
  minusSize_ = 0;
  int i, j;
  for (i = 0; i < major; ++i) {
    for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
      const double val = elem[j];
      if (val == 1.0) {
	++plusSize_;
      } else if (val == -1.0) {
	++minusSize_;
      }
    }
  }
  if (plusSize_ > 0) {
    plusInd_ = new int[plusSize_];
  }
  if (minusSize_ > 0) {
    minusInd_ = new int[minusSize_];
  }
  plusStart_ = new int[major];
  plusLength_ = new int[major];
  minusStart_ = new int[major];
  minusLength_ = new int[major];

  plusSize_ = 0;
  minusSize_ = 0;
  for (i = 0; i < major; ++i) {
    plusStart_[i] = plusSize_;
    minusStart_[i] = minusSize_;
    const int last = start[i] + length[i];
    for (j = start[i]; j < last; ++j) {
      const double val = elem[j];
      if (val == 1.0) {
	plusInd_[plusSize_++] = ind[j];
      } else if (val == -1.0) {
	minusInd_[minusSize_++] = ind[j];
      }
    }
    plusLength_[i] = plusSize_ - plusStart_[i];
    minusLength_[i] = minusSize_ - minusStart_[i];
  }
  if (plusSize_ == 0) {
    delete[] plusStart_;    plusStart_  = NULL;
    delete[] plusLength_;   plusLength_ = NULL;
  }
  if (minusSize_ == 0) {
    delete[] minusStart_;    minusStart_  = NULL;
    delete[] minusLength_;   minusLength_ = NULL;
  }
}
示例#20
0
ProblemStatus ColaModel::solve_numeric() {
  solve(false);
  // 1. determine original binding constraints
  std::vector<int> binding;
  int num_rows = getNumRows();
  int orig_num_rows = num_rows - total_num_cuts_;
  int num_cols = getNumCols();
  int * cstat = new int[num_cols];
  int * rstat = new int[num_rows];
  getBasisStatus(cstat, rstat);
  for (int i=0; i<orig_num_rows; ++i) {
    if (rstat[i]==2 or rstat[i]==3) {
      binding.push_back(i);
    }
  }
  int num_binding = binding.size();
  delete[] cstat;
  delete[] rstat;
  // 2. compute AA^T
  // A is sparse and instance of CoinPackedMatrix
  // 2.1 get A
  CoinPackedMatrix const * mat = getMatrixByRow();
  CoinPackedMatrix * A = new CoinPackedMatrix(false, 500, 500);
  std::vector<int>::const_iterator it;
  for (it=binding.begin(); it!=binding.end(); ++it) {
    int first = mat->getVectorFirst(*it);
    int last = mat->getVectorLast(*it);
    int num_elem  = last-first;
    int const * mat_cols = mat->getIndices() + first;
    double const * mat_value = mat->getElements() + first;
    A->appendRow(CoinPackedVector(num_elem, mat_cols, mat_value));
  }
  // 2.2 Compute AAt
  CoinPackedMatrix * AAt = new CoinPackedMatrix();
  double * Aa_i = new double[num_binding];
  int * Aa_i_cols = new int[num_binding];
  double * Aa_i_vals = new double[num_binding];
  for (it=binding.begin(); it!=binding.end(); ++it) {
    // A times row i of A
    int first = mat->getVectorFirst(*it);
    int last = mat->getVectorLast(*it);
    int num_elem  = last-first;
    int const * mat_cols = mat->getIndices() + first;
    double const * mat_value = mat->getElements() + first;
    A->times(CoinPackedVector(num_elem, mat_cols, mat_value), Aa_i);
    // sparsify and insert Aa_i
    int Aa_i_size = 0;
    for (int i=0; i<num_binding; ++i) {
      if (Aa_i[i]!=0.0) {
        Aa_i_cols[Aa_i_size] = i;
        Aa_i_vals[Aa_i_size] = Aa_i[i];
        Aa_i_size++;
      }
    }
    AAt->appendCol(CoinPackedVector(Aa_i_size, Aa_i_cols, Aa_i_vals));
  }
  delete[] Aa_i;
  delete[] Aa_i_cols;
  delete[] Aa_i_vals;
  //AAt->dumpMatrix();
  // 3. compute Ac
  double * Ac = new double[num_binding];
  double const * obj = getObjCoefficients();
  int obj_size;
  int * obj_cols = new int[num_cols];
  double * obj_vals = new double[num_cols];
  for (int i=0; i<num_cols; ++i) {
    if (obj[i]!=0) {
      obj_cols[obj_size] = i;
      obj_vals[obj_size] = obj[i];
      obj_size++;
    }
  }
  A->times(CoinPackedVector(obj_size, obj_cols, obj_vals), Ac);
  delete[] obj_cols;
  delete[] obj_vals;
  // 4. compute (b-Ac)
  double * b = new double[num_binding];
  int k=0;
  for (it=binding.begin(); it!=binding.end(); ++it) {
    b[k] = getRightHandSide()[*it];
    k++;
  }
  double * b_Ac = new double[num_binding];
  for (int i=0; i<num_binding; ++i) {
    b_Ac[i] = b[i] - Ac[i];
  }
  // 5. solve AA^Ty=(b-Ac)
  // 5.1 get AAt in lower triangular format
  double ** AAt_dense = new double*[num_binding];
  for (int i=0; i<num_binding; ++i) {
    AAt_dense[i] = new double[num_binding]();
  }
  int const * AAt_cols = AAt->getIndices();
  double const * AAt_value = AAt->getElements();
  for (int i=0; i<num_binding; ++i) {
    // get row i
    int first = AAt->getVectorFirst(i);
    int last = AAt->getVectorLast(i);
    //int num_elem  = last-first;
    for (int j=first; j<last; ++j) {
      AAt_dense[i][AAt_cols[j]] = AAt_value[j];
    }
  }
  // 5.2 call lapack routine to solve the system
  double * y = new double[num_binding];
  lapack_solve(AAt_dense, b_Ac, y, num_binding);
  // 6. compute d <- c+A^Ty
  // in other words x <- c + A'(AA')^{-1}b - A'(AA')^{-1}Ac when
  // we insert for y.
  // 6.1 compute Aty
  double * Aty = new double[num_cols];
  A->transposeTimes(y, Aty);
  // 6.2 compute d <- c+A^Ty
  double * dir = new double[num_cols];
  double const * cur_sol = getColSolution();
  for (int i=0; i<num_cols; ++i) {
    dir[i] = -obj[i] - Aty[i];
  }
  // 7. go along direction until we hit boundry, ie. compute step_size
  double step_size = 0.0;
  int num_cones = getNumCones();
  imp_solution_ = new double[num_cols];
  std::copy(cur_sol, cur_sol+num_cols, imp_solution_);
  double * par_sol;
  double * par_dir;
  for (int i=0; i<num_cones; ++i) {
    int cone_size = cones_[i]->size();
    LorentzCone * con = dynamic_cast<LorentzCone*>(cones_[i]);
    int const * members = con->members();
    par_sol = new double[cone_size];
    par_dir = new double[cone_size];
    // 7.1 compute step size
    // 7.2 compute a in ax^2+bx+c=0
    // 7.3 compute b in ax^2+bx+c=0
    // 7.4 compute c in ax^2+bx+c=0
    for (int j=0; j<con->size(); j++) {
      par_sol[j] = cur_sol[members[j]];
      par_dir[j] = dir[members[j]];
    }
    double feas_i = par_sol[0]*par_sol[0]-std::inner_product(par_sol+1, par_sol+cone_size, par_sol+1, 0.0);
    if (feas_i > options_->get_dbl_option(TOL)) {
      delete[] par_sol;
      delete[] par_dir;
      continue;
    }
    double a = par_dir[0]*par_dir[0];
    double b = par_sol[0]*par_dir[0];
    double c = par_sol[0]*par_sol[0];
    a = a - std::inner_product(par_dir+1, par_dir+con->size(), par_dir+1, 0.0);
    b = b - std::inner_product(par_sol+1, par_sol+con->size(), par_dir+1, 0.0);
    b = 2.0*b;
    c = c - std::inner_product(par_sol+1, par_sol+con->size(), par_sol+1, 0.0);
    // 7.5 compute step size
    double alpha1 = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
    double alpha2 = (-b-sqrt(b*b-4.0*a*c))/(2.0*a);
    double alpha=alpha1;
    std::cout << "alpha1 " << alpha1 << std::endl;
    std::cout << "alpha2 " << alpha2 << std::endl;
    // if (alpha2<alpha1)
    //   alpha=alpha2;
    for (int j=0; j<con->size(); j++) {
      imp_solution_[members[j]] = cur_sol[members[j]] + alpha*par_dir[j];
    }
    delete[] par_sol;
    delete[] par_dir;
    // get related portion of direction
    // get related portion of solution
  }
  delete A;
  delete AAt;
  delete[] Ac;
  delete[] b;
  delete[] b_Ac;
  for (int i=0; i<num_binding; ++i) {
    delete[] AAt_dense[i];
  }
  delete[] AAt_dense;
  delete[] y;
  delete[] Aty;
  delete[] dir;
  // remove all the cuts and add a cut using the improved solution
  int * indices = new int[total_num_cuts_];
  for (int i=0; i<total_num_cuts_; ++i) {
    indices[i] = orig_num_rows+i;
  }
  deleteRows(total_num_cuts_, indices);
  delete[] indices;
  total_num_cuts_ = 0;
  num_lp_solved_ = 0;
  std::fill(num_cuts_, num_cuts_+num_cones, 0);
  // separate from imp_solution
  Separate * sep = new Separate(cones_, imp_solution_, getNumCols(), options_);
  // returns true if given point is feasible for all cones.
  int feasible = sep->is_feasible();
  while(!feasible) {
    // number of cuts generated
    // std::cout << "ColaModel: " << sep->cuts()->size() << " cuts generated." << std::endl;
    // add all the cuts generated
        // Add all the cuts generated
    std::vector<CoinPackedVector*> cut = sep->cuts();
    std::vector<double> rhs = sep->rhs();
    std::vector<int> gen_cone = sep->generating_cone();
    int num_cuts = cut.size();
    for (int i=0; i<num_cuts; ++i) {
      addRow(*cut[i], -getInfinity(), rhs[i]);
      // print cut
      // end of cut print
      total_num_cuts_++;
      num_cuts_[gen_cone[i]]++;
    }
    // if (num_lp_solved_%2==0) {
    //   clean_redundant_constraints();
    // }
    // resolve the problem
    num_lp_solved_++;
    OsiClpSolverInterface::resolve();
    // update problem status
    update_problem_status();
    // check problem status
    if (soco_status_!=OPTIMAL)
      break;
    delete sep;
    // chec if the new solution is feasible for cones
    sep = new Separate(cones_, getColSolution(), getNumCols(), options_);
    feasible = sep->is_feasible();
  }
  delete sep;
  // update problem status
  update_problem_status();
  // report feasibility of imp_solution_
  double lhs = 0.0;
  double lhs_real = 0.0;
  std::cout << "Conic Constraints feasibility report" << std::endl;
  std::cout << std::setw(5) << std::left << "Cone";
  // todo(aykut) this is not true all the time, what if cone is rotated.
  std::cout << std::setw(20) << std::left << "x1^2-sum x_i^2"
            << std::setw(20) << std::left << "x1-||x_{2:n}||"
            << std::endl;
  const double * full_sol = imp_solution_;
  //double * par_sol;
  for (int i=0; i<num_cones; ++i) {
    int cone_size = cones_[i]->size();
    LorentzCone * con = dynamic_cast<LorentzCone*>(cones_[i]);
    const int * members = con->members();
    par_sol = new double[cone_size];
    for (int j=0; j<cone_size; ++j) {
      par_sol[j] = full_sol[members[j]];
    }
    if (con->type()==LORENTZ) {
      lhs = par_sol[0]*par_sol[0]
        - std::inner_product(par_sol+1, par_sol+cone_size, par_sol+1, 0.0);
      lhs_real = par_sol[0]
        -sqrt(std::inner_product(par_sol+1, par_sol+cone_size, par_sol+1, 0.0));
    }
    else if (con->type()==RLORENTZ) {
      lhs = 2.0*par_sol[0]*par_sol[1]
        - std::inner_product(par_sol+2, par_sol+cone_size, par_sol+2, 0.0);
      lhs_real = lhs;
    }
    std::cout << std::setw(5) << std::left << i
              << std::setw(20) << std::left << lhs
              << std::setw(20) << std::left << lhs_real
              << std::endl;
    delete[] par_sol;
  }
  return soco_status_;
}
//--------------------------------------------------------------------------
// test solution methods.
void OsiCbcSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir)
{
  {    
    CoinRelFltEq eq;
    OsiCbcSolverInterface m;
    std::string fn = mpsDir+"exmip1";
    m.readMps(fn.c_str(),"mps");

    {
      OsiCbcSolverInterface im;    
      OSIUNITTEST_ASSERT_ERROR(im.getNumCols() == 0, {}, "cbc", "default constructor");
      OSIUNITTEST_ASSERT_ERROR(im.getModelPtr() != NULL, {}, "cbc", "default constructor");
    }
    
    // Test copy constructor and assignment operator
    {
      OsiCbcSolverInterface lhs;
      {      
        OsiCbcSolverInterface im(m);        
        
        OsiCbcSolverInterface imC1(im);
        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols()  == im.getNumCols(),  {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows()  == im.getNumRows(),  {}, "cbc", "copy constructor");
        
        OsiCbcSolverInterface imC2(im);
        OSIUNITTEST_ASSERT_ERROR(imC2.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols()  == im.getNumCols(),  {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows()  == im.getNumRows(),  {}, "cbc", "copy constructor");

        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != imC2.getModelPtr(), {}, "cbc", "copy constructor");
        
        lhs = imC2;
      }

      // Test that lhs has correct values even though rhs has gone out of scope
      OSIUNITTEST_ASSERT_ERROR(lhs.getModelPtr() != m.getModelPtr(), {}, "cbc", "assignment operator");
      OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols()  == m.getNumCols(),  {}, "cbc", "copy constructor");
      OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows()  == m.getNumRows(),  {}, "cbc", "copy constructor");
    }

    // Test clone
    {
      OsiCbcSolverInterface cbcSi(m);
      OsiSolverInterface * siPtr = &cbcSi;
      OsiSolverInterface * siClone = siPtr->clone();
      OsiCbcSolverInterface * cbcClone = dynamic_cast<OsiCbcSolverInterface*>(siClone);

      OSIUNITTEST_ASSERT_ERROR(cbcClone != NULL, {}, "cbc", "clone");
      OSIUNITTEST_ASSERT_ERROR(cbcClone->getModelPtr() != cbcSi.getModelPtr(), {}, "cbc", "clone");
      OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumRows() == cbcSi.getNumRows(),   {}, "cbc", "clone");
      OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumCols() == m.getNumCols(),       {}, "cbc", "clone");
      
      delete siClone;
    }
  
    // test infinity
    {
      OsiCbcSolverInterface si;
      OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == OsiCbcInfinity, {}, "cbc", "infinity");
    }     
    
    // Test some catches
    if (!OsiCbcHasNDEBUG())
    {
      OsiCbcSolverInterface solver;
      try {
        solver.setObjCoeff(0,0.0);
        OSIUNITTEST_ADD_OUTCOME("cbc", "setObjCoeff on empty model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
      }
      catch (CoinError e) {
        if (OsiUnitTest::verbosity >= 1)
          std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl;
      }

      std::string fn = mpsDir+"exmip1";
      solver.readMps(fn.c_str(),"mps");
      OSIUNITTEST_CATCH_ERROR(solver.setObjCoeff(0,0.0), {}, "cbc", "setObjCoeff on nonempty model");

      try {
        int index[]={0,20};
        double value[]={0.0,0.0,0.0,0.0};
        solver.setColSetBounds(index,index+2,value);
        OSIUNITTEST_ADD_OUTCOME("cbc", "setColSetBounds on cols not in model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
      }
      catch (CoinError e) {
        if (OsiUnitTest::verbosity >= 1)
          std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl;
      }
    }
    
    {    
      OsiCbcSolverInterface cbcSi(m);
      int nc = cbcSi.getNumCols();
      int nr = cbcSi.getNumRows();
      const double * cl = cbcSi.getColLower();
      const double * cu = cbcSi.getColUpper();
      const double * rl = cbcSi.getRowLower();
      const double * ru = cbcSi.getRowUpper();
      OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cl[0],2.5), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cl[1],0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cu[1],4.1), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cu[2],1.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(rl[0],2.5), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(rl[4],3.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(ru[1],2.1), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(ru[4],15.), {}, "cbc", "read and copy exmip1");
      
      const double * cs = cbcSi.getColSolution();
      OSIUNITTEST_ASSERT_ERROR(eq(cs[0],2.5), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cs[7],0.0), {}, "cbc", "read and copy exmip1");
      
      OSIUNITTEST_ASSERT_ERROR(!eq(cl[3],1.2345), {}, "cbc", "set col lower");
      cbcSi.setColLower( 3, 1.2345 );
      OSIUNITTEST_ASSERT_ERROR( eq(cbcSi.getColLower()[3],1.2345), {}, "cbc", "set col lower");
      
      OSIUNITTEST_ASSERT_ERROR(!eq(cbcSi.getColUpper()[4],10.2345), {}, "cbc", "set col upper");
      cbcSi.setColUpper( 4, 10.2345 );
      OSIUNITTEST_ASSERT_ERROR( eq(cbcSi.getColUpper()[4],10.2345), {}, "cbc", "set col upper");

      // LH: Objective will depend on how underlying solver constructs and maintains initial solution
      double objValue = cbcSi.getObjValue();
      OSIUNITTEST_ASSERT_ERROR(eq(objValue,3.5) || eq(objValue,10.5), {}, "cbc", "getObjValue() before solve");

      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[0], 1.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[1], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[2], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[3], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[4], 2.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[5], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[6], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[7],-1.0), {}, "cbc", "read and copy exmip1");
    }
    
    // Test matrixByRow method
    { 
      const OsiCbcSolverInterface si(m);
      const CoinPackedMatrix * smP = si.getMatrixByRow();

      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim()    ==  5, return, "cbc", "getMatrixByRow: major dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim()    ==  8, return, "cbc", "getMatrixByRow: major dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByRow: num elements");
      OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 6, return, "cbc", "getMatrixByRow: num elements");

#ifdef OSICBC_TEST_MTX_STRUCTURE
      CoinRelFltEq eq;
      const double * ev = smP->getElements();
      OSIUNITTEST_ASSERT_ERROR(eq(ev[0],   3.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[1],   1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[2],  -2.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[3],  -1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[4],  -1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[5],   2.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[6],   1.1), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[7],   1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[8],   1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[9],   2.8), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[11],  5.6), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[12],  1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[13],  1.9), {}, "cbc", "getMatrixByRow: elements");
      
      const int * mi = smP->getVectorStarts();
      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "getMatrixByRow: vector starts");
      
      const int * ei = smP->getIndices();
      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "getMatrixByRow: indices");
#else	// OSICBC_TEST_MTX_STRUCTURE

      CoinPackedMatrix exmip1Mtx ;
      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByRow") ;
#endif	// OSICBC_TEST_MTX_STRUCTURE
    }

    // Test adding several cuts, and handling of a coefficient of infinity
    // in the constraint matrix.
    {
      OsiCbcSolverInterface fim;
      std::string fn = mpsDir+"exmip1";
      fim.readMps(fn.c_str(),"mps");
      // exmip1.mps has 2 integer variables with index 2 & 3
      fim.initialSolve();
      OsiRowCut cuts[3];
      
      
      // Generate one ineffective cut plus two trivial cuts
      int c;
      int nc = fim.getNumCols();
      int *inx = new int[nc];
      for (c=0;c<nc;c++) inx[c]=c;
      double *el = new double[nc];
      for (c=0;c<nc;c++) el[c]=1.0e-50+((double)c)*((double)c);
      
      cuts[0].setRow(nc,inx,el);
      cuts[0].setLb(-100.);
      cuts[0].setUb(500.);
      cuts[0].setEffectiveness(22);
      el[4]=0.0; // to get inf later
      
      for (c=2;c<4;c++) {
        el[0]=1.0;
        inx[0]=c;
        cuts[c-1].setRow(1,inx,el);
        cuts[c-1].setLb(1.);
        cuts[c-1].setUb(100.);
        cuts[c-1].setEffectiveness(c);
      }
      fim.writeMps("x1.mps");
      fim.applyRowCuts(3,cuts);
      fim.writeMps("x2.mps");
      // resolve - should get message about zero elements
      fim.resolve();
      fim.writeMps("x3.mps");
      // check integer solution
      const double * cs = fim.getColSolution();
      CoinRelFltEq eq;
      OSIUNITTEST_ASSERT_ERROR(eq(cs[2], 1.0), {}, "cbc", "add cuts");
      OSIUNITTEST_ASSERT_ERROR(eq(cs[3], 1.0), {}, "cbc", "add cuts");
      // check will find invalid matrix
      el[0]=1.0/el[4];
      inx[0]=0;
      cuts[0].setRow(nc,inx,el);
      cuts[0].setLb(-100.);
      cuts[0].setUb(500.);
      cuts[0].setEffectiveness(22);
      fim.applyRowCut(cuts[0]);
      // resolve - should get message about zero elements
      fim.resolve();
      OSIUNITTEST_ASSERT_WARNING(fim.isAbandoned(), {}, "cbc", "add cuts");
      delete[]el;
      delete[]inx;
    }

    // Test matrixByCol method
    {
      const OsiCbcSolverInterface si(m);
      const CoinPackedMatrix * smP = si.getMatrixByCol();

      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim()    ==  8, return, "cbc", "getMatrixByCol: major dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim()    ==  5, return, "cbc", "getMatrixByCol: minor dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByCol: number of elements");
      OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "cbc", "getMatrixByCol: vector starts size");

#ifdef OSICBC_TEST_MTX_STRUCTURE
      CoinRelFltEq eq;
      const double * ev = smP->getElements();
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 5.6), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 2.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 1.1), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6],-2.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 2.8), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8],-1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[11],-1.2), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[12],-1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByCol: elements");
      
      const CoinBigIndex * mi = smP->getVectorStarts();
      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  2, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  4, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  6, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[4] ==  8, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "cbc", "getMatrixByCol: vector starts");
      
      const int * ei = smP->getIndices();
      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 1, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 3, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 4, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "cbc", "getMatrixByCol: indices");
#else // OSICBC_TEST_MTX_STRUCTURE

      CoinPackedMatrix &exmip1Mtx = BuildExmip1Mtx() ;
      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByCol");
#endif	// OSICBC_TEST_MTX_STRUCTURE     
    }

    //--------------
    // Test rowsense, rhs, rowrange, matrixByRow, solver assignment
    {
      OsiCbcSolverInterface lhs;
      {
        OsiCbcSolverInterface siC1(m);

        const char   * siC1rs  = siC1.getRowSense();
        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense");

        const double * siC1rhs = siC1.getRightHandSide();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side");

        const double * siC1rr  = siC1.getRowRange();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range");
        
        const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow();
        OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "cbc", "matrix by row");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim()    ==  5, return, "cbc", "matrix by row: major dim");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMinorDim()    ==  8, return, "cbc", "matrix by row: major dim");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "cbc", "matrix by row: num elements");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getSizeVectorStarts() == 6, return, "cbc", "matrix by row: num elements");

#ifdef OSICBC_TEST_MTX_STRUCTURE
        const double * ev = siC1mbr->getElements();
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row: elements");

        const CoinBigIndex * mi = siC1mbr->getVectorStarts();
        OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row: vector starts");

        const int * ei = siC1mbr->getIndices();
        OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row: indices");
#else	// OSICBC_TEST_MTX_STRUCTURE

        CoinPackedMatrix exmip1Mtx ;
        exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
        OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*siC1mbr), {}, "cbc", "matrix by row");
#endif	// OSICBC_TEST_MTX_STRUCTURE

        OSIUNITTEST_ASSERT_WARNING(siC1rs  == siC1.getRowSense(), {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_WARNING(siC1rr  == siC1.getRowRange(), {}, "cbc", "row range");

        // Change CBC Model by adding free row
        OsiRowCut rc;
        rc.setLb(-COIN_DBL_MAX);
        rc.setUb( COIN_DBL_MAX);
        OsiCuts cuts;
        cuts.insert(rc);
        siC1.applyCuts(cuts);

        siC1rs  = siC1.getRowSense();
        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "cbc", "row sense after adding row");

        siC1rhs = siC1.getRightHandSide();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "cbc", "right hand side after adding row");

        siC1rr  = siC1.getRowRange();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "cbc", "row range after adding row");

        lhs = siC1;
      }

      // Test that lhs has correct values even though siC1 has gone out of scope    
      const char * lhsrs  = lhs.getRowSense();
      OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "cbc", "row sense after assignment");
      
      const double * lhsrhs = lhs.getRightHandSide();
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "cbc", "right hand side after assignment");
      
      const double *lhsrr = lhs.getRowRange();
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "cbc", "row range after assignment");
      
      const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow();
      OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "cbc", "matrix by row after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim()    ==  6, return, "cbc", "matrix by row after assignment: major dim");
      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "cbc", "matrix by row after assignment: num elements");


#ifdef OSICBC_TEST_MTX_STRUCTURE
      const double * ev = lhsmbr->getElements();
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row after assignment: elements");
      
      const CoinBigIndex * mi = lhsmbr->getVectorStarts();
      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row after assignment: vector starts");
      
      const int * ei = lhsmbr->getIndices();
      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row after assignment: indices");
#else	// OSICBC_TEST_MTX_STRUCTURE

/*
  This admittedly looks bogus, but it's the equivalent operation on the matrix
  for inserting a cut of the form -Inf <= +Inf (i.e., a cut with no
  coefficients).
*/
      CoinPackedMatrix exmip1Mtx ;
      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
      CoinPackedVector freeRow ;
      exmip1Mtx.appendRow(freeRow) ;
      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*lhsmbr), {}, "cbc", "matrix by row after assignment");
#endif	// OSICBC_TEST_MTX_STRUCTURE
    }
  }

  // Test add/delete columns
  {    
    OsiCbcSolverInterface m;
    std::string fn = mpsDir+"p0033";
    m.readMps(fn.c_str(),"mps");
    double inf = m.getInfinity();

    CoinPackedVector c0;
    c0.insert(0, 4);
    c0.insert(1, 1);
    m.addCol(c0, 0, inf, 3);
    m.initialSolve();
    double objValue = m.getObjValue();
    CoinRelFltEq eq(1.0e-2);
    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "cbc", "objvalue after adding col");

    // Try deleting first column that's nonbasic at lower bound (0).
    int * d = new int[1];
    CoinWarmStartBasis *cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ;
    OSIUNITTEST_ASSERT_ERROR(cwsb != NULL, {}, "cbc", "get warmstart basis");
    CoinWarmStartBasis::Status stati ;
    int iCol ;
    for (iCol = 0 ;  iCol < cwsb->getNumStructural() ; iCol++)
    { stati = cwsb->getStructStatus(iCol) ;
      if (stati == CoinWarmStartBasis::atLowerBound) break ; }
    d[0]=iCol;
    m.deleteCols(1,d);
    delete [] d;
    delete cwsb;
    d=NULL;
    m.resolve();
    objValue = m.getObjValue();
    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting first col");

    // Try deleting column we added. If basic, go to initialSolve as deleting
    // basic variable trashes basis required for warm start.
    iCol = m.getNumCols()-1;
    cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ;
    stati =  cwsb->getStructStatus(iCol) ;
    delete cwsb;
    m.deleteCols(1,&iCol);
    if (stati == CoinWarmStartBasis::basic)
    { m.initialSolve() ; }
    else
    { m.resolve(); }
    objValue = m.getObjValue();
    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting added col");
  }

  // Build a model
  {    
    OsiCbcSolverInterface model;
    std::string fn = mpsDir+"p0033";
    model.readMps(fn.c_str(),"mps");
    // Point to data
    int numberRows = model.getNumRows();
    const double * rowLower = model.getRowLower();
    const double * rowUpper = model.getRowUpper();
    int numberColumns = model.getNumCols();
    const double * columnLower = model.getColLower();
    const double * columnUpper = model.getColUpper();
    const double * columnObjective = model.getObjCoefficients();
    // get row copy
    CoinPackedMatrix rowCopy = *model.getMatrixByRow();
    const int * column = rowCopy.getIndices();
    const int * rowLength = rowCopy.getVectorLengths();
    const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
    const double * element = rowCopy.getElements();
    
    // solve
    model.initialSolve();
    // Now build new model
    CoinModel build;
    // Row bounds
    int iRow;
    for (iRow=0;iRow<numberRows;iRow++) {
      build.setRowBounds(iRow,rowLower[iRow],rowUpper[iRow]);
    }
    // Column bounds and objective
    int iColumn;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      build.setColumnLower(iColumn,columnLower[iColumn]);
      build.setColumnUpper(iColumn,columnUpper[iColumn]);
      build.setObjective(iColumn,columnObjective[iColumn]);
    }
    // Adds elements one by one by row (backwards by row)
    for (iRow=numberRows-1;iRow>=0;iRow--) {
      int start = rowStart[iRow];
      for (int j=start;j<start+rowLength[iRow];j++) 
        build(iRow,column[j],element[j]);
    }
    // Now create Model
    OsiCbcSolverInterface model2;
    model2.loadFromCoinModel(build);
    model2.initialSolve();
    // Save - should be continuous
    model2.writeMps("continuous");
    int * whichInteger = new int[numberColumns];
    for (iColumn=0;iColumn<numberColumns;iColumn++) 
      whichInteger[iColumn]=iColumn;
    // mark as integer
    model2.setInteger(whichInteger,numberColumns);
    delete [] whichInteger;
    // save - should be integer
    model2.writeMps("integer");
    
    // Now do with strings attached
    // Save build to show how to go over rows
    CoinModel saveBuild = build;
    build = CoinModel();
    // Column bounds
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      build.setColumnLower(iColumn,columnLower[iColumn]);
      build.setColumnUpper(iColumn,columnUpper[iColumn]);
    }
    // Objective - half the columns as is and half with multiplier of "1.0+multiplier"
    // Pick up from saveBuild (for no reason at all)
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value = saveBuild.objective(iColumn);
      if (iColumn*2<numberColumns) {
        build.setObjective(iColumn,columnObjective[iColumn]);
      } else {
        // create as string
        char temp[100];
        sprintf(temp,"%g + abs(%g*multiplier)",value,value);
        build.setObjective(iColumn,temp);
      }
    }
    // It then adds rows one by one but for half the rows sets their values
    //      with multiplier of "1.0+1.5*multiplier"
    for (iRow=0;iRow<numberRows;iRow++) {
      if (iRow*2<numberRows) {
        // add row in simple way
        int start = rowStart[iRow];
        build.addRow(rowLength[iRow],column+start,element+start,
                     rowLower[iRow],rowUpper[iRow]);
      } else {
        // As we have to add one by one let's get from saveBuild
        CoinModelLink triple=saveBuild.firstInRow(iRow);
        while (triple.column()>=0) {
          int iColumn = triple.column();
          if (iColumn*2<numberColumns) {
            // just value as normal
            build(iRow,triple.column(),triple.value());
          } else {
            // create as string
            char temp[100];
            sprintf(temp,"%g + (1.5*%g*multiplier)",triple.value(), triple.value());
            build(iRow,iColumn,temp);
          }
          triple=saveBuild.next(triple);
        }
        // but remember to do rhs
        build.setRowLower(iRow,rowLower[iRow]);
        build.setRowUpper(iRow,rowUpper[iRow]);
      }
    }
    // If small switch on error printing
    if (numberColumns<50)
      build.setLogLevel(1);
    // should fail as we never set multiplier
    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) != 0, {}, "cbc", "build model with missing multipliers");
    build.associateElement("multiplier",0.0);
    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) == 0, {}, "cbc", "build model");
    model2.initialSolve();
    // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1
    for (double multiplier=0.0;multiplier<2.0;multiplier+= 0.1) {
      build.associateElement("multiplier",multiplier);
      OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build,true) == 0, {}, "cbc", "build model with increasing multiplier");
      model2.resolve();
    }
  }

  // branch and bound
  {    
    OsiCbcSolverInterface m;
    std::string fn = mpsDir+"p0033";
    m.readMps(fn.c_str(),"mps");
    m.initialSolve();
    //m.messageHandler()->setLogLevel(0);
    m.getModelPtr()->messageHandler()->setLogLevel(0);
    m.branchAndBound();
  }

  // branch and bound using CbcModel!!!!!!!
  {    
    OsiCbcSolverInterface mm;
    OsiCbcSolverInterface m(&mm);
    std::string fn = mpsDir+"p0033";
    m.readMps(fn.c_str(),"mps");
    m.initialSolve();
    m.branchAndBound();
  }

  // Do common solverInterface testing 
  {
    OsiCbcSolverInterface m;
    OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir);
  }
  {
    OsiCbcSolverInterface mm;
    OsiCbcSolverInterface m(&mm);
    OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir);
  }
}
示例#22
0
//--------------------------------------------------------------------------
// Test building a model
void
CoinModelUnitTest(const std::string & mpsDir,
                  const std::string & netlibDir, const std::string & testModel)
{

    // Get a model
    CoinMpsIO m;
    std::string fn = mpsDir+"exmip1";
    int numErr = m.readMps(fn.c_str(),"mps");
    assert( numErr== 0 );

    int numberRows = m.getNumRows();
    int numberColumns = m.getNumCols();

    // Build by row from scratch
    {
        CoinPackedMatrix matrixByRow = * m.getMatrixByRow();
        const double * element = matrixByRow.getElements();
        const int * column = matrixByRow.getIndices();
        const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
        const int * rowLength = matrixByRow.getVectorLengths();
        const double * rowLower = m.getRowLower();
        const double * rowUpper = m.getRowUpper();
        const double * columnLower = m.getColLower();
        const double * columnUpper = m.getColUpper();
        const double * objective = m.getObjCoefficients();
        int i;
        CoinModel temp;
        for (i=0; i<numberRows; i++) {
            temp.addRow(rowLength[i],column+rowStart[i],
                        element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i));
        }
        // Now do column part
        for (i=0; i<numberColumns; i++) {
            temp.setColumnBounds(i,columnLower[i],columnUpper[i]);
            temp.setColumnObjective(i,objective[i]);
            if (m.isInteger(i))
                temp.setColumnIsInteger(i,true);;
        }
        // write out
        temp.writeMps("byRow.mps");
    }

    // Build by column from scratch and save
    CoinModel model;
    {
        CoinPackedMatrix matrixByColumn = * m.getMatrixByCol();
        const double * element = matrixByColumn.getElements();
        const int * row = matrixByColumn.getIndices();
        const CoinBigIndex * columnStart = matrixByColumn.getVectorStarts();
        const int * columnLength = matrixByColumn.getVectorLengths();
        const double * rowLower = m.getRowLower();
        const double * rowUpper = m.getRowUpper();
        const double * columnLower = m.getColLower();
        const double * columnUpper = m.getColUpper();
        const double * objective = m.getObjCoefficients();
        int i;
        for (i=0; i<numberColumns; i++) {
            model.addColumn(columnLength[i],row+columnStart[i],
                            element+columnStart[i],columnLower[i],columnUpper[i],
                            objective[i],m.columnName(i),m.isInteger(i));
        }
        // Now do row part
        for (i=0; i<numberRows; i++) {
            model.setRowBounds(i,rowLower[i],rowUpper[i]);
        }
        // write out
        model.writeMps("byColumn.mps");
    }

    // model was created by column - play around
    {
        CoinModel temp;
        int i;
        for (i=numberRows-1; i>=0; i--)
            temp.setRowLower(i,model.getRowLower(i));
        for (i=0; i<numberColumns; i++) {
            temp.setColumnUpper(i,model.getColumnUpper(i));
            temp.setColumnName(i,model.getColumnName(i));
        }
        for (i=numberColumns-1; i>=0; i--) {
            temp.setColumnLower(i,model.getColumnLower(i));
            temp.setColumnObjective(i,model.getColumnObjective(i));
            temp.setColumnIsInteger(i,model.getColumnIsInteger(i));
        }
        for (i=0; i<numberRows; i++) {
            temp.setRowUpper(i,model.getRowUpper(i));
            temp.setRowName(i,model.getRowName(i));
        }
        // Now elements
        for (i=0; i<numberRows; i++) {
            CoinModelLink triple=model.firstInRow(i);
            while (triple.column()>=0) {
                temp(i,triple.column(),triple.value());
                triple=model.next(triple);
            }
        }
        // and by column
        for (i=numberColumns-1; i>=0; i--) {
            CoinModelLink triple=model.lastInColumn(i);
            while (triple.row()>=0) {
                assert (triple.value()==temp(triple.row(),i));
                temp(triple.row(),i,triple.value());
                triple=model.previous(triple);
            }
        }
        // check equal
        model.setLogLevel(1);
        assert (!model.differentModel(temp,false));
    }
    // Try creating model with strings
    {
        CoinModel temp;
        int i;
        for (i=numberRows-1; i>=0; i--) {
            double value = model.getRowLower(i);
            if (value==-1.0)
                temp.setRowLower(i,"minusOne");
            else if (value==1.0)
                temp.setRowLower(i,"sqrt(plusOne)");
            else if (value==4.0)
                temp.setRowLower(i,"abs(4*plusOne)");
            else
                temp.setRowLower(i,value);
        }
        for (i=0; i<numberColumns; i++) {
            double value;
            value = model.getColumnUpper(i);
            if (value==-1.0)
                temp.setColumnUpper(i,"minusOne");
            else if (value==1.0)
                temp.setColumnUpper(i,"plusOne");
            else
                temp.setColumnUpper(i,value);
            temp.setColumnName(i,model.getColumnName(i));
        }
        for (i=numberColumns-1; i>=0; i--) {
            temp.setColumnLower(i,model.getColumnLower(i));
            temp.setColumnObjective(i,model.getColumnObjective(i));
            temp.setColumnIsInteger(i,model.getColumnIsInteger(i));
        }
        for (i=0; i<numberRows; i++) {
            double value = model.getRowUpper(i);
            if (value==-1.0)
                temp.setRowUpper(i,"minusOne");
            else if (value==1.0)
                temp.setRowUpper(i,"plusOne");
            else
                temp.setRowUpper(i,value);
            temp.setRowName(i,model.getRowName(i));
        }
        // Now elements
        for (i=0; i<numberRows; i++) {
            CoinModelLink triple=model.firstInRow(i);
            while (triple.column()>=0) {
                double value = triple.value();
                if (value==-1.0)
                    temp(i,triple.column(),"minusOne");
                else if (value==1.0)
                    temp(i,triple.column(),"plusOne");
                else if (value==-2.0)
                    temp(i,triple.column(),"minusOne-1.0");
                else if (value==2.0)
                    temp(i,triple.column(),"plusOne+1.0+minusOne+(2.0-plusOne)");
                else
                    temp(i,triple.column(),value);
                triple=model.next(triple);
            }
        }
        temp.associateElement("minusOne",-1.0);
        temp.associateElement("plusOne",1.0);
        temp.setProblemName("fromStrings");
        temp.writeMps("string.mps");

        // check equal
        model.setLogLevel(1);
        assert (!model.differentModel(temp,false));
    }
    // Test with various ways of generating
    {
        /*
          Get a model. Try first with netlibDir, fall back to mpsDir (sampleDir)
          if that fails.
        */
        CoinMpsIO m;
        std::string fn = netlibDir+testModel;
        double time1 = CoinCpuTime();
        int numErr = m.readMps(fn.c_str(),"");
        if (numErr != 0) {
            std::cout
                    << "Could not read " << testModel << " in " << netlibDir
                    << "; falling back to " << mpsDir << "." << std::endl ;
            fn = mpsDir+testModel ;
            numErr = m.readMps(fn.c_str(),"") ;
            if (numErr != 0) {
                std::cout << "Could not read " << testModel << "; skipping test." << std::endl ;
            }
        }
        if (numErr == 0) {
            std::cout
                    << "Time for readMps is "
                    << (CoinCpuTime()-time1) << " seconds." << std::endl ;
            int numberRows = m.getNumRows();
            int numberColumns = m.getNumCols();
            // Build model
            CoinModel model;
            CoinPackedMatrix matrixByRow = * m.getMatrixByRow();
            const double * element = matrixByRow.getElements();
            const int * column = matrixByRow.getIndices();
            const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
            const int * rowLength = matrixByRow.getVectorLengths();
            const double * rowLower = m.getRowLower();
            const double * rowUpper = m.getRowUpper();
            const double * columnLower = m.getColLower();
            const double * columnUpper = m.getColUpper();
            const double * objective = m.getObjCoefficients();
            int i;
            for (i=0; i<numberRows; i++) {
                model.addRow(rowLength[i],column+rowStart[i],
                             element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i));
            }
            // Now do column part
            for (i=0; i<numberColumns; i++) {
                model.setColumnBounds(i,columnLower[i],columnUpper[i]);
                model.setColumnObjective(i,objective[i]);
                model.setColumnName(i,m.columnName(i));
                if (m.isInteger(i))
                    model.setColumnIsInteger(i,true);;
            }
            // Test
            CoinSeedRandom(11111);
            time1 = 0.0;
            int nPass=50;
            for (i=0; i<nPass; i++) {
                double random = CoinDrand48();
                int iSeed = (int) (random*1000000);
                //iSeed = 776151;
                CoinSeedRandom(iSeed);
                std::cout << "before pass " << i << " with seed of " << iSeed << std::endl ;
                buildRandom(model,CoinDrand48(),time1,i);
                model.validateLinks();
            }
            std::cout
                    << "Time for " << nPass << " CoinModel passes is "
                    << time1 << " seconds\n" << std::endl ;
        }
    }
}
示例#23
0
int main(int argc, const char *argv[])
{
     int numberColumns;
     int numberRows;

     FILE * fp;
     if (argc > 1) {
          fp = fopen(argv[1], "r");
          if (!fp) {
               fprintf(stderr, "Unable to open file %s\n", argv[1]);
               exit(1);
          }
     } else {
          fp = fopen("input.130", "r");
          if (!fp) {
               fprintf(stderr, "Unable to open file input.l30 in Samples directory\n");
               exit(1);
          }
     }
     int problem;
     char temp[100];
     // read and skip
     fscanf(fp, "%s", temp);
     assert(!strcmp(temp, "BEGIN"));
     fscanf(fp, "%*s %*s %d %d %*s %*s %d %*s", &problem, &numberRows,
            &numberColumns);
     // scan down to SUPPLY
     while (fgets(temp, 100, fp)) {
          if (!strncmp(temp, "SUPPLY", 6))
               break;
     }
     if (strncmp(temp, "SUPPLY", 6)) {
          fprintf(stderr, "Unable to find SUPPLY\n");
          exit(2);
     }
     // get space for rhs
     double * lower = new double[numberRows];
     double * upper = new double[numberRows];
     int i;
     for (i = 0; i < numberRows; i++) {
          lower[i] = 0.0;
          upper[i] = 0.0;
     }
     // ***** Remember to convert to C notation
     while (fgets(temp, 100, fp)) {
          int row;
          int value;
          if (!strncmp(temp, "ARCS", 4))
               break;
          sscanf(temp, "%d %d", &row, &value);
          upper[row-1] = -value;
          lower[row-1] = -value;
     }
     if (strncmp(temp, "ARCS", 4)) {
          fprintf(stderr, "Unable to find ARCS\n");
          exit(2);
     }
     // number of columns may be underestimate
     int * head = new int[2*numberColumns];
     int * tail = new int[2*numberColumns];
     int * ub = new int[2*numberColumns];
     int * cost = new int[2*numberColumns];
     // ***** Remember to convert to C notation
     numberColumns = 0;
     while (fgets(temp, 100, fp)) {
          int iHead;
          int iTail;
          int iUb;
          int iCost;
          if (!strncmp(temp, "DEMAND", 6))
               break;
          sscanf(temp, "%d %d %d %d", &iHead, &iTail, &iCost, &iUb);
          iHead--;
          iTail--;
          head[numberColumns] = iHead;
          tail[numberColumns] = iTail;
          ub[numberColumns] = iUb;
          cost[numberColumns] = iCost;
          numberColumns++;
     }
     if (strncmp(temp, "DEMAND", 6)) {
          fprintf(stderr, "Unable to find DEMAND\n");
          exit(2);
     }
     // ***** Remember to convert to C notation
     while (fgets(temp, 100, fp)) {
          int row;
          int value;
          if (!strncmp(temp, "END", 3))
               break;
          sscanf(temp, "%d %d", &row, &value);
          upper[row-1] = value;
          lower[row-1] = value;
     }
     if (strncmp(temp, "END", 3)) {
          fprintf(stderr, "Unable to find END\n");
          exit(2);
     }
     printf("Problem %d has %d rows and %d columns\n", problem,
            numberRows, numberColumns);
     fclose(fp);
     ClpSimplex  model;
     // now build model - we have rhs so build columns - two elements
     // per column

     double * objective = new double[numberColumns];
     double * lowerColumn = new double[numberColumns];
     double * upperColumn = new double[numberColumns];

     double * element = new double [2*numberColumns];
     int * start = new int[numberColumns+1];
     int * row = new int[2*numberColumns];
     start[numberColumns] = 2 * numberColumns;
     for (i = 0; i < numberColumns; i++) {
          start[i] = 2 * i;
          element[2*i] = -1.0;
          element[2*i+1] = 1.0;
          row[2*i] = head[i];
          row[2*i+1] = tail[i];
          lowerColumn[i] = 0.0;
          upperColumn[i] = ub[i];
          objective[i] = cost[i];
     }
     // Create Packed Matrix
     CoinPackedMatrix matrix;
     int * lengths = NULL;
     matrix.assignMatrix(true, numberRows, numberColumns,
                         2 * numberColumns, element, row, start, lengths);
     ClpNetworkMatrix network(matrix);
     // load model

     model.loadProblem(network,
                       lowerColumn, upperColumn, objective,
                       lower, upper);

     delete [] lower;
     delete [] upper;
     delete [] head;
     delete [] tail;
     delete [] ub;
     delete [] cost;
     delete [] objective;
     delete [] lowerColumn;
     delete [] upperColumn;
     delete [] element;
     delete [] start;
     delete [] row;

     /* The confusing flow below is in to exercise both dual and primal
        when ClpNetworkMatrix storage used.

        For practical use just one call e.g. model.dual(); would be used.

        If network then factorization scheme is changed
        to be much faster.

        Still not as fast as a real network code, but more flexible
     */
     model.factorization()->maximumPivots(200 + model.numberRows() / 100);
     model.factorization()->maximumPivots(1000);
     //model.factorization()->maximumPivots(1);
     if (model.numberRows() < 50)
          model.messageHandler()->setLogLevel(63);
     model.dual();
     model.setOptimizationDirection(-1);
     //model.messageHandler()->setLogLevel(63);
     model.primal();
     model.setOptimizationDirection(1);
     model.primal();
     return 0;
}
示例#24
0
bool OSI_X_SolverWrapper<SOLVERINTERFACE>::setup(const LP_Constraints_Sparse & cstraints) //cstraints <-> constraints
{
  bool bOk = true;
  if ( si == NULL )
  {
    return false;
  }
  assert(nbParams_ == cstraints.nbParams_);

  const int NUMVAR = cstraints.constraint_mat_.cols();
  std::vector<double> col_lb(NUMVAR);//the column lower bounds
  std::vector<double> col_ub(NUMVAR);//the column upper bounds

  this->nbParams_ = NUMVAR;

  si->setObjSense( ((cstraints.bminimize_) ? 1 : -1) );

  const sRMat & A = cstraints.constraint_mat_;

  //Equality constraint will be done by two constraints due to the API limitation (>= & <=)
  const size_t nbLine = A.rows() +
    std::count(cstraints.vec_sign_.begin(), cstraints.vec_sign_.end(), LP_Constraints::LP_EQUAL);

  std::vector<double> row_lb(nbLine);//the row lower bounds
  std::vector<double> row_ub(nbLine);//the row upper bounds

  CoinPackedMatrix * matrix = new CoinPackedMatrix(false,0,0);
  matrix->setDimensions(0, NUMVAR);

  //-- Add row-wise constraint
  size_t rowindex = 0;
  for (int i=0; i < A.rows(); ++i)
  {
    std::vector<int> vec_colno;
    std::vector<double> vec_value;
    for (sRMat::InnerIterator it(A,i); it; ++it)
    {
      vec_colno.push_back(it.col());
      vec_value.push_back(it.value());
    }


    if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_LESS_OR_EQUAL )
    {
      int coef = 1;
      row_lb[rowindex] = -1.0 * si->getInfinity();
      row_ub[rowindex] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow( vec_colno.size(),
                   &vec_colno[0],
                   &vec_value[0] );
      rowindex++;
    }

    if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_GREATER_OR_EQUAL )
    {
      int coef = -1;
      for ( std::vector<double>::iterator iter_val = vec_value.begin();
        iter_val != vec_value.end();
        iter_val++)
      {
        *iter_val *= coef;
      }
      row_lb[rowindex] = -1.0 * si->getInfinity();
      row_ub[rowindex] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow( vec_colno.size(),
                   &vec_colno[0],
                   &vec_value[0] );
      rowindex++;
    }
  }

  //-- Setup bounds for all the parameters
  if (cstraints.vec_bounds_.size() == 1)
  {
    // Setup the same bound for all the parameters
    for (int i=0; i < this->nbParams_; ++i)
    {
      col_lb[i] = cstraints.vec_bounds_[0].first;
      col_ub[i] = cstraints.vec_bounds_[0].second;
    }
  }
  else  // each parameter have it's own bounds
  {
    for (int i=0; i < this->nbParams_; ++i)
    {
      col_lb[i] = cstraints.vec_bounds_[i].first;
      col_ub[i] = cstraints.vec_bounds_[i].second;
    }
  }

  si->loadProblem(
    *matrix,
    &col_lb[0],
    &col_ub[0],
    cstraints.vec_cost_.empty() ? NULL : &cstraints.vec_cost_[0],
    &row_lb[0],
    &row_ub[0]);

  delete matrix;

  return bOk;
}
示例#25
0
bool OSI_X_SolverWrapper<SOLVERINTERFACE>::setup(const LP_Constraints & cstraints) //cstraints <-> constraints
{
  bool bOk = true;
  if ( si == NULL )
  {
    return false;
  }
  assert(nbParams_ == cstraints.nbParams_);

  const unsigned int NUMVAR = cstraints.constraint_mat_.cols();
  std::vector<double> col_lb(NUMVAR);//the column lower bounds
  std::vector<double> col_ub(NUMVAR);//the column upper bounds

  this->nbParams_ = NUMVAR;

  si->setObjSense( ((cstraints.bminimize_) ? 1 : -1) );

  const Mat & A = cstraints.constraint_mat_;

  //Equality constraint will be done by two constraints due to the API limitation ( >= & <=).
  const size_t nbLine = A.rows() +
    std::count(cstraints.vec_sign_.begin(), cstraints.vec_sign_.end(), LP_Constraints::LP_EQUAL);

  std::vector<double> row_lb(nbLine);//the row lower bounds
  std::vector<double> row_ub(nbLine);//the row upper bounds

  CoinPackedMatrix * matrix = new CoinPackedMatrix(false,0,0);
  matrix->setDimensions(0, NUMVAR);

  //-- Add row-wise constraint
  size_t indexRow = 0;
  for (int i=0; i < A.rows(); ++i)
  {
    Vec temp = A.row(i);

    CoinPackedVector row;
    if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_LESS_OR_EQUAL )
    {
      int coef = 1;
      for ( int j = 0; j < A.cols() ; j++ )
      {
        row.insert(j, coef * temp.data()[j]);
      }
      row_lb[indexRow] = -1.0 * si->getInfinity();
      row_ub[indexRow] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow(row);
      indexRow++;
    }
    if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_GREATER_OR_EQUAL )
    {
      int coef = -1;
      for ( int j = 0; j < A.cols() ; j++ )
      {
	      row.insert(j, coef * temp.data()[j]);
      }
      row_lb[indexRow] = -1.0 * si->getInfinity();
      row_ub[indexRow] = coef * cstraints.constraint_objective_(i);
      matrix->appendRow(row);
      indexRow++;
    }
  }

  //-- Setup bounds for all the parameters
  if (cstraints.vec_bounds_.size() == 1)
  {
    // Setup the same bound for all the parameters
    for (int i=0; i < this->nbParams_; ++i)
    {
      col_lb[i] = cstraints.vec_bounds_[0].first;
      col_ub[i] = cstraints.vec_bounds_[0].second;
    }
  }
  else // each parameter have it's own bounds
  {
    for (int i=0; i < this->nbParams_; ++i)
    {
      col_lb[i] = cstraints.vec_bounds_[i].first;
      col_ub[i] = cstraints.vec_bounds_[i].second;
    }
  }

  si->loadProblem(*matrix, &col_lb[0], &col_ub[0], cstraints.vec_cost_.empty() ? NULL : &cstraints.vec_cost_[0], &row_lb[0], &row_ub[0] );

  delete matrix;

  return bOk;
}
/* Factorize - filling in rowsDropped and returning number dropped */
int
ClpCholeskyWssmpKKT::factorize(const double * diagonal, int * rowsDropped)
{
    int numberRowsModel = model_->numberRows();
    int numberColumns = model_->numberColumns();
    int numberTotal = numberColumns + numberRowsModel;
    int newDropped = 0;
    double largest = 0.0;
    double smallest;
    //perturbation
    double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm();
    perturbation = perturbation * perturbation;
    if (perturbation > 1.0) {
#ifdef COIN_DEVELOP
        //if (model_->model()->logLevel()&4)
        std::cout << "large perturbation " << perturbation << std::endl;
#endif
        perturbation = sqrt(perturbation);;
        perturbation = 1.0;
    }
    // need to recreate every time
    int iRow, iColumn;
    const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts();
    const int * columnLength = model_->clpMatrix()->getVectorLengths();
    const int * row = model_->clpMatrix()->getIndices();
    const double * element = model_->clpMatrix()->getElements();

    CoinBigIndex numberElements = 0;
    CoinPackedMatrix * quadratic = NULL;
    ClpQuadraticObjective * quadraticObj =
        (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject()));
    if (quadraticObj)
        quadratic = quadraticObj->quadraticObjective();
    // matrix
    if (!quadratic) {
        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
            choleskyStart_[iColumn] = numberElements;
            double value = diagonal[iColumn];
            if (fabs(value) > 1.0e-100) {
                value = 1.0 / value;
                largest = CoinMax(largest, fabs(value));
                sparseFactor_[numberElements] = -value;
                choleskyRow_[numberElements++] = iColumn;
                CoinBigIndex start = columnStart[iColumn];
                CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                for (CoinBigIndex j = start; j < end; j++) {
                    choleskyRow_[numberElements] = row[j] + numberTotal;
                    sparseFactor_[numberElements++] = element[j];
                    largest = CoinMax(largest, fabs(element[j]));
                }
            } else {
                sparseFactor_[numberElements] = -1.0e100;
                choleskyRow_[numberElements++] = iColumn;
            }
        }
    } else {
        // Quadratic
        const int * columnQuadratic = quadratic->getIndices();
        const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts();
        const int * columnQuadraticLength = quadratic->getVectorLengths();
        const double * quadraticElement = quadratic->getElements();
        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
            choleskyStart_[iColumn] = numberElements;
            CoinBigIndex savePosition = numberElements;
            choleskyRow_[numberElements++] = iColumn;
            double value = diagonal[iColumn];
            if (fabs(value) > 1.0e-100) {
                value = 1.0 / value;
                for (CoinBigIndex j = columnQuadraticStart[iColumn];
                        j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                    int jColumn = columnQuadratic[j];
                    if (jColumn > iColumn) {
                        sparseFactor_[numberElements] = -quadraticElement[j];
                        choleskyRow_[numberElements++] = jColumn;
                    } else if (iColumn == jColumn) {
                        value += quadraticElement[j];
                    }
                }
                largest = CoinMax(largest, fabs(value));
                sparseFactor_[savePosition] = -value;
                CoinBigIndex start = columnStart[iColumn];
                CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                for (CoinBigIndex j = start; j < end; j++) {
                    choleskyRow_[numberElements] = row[j] + numberTotal;
                    sparseFactor_[numberElements++] = element[j];
                    largest = CoinMax(largest, fabs(element[j]));
                }
            } else {
                value = 1.0e100;
                sparseFactor_[savePosition] = -value;
            }
        }
    }
    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
        assert (sparseFactor_[choleskyStart_[iColumn]] < 0.0);
    }
    // slacks
    for (iColumn = numberColumns; iColumn < numberTotal; iColumn++) {
        choleskyStart_[iColumn] = numberElements;
        double value = diagonal[iColumn];
        if (fabs(value) > 1.0e-100) {
            value = 1.0 / value;
            largest = CoinMax(largest, fabs(value));
        } else {
            value = 1.0e100;
        }
        sparseFactor_[numberElements] = -value;
        choleskyRow_[numberElements++] = iColumn;
        choleskyRow_[numberElements] = iColumn - numberColumns + numberTotal;
        sparseFactor_[numberElements++] = -1.0;
    }
    // Finish diagonal
    double delta2 = model_->delta(); // add delta*delta to bottom
    delta2 *= delta2;
    for (iRow = 0; iRow < numberRowsModel; iRow++) {
        choleskyStart_[iRow+numberTotal] = numberElements;
        choleskyRow_[numberElements] = iRow + numberTotal;
        sparseFactor_[numberElements++] = delta2;
    }
    choleskyStart_[numberRows_] = numberElements;
    int i1 = 1;
    int i0 = 0;
    integerParameters_[1] = 3;
    integerParameters_[2] = 3;
    integerParameters_[10] = 2;
    //integerParameters_[11]=1;
    integerParameters_[12] = 2;
    // LDLT
    integerParameters_[30] = 1;
    doubleParameters_[20] = 1.0e100;
    double largest2 = largest * 1.0e-20;
    largest = CoinMin(largest2, 1.0e-11);
    doubleParameters_[10] = CoinMax(1.0e-20, largest);
    if (doubleParameters_[10] > 1.0e-3)
        integerParameters_[9] = 1;
    else
        integerParameters_[9] = 0;
#ifndef WSMP
    // Set up LDL cutoff
    integerParameters_[34] = numberTotal;
    doubleParameters_[20] = 1.0e-15;
    doubleParameters_[34] = 1.0e-12;
    //printf("tol is %g\n",doubleParameters_[10]);
    //doubleParameters_[10]=1.0e-17;
#endif
    int * rowsDropped2 = new int[numberRows_];
    CoinZeroN(rowsDropped2, numberRows_);
    F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_,
                          NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1,
                          NULL, &i0, rowsDropped2, integerParameters_, doubleParameters_);
    //std::cout<<"factorization took "<<doubleParameters_[0]<<std::endl;
    if (integerParameters_[9]) {
        std::cout << "scaling applied" << std::endl;
    }
    newDropped = integerParameters_[20];
#if 1
    // Should save adjustments in ..R_
    int n1 = 0, n2 = 0;
    double * primalR = model_->primalR();
    double * dualR = model_->dualR();
    for (iRow = 0; iRow < numberTotal; iRow++) {
        if (rowsDropped2[iRow]) {
            n1++;
            //printf("row region1 %d dropped\n",iRow);
            //rowsDropped_[iRow]=1;
            rowsDropped_[iRow] = 0;
            primalR[iRow] = doubleParameters_[20];
        } else {
            rowsDropped_[iRow] = 0;
            primalR[iRow] = 0.0;
        }
    }
    for (; iRow < numberRows_; iRow++) {
        if (rowsDropped2[iRow]) {
            n2++;
            //printf("row region2 %d dropped\n",iRow);
            //rowsDropped_[iRow]=1;
            rowsDropped_[iRow] = 0;
            dualR[iRow-numberTotal] = doubleParameters_[34];
        } else {
            rowsDropped_[iRow] = 0;
            dualR[iRow-numberTotal] = 0.0;
        }
    }
    //printf("%d rows dropped in region1, %d in region2\n",n1,n2);
#endif
    delete [] rowsDropped2;
    //if (integerParameters_[20])
    //std::cout<<integerParameters_[20]<<" rows dropped"<<std::endl;
    largest = doubleParameters_[3];
    smallest = doubleParameters_[4];
    if (model_->messageHandler()->logLevel() > 1)
        std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl;
    choleskyCondition_ = largest / smallest;
    if (integerParameters_[63] < 0)
        return -1; // out of memory
    status_ = 0;
    return 0;
}
示例#27
0
int main(int argc, const char *argv[])
{
     try {
          // Empty model
          ClpSimplex  model;

          // Objective - just nonzeros
          int objIndex[] = {0, 2};
          double objValue[] = {1.0, 4.0};
          // Upper bounds - as dense vector
          double upper[] = {2.0, COIN_DBL_MAX, 4.0};

          // Create space for 3 columns
          model.resize(0, 3);
          // Fill in
          int i;
          // Virtuous way
          // First objective
          for (i = 0; i < 2; i++)
               model.setObjectiveCoefficient(objIndex[i], objValue[i]);
          // Now bounds (lower will be zero by default but do again)
          for (i = 0; i < 3; i++) {
               model.setColumnLower(i, 0.0);
               model.setColumnUpper(i, upper[i]);
          }
          /*
            We could also have done in non-virtuous way e.g.
            double * objective = model.objective();
            and then set directly
          */
          // Faster to add rows all at once - but this is easier to show
          // Now add row 1 as >= 2.0
          int row1Index[] = {0, 2};
          double row1Value[] = {1.0, 1.0};
          model.addRow(2, row1Index, row1Value,
                       2.0, COIN_DBL_MAX);
          // Now add row 2 as == 1.0
          int row2Index[] = {0, 1, 2};
          double row2Value[] = {1.0, -5.0, 1.0};
          model.addRow(3, row2Index, row2Value,
                       1.0, 1.0);
          // solve
          model.dual();

          /*
            Adding one row at a time has a significant overhead so let's
            try a more complicated but faster way

            First time adding in 10000 rows one by one
          */
          model.allSlackBasis();
          ClpSimplex modelSave = model;
          double time1 = CoinCpuTime();
          int k;
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               model.addRow(3, row2Index, row2Value,
                            1.0, 1.0);
          }
          printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build
          CoinBuild buildObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               buildObject.addRow(3, row2Index, row2Value,
                                  1.0, 1.0);
          }
          model.addRows(buildObject);
          printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          int del[] = {0, 1, 2};
          model.deleteRows(2, del);
          // Now use build +-1
          CoinBuild buildObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               buildObject2.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(buildObject2, true);
          printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          model.deleteRows(2, del);
          // Now use build +-1
          CoinModel modelObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               modelObject2.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(modelObject2, true);
          printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = ClpSimplex();
          // Now use build +-1
          CoinModel modelObject3;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               modelObject3.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.loadProblem(modelObject3, true);
          printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1);
          model.writeMps("xx.mps");
          model.dual();
          model = modelSave;
          // Now use model
          CoinModel modelObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               modelObject.addRow(3, row2Index, row2Value,
                                  1.0, 1.0);
          }
          model.addRows(modelObject);
          printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1);
          model.dual();
          model.writeMps("b.mps");
          // Method using least memory - but most complicated
          time1 = CoinCpuTime();
          // Assumes we know exact size of model and matrix
          // Empty model
          ClpSimplex  model2;
          {
               // Create space for 3 columns and 10000 rows
               int numberRows = 10000;
               int numberColumns = 3;
               // This is fully dense - but would not normally be so
               int numberElements = numberRows * numberColumns;
               // Arrays will be set to default values
               model2.resize(numberRows, numberColumns);
               double * elements = new double [numberElements];
               CoinBigIndex * starts = new CoinBigIndex [numberColumns+1];
               int * rows = new int [numberElements];;
               int * lengths = new int[numberColumns];
               // Now fill in - totally unsafe but ....
               // no need as defaults to 0.0 double * columnLower = model2.columnLower();
               double * columnUpper = model2.columnUpper();
               double * objective = model2.objective();
               double * rowLower = model2.rowLower();
               double * rowUpper = model2.rowUpper();
               // Columns - objective was packed
               for (k = 0; k < 2; k++) {
                    int iColumn = objIndex[k];
                    objective[iColumn] = objValue[k];
               }
               for (k = 0; k < numberColumns; k++)
                    columnUpper[k] = upper[k];
               // Rows
               for (k = 0; k < numberRows; k++) {
                    rowLower[k] = 1.0;
                    rowUpper[k] = 1.0;
               }
               // Now elements
               double row2Value[] = {1.0, -5.0, 1.0};
               CoinBigIndex put = 0;
               for (k = 0; k < numberColumns; k++) {
                    starts[k] = put;
                    lengths[k] = numberRows;
                    double value = row2Value[k];
                    for (int i = 0; i < numberRows; i++) {
                         rows[put] = i;
                         elements[put] = value;
                         put++;
                    }
               }
               starts[numberColumns] = put;
               // assign to matrix
               CoinPackedMatrix * matrix = new CoinPackedMatrix(true, 0.0, 0.0);
               matrix->assignMatrix(true, numberRows, numberColumns, numberElements,
                                    elements, rows, starts, lengths);
               ClpPackedMatrix * clpMatrix = new ClpPackedMatrix(matrix);
               model2.replaceMatrix(clpMatrix, true);
               printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1);
               // If matrix is really big could switch off creation of row copy
               // model2.setSpecialOptions(256);
          }
          model2.dual();
          model2.writeMps("a.mps");
          // Print column solution
          int numberColumns = model.numberColumns();

          // Alternatively getColSolution()
          double * columnPrimal = model.primalColumnSolution();
          // Alternatively getReducedCost()
          double * columnDual = model.dualColumnSolution();
          // Alternatively getColLower()
          double * columnLower = model.columnLower();
          // Alternatively getColUpper()
          double * columnUpper = model.columnUpper();
          // Alternatively getObjCoefficients()
          double * columnObjective = model.objective();

          int iColumn;

          std::cout << "               Primal          Dual         Lower         Upper          Cost"
                    << std::endl;

          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               double value;
               std::cout << std::setw(6) << iColumn << " ";
               value = columnPrimal[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnDual[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnLower[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnUpper[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnObjective[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;

               std::cout << std::endl;
          }
          std::cout << "--------------------------------------" << std::endl;
          // Test CoinAssert
          std::cout << "If Clp compiled with -g below should give assert, if with -O1 or COIN_ASSERT CoinError" << std::endl;
          model = modelSave;
          model.deleteRows(2, del);
          // Deliberate error
          model.deleteColumns(1, del + 2);
          // Now use build +-1
          CoinBuild buildObject3;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               buildObject3.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(buildObject3, true);
     } catch (CoinError e) {
          e.print();
          if (e.lineNumber() >= 0)
               std::cout << "This was from a CoinAssert" << std::endl;
     }
     return 0;
}
示例#28
0
void CglOddHole::generateCuts(const OsiRowCutDebugger * /*debugger*/,
			      const CoinPackedMatrix & rowCopy, 
				 const double * solution, 
			      const double * dj, OsiCuts & cs,
				 const int * suitableRow,
			      const int * fixedColumn,
			      const CglTreeInfo info,
			      bool packed)
{
  CoinPackedMatrix columnCopy = rowCopy;
  columnCopy.reverseOrdering();

  // Get basic problem information
  int nRows=columnCopy.getNumRows(); 
  int nCols=columnCopy.getNumCols(); 
  
  const int * column = rowCopy.getIndices();
  const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
  const int * rowLength = rowCopy.getVectorLengths(); 
  
  const int * row = columnCopy.getIndices();
  const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
  const int * columnLength = columnCopy.getVectorLengths(); 

  // we need only look at suitable rows and variables with unsatisfied 0-1
  // lookup from true row to compressed matrix
  int * mrow = new int[nRows];
  // lookup from true column to compressed
  int * lookup = new int[nCols];
  // number of columns in compressed matrix
  int nSmall=0;
  int i;
  //do lookup from true sequence to compressed
  int n=0;
  for (i=0;i<nRows;i++) {
    if (suitableRow[i]>0) {
      mrow[i]=n++;
    } else {
      mrow[i]=-1;
    }
  }
  for (i=0;i<nCols;i++) {
    if (!fixedColumn[i]) {
      lookup[i]=nSmall++;
    } else {
      lookup[i]=-1;
    }
  }
  int nSmall2=2*nSmall;
  // we don't know how big matrix will be
#define MAXELS 50000
  int maxels=MAXELS;
  //How do I do reallocs in C++?
  // 1.0 - value x(i) - value x(j) for each node pair (or reverse if cover) 
  double * cost = reinterpret_cast<double *> (malloc(maxels*sizeof(double)));
  // arc i.e. j which can be reached from i
  int * to= reinterpret_cast<int *> (malloc(maxels*sizeof(int)));
  //original row for each arc
  int * rowfound=reinterpret_cast<int *> (malloc(maxels*sizeof(int)));
  // start of each column
  int * starts=new int[2*nSmall+1];
  starts[0]=0;
  // useful array for marking if already connected
  int * mark =new int[nSmall2];
  memset(mark,0,nSmall2*sizeof(int));
  n=0; //number of elements in matrix
  for (i=0;i<nCols;i++) {
    int icol=lookup[i];
    if (icol>=0) {
      // column in compressed matrix
      int k;
      double dd=1.0000001-solution[i];
      mark[icol]=1;
      // reallocate if matrix reached size limit
      if (n+nCols>maxels) {
	maxels*=2;
	cost=reinterpret_cast<double *> (realloc(cost,maxels*sizeof(double)));
	to=reinterpret_cast<int *> (realloc(to,maxels*sizeof(int)));
	rowfound=reinterpret_cast<int *> (realloc(rowfound,maxels*sizeof(int)));
      }
      // get all other connected variables
      for (k=columnStart[i];k<columnStart[i]+columnLength[i];k++) {
	int irow=row[k];
	int jrow=mrow[irow];
	// but only if row in compressed matrix
	if (jrow>=0) {
	  int j;
	  for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
	    int jcol=column[j];
	    int kcol=lookup[jcol];
	    if (kcol>=0&&!mark[kcol]) {
	      cost[n]=dd-solution[jcol];
	      to[n]=kcol;
	      rowfound[n++]=irow;//original row
	      mark[kcol]=1;
	    }
	  }
	}
      }
      starts[icol+1]=n;
      // zero out markers for next column
      mark[icol]=0;
      for (k=starts[icol];k<starts[icol+1];k++) {
	int ito=to[k];
	if (ito<0||ito>=nSmall) abort();
	mark[to[k]]=0;
      }
    }
  }
  //if cover then change sign - otherwise make sure positive
  if (packed) {
    for (i=0;i<n;i++) {
      if (cost[i]<1.0e-10) {
	cost[i]=1.0e-10;
      }
    }
  } else {
    for (i=0;i<n;i++) {
      cost[i]=-cost[i];
      if (cost[i]<1.0e-10) {
	cost[i]=1.0e-10;
      }
    }
  }
  // we are going to double size 

  if (2*n>maxels) {
    maxels=2*n;
    cost=reinterpret_cast<double *> (realloc(cost,maxels*sizeof(double)));
    to=reinterpret_cast<int *> (realloc(to,maxels*sizeof(int)));
    rowfound=reinterpret_cast<int *> (realloc(rowfound,maxels*sizeof(int)));
  }
  /* copy and make bipartite*/

  for (i=0;i<nSmall;i++) {
    int k,j=i+nSmall;
    for (k=starts[i];k<starts[i+1];k++) {
      int ito=to[k];
      to[n]=ito;
      to[k]=ito+nSmall;
      cost[n]=cost[k];
      rowfound[n++]=rowfound[k];;
    }
    starts[j+1]=n;
  }
  //random numbers to winnow out duplicate cuts
  double * check = new double[nCols];
  if (info.randomNumberGenerator) {
    const CoinThreadRandom * randomGenerator = info.randomNumberGenerator;
    for (i=0;i<nCols;i++) {
      check[i]=randomGenerator->randomDouble();
    }
  } else {
    CoinSeedRandom(13579);
    for (i=0;i<nCols;i++) {
      check[i]=CoinDrand48(); // NOT on a thread by thread basis
    }
  }

  // Shortest path algorithm from Dijkstra - is there a better one?

  typedef struct {
    double cost; //cost to starting node
    int back; //previous node
  } Path;
  typedef struct {
    double cost; //cost to starting node
    int node; //node
  } Item;
  Item * stack = new Item [nSmall2];
  Path * path = new Path [nSmall2];
  // arrays below are used only if looks promising
  // allocate here
  // we don't know how many cuts will be generated
  int ncuts=0;
  int maxcuts=1000;
  double * hash = reinterpret_cast<double *> (malloc(maxcuts*sizeof(double)));
  // to clean (should not be needed)
  int * clean = new int[nSmall2];
  int * candidate = new int[CoinMax(nSmall2,nCols)];
  double * element = new double[nCols];
  // in case we want to sort
  double_double_int_triple * sortit = 
    new double_double_int_triple [nCols];
  memset(mark,0,nSmall2*sizeof(int));
  int * countcol = new int[nCols];
  memset(countcol,0,nCols*sizeof(int));
  int bias = packed ? 0 : 1; //amount to add before halving
  // If nSmall large then should do a randomized subset
  // Improvement 1
  int icol;
  for (icol=0;icol<nSmall;icol++) {
    int j;
    int jcol=icol+nSmall;
    int istack=1;
    for (j=0;j<nSmall2;j++) {
      path[j].cost=1.0e70;
      path[j].back=nSmall2+1;
    }
    path[icol].cost=0.0;
    path[icol].back=-1;
    stack[0].cost=0.0;
    stack[0].node=icol;
    mark[icol]=1;
    while(istack) {
      Item thisItem=stack[--istack];
      double thisCost=thisItem.cost;
      int inode=thisItem.node;
      int k;
      mark[inode]=0; //say available for further work
      // See if sorting every so many would help (and which way)?
      // Improvement 2
      for (k=starts[inode];k<starts[inode+1];k++) {
	int jnode=to[k];
	if (!mark[jnode]&&thisCost+cost[k]<path[jnode].cost-1.0e-12) {
	  path[jnode].cost=thisCost+cost[k];
	  path[jnode].back=inode;
	  // add to stack
	  stack[istack].cost=path[jnode].cost;
	  stack[istack++].node=jnode;
	  mark[jnode]=1;
#ifdef CGL_DEBUG
	  assert (istack<=nSmall2);
#endif
	}
      }
    }
    bool good=(path[jcol].cost<0.9999);

    if (good)  { /* try */
      int ii;
      int nrow2=0;
      int nclean=0;
      double sum=0;
#ifdef CGL_DEBUG
      printf("** %d ",jcol-nSmall);
#endif
      ii=1;
      candidate[0]=jcol;
      while(jcol!=icol) {
	int jjcol;
	jcol=path[jcol].back;
	if (jcol>=nSmall) {
	  jjcol=jcol-nSmall;
	} else {
	  jjcol=jcol;
	}
#ifdef CGL_DEBUG
	printf(" %d",jjcol);
#endif
	if (mark[jjcol]) {
	  // good=false;
	  // probably means this is from another cycle (will have been found)
	  // one of cycles must be zero cost
	  // printf("variable already on chain!\n");
	} else {
	  mark[jjcol]=1;
	  clean[nclean++]=jjcol;
	  candidate[ii++]=jcol;
#ifdef CGL_DEBUG
	  assert (ii<=nSmall2);
#endif
	}
      }
#ifdef CGL_DEBUG
      printf("\n");
#endif
      for (j=0;j<nclean;j++) {
	int k=clean[j];
	mark[k]=0;
      }
      if (good) {
	int k;
	for (k=ii-1;k>0;k--) {
	  int jk,kk=candidate[k];
	  int ix=0;
	  for (jk=starts[kk];jk<starts[kk+1];jk++) {
	    int ito=to[jk];
	    if (ito==candidate[k-1]) {
	      ix=1;
	      // back to original row
	      mrow[nrow2++]=rowfound[jk];
	      break;
	    }
	  }
	  if (!ix) {
	    good=false;
	  }
	}
	if ((nrow2&1)!=1) {
	  good=false;
	}
	if (good) {
	  int nincut=0;
	  for (k=0;k<nrow2;k++) {
	    int j,irow=mrow[k];
	    for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
	      int icol=column[j];
	      if (!countcol[icol]) candidate[nincut++]=icol;
	      countcol[icol]++;
	    }
	  }
#ifdef CGL_DEBUG
	  printf("true constraint %d",nrow2);
#endif
	  nrow2=nrow2>>1;
	  double rhs=nrow2; 
	  if (!packed) rhs++; // +1 for cover
	  ii=0;
	  for (k=0;k<nincut;k++) {
	    int jcol=candidate[k];
	    if (countcol[jcol]) {
#ifdef CGL_DEBUG
	      printf(" %d %d",jcol,countcol[jcol]);
#endif
	      int ihalf=(countcol[jcol]+bias)>>1;
	      if (ihalf) {
		element[ii]=ihalf;
		sum+=solution[jcol]*element[ii];
		/*printf("%d %g %g\n",jcol,element[ii],sumall[jcol]);*/
		candidate[ii++]=jcol;
	      }
	      countcol[jcol]=0;
	    }
	  }
#ifdef CGL_DEBUG
          printf("\n");
#endif
	  OsiRowCut rc;
	  double violation=0.0;
	  if (packed) {
	    violation = sum-rhs;
	    rc.setLb(-COIN_DBL_MAX);
	    rc.setUb(rhs);   
	  } else {
	    // other way for cover
	    violation = rhs-sum;
	    rc.setUb(COIN_DBL_MAX);
	    rc.setLb(rhs);   
	  }
	  if (violation<minimumViolation_) {
#ifdef CGL_DEBUG
	    printf("why no cut\n");
#endif
	    good=false;
	  } else {
	    if (static_cast<double> (ii) * minimumViolationPer_>violation||
		ii>maximumEntries_) {
#ifdef CGL_DEBUG
	      printf("why no cut\n");
#endif
	      if (packed) {
		// sort and see if we can get down to length
		// relax by taking out ones with solution 0.0
		nincut=ii;
		for (k=0;k<nincut;k++) {
		  int jcol=candidate[k];
		  double value = fabs(dj[jcol]);
		  if (solution[jcol])
		  value = -solution[jcol];
		  sortit[k].dj=value;
		  sortit[k].element=element[k];
		  sortit[k].sequence=jcol;
		}
		// sort 
		std::sort(sortit,sortit+nincut,double_double_int_triple_compare());
		nincut = CoinMin(nincut,maximumEntries_);
		sum=0.0;
		for (k=0;k<nincut;k++) {
		  int jcol=sortit[k].sequence;
		  candidate[k]=jcol;
		  element[k]=sortit[k].element;
		  sum+=solution[jcol]*element[k];
		}
		violation = sum-rhs;
		ii=nincut;
		if (violation<minimumViolation_) {
		  good=false;
		}
	      } else { 
		good=false;
	      }
	    }
	  }
	  if (good) {
	    //this assumes not many cuts
	    int j;
#if 0
	    double value=0.0;
	    for (j=0;j<ii;j++) {
	      int icol=candidate[j];
	      value += check[icol]*element[j];
	    }
#else
            CoinPackedVector candidatePv(ii,candidate,element);
            candidatePv.sortIncrIndex();
            double value = candidatePv.dotProduct(check);
#endif

	    for (j=0;j<ncuts;j++) {
	      if (value==hash[j]) {
		//could check equality - quicker just to assume
		break;
	      }
	    }
	    if (j==ncuts) {
	      //new
	      if (ncuts==maxcuts) {
		maxcuts *= 2;
		hash = reinterpret_cast<double *> (realloc(hash,maxcuts*sizeof(double)));
	      }
	      hash[ncuts++]=value;
	      rc.setRow(ii,candidate,element);
#ifdef CGL_DEBUG
	      printf("sum %g rhs %g %d\n",sum,rhs,ii);
	      if (debugger) 
		assert(!debugger->invalidCut(rc)); 
#endif
	      cs.insert(rc);
	    }
	  }
	}
	/* end of adding cut */
      }
    }
  }
  delete [] countcol;
  delete [] element;
  delete [] candidate;
  delete [] sortit;
  delete [] clean;
  delete [] path;
  delete [] stack;
  free(hash);
  delete [] check;
  delete [] mark;
  delete [] starts;
  delete [] lookup;
  delete [] mrow;
  free(rowfound);
  free(to);
  free(cost);
}
示例#29
0
文件: testGub2.cpp 项目: coin-or/Clp
int main(int argc, const char *argv[])
{
#if COIN_BIG_INDEX<2
     ClpSimplex  model;
     int status;
     int maxIts = 0;
     int maxFactor = 100;
     if (argc < 2) {
#if defined(SAMPLEDIR)
          status = model.readMps(SAMPLEDIR "/p0033.mps", true);
#else
          fprintf(stderr, "Do not know where to find sample MPS files.\n");
          exit(1);
#endif
     } else
          status = model.readMps(argv[1]);
     if (status) {
          printf("errors on input\n");
          exit(77);
     }
     if (argc > 2) {
          maxFactor = atoi(argv[2]);
          printf("max factor %d\n", maxFactor);
     }
     if (argc > 3) {
          maxIts = atoi(argv[3]);
          printf("max its %d\n", maxIts);
     }
     // For now scaling off
     model.scaling(0);
     if (maxIts) {
          // Do partial dantzig
          ClpPrimalColumnSteepest dantzig(5);
          model.setPrimalColumnPivotAlgorithm(dantzig);
          //model.messageHandler()->setLogLevel(63);
          model.setFactorizationFrequency(maxFactor);
          model.setMaximumIterations(maxIts);
          model.primal();
          if (!model.status())
               exit(1);
     }
     // find gub
     int numberRows = model.numberRows();
     int * gubStart = new int[numberRows+1];
     int * gubEnd = new int[numberRows];
     int * which = new int[numberRows];
     int * whichGub = new int[numberRows];
     int numberColumns = model.numberColumns();
     int * mark = new int[numberColumns];
     int iRow, iColumn;
     // delete variables fixed to zero
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     int numberDelete = 0;
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0)
               mark[numberDelete++] = iColumn;
     }
     if (numberDelete) {
          model.deleteColumns(numberDelete, mark);
          numberColumns -= numberDelete;
          columnLower = model.columnLower();
          columnUpper = model.columnUpper();
#if 0
          CoinMpsIO writer;
          writer.setMpsData(*model.matrix(), COIN_DBL_MAX,
                            model.getColLower(), model.getColUpper(),
                            model.getObjCoefficients(),
                            (const char*) 0 /*integrality*/,
                            model.getRowLower(), model.getRowUpper(),
                            NULL, NULL);
          writer.writeMps("cza.mps", 0, 0, 1);
#endif
     }
     double * lower = new double[numberRows];
     double * upper = new double[numberRows];
     const double * rowLower = model.rowLower();
     const double * rowUpper = model.rowUpper();
     for (iColumn = 0; iColumn < numberColumns; iColumn++)
          mark[iColumn] = -1;
     CoinPackedMatrix * matrix = model.matrix();
     // get row copy
     CoinPackedMatrix rowCopy = *matrix;
     rowCopy.reverseOrdering();
     const int * column = rowCopy.getIndices();
     const int * rowLength = rowCopy.getVectorLengths();
     const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
     const double * element = rowCopy.getElements();
     int putGub = numberRows;
     int putNonGub = numberRows;
     int * rowIsGub = new int [numberRows];
     for (iRow = numberRows - 1; iRow >= 0; iRow--) {
          bool gubRow = true;
          int first = numberColumns + 1;
          int last = -1;
          for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
               if (element[j] != 1.0) {
                    gubRow = false;
                    break;
               } else {
                    int iColumn = column[j];
                    if (mark[iColumn] >= 0) {
                         gubRow = false;
                         break;
                    } else {
                         last = CoinMax(last, iColumn);
                         first = CoinMin(first, iColumn);
                    }
               }
          }
          if (last - first + 1 != rowLength[iRow] || !gubRow) {
               which[--putNonGub] = iRow;
               rowIsGub[iRow] = 0;
          } else {
               for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
                    int iColumn = column[j];
                    mark[iColumn] = iRow;
               }
               rowIsGub[iRow] = -1;
               putGub--;
               gubStart[putGub] = first;
               gubEnd[putGub] = last + 1;
               lower[putGub] = rowLower[iRow];
               upper[putGub] = rowUpper[iRow];
               whichGub[putGub] = iRow;
          }
     }
     int numberNonGub = numberRows - putNonGub;
     int numberGub = numberRows - putGub;
     if (numberGub > 0) {
          printf("** %d gub rows\n", numberGub);
          int numberNormal = 0;
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          int numberElements = 0;
          bool doLower = false;
          bool doUpper = false;
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               if (mark[iColumn] < 0) {
                    mark[numberNormal++] = iColumn;
               } else {
                    numberElements += columnLength[iColumn];
                    if (columnLower[iColumn] != 0.0)
                         doLower = true;
                    if (columnUpper[iColumn] < 1.0e20)
                         doUpper = true;
               }
          }
          if (!numberNormal) {
               printf("Putting back one gub row to make non-empty\n");
               for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++)
                    mark[numberNormal++] = iColumn;
               putGub++;
               numberGub--;
          }
          ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark);
          int numberGubColumns = numberColumns - numberNormal;
          // sort gubs so monotonic
          int * which = new int[numberGub];
          int i;
          for (i = 0; i < numberGub; i++)
               which[i] = i;
          CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which);
          int * temp1 = new int [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp1[i] = gubEnd[putGub+k];
          }
          memcpy(gubEnd + putGub, temp1, numberGub * sizeof(int));
          delete [] temp1;
          double * temp2 = new double [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = lower[putGub+k];
          }
          memcpy(lower + putGub, temp2, numberGub * sizeof(double));
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = upper[putGub+k];
          }
          memcpy(upper + putGub, temp2, numberGub * sizeof(double));
          delete [] temp2;
          delete [] which;
          numberElements -= numberGubColumns;
          int * start2 = new int[numberGubColumns+1];
          int * row2 = new int[numberElements];
          double * element2 = new double[numberElements];
          double * cost2 = new double [numberGubColumns];
          double * lowerColumn2 = NULL;
          if (doLower) {
               lowerColumn2 = new double [numberGubColumns];
               CoinFillN(lowerColumn2, numberGubColumns, 0.0);
          }
          double * upperColumn2 = NULL;
          if (doUpper) {
               upperColumn2 = new double [numberGubColumns];
               CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX);
          }
          numberElements = 0;
          int numberNonGubRows = 0;
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (!rowIsGub[iRow])
                    rowIsGub[iRow] = numberNonGubRows++;
          }
          numberColumns = 0;
          gubStart[0] = 0;
          start2[0] = 0;
          const double * cost = model.objective();
          for (int iSet = 0; iSet < numberGub; iSet++) {
               int iStart = gubStart[iSet+putGub];
               int iEnd = gubEnd[iSet+putGub];
               for (int k = iStart; k < iEnd; k++) {
                    cost2[numberColumns] = cost[k];
                    if (columnLower[k])
                         lowerColumn2[numberColumns] = columnLower[k];
                    if (columnUpper[k] < 1.0e20)
                         upperColumn2[numberColumns] = columnUpper[k];
                    for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) {
                         int iRow = rowIsGub[row[j]];
                         if (iRow >= 0) {
                              row2[numberElements] = iRow;
                              element2[numberElements++] = elementByColumn[j];
                         }
                    }
                    start2[++numberColumns] = numberElements;
               }
               gubStart[iSet+1] = numberColumns;
          }
          model2.replaceMatrix(new ClpGubDynamicMatrix(&model2, numberGub,
                               numberColumns, gubStart,
                               lower + putGub, upper + putGub,
                               start2, row2, element2, cost2,
                               lowerColumn2, upperColumn2));
          delete [] rowIsGub;
          delete [] start2;
          delete [] row2;
          delete [] element2;
          delete [] cost2;
          delete [] lowerColumn2;
          delete [] upperColumn2;
          // For now scaling off
          model2.scaling(0);
          // Do partial dantzig
          ClpPrimalColumnSteepest dantzig(5);
          model2.setPrimalColumnPivotAlgorithm(dantzig);
          //model2.messageHandler()->setLogLevel(63);
          model2.setFactorizationFrequency(maxFactor);
          model2.setMaximumIterations(4000000);
          double time1 = CoinCpuTime();
          model2.primal();
          {
               ClpGubDynamicMatrix * gubMatrix =
                    dynamic_cast< ClpGubDynamicMatrix*>(model2.clpMatrix());
               assert(gubMatrix);
               const double * solution = model2.primalColumnSolution();
               int numberGubColumns = gubMatrix->numberGubColumns();
               int firstOdd = gubMatrix->firstDynamic();
               int lastOdd = gubMatrix->firstAvailable();
               int numberTotalColumns = firstOdd + numberGubColumns;
               int numberRows = model2.numberRows();
               char * status = new char [numberTotalColumns];
               double * gubSolution = new double [numberTotalColumns];
               int numberSets = gubMatrix->numberSets();
               const int * id = gubMatrix->id();
               int i;
               const double * lowerColumn = gubMatrix->lowerColumn();
               const double * upperColumn = gubMatrix->upperColumn();
               for (i = 0; i < numberGubColumns; i++) {
                    if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atUpperBound) {
                         gubSolution[i+firstOdd] = upperColumn[i];
                         status[i+firstOdd] = 2;
                    } else if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atLowerBound && lowerColumn) {
                         gubSolution[i+firstOdd] = lowerColumn[i];
                         status[i+firstOdd] = 1;
                    } else {
                         gubSolution[i+firstOdd] = 0.0;
                         status[i+firstOdd] = 1;
                    }
               }
               for (i = 0; i < firstOdd; i++) {
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[i] = 3;
                    else
                         abort();
                    gubSolution[i] = solution[i];
               }
               for (i = firstOdd; i < lastOdd; i++) {
                    int iBig = id[i-firstOdd] + firstOdd;
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[iBig] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[iBig] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[iBig] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[iBig] = 3;
                    else
                         abort();
                    gubSolution[iBig] = solution[i];
               }
               char * rowStatus = new char[numberRows];
               for (i = 0; i < numberRows; i++) {
                    ClpSimplex::Status thisStatus = model2.getRowStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         rowStatus[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         rowStatus[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         rowStatus[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         rowStatus[i] = 3;
                    else
                         abort();
               }
               char * setStatus = new char[numberSets];
               int * keyVariable = new int[numberSets];
               memcpy(keyVariable, gubMatrix->keyVariable(), numberSets * sizeof(int));
               for (i = 0; i < numberSets; i++) {
                    int iKey = keyVariable[i];
                    if (iKey > lastOdd)
                         iKey = numberTotalColumns + i;
                    else
                         iKey = id[iKey-firstOdd] + firstOdd;
                    keyVariable[i] = iKey;
                    ClpSimplex::Status thisStatus = gubMatrix->getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         setStatus[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         setStatus[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         setStatus[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         setStatus[i] = 3;
                    else
                         abort();
               }
               FILE * fp = fopen("xx.sol", "w");
               fwrite(gubSolution, sizeof(double), numberTotalColumns, fp);
               fwrite(status, sizeof(char), numberTotalColumns, fp);
               const double * rowsol = model2.primalRowSolution();
               int originalNumberRows = model.numberRows();
               double * rowsol2 = new double[originalNumberRows];
               memset(rowsol2, 0, originalNumberRows * sizeof(double));
               model.times(1.0, gubSolution, rowsol2);
               for (i = 0; i < numberRows; i++)
                    assert(fabs(rowsol[i] - rowsol2[i]) < 1.0e-3);
               //for (;i<originalNumberRows;i++)
               //printf("%d %g\n",i,rowsol2[i]);
               delete [] rowsol2;
               fwrite(rowsol, sizeof(double), numberRows, fp);
               fwrite(rowStatus, sizeof(char), numberRows, fp);
               fwrite(setStatus, sizeof(char), numberSets, fp);
               fwrite(keyVariable, sizeof(int), numberSets, fp);
               fclose(fp);
               delete [] status;
               delete [] gubSolution;
               delete [] setStatus;
               delete [] keyVariable;
               // ** if going to rstart as dynamic need id_
               // also copy coding in useEf.. from ClpGubMatrix (i.e. test for basis)
          }
          printf("obj offset is %g\n", model2.objectiveOffset());
          printf("Primal took %g seconds\n", CoinCpuTime() - time1);
          //model2.primal(1);
     }
     delete [] mark;
     delete [] gubStart;
     delete [] gubEnd;
     delete [] which;
     delete [] whichGub;
     delete [] lower;
     delete [] upper;
#else
     printf("testGub2 not available with COIN_BIG_INDEX=2\n");
#endif
     return 0;
}
示例#30
0
CbcLagrangeSolver::CbcLagrangeSolver(stochasticInput &input, int scenarioNumber, const vector<double> &lagrangeDiff) {

	absgap = ratio = 0.;
	nvar1 = input.nFirstStageVars();
	int nvar2 = input.nSecondStageVars(scenarioNumber);
	int ncons1 = input.nFirstStageCons();
	int ncons2 = input.nSecondStageCons(scenarioNumber);

	const CoinPackedMatrix &Amat = input.getFirstStageConstraints(),
		&Tmat = input.getLinkingConstraints(scenarioNumber),
		&Wmat = input.getSecondStageConstraints(scenarioNumber);
	
	
	int totalVar = nvar1 + nvar2;
	int totalCons = ncons1 + ncons2;

	CoinBigIndex totalNnz = Amat.getNumElements() + Tmat.getNumElements() + Wmat.getNumElements();

	// CoinPackedMatrix takes ownership of these, so we don't free them
	CoinBigIndex *starts = new CoinBigIndex[totalVar+1];
	double *elts = new double[totalNnz];
	int *rowIdx = new int[totalNnz];
	
	CoinBigIndex nnz = 0, start, end;
	// put first-stage variables first, as is customary
	int const *Aidx = Amat.getIndices();
	double const *Aelts = Amat.getElements();
	int const *Tidx = Tmat.getIndices();
	double const *Telts = Tmat.getElements();

	for (int c = 0; c < nvar1; c++) {
		starts[c] = nnz;
		start = Amat.getVectorFirst(c);
		end = Amat.getVectorLast(c);
		for (CoinBigIndex j = start; j < end; j++) {
			elts[nnz] = Aelts[j];
			rowIdx[nnz++] = Aidx[j];
		}
		start = Tmat.getVectorFirst(c);
		end = Tmat.getVectorLast(c);
		for (CoinBigIndex j = start; j < end; j++) {
			elts[nnz] = Telts[j];
			rowIdx[nnz++] = Tidx[j]+ncons1;
		}
	
	}

	// now W blocks
	int rowOffset = ncons1;
	int colOffset = nvar1;
	int const *Widx = Wmat.getIndices();
	double const *Welts = Wmat.getElements();

	for (int c = 0; c < nvar2; c++) {
		starts[colOffset++] = nnz;
		start = Wmat.getVectorFirst(c);
		end = Wmat.getVectorLast(c);
		for (CoinBigIndex j = start; j < end; j++) {
			elts[nnz] = Welts[j];
			rowIdx[nnz++] = Widx[j]+rowOffset;
		}
	}
	starts[totalVar] = nnz;
	assert(nnz == totalNnz);

	CoinPackedMatrix *constr = new CoinPackedMatrix();
	int *lens = 0;
	constr->assignMatrix(true,totalCons,totalVar,totalNnz,elts,rowIdx,starts,lens);
	constr->verifyMtx(); // debugging

	// OsiClpSolverInterface takes ownership of these
	double *collb = new double[totalVar];
	double *colub = new double[totalVar];
	double *obj = new double[totalVar];
	double *rowlb = new double[totalCons];
	double *rowub = new double[totalCons];

	concatenateOne(input, collb, &stochasticInput::getFirstStageColLB,
			&stochasticInput::getSecondStageColLB, scenarioNumber);
	
	concatenateOne(input, colub, &stochasticInput::getFirstStageColUB,
			&stochasticInput::getSecondStageColUB, scenarioNumber);

	concatenateOne(input, obj, &stochasticInput::getFirstStageObj,
			&stochasticInput::getSecondStageObj, scenarioNumber);
	
	concatenateOne(input, rowlb, &stochasticInput::getFirstStageRowLB,
			&stochasticInput::getSecondStageRowLB, scenarioNumber);

	concatenateOne(input, rowub, &stochasticInput::getFirstStageRowUB,
			&stochasticInput::getSecondStageRowUB, scenarioNumber);

	// rescale first-stage objective
	double scale = input.scenarioProbability(scenarioNumber);
	assert(lagrangeDiff.size() == static_cast<unsigned>(nvar1));
	for (int i = 0; i < nvar1; i++) {
		obj[i] = scale*obj[i] + lagrangeDiff[i];
	}

	m.assignProblem(constr, collb, colub, obj, rowlb, rowub);

	for (int i = 0; i < nvar1; i++) {
		if (input.isFirstStageColInteger(i)) m.setInteger(i);
	}
	for (int i = 0; i < nvar2; i++) {
		if (input.isSecondStageColInteger(scenarioNumber,i)) m.setInteger(i+nvar1);
	}

	//m.writeMps("problem");

	cbcm.reset(new CbcModel(m));
	CbcMain0(*cbcm);
	//m.messageHandler()->setLogLevel(0);
	//cbcm->messageHandler()->setLogLevel(0);

	//assert(CbcModel::haveMultiThreadSupport());
	//cbcm->setNumberThreads(4); // this should be adjusted to the system	


}