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; }
/** 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); }
/* 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(); }
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); }
// 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; }
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; }
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; }
// 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; }
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; }
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; }
/** 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; }
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; }
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_); }
/* 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; }
//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; } }
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); } }
//-------------------------------------------------------------------------- // 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 ; } } }
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; }
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; }
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; }
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; }
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); }
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; }
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 }