void CoinPackedVector::gutsOfSetConstant(int size, const int * inds, double value, bool testForDuplicateIndex, const char * method) { if ( size != 0 ) { reserve(size); nElements_ = size; CoinDisjointCopyN(inds, size, indices_); CoinFillN(elements_, size, value); CoinIotaN(origIndices_, size, 0); } try { CoinPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } catch (CoinError e) { throw CoinError("duplicate index", method, "CoinPackedVector"); } }
void CoinPresolveMatrix::setVariableType (bool allIntegers, int lenParam) { int len ; if (lenParam < 0) { len = ncols_ ; } else if (lenParam > ncols0_) { throw CoinError("length exceeds allocated size", "setIntegerType","CoinPresolveMatrix") ; } else { len = lenParam ; } if (integerType_ == 0) integerType_ = new unsigned char [ncols0_] ; const unsigned char value = 1 ; if (allIntegers == true) { CoinFillN(integerType_,len,value) ; } else { CoinZeroN(integerType_,len) ; } return ; }
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; }
// factorSparse. Does sparse phase of factorization //return code is <0 error, 0= finished int CoinFactorization::factorSparseSmall() { int *indexRow = indexRowU_.array(); int *indexColumn = indexColumnU_.array(); CoinFactorizationDouble *element = elementU_.array(); int count = 1; workArea_.conditionalNew(numberRows_); CoinFactorizationDouble *workArea = workArea_.array(); #ifndef NDEBUG counter1++; #endif // when to go dense int denseThreshold = abs(denseThreshold_); CoinZeroN(workArea, numberRows_); //get space for bit work area int workSize = 1000; workArea2_.conditionalNew(workSize); unsigned int *workArea2 = workArea2_.array(); //set markRow so no rows updated unsigned short *markRow = reinterpret_cast< unsigned short * >(markRow_.array()); CoinFillN(markRow, numberRows_, static_cast< unsigned short >(SMALL_UNSET)); int status = 0; //do slacks first int *numberInRow = numberInRow_.array(); int *numberInColumn = numberInColumn_.array(); int *numberInColumnPlus = numberInColumnPlus_.array(); int *startColumnU = startColumnU_.array(); int *startColumnL = startColumnL_.array(); if (biasLU_ < 3 && numberColumns_ == numberRows_) { int iPivotColumn; int *pivotColumn = pivotColumn_.array(); int *nextRow = nextRow_.array(); int *lastRow = lastRow_.array(); for (iPivotColumn = 0; iPivotColumn < numberColumns_; iPivotColumn++) { if (numberInColumn[iPivotColumn] == 1) { int start = startColumnU[iPivotColumn]; CoinFactorizationDouble value = element[start]; if (value == slackValue_ && numberInColumnPlus[iPivotColumn] == 0) { // treat as slack int iRow = indexRow[start]; // but only if row not marked if (numberInRow[iRow] > 0) { totalElements_ -= numberInRow[iRow]; //take out this bit of indexColumnU int next = nextRow[iRow]; int last = lastRow[iRow]; nextRow[last] = next; lastRow[next] = last; nextRow[iRow] = numberGoodU_; //use for permute lastRow[iRow] = -2; //mark //modify linked list for pivots deleteLink(iRow); numberInRow[iRow] = -1; numberInColumn[iPivotColumn] = 0; numberGoodL_++; startColumnL[numberGoodL_] = 0; pivotColumn[numberGoodU_] = iPivotColumn; numberGoodU_++; } } } } // redo preProcess(4); CoinFillN(markRow, numberRows_, static_cast< unsigned short >(SMALL_UNSET)); } numberSlacks_ = numberGoodU_; int *nextCount = nextCount_.array(); int *firstCount = firstCount_.array(); int *startRow = startRowU_.array(); int *startColumn = startColumnU; //#define UGLY_COIN_FACTOR_CODING #ifdef UGLY_COIN_FACTOR_CODING CoinFactorizationDouble *elementL = elementL_.array(); int *indexRowL = indexRowL_.array(); int *saveColumn = saveColumn_.array(); int *nextRow = nextRow_.array(); int *lastRow = lastRow_.array(); #endif double pivotTolerance = pivotTolerance_; int numberTrials = numberTrials_; int numberRows = numberRows_; // Put column singletons first - (if false) separateLinks(1, (biasLU_ > 1)); #ifndef NDEBUG int counter2 = 0; #endif while (count <= biggerDimension_) { #ifndef NDEBUG counter2++; int badRow = -1; if (counter1 == -1 && counter2 >= 0) { // check counts consistent for (int iCount = 1; iCount < numberRows_; iCount++) { int look = firstCount[iCount]; while (look >= 0) { if (look < numberRows_) { int iRow = look; if (iRow == badRow) printf("row count for row %d is %d\n", iCount, iRow); if (numberInRow[iRow] != iCount) { printf("failed debug on %d entry to factorSparse and %d try\n", counter1, counter2); printf("row %d - count %d number %d\n", iRow, iCount, numberInRow[iRow]); abort(); } look = nextCount[look]; } else { int iColumn = look - numberRows; if (numberInColumn[iColumn] != iCount) { printf("failed debug on %d entry to factorSparse and %d try\n", counter1, counter2); printf("column %d - count %d number %d\n", iColumn, iCount, numberInColumn[iColumn]); abort(); } look = nextCount[look]; } } } } #endif int minimumCount = COIN_INT_MAX; double minimumCost = COIN_DBL_MAX; int iPivotRow = -1; int iPivotColumn = -1; int pivotRowPosition = -1; int pivotColumnPosition = -1; int look = firstCount[count]; int trials = 0; int *pivotColumn = pivotColumn_.array(); if (count == 1 && firstCount[1] >= 0 && !biasLU_) { //do column singletons first to put more in U while (look >= 0) { if (look < numberRows_) { look = nextCount[look]; } else { int iColumn = look - numberRows_; assert(numberInColumn[iColumn] == count); int start = startColumnU[iColumn]; int iRow = indexRow[start]; iPivotRow = iRow; pivotRowPosition = start; iPivotColumn = iColumn; assert(iPivotRow >= 0 && iPivotColumn >= 0); pivotColumnPosition = -1; look = -1; break; } } /* endwhile */ if (iPivotRow < 0) { //back to singletons look = firstCount[1]; } } while (look >= 0) { if (look < numberRows_) { int iRow = look; #ifndef NDEBUG if (numberInRow[iRow] != count) { printf("failed on %d entry to factorSparse and %d try\n", counter1, counter2); printf("row %d - count %d number %d\n", iRow, count, numberInRow[iRow]); abort(); } #endif look = nextCount[look]; bool rejected = false; int start = startRow[iRow]; int end = start + count; int i; for (i = start; i < end; i++) { int iColumn = indexColumn[i]; assert(numberInColumn[iColumn] > 0); double cost = (count - 1) * numberInColumn[iColumn]; if (cost < minimumCost) { int where = startColumn[iColumn]; double minimumValue = element[where]; minimumValue = fabs(minimumValue) * pivotTolerance; while (indexRow[where] != iRow) { where++; } /* endwhile */ assert(where < startColumn[iColumn] + numberInColumn[iColumn]); CoinFactorizationDouble value = element[where]; value = fabs(value); if (value >= minimumValue) { minimumCost = cost; minimumCount = numberInColumn[iColumn]; iPivotRow = iRow; pivotRowPosition = -1; iPivotColumn = iColumn; assert(iPivotRow >= 0 && iPivotColumn >= 0); pivotColumnPosition = i; rejected = false; if (minimumCount < count) { look = -1; break; } } else if (iPivotRow == -1) { rejected = true; } } } trials++; if (trials >= numberTrials && iPivotRow >= 0) { look = -1; break; } if (rejected) { //take out for moment //eligible when row changes deleteLink(iRow); addLink(iRow, biggerDimension_ + 1); } } else { int iColumn = look - numberRows; assert(numberInColumn[iColumn] == count); look = nextCount[look]; int start = startColumn[iColumn]; int end = start + numberInColumn[iColumn]; CoinFactorizationDouble minimumValue = element[start]; minimumValue = fabs(minimumValue) * pivotTolerance; int i; for (i = start; i < end; i++) { CoinFactorizationDouble value = element[i]; value = fabs(value); if (value >= minimumValue) { int iRow = indexRow[i]; int nInRow = numberInRow[iRow]; assert(nInRow > 0); double cost = (count - 1) * nInRow; if (cost < minimumCost) { minimumCost = cost; minimumCount = nInRow; iPivotRow = iRow; pivotRowPosition = i; iPivotColumn = iColumn; assert(iPivotRow >= 0 && iPivotColumn >= 0); pivotColumnPosition = -1; if (minimumCount <= count + 1) { look = -1; break; } } } } trials++; if (trials >= numberTrials && iPivotRow >= 0) { look = -1; break; } } } /* endwhile */ if (iPivotRow >= 0) { assert(iPivotRow < numberRows_); int numberDoRow = numberInRow[iPivotRow] - 1; int numberDoColumn = numberInColumn[iPivotColumn] - 1; totalElements_ -= (numberDoRow + numberDoColumn + 1); if (numberDoColumn > 0) { if (numberDoRow > 0) { if (numberDoColumn > 1) { // if (1) { //need to adjust more for cache and SMP //allow at least 4 extra int increment = numberDoColumn + 1 + 4; if (increment & 15) { increment = increment & (~15); increment += 16; } int increment2 = (increment + COINFACTORIZATION_BITS_PER_INT - 1) >> COINFACTORIZATION_SHIFT_PER_INT; int size = increment2 * numberDoRow; if (size > workSize) { workSize = size; workArea2_.conditionalNew(workSize); workArea2 = workArea2_.array(); } bool goodPivot; #ifndef UGLY_COIN_FACTOR_CODING //branch out to best pivot routine goodPivot = pivot(iPivotRow, iPivotColumn, pivotRowPosition, pivotColumnPosition, workArea, workArea2, increment2, markRow, SMALL_SET); #else #define FAC_SET SMALL_SET #include "CoinFactorization.hpp" #undef FAC_SET #undef UGLY_COIN_FACTOR_CODING #endif if (!goodPivot) { status = -99; count = biggerDimension_ + 1; break; } } else { if (!pivotOneOtherRow(iPivotRow, iPivotColumn)) { status = -99; count = biggerDimension_ + 1; break; } } } else {
//----------------------------------------------------------------------------- // Generate Lift-and-Project cuts //------------------------------------------------------------------- void CglLiftAndProject::generateCuts(const OsiSolverInterface& si, OsiCuts& cs, const CglTreeInfo /*info*/) { // Assumes the mixed 0-1 problem // // min {cx: <Atilde,x> >= btilde} // // is in canonical form with all bounds, // including x_t>=0, -x_t>=-1 for x_t binary, // explicitly stated in the constraint matrix. // See ~/COIN/Examples/Cgl2/cgl2.cpp // for a general purpose "convert" function. // Reference [BCC]: Balas, Ceria, and Corneujols, // "A lift-and-project cutting plane algorithm // for mixed 0-1 program", Math Prog 58, (1993) // 295-324. // This implementation uses Normalization 1. // Given canonical problem and // the lp-relaxation solution, x, // the LAP cut generator attempts to construct // a cut for every x_j such that 0<x_j<1 // [BCC:307] // x_j is the strictly fractional binary variable // the cut is generated from int j = 0; // Get basic problem information // let Atilde be an m by n matrix const int m = si.getNumRows(); const int n = si.getNumCols(); const double * x = si.getColSolution(); // Remember - Atildes may have gaps.. const CoinPackedMatrix * Atilde = si.getMatrixByRow(); const double * AtildeElements = Atilde->getElements(); const int * AtildeIndices = Atilde->getIndices(); const CoinBigIndex * AtildeStarts = Atilde->getVectorStarts(); const int * AtildeLengths = Atilde->getVectorLengths(); const int AtildeFullSize = AtildeStarts[m]; const double * btilde = si.getRowLower(); // Set up memory for system (10) [BCC:307] // (the problem over the norm intersected // with the polar cone) // // min <<x^T,Atilde^T>,u> + x_ju_0 // s.t. // <B,w> = (0,...,0,beta_,beta)^T // w is nonneg for all but the // last two entries, which are free. // where // w = (u,v,v_0,u_0)in BCC notation // u and v are m-vectors; u,v >=0 // v_0 and u_0 are free-scalars, and // // B = Atilde^T -Atilde^T -e_j e_j // btilde^T e_0^T 0 0 // e_0^T btilde^T 1 0 // ^T indicates Transpose // e_0 is a (AtildeNCols x 1) vector of all zeros // e_j is e_0 with a 1 in the jth position // Storing B in column order. B is a (n+2 x 2m+2) matrix // But need to allow for possible gaps in Atilde. // At each iteration, only need to change 2 cols and objfunc // Sane design of OsiSolverInterface does not permit mucking // with matrix. // Because we must delete and add cols to alter matrix, // and we can only add columns on the end of the matrix // put the v_0 and u_0 columns on the end. // rather than as described in [BCC] // Initially allocating B with space for v_0 and u_O cols // but not populating, for efficiency. // B without u_0 and v_0 is a (n+2 x 2m) size matrix. int twoM = 2*m; int BNumRows = n+2; int BNumCols = twoM+2; int BFullSize = 2*AtildeFullSize+twoM+3; double * BElements = new double[BFullSize]; int * BIndices = new int[BFullSize]; CoinBigIndex * BStarts = new CoinBigIndex [BNumCols+1]; int * BLengths = new int[BNumCols]; int i, ij, k=0; int nPlus1=n+1; int offset = AtildeStarts[m]+m; for (i=0; i<m; i++){ for (ij=AtildeStarts[i];ij<AtildeStarts[i]+AtildeLengths[i];ij++){ BElements[k]=AtildeElements[ij]; BElements[k+offset]=-AtildeElements[ij]; BIndices[k]= AtildeIndices[ij]; BIndices[k+offset]= AtildeIndices[ij]; k++; } BElements[k]=btilde[i]; BElements[k+offset]=btilde[i]; BIndices[k]=n; BIndices[k+offset]=nPlus1; BStarts[i]= AtildeStarts[i]+i; BStarts[i+m]=offset+BStarts[i];// = AtildeStarts[m]+m+AtildeStarts[i]+i BLengths[i]= AtildeLengths[i]+1; BLengths[i+m]= AtildeLengths[i]+1; k++; } BStarts[twoM]=BStarts[twoM-1]+BLengths[twoM-1]; // Cols that will be deleted each iteration int BNumColsLessOne=BNumCols-1; int BNumColsLessTwo=BNumCols-2; const int delCols[2] = {BNumColsLessOne, BNumColsLessTwo}; // Set lower bound on u and v // u_0, v_0 will be reset as free const double solverINFINITY = si.getInfinity(); double * BColLowers = new double[BNumCols]; double * BColUppers = new double[BNumCols]; CoinFillN(BColLowers,BNumCols,0.0); CoinFillN(BColUppers,BNumCols,solverINFINITY); // Set row lowers and uppers. // The rhs is zero, for but the last two rows. // For these the rhs is beta_ double * BRowLowers = new double[BNumRows]; double * BRowUppers = new double[BNumRows]; CoinFillN(BRowLowers,BNumRows,0.0); CoinFillN(BRowUppers,BNumRows,0.0); BRowLowers[BNumRows-2]=beta_; BRowUppers[BNumRows-2]=beta_; BRowLowers[BNumRows-1]=beta_; BRowUppers[BNumRows-1]=beta_; // Calculate base objective <<x^T,Atilde^T>,u> // Note: at each iteration coefficient u_0 // changes to <x^T,e_j> // w=(u,v,beta,v_0,u_0) size 2m+3 // So, BOjective[2m+2]=x[j] double * BObjective= new double[BNumCols]; double * Atildex = new double[m]; CoinFillN(BObjective,BNumCols,0.0); Atilde->times(x,Atildex); // Atildex is size m, x is size n CoinDisjointCopyN(Atildex,m,BObjective); // Number of cols and size of Elements vector // in B without the v_0 and u_0 cols int BFullSizeLessThree = BFullSize-3; // Load B matrix into a column orders CoinPackedMatrix CoinPackedMatrix * BMatrix = new CoinPackedMatrix(true, BNumRows, BNumColsLessTwo, BFullSizeLessThree, BElements,BIndices, BStarts,BLengths); // Assign problem into a solver interface // Note: coneSi will cleanup the memory itself OsiSolverInterface * coneSi = si.clone(false); coneSi->assignProblem (BMatrix, BColLowers, BColUppers, BObjective, BRowLowers, BRowUppers); // Problem sense should default to "min" by default, // but just to be virtuous... coneSi->setObjSense(1.0); // The plot outline from here on down: // coneSi has been assigned B without the u_0 and v_0 columns // Calculate base objective <<x^T,Atilde^T>,u> // bool haveWarmStart = false; // For (j=0; j<n, j++) // if (!isBinary(x_j) || x_j<=0 || x_j>=1) continue; // // IMPROVEME: if(haveWarmStart) check if j attractive // add {-e_j,0,-1} matrix column for v_0 // add {e_j,0,0} matrix column for u_0 // objective coefficient for u_0 is x_j // if (haveWarmStart) // set warmstart info // solve min{objw:Bw=0; w>=0,except v_0, u_0 free} // if (bounded) // get warmstart info // haveWarmStart=true; // ustar = optimal u solution // ustar_0 = optimal u_0 solution // alpha^T= <ustar^T,Atilde> -ustar_0e_j^T // (double check <alpha^T,x> >= beta_ should be violated) // add <alpha^T,x> >= beta_ to cutset // endif // delete column for u_0 // this deletes all column info. // delete column for v_0 // endFor // clean up memory // return 0; int * nVectorIndices = new int[n]; CoinIotaN(nVectorIndices, n, 0); bool haveWarmStart = false; bool equalObj1, equalObj2; CoinRelFltEq eq; double v_0Elements[2] = {-1,1}; double u_0Elements[1] = {1}; CoinWarmStart * warmStart = 0; double * ustar = new double[m]; CoinFillN(ustar, m, 0.0); double* alpha = new double[n]; CoinFillN(alpha, n, 0.0); for (j=0;j<n;j++){ if (!si.isBinary(j)) continue; // Better to ask coneSi? No! // coneSi has no binInfo. equalObj1=eq(x[j],0); equalObj2=eq(x[j],1); if (equalObj1 || equalObj2) continue; // IMPROVEME: if (haveWarmStart) check if j attractive; // AskLL:wanted to declare u_0 and v_0 packedVec outside loop // and setIndices, but didn't see a method to do that(?) // (Could "insert". Seems inefficient) int v_0Indices[2]={j,nPlus1}; int u_0Indices[1]={j}; // CoinPackedVector v_0(2,v_0Indices,v_0Elements,false); CoinPackedVector u_0(1,u_0Indices,u_0Elements,false); #if CGL_DEBUG const CoinPackedMatrix *see1 = coneSi->getMatrixByRow(); #endif coneSi->addCol(v_0,-solverINFINITY,solverINFINITY,0); coneSi->addCol(u_0,-solverINFINITY,solverINFINITY,x[j]); if(haveWarmStart) { coneSi->setWarmStart(warmStart); coneSi->resolve(); } else { #if CGL_DEBUG const CoinPackedMatrix *see2 = coneSi->getMatrixByRow(); #endif coneSi->initialSolve(); } if(coneSi->isProvenOptimal()){ warmStart = coneSi->getWarmStart(); haveWarmStart=true; const double * wstar = coneSi->getColSolution(); CoinDisjointCopyN(wstar, m, ustar); Atilde->transposeTimes(ustar,alpha); alpha[j]+=wstar[BNumCols-1]; #if debug int p; double sum; for(p=0;p<n;p++)sum+=alpha[p]*x[p]; if (sum<=beta_){ throw CoinError("Cut not violated", "cutGeneration", "CglLiftAndProject"); } #endif // add <alpha^T,x> >= beta_ to cutset OsiRowCut rc; rc.setRow(n,nVectorIndices,alpha); rc.setLb(beta_); rc.setUb(solverINFINITY); cs.insert(rc); } // delete col for u_o and v_0 coneSi->deleteCols(2,delCols); // clean up memory } // clean up delete [] alpha; delete [] ustar; delete [] nVectorIndices; // BMatrix, BColLowers,BColUppers, BObjective, BRowLowers, BRowUppers // are all freed by OsiSolverInterface destructor (?) delete [] BLengths; delete [] BStarts; delete [] BIndices; delete [] BElements; }
void CoinPostsolveMatrix::assignPresolveToPostsolve (CoinPresolveMatrix *&preObj) { /* Start with simple data --- allocated and current size. */ ncols0_ = preObj->ncols0_ ; nrows0_ = preObj->nrows0_ ; nelems0_ = preObj->nelems0_ ; bulk0_ = preObj->bulk0_ ; ncols_ = preObj->ncols_ ; nrows_ = preObj->nrows_ ; nelems_ = preObj->nelems_ ; /* Now bring over the column-major matrix and other problem data. */ mcstrt_ = preObj->mcstrt_ ; preObj->mcstrt_ = 0 ; hincol_ = preObj->hincol_ ; preObj->hincol_ = 0 ; hrow_ = preObj->hrow_ ; preObj->hrow_ = 0 ; colels_ = preObj->colels_ ; preObj->colels_ = 0 ; cost_ = preObj->cost_ ; preObj->cost_ = 0 ; originalOffset_ = preObj->originalOffset_ ; clo_ = preObj->clo_ ; preObj->clo_ = 0 ; cup_ = preObj->cup_ ; preObj->cup_ = 0 ; rlo_ = preObj->rlo_ ; preObj->rlo_ = 0 ; rup_ = preObj->rup_ ; preObj->rup_ = 0 ; originalColumn_ = preObj->originalColumn_ ; preObj->originalColumn_ = 0 ; originalRow_ = preObj->originalRow_ ; preObj->originalRow_ = 0 ; ztolzb_ = preObj->ztolzb_ ; ztoldj_ = preObj->ztoldj_ ; maxmin_ = preObj->maxmin_ ; /* Now the problem solution. Often this will be empty, but that's not a problem. */ sol_ = preObj->sol_ ; preObj->sol_ = 0 ; rowduals_ = preObj->rowduals_ ; preObj->rowduals_ = 0 ; acts_ = preObj->acts_ ; preObj->acts_ = 0 ; rcosts_ = preObj->rcosts_ ; preObj->rcosts_ = 0 ; colstat_ = preObj->colstat_ ; preObj->colstat_ = 0 ; rowstat_ = preObj->rowstat_ ; preObj->rowstat_ = 0 ; /* The CoinPostsolveMatrix comes with messages and a handler, but replace them with the versions from the CoinPresolveObject, in case they've been customized. Let preObj believe it's no longer responsible for the handler. */ if (defaultHandler_ == true) delete handler_ ; handler_ = preObj->handler_ ; preObj->defaultHandler_ = false ; messages_ = preObj->messages_ ; /* Initialise the postsolve portions of this object. Which amounts to setting up the thread links to match the column-major matrix representation. This would be trivial except that the presolve matrix is loosely packed. We can either compress the matrix, or record the existing free space pattern. Bet that the latter is more efficient. Remember that mcstrt_[ncols_] actually points to the end of the bulk storage area, so when we process the last column in the bulk storage area, we'll add the free space block at the end of bulk storage to the free list. We need to allow for a 0x0 matrix here --- a pathological case, but it slips in when (for example) confirming a solution in an ILP code. */ free_list_ = NO_LINK ; maxlink_ = bulk0_ ; link_ = new CoinBigIndex [maxlink_] ; if (ncols_ > 0) { CoinBigIndex minkcs = -1 ; for (int j = 0 ; j < ncols_ ; j++) { CoinBigIndex kcs = mcstrt_[j] ; int lenj = hincol_[j] ; assert(lenj > 0) ; CoinBigIndex kce = kcs+lenj-1 ; CoinBigIndex k ; for (k = kcs ; k < kce ; k++) { link_[k] = k+1 ; } link_[k++] = NO_LINK ; if (preObj->clink_[j].pre == NO_LINK) { minkcs = kcs ; } int nxtj = preObj->clink_[j].suc ; assert(nxtj >= 0 && nxtj <= ncols_) ; CoinBigIndex nxtcs = mcstrt_[nxtj] ; for ( ; k < nxtcs ; k++) { link_[k] = free_list_ ; free_list_ = k ; } } assert(minkcs >= 0) ; if (minkcs > 0) { for (CoinBigIndex k = 0 ; k < minkcs ; k++) { link_[k] = free_list_ ; free_list_ = k ; } } } else { for (CoinBigIndex k = 0 ; k < maxlink_ ; k++) { link_[k] = free_list_ ; free_list_ = k ; } } /* That's it, preObj can die now. */ delete preObj ; preObj = 0 ; # if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY /* These are used to track the action of postsolve transforms during debugging. */ cdone_ = new char [ncols0_] ; CoinFillN(cdone_,ncols_,PRESENT_IN_REDUCED) ; CoinZeroN(cdone_+ncols_,ncols0_-ncols_) ; rdone_ = new char [nrows0_] ; CoinFillN(rdone_,nrows_,PRESENT_IN_REDUCED) ; CoinZeroN(rdone_+nrows_,nrows0_-nrows_) ; # else cdone_ = 0 ; rdone_ = 0 ; # endif # if PRESOLVE_CONSISTENCY presolve_check_free_list(this,true) ; presolve_check_threads(this) ; # endif return ; }
int main (int argc, const char *argv[]) { ClpSimplex model; int status; int maxFactor = 100; if (argc < 2) { status = model.readMps("../../Data/Netlib/czprob.mps"); if (status) { printf("Unable to read matrix - trying gzipped version\n"); status = model.readMps("../../Data/Netlib/czprob.mps.gz"); } } 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) { printf("Using ClpDynamicMatrix\n"); } else { printf("Using ClpDynamicExampleMatrix\n"); } // 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(); } 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); // and copy for restart test ClpSimplex model3 = model2; 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); // move to bottom if we want to use later memmove(gubStart, gubStart + putGub, numberGub * sizeof(int)); int * temp1 = new int [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp1[i] = gubEnd[putGub+k]; } memcpy(gubEnd, 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, temp2, numberGub * sizeof(double)); for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = upper[putGub+k]; } memcpy(upper, 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; int iStart = gubStart[0]; gubStart[0] = 0; start2[0] = 0; const double * cost = model.objective(); for (int iSet = 0; iSet < numberGub; iSet++) { int iEnd = gubEnd[iSet]; 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; } if (iSet < numberGub - 1) iStart = gubStart[iSet+1]; gubStart[iSet+1] = numberColumns; } printf("** Before adding matrix there are %d rows and %d columns\n", model2.numberRows(), model2.numberColumns()); if (argc > 3) { ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model2, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2); model2.replaceMatrix(newMatrix); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } else { ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model2, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2); model2.replaceMatrix(newMatrix); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } printf("** While after adding matrix there are %d rows and %d columns\n", model2.numberRows(), model2.numberColumns()); model2.setSpecialOptions(4); // exactly to bound // For now scaling off model2.scaling(0); ClpPrimalColumnSteepest steepest(5); model2.setPrimalColumnPivotAlgorithm(steepest); //model2.messageHandler()->setLogLevel(63); model2.setFactorizationFrequency(maxFactor); model2.setMaximumIterations(4000000); double time1 = CoinCpuTime(); model2.primal(); // can't use values pass model2.primal(0); // test proper restart if (argc > 3) { ClpDynamicMatrix * oldMatrix = dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix()); assert (oldMatrix); ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model3, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2, oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus()); model3.replaceMatrix(newMatrix); // and ordinary status (but only NON gub rows) memcpy(model3.statusArray(), model2.statusArray(), (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char)); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } else { ClpDynamicExampleMatrix * oldMatrix = dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix()); assert (oldMatrix); ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model3, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2, oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus(), oldMatrix->numberGubColumns(), oldMatrix->idGen()); model3.replaceMatrix(newMatrix); // and ordinary status (but only NON gub rows) memcpy(model3.statusArray(), model2.statusArray(), (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char)); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } model3.setSpecialOptions(4); // exactly to bound // For now scaling off model3.scaling(0); model3.setPrimalColumnPivotAlgorithm(steepest); model3.messageHandler()->setLogLevel(63); model3.setFactorizationFrequency(maxFactor); model3.setMaximumIterations(4000000); delete [] rowIsGub; delete [] start2; delete [] row2; delete [] element2; delete [] cost2; delete [] lowerColumn2; delete [] upperColumn2; model3.primal(); // this code expects non gub first in original matrix // and only works at present for ClpDynamicMatrix ClpDynamicMatrix * gubMatrix = dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix()); assert (gubMatrix); ClpDynamicExampleMatrix * gubMatrix2 = dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix()); if (!gubMatrix2) { const double * solution = model2.primalColumnSolution(); const double * cost = model.objective(); int numberGubColumns = gubMatrix->numberGubColumns(); int firstOdd = gubMatrix->firstDynamic(); int lastOdd = gubMatrix->firstAvailable(); int numberTotalColumns = firstOdd + numberGubColumns; int originalNumberRows = model.numberRows(); int numberStaticRows = gubMatrix->numberStaticRows(); char * status = new char [numberTotalColumns]; double * gubSolution = new double [numberTotalColumns]; int numberSets = gubMatrix->numberSets(); const int * id = gubMatrix->id(); int i; const float * columnLower = gubMatrix->columnLower(); const float * columnUpper = gubMatrix->columnUpper(); for (i = 0; i < numberGubColumns; i++) { if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) { gubSolution[i+firstOdd] = columnUpper[i]; status[i+firstOdd] = 2; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound && columnLower) { gubSolution[i+firstOdd] = columnLower[i]; status[i+firstOdd] = 1; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) { int iSet = gubMatrix->whichSet(i); gubSolution[i+firstOdd] = gubMatrix->keyValue(iSet); status[i+firstOdd] = 0; } 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[originalNumberRows]; for (i = 0; i < numberStaticRows; 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(); } double objValue = 0.0; for (i = 0; i < numberTotalColumns; i++) objValue += cost[i] * gubSolution[i]; printf("objective value is %g\n", objValue); for (i = 0; i < numberSets; i++) { ClpSimplex::Status thisStatus = gubMatrix->getStatus(i); if (thisStatus == ClpSimplex::basic) rowStatus[numberStaticRows+i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) rowStatus[numberStaticRows+i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) rowStatus[numberStaticRows+i] = 2; else if (thisStatus == ClpSimplex::isFixed) rowStatus[numberStaticRows+i] = 3; else abort(); } // Coding below may not work if gub rows not at end FILE * fp = fopen ("xx.sol", "w"); fwrite(gubSolution, sizeof(double), numberTotalColumns, fp); fwrite(status, sizeof(char), numberTotalColumns, fp); const double * rowsol = model2.primalRowSolution(); double * rowsol2 = new double[originalNumberRows]; memset(rowsol2, 0, originalNumberRows * sizeof(double)); model.times(1.0, gubSolution, rowsol2); for (i = 0; i < numberStaticRows; i++) assert (fabs(rowsol[i] - rowsol2[i]) < 1.0e-3); for (; i < originalNumberRows; i++) assert (rowsol2[i] > lower[i-numberStaticRows] - 1.0e-3 && rowsol2[i] < upper[i-numberStaticRows] + 1.0e-3); //for (;i<originalNumberRows;i++) //printf("%d %g\n",i,rowsol2[i]); fwrite(rowsol2, sizeof(double), originalNumberRows, fp); delete [] rowsol2; fwrite(rowStatus, sizeof(char), originalNumberRows, fp); fclose(fp); delete [] status; delete [] gubSolution; // ** 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); } delete [] mark; delete [] gubStart; delete [] gubEnd; delete [] which; delete [] whichGub; delete [] lower; delete [] upper; return 0; }
/** construct master problem */ STO_RTN_CODE TssBd::constructMasterProblem(TssBdSub * tssbdsub, double lowerbound) { #define FREE_MEMORY \ FREE_PTR(mat) \ FREE_ARRAY_PTR(clbd) \ FREE_ARRAY_PTR(cubd) \ FREE_ARRAY_PTR(ctype) \ FREE_ARRAY_PTR(obj) \ FREE_ARRAY_PTR(rlbd) \ FREE_ARRAY_PTR(rubd) \ FREE_ARRAY_PTR(auxind) \ FREE_ARRAY_PTR(auxcoef) assert(model_); if (naux_ <= 0 || !obj_aux_ || !clbd_aux_ || !cubd_aux_) { printf("Warning: Auxiliary column information is required.\n"); return 1; } /** master problem */ CoinPackedMatrix * mat = NULL; double * clbd = NULL; double * cubd = NULL; double * obj = NULL; char * ctype = NULL; double * rlbd = NULL; double * rubd = NULL; /** for recourse lower bound */ int * auxind = NULL; double * auxcoef = NULL; BGN_TRY_CATCH int ncols = model_->getNumCols(0) + naugs_ * model_->getNumCols(1) + naux_; /** number of integer variables in the core */ int nIntegers = model_->getNumCoreIntegers(); /** allocate memory */ auxind = new int [ncols]; auxcoef = new double [ncols]; /** decompose model */ STO_RTN_CHECK_THROW(model_->decompose( naugs_, augs_, naux_, clbd_aux_, cubd_aux_, obj_aux_, mat, clbd, cubd, ctype, obj, rlbd, rubd), "decompose", "TssModel"); /** convert column types */ if (par_->relaxIntegrality_[0]) { for (int j = 0; j < model_->getNumCols(0); ++j) { if (ctype[j] != 'C') nIntegers--; ctype[j] = 'C'; } } if (par_->relaxIntegrality_[1] && naugs_ > 0) { for (int j = 0; j < model_->getNumCols(1); ++j) { if (ctype[model_->getNumCols(0) + j] != 'C') nIntegers--; } CoinFillN(ctype + model_->getNumCols(0), naugs_ * model_->getNumCols(1), 'C'); } if (nIntegers > 0) { si_ = new SolverInterfaceScip(par_); si_->setPrintLevel(CoinMin(par_->logLevel_ + 1, 5)); } else { si_ = new SolverInterfaceSpx(par_); si_->setPrintLevel(CoinMax(par_->logLevel_ - 1, 0)); } /** load problem data */ si_->loadProblem(mat, clbd, cubd, obj, ctype, rlbd, rubd, "BdMaster"); /** add row for lower bound */ for (int j = 0; j < ncols; ++j) auxind[j] = j; CoinCopyN(obj, ncols, auxcoef); si_->addRow(ncols, auxind, auxcoef, lowerbound, COIN_DBL_MAX); /** save memory */ FREE_MEMORY END_TRY_CATCH_RTN(FREE_MEMORY,STO_RTN_ERR) return STO_RTN_OK; #undef FREE_MEMORY }
//############################################################################# OsiSolverInterface * MibSBilevel::setUpModel(OsiSolverInterface * oSolver, bool newOsi, const double *lpSol) { /** Create lower-level model with fixed upper-level vars **/ int probType = model_->MibSPar_->entry(MibSParams::bilevelProblemType); bool warmStartLL = model_->MibSPar_->entry(MibSParams::warmStartLL); bool doDualFixing = model_->MibSPar_->entry(MibSParams::doDualFixing); std::string feasCheckSolver = model_->MibSPar_->entry(MibSParams::feasCheckSolver); OsiSolverInterface * nSolver; double etol(model_->etol_); int i(0), j(0), index1(0), index2(0); int uCols(model_->getUpperDim()); int lRows(model_->getLowerRowNum()); int lCols(model_->getLowerDim()); int * uColIndices = model_->getUpperColInd(); int * lColIndices = model_->getLowerColInd(); int * lRowIndices = model_->getLowerRowInd(); double objSense(model_->getLowerObjSense()); double * lObjCoeffs = model_->getLowerObjCoeffs(); const CoinPackedMatrix * matrix = oSolver->getMatrixByRow(); double coeff(0.0); if (!lpSol){ lpSol = oSolver->getColSolution(); } const double * origRowLb = model_->getOrigRowLb(); const double * origRowUb = model_->getOrigRowUb(); const double * origColLb = model_->getOrigColLb(); const double * origColUb = model_->getOrigColUb(); double * rowUb = new double[lRows]; double * rowLb = new double[lRows]; double * colUb = new double[lCols]; double * colLb = new double[lCols]; //CoinZeroN(rowUb, lRows); //CoinZeroN(rowLb, lRows); //CoinZeroN(colUb, lCols); //CoinZeroN(colLb, lCols); /** Set the row bounds **/ for(i = 0; i < lRows; i++){ rowLb[i] = origRowLb[lRowIndices[i]]; rowUb[i] = origRowUb[lRowIndices[i]]; } for(i = 0; i < lCols; i++){ colLb[i] = origColLb[lColIndices[i]]; colUb[i] = origColUb[lColIndices[i]]; } if (newOsi){ if (feasCheckSolver == "Cbc"){ nSolver = new OsiCbcSolverInterface(); }else if (feasCheckSolver == "SYMPHONY"){ nSolver = new OsiSymSolverInterface(); }else if (feasCheckSolver == "CPLEX"){ #ifdef USE_CPLEX nSolver = new OsiCpxSolverInterface(); #else throw CoinError("CPLEX chosen as solver, but it has not been enabled", "setUpModel", "MibsBilevel"); #endif }else{ throw CoinError("Unknown solver chosen", "setUpModel", "MibsBilevel"); } int * integerVars = new int[lCols]; double * objCoeffs = new double[lCols]; CoinFillN(integerVars, lCols, 0); //CoinZeroN(objCoeffs, lCols); int intCnt(0); /** Fill in array of lower-level integer variables **/ for(i = 0; i < lCols; i++){ index1 = lColIndices[i]; if(oSolver->isInteger(index1)){ integerVars[intCnt] = i; intCnt++; } } CoinDisjointCopyN(lObjCoeffs, lCols, objCoeffs); CoinPackedMatrix * newMat = new CoinPackedMatrix(false, 0, 0); newMat->setDimensions(0, lCols); double tmp(0.0); /* for(i = 0; i < lRows; i++){ CoinPackedVector row; index1 = lRowIndices[i]; start = matStarts[index1]; end = start + matrix->getVectorSize(index1); for(j = start; j < end; j++){ index2 = matIndices[j]; //tmp = findIndex(index, lCols, lColIndices); tmp = binarySearch(0, lCols - 1, index2, lColIndices); if(tmp > -1) row.insert(tmp, matElements[j]); } newMat->appendRow(row); } */ for(i = 0; i < lRows; i++){ CoinPackedVector row; index1 = lRowIndices[i]; for(j = 0; j < lCols; j++){ index2 = lColIndices[j]; tmp = matrix->getCoefficient(index1, index2); row.insert(j, tmp); } newMat->appendRow(row); } /* nSolver->assignProblem(newMat, colLb, colUb, objCoeffs, rowLb, rowUb); */ nSolver->loadProblem(*newMat, colLb, colUb, objCoeffs, rowLb, rowUb); for(i = 0; i < intCnt; i++){ nSolver->setInteger(integerVars[i]); } //nSolver->setInteger(integerVars, intCnt); nSolver->setObjSense(objSense); //1 min; -1 max nSolver->setHintParam(OsiDoReducePrint, true, OsiHintDo); #if 0 if(0){ dynamic_cast<OsiCbcSolverInterface *> (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("max_active_nodes", 1); } #endif delete [] integerVars; }else{ nSolver = solver_; } #define SYM_VERSION_IS_WS strcmp(SYMPHONY_VERSION, "WS") #if SYMPHONY_VERSION_IS_WS if (feasCheckSolver == "SYMPHONY" && probType == 1 && warmStartLL && !newOsi && doDualFixing){ //Interdiction /** Get upper bound from best known (feasible) lower level solution and try to fix additional variables by sensitivity analysis **/ std::vector<std::pair<AlpsKnowledge*, double> > solutionPool; model_->getKnowledgeBroker()-> getAllKnowledges(AlpsKnowledgeTypeSolution, solutionPool); const double * sol; double objval, Ub(objSense*nSolver->getInfinity()); BlisSolution* blisSol; std::vector<std::pair<AlpsKnowledge*, double> >::const_iterator si; for (si = solutionPool.begin(); si != solutionPool.end(); ++si){ blisSol = dynamic_cast<BlisSolution*>(si->first); sol = blisSol->getValues(); for (i = 0; i < uCols; i++){ if (lpSol[uColIndices[i]] > 1 - etol && sol[lColIndices[i]] > 1-etol){ break; } } if (i == uCols && -objSense*blisSol->getQuality() < Ub){ Ub = -objSense*blisSol->getQuality(); } } /** Figure out which variables get fixed by the upper level solution **/ int *newUbInd = new int[uCols]; int *newLbInd = new int[uCols]; double *newUbVal = new double[uCols]; double *newLbVal = new double[uCols]; double newLb; for (i = 0; i < uCols; i++){ newUbInd[i] = uColIndices[i]; newLbInd[i] = uColIndices[i]; newLbVal[i] = 0; if (lpSol[uColIndices[i]] > 1 - etol){ newUbVal[i] = 0; }else{ newUbVal[i] = 1; } } /** If we found an upper bound, then do the dual fixing **/ if (Ub < objSense*nSolver->getInfinity()){ sym_environment *env = dynamic_cast<OsiSymSolverInterface *>(nSolver)->getSymphonyEnvironment(); for (i = 0; i < uCols; i++){ if (newUbVal[i] == 1){ // Try fixing it to zero newUbVal[i] = 0; sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd, newLbVal, uCols, newUbInd, newUbVal, &newLb); if (objSense*newLb > Ub + etol){ //Victory! This variable can be fixed to 1 permanently newLbVal[i] = 1; } //Set upper bound back to 1 newUbVal[i] = 1; if (newLbVal[i] == 0){ // Try fixing it to one newLbVal[i] = 1; sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd, newLbVal, uCols, newUbInd, newUbVal, &newLb); if (objSense*newLb > Ub + etol){ //Victory! This variable can be fixed to 0 permanently newUbVal[i] = 0; } newLbVal[i] = 0; } } } } /** Now set the row bounds to account for fixings **/ /** This is probably very frgaile. Assuming interdiction rows come last. It would be better to set variable bounds directly, but this doesn't seem to work right now. **/ int iRowStart = lRows-uCols; #if 1 for(i = iRowStart; i < lRows; i++){ nSolver->setRowLower(i, newLbVal[i-iRowStart]); nSolver->setRowUpper(i, newUbVal[i-iRowStart]); } #else for(i = 0; i < uCols; i++){ nSolver->setColLower(i, newLbVal[i]); nSolver->setColUpper(i, newUbVal[i]); } #endif delete[] newUbInd; delete[] newLbInd; delete[] newUbVal; delete[] newLbVal; }else{ #endif //FIXME: NEED TO GET ROW SENSE HERE /** Get contribution of upper-level columns **/ double * upComp = new double[lRows]; CoinFillN(upComp, lRows, 0.0); for(i = 0; i < lRows; i++){ index1 = lRowIndices[i]; for(j = 0; j < uCols; j++){ index2 = uColIndices[j]; coeff = matrix->getCoefficient(index1, index2); if (coeff != 0){ upComp[i] += coeff * lpSol[index2]; } } } /** Correct the row bounds to account for fixed upper-level vars **/ for(i = 0; i < lRows; i++){ nSolver->setRowLower(i, rowLb[i] - upComp[i]); nSolver->setRowUpper(i, rowUb[i] - upComp[i]); } delete [] upComp; #if SYMPHONY_VERSION_IS_WS } #endif //I don't think this is needed //if(!getWarmStart()) // setWarmStart(nSolver->getWarmStart()); return nSolver; }
void BM_tm::initialize_core(BCP_vec<BCP_var_core*>& vars, BCP_vec<BCP_cut_core*>& cuts, BCP_lp_relax*& matrix) { char* argv_[3]; char** argv = argv_; argv[0] = NULL; argv[1] = strdup(par.entry(BM_par::NL_filename).c_str()); argv[2] = NULL; /* Get the basic options. */ Bonmin::BonminAmplSetup bonmin; bonmin.readOptionsFile(par.entry(BM_par::IpoptParamfile).c_str()); bonmin.initialize(argv); free(argv[1]); Bonmin::OsiTMINLPInterface& nlp = *bonmin.nonlinearSolver(); #if defined(BM_DISREGARD_SOS) const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints(); if (sos->num > 0) { printf("There are SOS constraints... disregarding them...\n"); } #endif OsiSolverInterface& clp = *bonmin.continuousSolver(); const int numCols = clp.getNumCols(); const int numRows = clp.getNumRows(); const double* clb = clp.getColLower(); const double* cub = clp.getColUpper(); double* obj = new double[numCols]; if (bonmin.getAlgorithm() == Bonmin::B_BB /* pure B&B */) { std::cout<<"Doing branch and bound"<<std::endl; CoinFillN(obj, numCols, 0.0); matrix = NULL; } else { std::cout<<"Doing hybrid"<<std::endl; CoinDisjointCopyN(clp.getObjCoefficients(), numCols, obj); cuts.reserve(numRows); const double* rlb = clp.getRowLower(); const double* rub = clp.getRowUpper(); for (int i = 0; i < numRows; ++i) { cuts.push_back(new BCP_cut_core(rlb[i], rub[i])); } matrix = new BCP_lp_relax(true /*column major ordered*/); matrix->copyOf(*clp.getMatrixByCol(), obj, clb, cub, rlb, rub); } vars.reserve(numCols); for (int i = 0; i < numCols; ++i) { BCP_var_t type = BCP_ContinuousVar; if (clp.isBinary(i)) type = BCP_BinaryVar; if (clp.isInteger(i)) type = BCP_IntegerVar; vars.push_back(new BCP_var_core(type, obj[i], clb[i], cub[i])); } delete[] obj; /* Initialize pseudocosts */ int nObj = 0; for (int i = 0; i < numCols; ++i) { if (nlp.isInteger(i)) { ++nObj; } } #if ! defined(BM_DISREGARD_SOS) const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints(); nObj += sos->num; #endif pseudoCosts_.initialize(nObj); }
/************************************************************************ This main program reads in an integer model from an mps file. It then tries to find SOS structure and solves using N-way variables *************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(MIPLIB3DIR) mpsFileName = MIPLIB3DIR "/10teams"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find miplib3 MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } int iRow, iColumn; int numberColumns = solver1.getNumCols(); int numberRows = solver1.getNumRows(); // get row copy const CoinPackedMatrix * matrix = solver1.getMatrixByRow(); const double * element = matrix->getElements(); const int * column = matrix->getIndices(); const CoinBigIndex * rowStart = matrix->getVectorStarts(); const int * rowLength = matrix->getVectorLengths(); const double * rowLower = solver1.getRowLower(); const double * rowUpper = solver1.getRowUpper(); const double * columnLower = solver1.getColLower(); // Look for possible SOS int numberSOS=0; int * mark = new int[numberColumns]; CoinFillN(mark,numberColumns,-1); for (iRow=0;iRow<numberRows;iRow++) { if (rowLower[iRow]==1.0&&rowUpper[iRow]==1.0) { bool goodRow=true; for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { int iColumn = column[j]; if (element[j]!=1.0||!solver1.isInteger(iColumn)||mark[iColumn]>=0||columnLower[iColumn]) { goodRow=false; break; } } if (goodRow) { // mark all for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { int iColumn = column[j]; mark[iColumn]=numberSOS; } numberSOS++; } } } std::cout<<numberSOS<<" SOS"<<std::endl; if (!numberSOS) return 0; CbcModel model(solver1); // Do sets and priorities CbcObject ** objects = new CbcObject * [numberSOS]; int numberIntegers = model.numberIntegers(); /* model may not have created objects If none then create */ if (!numberIntegers||!model.numberObjects()) { model.findIntegers(true); numberIntegers = model.numberIntegers(); } int * priority = new int[numberSOS]; // Set SOS priorities high CoinFillN(priority,numberSOS,1); // Set up SOS int * which = new int[numberColumns]; for (int iSOS =0;iSOS<numberSOS;iSOS++) { int n=0; for (iColumn=0;iColumn<numberColumns;iColumn++) { if (mark[iColumn]==iSOS) which[n++]=iColumn; } // NULL uses 0,1,2 .. as weights objects[iSOS]= new CbcNWay(&model,n,which,iSOS); } delete [] mark; delete [] which; model.addObjects(numberSOS,objects); for (iColumn=0;iColumn<numberSOS;iColumn++) delete objects[iColumn]; delete [] objects; model.passInPriorities(priority,true); delete [] priority; // If time is given then stop after that number of minutes if (argc>2) { int minutes = atoi(argv[2]); std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl; assert (minutes>=0); model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(1); double time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, " <<model.getNodeCount()<<" nodes with objective " <<model.getObjValue() <<(!model.status() ? " Finished" : " Not finished") <<std::endl; // Print solution - we can't get names from Osi! if (model.getMinimizationObjValue()<1.0e50) { int numberColumns = model.solver()->getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14); std::cout<<"--------------------------------------"<<std::endl; for (iColumn=0;iColumn<numberColumns;iColumn++) { double value=solution[iColumn]; if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl; } std::cout<<"--------------------------------------"<<std::endl; std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific); } return 0; }
// Returns type int CbcFathomDynamicProgramming::checkPossible(int allowableSize) { algorithm_ = -1; assert(model_->solver()); OsiSolverInterface * solver = model_->solver(); const CoinPackedMatrix * matrix = solver->getMatrixByCol(); int numberIntegers = model_->numberIntegers(); int numberColumns = solver->getNumCols(); size_ = 0; if (numberIntegers != numberColumns) return -1; // can't do dynamic programming const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * rowUpper = solver->getRowUpper(); int numberRows = model_->getNumRows(); int i; // First check columns to see if possible double * rhs = new double [numberRows]; CoinCopyN(rowUpper, numberRows, rhs); // Column copy const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); bool bad = false; /* It is just possible that we could say okay as variables may get fixed but seems unlikely */ for (i = 0; i < numberColumns; i++) { int j; double lowerValue = lower[i]; assert (lowerValue == floor(lowerValue)); for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; double value = element[j]; if (upper[i] > lowerValue && (value <= 0.0 || value != floor(value))) bad = true; if (lowerValue) rhs[iRow] -= lowerValue * value; } } // check possible (at present do not allow covering) int numberActive = 0; bool infeasible = false; bool saveBad = bad; for (i = 0; i < numberRows; i++) { if (rhs[i] < 0) infeasible = true; else if (rhs[i] > 1.0e5 || fabs(rhs[i] - floor(rhs[i] + 0.5)) > 1.0e-7) bad = true; else if (rhs[i] > 0.0) numberActive++; } if (bad || infeasible) { delete [] rhs; if (!saveBad && infeasible) return -2; else return -1; } // check size of array needed double size = 1.0; double check = COIN_INT_MAX; for (i = 0; i < numberRows; i++) { int n = static_cast<int> (floor(rhs[i] + 0.5)); if (n) { n++; // allow for 0,1... n if (numberActive != 1) { // power of 2 int iBit = 0; int k = n; k &= ~1; while (k) { iBit++; k &= ~(1 << iBit); } // See if exact power if (n != (1 << iBit)) { // round up to next power of 2 n = 1 << (iBit + 1); } size *= n; if (size >= check) break; } else { size = n; // just one constraint } } } // set size needed if (size >= check) size_ = COIN_INT_MAX; else size_ = static_cast<int> (size); int n01 = 0; int nbadcoeff = 0; // See if we can tighten bounds for (i = 0; i < numberColumns; i++) { int j; double lowerValue = lower[i]; double gap = upper[i] - lowerValue; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; double value = element[j]; if (value != 1.0) nbadcoeff++; if (gap*value > rhs[iRow] + 1.0e-8) gap = rhs[iRow] / value; } gap = lowerValue + floor(gap + 1.0e-7); if (gap < upper[i]) solver->setColUpper(i, gap); if (gap <= 1.0) n01++; } if (allowableSize && size_ <= allowableSize) { if (n01 == numberColumns && !nbadcoeff) algorithm_ = 0; // easiest else algorithm_ = 1; } if (allowableSize && size_ <= allowableSize) { numberActive_ = numberActive; indices_ = new int [numberActive_]; cost_ = new double [size_]; CoinFillN(cost_, size_, COIN_DBL_MAX); // but do nothing is okay cost_[0] = 0.0; back_ = new int[size_]; CoinFillN(back_, size_, -1); startBit_ = new int[numberActive_]; numberBits_ = new int[numberActive_]; lookup_ = new int [numberRows]; rhs_ = new int [numberActive_]; numberActive = 0; int kBit = 0; for (i = 0; i < numberRows; i++) { int n = static_cast<int> (floor(rhs[i] + 0.5)); if (n) { lookup_[i] = numberActive; rhs_[numberActive] = n; startBit_[numberActive] = kBit; n++; // allow for 0,1... n int iBit = 0; // power of 2 int k = n; k &= ~1; while (k) { iBit++; k &= ~(1 << iBit); } // See if exact power if (n != (1 << iBit)) { // round up to next power of 2 iBit++; } if (numberActive != 1) { n = 1 << iBit; size *= n; if (size >= check) break; } else { size = n; // just one constraint } numberBits_[numberActive++] = iBit; kBit += iBit; } else { lookup_[i] = -1; } } const double * rowLower = solver->getRowLower(); if (algorithm_ == 0) { // rhs 1 and coefficients 1 // Get first possible solution for printing target_ = -1; int needed = 0; int numberActive = 0; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { if (rowLower[i] == rowUpper[i]) { needed += 1 << numberActive; numberActive++; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { break; } } target_ = i; } else { coefficients_ = new int[numberActive_]; // If not too many general rhs then we can be more efficient numberNonOne_ = 0; for (i = 0; i < numberActive_; i++) { if (rhs_[i] != 1) numberNonOne_++; } if (numberNonOne_*2 < numberActive_) { // put rhs >1 every second int * permute = new int[numberActive_]; int * temp = new int[numberActive_]; // try different ways int k = 0; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0 && rhs_[newRow] > 1) { permute[newRow] = k; k += 2; } } // adjust so k points to last k -= 2; // and now rest int k1 = 1; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0 && rhs_[newRow] == 1) { permute[newRow] = k1; k1++; if (k1 <= k) k1++; } } for (i = 0; i < numberActive_; i++) { int put = permute[i]; temp[put] = rhs_[i]; } memcpy(rhs_, temp, numberActive_*sizeof(int)); for (i = 0; i < numberActive_; i++) { int put = permute[i]; temp[put] = numberBits_[i]; } memcpy(numberBits_, temp, numberActive_*sizeof(int)); k = 0; for (i = 0; i < numberActive_; i++) { startBit_[i] = k; k += numberBits_[i]; } for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) lookup_[i] = permute[newRow]; } delete [] permute; delete [] temp; // mark new method algorithm_ = 2; } // Get first possible solution for printing target_ = -1; int needed = 0; int * lower2 = new int[numberActive_]; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { int gap = static_cast<int> (rowUpper[i] - CoinMax(0.0, rowLower[i])); lower2[newRow] = rhs_[newRow] - gap; int numberBits = numberBits_[newRow]; int startBit = startBit_[newRow]; if (numberBits == 1 && !gap) { needed |= 1 << startBit; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { // this one may do bool good = true; for (int kk = 0; kk < numberActive_; kk++) { int numberBits = numberBits_[kk]; int startBit = startBit_[kk]; int size = 1 << numberBits; int start = 1 << startBit; int mask = start * (size - 1); int level = (i & mask) >> startBit; if (level < lower2[kk]) { good = false; break; } } if (good) { break; } } } delete [] lower2; target_ = i; }
void OsiVolSolverInterface::assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, char*& rowsen, double*& rowrhs, double*& rowrng) { gutsOfDestructor_(); const int rownum = matrix->getNumRows(); const int colnum = matrix->getNumCols(); maxNumcols_ = colnum; maxNumrows_ = rownum; if (matrix->isColOrdered()) { colMatrix_.swap(*matrix); colMatrixCurrent_ = true; rowMatrixCurrent_ = false; } else { rowMatrix_.swap(*matrix); rowMatrixCurrent_ = true; colMatrixCurrent_ = false; } delete matrix; matrix = 0; rowsense_ = rowsen; rowsen = 0; rhs_ = rowrhs; rowrhs = 0; rowrange_ = rowrng; rowrng = 0; colupper_ = colub; colub = 0; collower_ = collb; collb = 0; objcoeffs_ = obj; obj = 0; if (maxNumrows_ > 0) { if (!rowsense_) { rowsense_ = new char[maxNumrows_]; CoinFillN(rowsense_, rownum, 'G'); } if (!rhs_) { rhs_ = new double[maxNumrows_]; CoinFillN(rhs_, rownum, 0.0); } if (!rowrange_) { rowrange_ = new double[maxNumrows_]; CoinFillN(rowrange_, rownum, 0.0); } rowlower_ = new double[maxNumrows_]; rowupper_ = new double[maxNumrows_]; rowprice_ = new double[maxNumrows_]; lhs_ = new double[maxNumrows_]; // Set the initial dual solution CoinFillN(rowprice_, rownum, 0.0); convertSensesToBounds_(); } if (maxNumcols_ > 0) { if (!colupper_) { colupper_ = new double[maxNumcols_]; CoinFillN(colupper_, colnum, OsiVolInfinity); } if (!collower_) { collower_ = new double[maxNumcols_]; CoinFillN(collower_, colnum, -OsiVolInfinity); } if (!objcoeffs_) { objcoeffs_ = new double[maxNumcols_]; CoinFillN(objcoeffs_, colnum, -OsiVolInfinity); } colsol_ = new double[maxNumcols_]; int c; for ( c=0; c<colnum; c++ ) { if ( fabs(collower_[c]) < fabs(colupper_[c]) ) { colsol_[c] = collower_[c]; } else { colsol_[c] = colupper_[c]; } } rc_ = new double[maxNumcols_]; continuous_ = new bool[maxNumcols_]; } }