//------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpQuadraticObjective::ClpQuadraticObjective(const ClpQuadraticObjective &rhs, int type) : ClpObjective(rhs) { numberColumns_ = rhs.numberColumns_; numberExtendedColumns_ = rhs.numberExtendedColumns_; fullMatrix_ = rhs.fullMatrix_; if (rhs.objective_) { objective_ = new double[numberExtendedColumns_]; CoinMemcpyN(rhs.objective_, numberExtendedColumns_, objective_); } else { objective_ = NULL; } if (rhs.gradient_) { gradient_ = new double[numberExtendedColumns_]; CoinMemcpyN(rhs.gradient_, numberExtendedColumns_, gradient_); } else { gradient_ = NULL; } if (rhs.quadraticObjective_) { // see what type of matrix wanted if (type == 0) { // just copy quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_); } else if (type == 1) { // expand to full symmetric fullMatrix_ = true; const int *columnQuadratic1 = rhs.quadraticObjective_->getIndices(); const CoinBigIndex *columnQuadraticStart1 = rhs.quadraticObjective_->getVectorStarts(); const int *columnQuadraticLength1 = rhs.quadraticObjective_->getVectorLengths(); const double *quadraticElement1 = rhs.quadraticObjective_->getElements(); CoinBigIndex *columnQuadraticStart2 = new CoinBigIndex[numberExtendedColumns_ + 1]; int *columnQuadraticLength2 = new int[numberExtendedColumns_]; int iColumn; int numberColumns = rhs.quadraticObjective_->getNumCols(); int numberBelow = 0; int numberAbove = 0; int numberDiagonal = 0; CoinZeroN(columnQuadraticLength2, numberExtendedColumns_); for (iColumn = 0; iColumn < numberColumns; iColumn++) { for (CoinBigIndex j = columnQuadraticStart1[iColumn]; j < columnQuadraticStart1[iColumn] + columnQuadraticLength1[iColumn]; j++) { int jColumn = columnQuadratic1[j]; if (jColumn > iColumn) { numberBelow++; columnQuadraticLength2[jColumn]++; columnQuadraticLength2[iColumn]++; } else if (jColumn == iColumn) { numberDiagonal++; columnQuadraticLength2[iColumn]++; } else { numberAbove++; } } } if (numberAbove > 0) { if (numberAbove == numberBelow) { // already done quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_); delete[] columnQuadraticStart2; delete[] columnQuadraticLength2; } else { printf("number above = %d, number below = %d, error\n", numberAbove, numberBelow); abort(); } } else { int numberElements = numberDiagonal + 2 * numberBelow; int *columnQuadratic2 = new int[numberElements]; double *quadraticElement2 = new double[numberElements]; columnQuadraticStart2[0] = 0; numberElements = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int n = columnQuadraticLength2[iColumn]; columnQuadraticLength2[iColumn] = 0; numberElements += n; columnQuadraticStart2[iColumn + 1] = numberElements; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { for (CoinBigIndex j = columnQuadraticStart1[iColumn]; j < columnQuadraticStart1[iColumn] + columnQuadraticLength1[iColumn]; j++) { int jColumn = columnQuadratic1[j]; if (jColumn > iColumn) { // put in two places CoinBigIndex put = columnQuadraticLength2[jColumn] + columnQuadraticStart2[jColumn]; columnQuadraticLength2[jColumn]++; quadraticElement2[put] = quadraticElement1[j]; columnQuadratic2[put] = iColumn; put = columnQuadraticLength2[iColumn] + columnQuadraticStart2[iColumn]; columnQuadraticLength2[iColumn]++; quadraticElement2[put] = quadraticElement1[j]; columnQuadratic2[put] = jColumn; } else if (jColumn == iColumn) { CoinBigIndex put = columnQuadraticLength2[iColumn] + columnQuadraticStart2[iColumn]; columnQuadraticLength2[iColumn]++; quadraticElement2[put] = quadraticElement1[j]; columnQuadratic2[put] = iColumn; } else { abort(); } } } // Now create quadraticObjective_ = new CoinPackedMatrix(true, rhs.numberExtendedColumns_, rhs.numberExtendedColumns_, numberElements, quadraticElement2, columnQuadratic2, columnQuadraticStart2, columnQuadraticLength2, 0.0, 0.0); delete[] columnQuadraticStart2; delete[] columnQuadraticLength2; delete[] columnQuadratic2; delete[] quadraticElement2; } } else { fullMatrix_ = false; abort(); // code when needed } } else { quadraticObjective_ = NULL; } }
void CoinPresolveMatrix::setMatrix (const CoinPackedMatrix *mtx) { /* Check to make sure the matrix will fit and is column ordered. */ if (mtx->isColOrdered() == false) { throw CoinError("source matrix must be column ordered", "setMatrix","CoinPrePostsolveMatrix") ; } int numCols = mtx->getNumCols() ; if (numCols > ncols0_) { throw CoinError("source matrix exceeds allocated capacity", "setMatrix","CoinPrePostsolveMatrix") ; } /* Acquire the actual size, but allocate the matrix storage to the requested capacity. The column-major rep is part of the PrePostsolve object, the row-major rep belongs to the Presolve object. */ ncols_ = numCols ; nrows_ = mtx->getNumRows() ; nelems_ = mtx->getNumElements() ; bulk0_ = static_cast<CoinBigIndex> (bulkRatio_*nelems0_) ; if (mcstrt_ == 0) mcstrt_ = new CoinBigIndex [ncols0_+1] ; if (hincol_ == 0) hincol_ = new int [ncols0_+1] ; if (hrow_ == 0) hrow_ = new int [bulk0_] ; if (colels_ == 0) colels_ = new double [bulk0_] ; if (mrstrt_ == 0) mrstrt_ = new CoinBigIndex [nrows0_+1] ; if (hinrow_ == 0) hinrow_ = new int [nrows0_+1] ; if (hcol_ == 0) hcol_ = new int [bulk0_] ; if (rowels_ == 0) rowels_ = new double [bulk0_] ; /* Grab the corresponding vectors from the source matrix. */ const CoinBigIndex *src_mcstrt = mtx->getVectorStarts() ; const int *src_hincol = mtx->getVectorLengths() ; const double *src_colels = mtx->getElements() ; const int *src_hrow = mtx->getIndices() ; /* Bulk copy the column starts and lengths. */ CoinMemcpyN(src_mcstrt,mtx->getSizeVectorStarts(),mcstrt_) ; CoinMemcpyN(src_hincol,mtx->getSizeVectorLengths(),hincol_) ; /* Copy the coefficients column by column in case there are gaps between the columns in the bulk storage area. The assert is just in case the gaps are *really* big. */ assert(src_mcstrt[ncols_] <= bulk0_) ; int j; for ( j = 0 ; j < numCols ; j++) { int lenj = src_hincol[j] ; CoinBigIndex offset = mcstrt_[j] ; CoinMemcpyN(src_colels+offset,lenj,colels_+offset) ; CoinMemcpyN(src_hrow+offset,lenj,hrow_+offset) ; } /* Now make a row-major copy. Start by counting the number of coefficients in each row; we can do this directly in hinrow. Given the number of coefficients in a row, we know how to lay out the bulk storage area. */ CoinZeroN(hinrow_,nrows0_+1) ; for ( j = 0 ; j < ncols_ ; j++) { int *rowIndices = hrow_+mcstrt_[j] ; int lenj = hincol_[j] ; for (int k = 0 ; k < lenj ; k++) { int i = rowIndices[k] ; hinrow_[i]++ ; } } /* Initialize mrstrt[i] to the start of row i+1. As we drop each coefficient and column index into the bulk storage arrays, we'll decrement and store. When we're done, mrstrt[i] will point to the start of row i, as it should. */ int totalCoeffs = 0 ; int i; for ( i = 0 ; i < nrows_ ; i++) { totalCoeffs += hinrow_[i] ; mrstrt_[i] = totalCoeffs ; } mrstrt_[nrows_] = totalCoeffs ; for ( j = ncols_-1 ; j >= 0 ; j--) { int lenj = hincol_[j] ; double *colCoeffs = colels_+mcstrt_[j] ; int *rowIndices = hrow_+mcstrt_[j] ; for (int k = 0 ; k < lenj ; k++) { int ri; ri = rowIndices[k] ; double aij = colCoeffs[k] ; CoinBigIndex l = --mrstrt_[ri] ; rowels_[l] = aij ; hcol_[l] = j ; } } /* Now the support structures. The entry for original column j should start out as j; similarly for row i. originalColumn_ and originalRow_ belong to the PrePostsolve object. */ if (originalColumn_ == 0) originalColumn_ = new int [ncols0_] ; if (originalRow_ == 0) originalRow_ = new int [nrows0_] ; for ( j = 0 ; j < ncols0_ ; j++) originalColumn_[j] = j ; for ( i = 0 ; i < nrows0_ ; i++) originalRow_[i] = i ; /* We have help to set up the clink_ and rlink_ vectors (aids for matrix bulk storage management). clink_ and rlink_ belong to the Presolve object. Once this is done, it's safe to set mrstrt_[nrows_] and mcstrt_[ncols_] to the full size of the bulk storage area. */ if (clink_ == 0) clink_ = new presolvehlink [ncols0_+1] ; if (rlink_ == 0) rlink_ = new presolvehlink [nrows0_+1] ; presolve_make_memlists(/*mcstrt_,*/hincol_,clink_,ncols_) ; presolve_make_memlists(/*mrstrt_,*/hinrow_,rlink_,nrows_) ; mcstrt_[ncols_] = bulk0_ ; mrstrt_[nrows_] = bulk0_ ; /* No rows or columns have been changed just yet. colChanged_ and rowChanged_ belong to the Presolve object. */ if (colChanged_ == 0) colChanged_ = new unsigned char [ncols0_] ; CoinZeroN(colChanged_,ncols0_) ; if (rowChanged_ == 0) rowChanged_ = new unsigned char [nrows0_] ; CoinZeroN(rowChanged_,nrows0_) ; /* Finally, allocate the various *ToDo arrays. These are used to track the rows and columns which should be processed in a given round of presolve transforms. These belong to the Presolve object. Setting number*ToDo to 0 is all the initialization that's required here. */ rowsToDo_ = new int [nrows0_] ; numberRowsToDo_ = 0 ; nextRowsToDo_ = new int [nrows0_] ; numberNextRowsToDo_ = 0 ; colsToDo_ = new int [ncols0_] ; numberColsToDo_ = 0 ; nextColsToDo_ = new int [ncols0_] ; numberNextColsToDo_ = 0 ; initializeStuff(); return ; }
// fix variables interior says should be void ClpInterior::fixFixed(bool reallyFix) { // Arrays for change in columns and rhs CoinWorkDouble * columnChange = new CoinWorkDouble[numberColumns_]; CoinWorkDouble * rowChange = new CoinWorkDouble[numberRows_]; CoinZeroN(columnChange, numberColumns_); CoinZeroN(rowChange, numberRows_); matrix_->times(1.0, columnChange, rowChange); int i; CoinWorkDouble tolerance = primalTolerance(); for (i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < 1.0e20 || columnLower_[i] > -1.0e20) { if (columnUpper_[i] > columnLower_[i]) { if (fixedOrFree(i)) { if (columnActivity_[i] - columnLower_[i] < columnUpper_[i] - columnActivity_[i]) { CoinWorkDouble change = columnLower_[i] - columnActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) columnUpper_[i] = columnLower_[i]; columnChange[i] = change; columnActivity_[i] = columnLower_[i]; } } else { CoinWorkDouble change = columnUpper_[i] - columnActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) columnLower_[i] = columnUpper_[i]; columnChange[i] = change; columnActivity_[i] = columnUpper_[i]; } } } } } } CoinZeroN(rowChange, numberRows_); matrix_->times(1.0, columnChange, rowChange); // If makes mess of things then don't do CoinWorkDouble newSum = 0.0; for (i = 0; i < numberRows_; i++) { CoinWorkDouble value = rowActivity_[i] + rowChange[i]; if (value > rowUpper_[i] + tolerance) newSum += value - rowUpper_[i] - tolerance; else if (value < rowLower_[i] - tolerance) newSum -= value - rowLower_[i] + tolerance; } if (newSum > 1.0e-5 + 1.5 * sumPrimalInfeasibilities_) { // put back and skip changes for (i = 0; i < numberColumns_; i++) columnActivity_[i] -= columnChange[i]; } else { CoinZeroN(rowActivity_, numberRows_); matrix_->times(1.0, columnActivity_, rowActivity_); if (reallyFix) { for (i = 0; i < numberRows_; i++) { if (rowUpper_[i] < 1.0e20 || rowLower_[i] > -1.0e20) { if (rowUpper_[i] > rowLower_[i]) { if (fixedOrFree(i + numberColumns_)) { if (rowActivity_[i] - rowLower_[i] < rowUpper_[i] - rowActivity_[i]) { CoinWorkDouble change = rowLower_[i] - rowActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) rowUpper_[i] = rowLower_[i]; rowActivity_[i] = rowLower_[i]; } } else { CoinWorkDouble change = rowLower_[i] - rowActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) rowLower_[i] = rowUpper_[i]; rowActivity_[i] = rowUpper_[i]; } } } } } } } } delete [] rowChange; delete [] columnChange; }
/* This routine empties the columns for the list of fixed variables passed in (fcols, nfcols). As each coefficient a<ij> is set to 0, rlo<i> and rup<i> are adjusted accordingly. Note, however, that c<j> is not considered to be removed from the objective until column j is physically removed from the matrix (drop_empty_cols_action), so the correction to the objective is adjusted there. If a column solution is available, row activity (acts_) is adjusted. remove_fixed_action implicitly assumes that the value of the variable has already been forced within bounds. If this isn't true, the correction to acts_ will be wrong. See make_fixed_action if you need to force the value within bounds first. */ const remove_fixed_action* remove_fixed_action::presolve (CoinPresolveMatrix *prob, int *fcols, int nfcols, const CoinPresolveAction *next) { double *colels = prob->colels_; int *hrow = prob->hrow_; CoinBigIndex *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; double *rowels = prob->rowels_; int *hcol = prob->hcol_; CoinBigIndex *mrstrt = prob->mrstrt_; int *hinrow = prob->hinrow_; double *clo = prob->clo_; double *rlo = prob->rlo_; double *rup = prob->rup_; double *sol = prob->sol_; double *acts = prob->acts_; presolvehlink *clink = prob->clink_; presolvehlink *rlink = prob->rlink_; action *actions = new action[nfcols+1]; # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 # if PRESOLVE_DEBUG > 0 std::cout << "Entering remove_fixed_action::presolve; processing " << nfcols << " fixed columns." << std::endl ; # endif presolve_check_sol(prob) ; presolve_check_nbasic(prob) ; # endif /* Scan columns to be removed and total up the number of coefficients. */ int estsize=0; int ckc; for (ckc = 0 ; ckc < nfcols ; ckc++) { int j = fcols[ckc]; estsize += hincol[j]; } // Allocate arrays to hold coefficients and associated row indices double * els_action = new double[estsize]; int * rows_action = new int[estsize]; int actsize=0; // faster to do all deletes in row copy at once int nrows = prob->nrows_; CoinBigIndex * rstrt = new int[nrows+1]; CoinZeroN(rstrt,nrows); /* Open a loop to excise each column a<j>. The first thing to do is load the action entry with the index j, the value of x<j>, and the number of entries in a<j>. After we walk the column and tweak the row-major representation, we'll simply claim this column is empty by setting hincol[j] = 0. */ for (ckc = 0 ; ckc < nfcols ; ckc++) { int j = fcols[ckc]; double solj = clo[j]; CoinBigIndex kcs = mcstrt[j]; CoinBigIndex kce = kcs + hincol[j]; CoinBigIndex k; { action &f = actions[ckc]; f.col = j; f.sol = solj; f.start = actsize; } /* Now walk a<j>. For each row i with a coefficient a<ij> != 0: * save the coefficient and row index, * substitute the value of x<j>, adjusting the row bounds and lhs value accordingly, then * delete a<ij> from the row-major representation. * Finally: mark the row as changed and add it to the list of rows to be processed next. Then, for each remaining column in the row, put it on the list of columns to be processed. */ for (k = kcs ; k < kce ; k++) { int row = hrow[k]; double coeff = colels[k]; els_action[actsize]=coeff; rstrt[row]++; // increase counts rows_action[actsize++]=row; // Avoid reducing finite infinity. if (-PRESOLVE_INF < rlo[row]) rlo[row] -= solj*coeff; if (rup[row] < PRESOLVE_INF) rup[row] -= solj*coeff; if (sol) { acts[row] -= solj*coeff; } #define TRY2 #ifndef TRY2 presolve_delete_from_row(row,j,mrstrt,hinrow,hcol,rowels); if (hinrow[row] == 0) { PRESOLVE_REMOVE_LINK(rlink,row) ; } // mark unless already marked if (!prob->rowChanged(row)) { prob->addRow(row); CoinBigIndex krs = mrstrt[row]; CoinBigIndex kre = krs + hinrow[row]; for (CoinBigIndex k=krs; k<kre; k++) { int jcol = hcol[k]; prob->addCol(jcol); } } #endif } /* Remove the column's link from the linked list of columns, and declare it empty in the column-major representation. Link removal must execute even if the column is already of length 0 when it arrives. */ PRESOLVE_REMOVE_LINK(clink, j); hincol[j] = 0; } /* Set the actual end of the coefficient and row index arrays. */ actions[nfcols].start=actsize; # if PRESOLVE_SUMMARY printf("NFIXED: %d", nfcols); if (estsize-actsize > 0) { printf(", overalloc %d",estsize-actsize) ; } printf("\n") ; # endif // Now get columns by row int * column = new int[actsize]; int nel=0; int iRow; for (iRow=0; iRow<nrows; iRow++) { int n=rstrt[iRow]; rstrt[iRow]=nel; nel += n; } rstrt[nrows]=nel; for (ckc = 0 ; ckc < nfcols ; ckc++) { int kcs = actions[ckc].start; int j=actions[ckc].col; int kce; if (ckc<nfcols-1) kce = actions[ckc+1].start; else kce = actsize; for (int k=kcs; k<kce; k++) { int iRow = rows_action[k]; CoinBigIndex put = rstrt[iRow]; rstrt[iRow]++; column[put]=j; } } // Now do rows int ncols = prob->ncols_; char * mark = new char[ncols]; memset(mark,0,ncols); // rstrts are now one out i.e. rstrt[0] is end of row 0 nel=0; #ifdef TRY2 for (iRow=0; iRow<nrows; iRow++) { int k; for (k=nel; k<rstrt[iRow]; k++) { mark[column[k]]=1; } presolve_delete_many_from_major(iRow,mark,mrstrt,hinrow,hcol,rowels); #if PRESOLVE_DEBUG > 0 for (k = nel ; k < rstrt[iRow] ; k++) { assert(mark[column[k]] == 0) ; } #endif if (hinrow[iRow] == 0) { PRESOLVE_REMOVE_LINK(rlink,iRow) ; } // mark unless already marked if (!prob->rowChanged(iRow)) { prob->addRow(iRow); CoinBigIndex krs = mrstrt[iRow]; CoinBigIndex kre = krs + hinrow[iRow]; for (CoinBigIndex k=krs; k<kre; k++) { int jcol = hcol[k]; prob->addCol(jcol); } } nel=rstrt[iRow]; } #endif delete [] mark; delete [] column; delete [] rstrt; /* Create the postsolve object, link it at the head of the list of postsolve objects, and return a pointer. */ const remove_fixed_action *fixedActions = new remove_fixed_action(nfcols,actions,els_action,rows_action,next) ; # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 presolve_check_sol(prob) ; # if PRESOLVE_DEBUG > 0 std::cout << "Leaving remove_fixed_action::presolve." << std::endl ; # endif # endif return (fixedActions) ; }
/* Reintroduce the column (y) and doubleton row (irow) removed in presolve. Correct the other column (x) involved in the doubleton, update the solution, etc. A fair amount of complication arises because the presolve transform saves the shorter of x or y. Postsolve thus includes portions to restore either. */ void doubleton_action::postsolve(CoinPostsolveMatrix *prob) const { const action *const actions = actions_ ; const int nactions = nactions_ ; double *colels = prob->colels_ ; int *hrow = prob->hrow_ ; CoinBigIndex *mcstrt = prob->mcstrt_ ; int *hincol = prob->hincol_ ; int *link = prob->link_ ; double *clo = prob->clo_ ; double *cup = prob->cup_ ; double *rlo = prob->rlo_ ; double *rup = prob->rup_ ; double *dcost = prob->cost_ ; double *sol = prob->sol_ ; double *acts = prob->acts_ ; double *rowduals = prob->rowduals_ ; double *rcosts = prob->rcosts_ ; unsigned char *colstat = prob->colstat_ ; unsigned char *rowstat = prob->rowstat_ ; const double maxmin = prob->maxmin_ ; CoinBigIndex &free_list = prob->free_list_ ; const double ztolzb = prob->ztolzb_ ; const double ztoldj = prob->ztoldj_ ; const double ztolzero = 1.0e-12 ; int nrows = prob->nrows_ ; // Arrays to rebuild the unsaved column. int *index1 = new int[nrows] ; double *element1 = new double[nrows] ; CoinZeroN(element1,nrows) ; # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 char *cdone = prob->cdone_ ; char *rdone = prob->rdone_ ; presolve_check_threads(prob) ; presolve_check_sol(prob,2,2,2) ; presolve_check_nbasic(prob) ; presolve_check_reduced_costs(prob) ; # if PRESOLVE_DEBUG > 0 std::cout << "Entering doubleton_action::postsolve, " << nactions << " transforms to undo." << std::endl ; # endif # endif /* The outer loop: step through the doubletons in this array of actions. The first activity is to unpack the doubleton. */ for (const action *f = &actions[nactions-1] ; actions <= f ; f--) { const int irow = f->row ; const double lo0 = f->clox ; const double up0 = f->cupx ; const double coeffx = f->coeffx ; const double coeffy = f->coeffy ; const int jcolx = f->icolx ; const int jcoly = f->icoly ; const double rhs = f->rlo ; # if PRESOLVE_DEBUG > 2 std::cout << std::endl << " restoring doubleton " << irow << ", elim x(" << jcoly << "), kept x(" << jcolx << "); stored col " ; if (f->ncoly) std::cout << jcoly ; else std::cout << jcolx ; std::cout << "." << std::endl ; std::cout << " x(" << jcolx << ") " << prob->columnStatusString(jcolx) << " " << clo[jcolx] << " <= " << sol[jcolx] << " <= " << cup[jcolx] << "; cj " << f->costx << " dj " << rcosts[jcolx] << "." << std::endl ; # endif /* jcolx is in the problem (for whatever reason), and the doubleton row (irow) and column (jcoly) have only been processed by empty row/column postsolve (i.e., reintroduced with length 0). */ PRESOLVEASSERT(cdone[jcolx] && rdone[irow] == DROP_ROW) ; PRESOLVEASSERT(cdone[jcoly] == DROP_COL) ; /* Restore bounds for doubleton row, bounds and objective coefficient for x, objective for y. Original comment: restoration of rlo and rup likely isn't necessary. */ rlo[irow] = f->rlo ; rup[irow] = f->rlo ; clo[jcolx] = lo0 ; cup[jcolx] = up0 ; dcost[jcolx] = f->costx ; dcost[jcoly] = f->costy ; /* Set primal solution for y (including status) and row activity for the doubleton row. The motivation (up in presolve) for wanting coeffx < coeffy is to avoid inflation into sol[y]. Since this is a (satisfied) equality, activity is the rhs value and the logical is nonbasic. */ const double diffy = rhs-coeffx*sol[jcolx] ; if (fabs(diffy) < ztolzero) sol[jcoly] = 0 ; else sol[jcoly] = diffy/coeffy ; acts[irow] = rhs ; if (rowstat) prob->setRowStatus(irow,CoinPrePostsolveMatrix::atLowerBound) ; # if PRESOLVE_DEBUG > 2 /* Original comment: I've forgotten what this is about We have sol[y] = (rhs - coeffx*sol[x])/coeffy. As best I can figure, the original check here tested for the possibility of loss of significant digits through cancellation, followed by inflation if coeffy is small. The hazard is clear enough, but the test was puzzling. Overly complicated and it generated false warnings for the common case of sol[y] a clean zero. Replaced with something that I hope is more useful. The tolerances are, sad to say, completely arbitrary. -- lh, 121106 -- */ if ((fabs(diffy) < 1.0e-6) && (fabs(diffy) >= ztolzero) && (fabs(coeffy) < 1.0e-3)) std::cout << " loss of significance? rhs " << rhs << " (coeffx*sol[jcolx])" << (coeffx*sol[jcolx]) << " diff " << diffy << "." << std::endl ; # endif /* Time to get into the correction/restoration of coefficients for columns x and y, with attendant correction of row bounds and activities. Accumulate partial reduced costs (missing the contribution from the doubleton row) so that we can eventually calculate a dual for the doubleton row. */ double djy = maxmin*dcost[jcoly] ; double djx = maxmin*dcost[jcolx] ; /* We saved column y in the action, so we'll use it to reconstruct column x. There are two aspects: correction of existing x coefficients, and fill in. Given coeffx'[k] = coeffx[k]+coeffy[k]*coeff_factor we have coeffx[k] = coeffx'[k]-coeffy[k]*coeff_factor where coeff_factor = -coeffx[dblton]/coeffy[dblton]. Keep in mind that the major vector stored in the action does not include the coefficient from the doubleton row --- the doubleton coefficients are held in coeffx and coeffy. */ if (f->ncoly) { int ncoly = f->ncoly-1 ; int *indy = reinterpret_cast<int *>(f->colel+ncoly) ; /* Rebuild a threaded column y, starting with the end of the thread and working back to the beginning. In the process, accumulate corrections to column x in element1 and index1. Fix row bounds and activity as we go (add back the constant correction removed in presolve), and accumulate contributions to the reduced cost for y. Don't tweak finite infinity. The PRESOLVEASSERT says this row should already be present. */ int ystart = NO_LINK ; int nX = 0 ; for (int kcol = 0 ; kcol < ncoly ; ++kcol) { const int i = indy[kcol] ; PRESOLVEASSERT(rdone[i]) ; double yValue = f->colel[kcol] ; if (-PRESOLVE_INF < rlo[i]) rlo[i] += (yValue*rhs)/coeffy ; if (rup[i] < PRESOLVE_INF) rup[i] += (yValue*rhs)/coeffy ; acts[i] += (yValue*rhs)/coeffy ; djy -= rowduals[i]*yValue ; /* Link the coefficient into column y: Acquire the first free slot in the bulk arrays and store the row index and coefficient. Then link the slot in front of coefficients we've already processed. */ const CoinBigIndex kfree = free_list ; assert(kfree >= 0 && kfree < prob->bulk0_) ; free_list = link[free_list] ; hrow[kfree] = i ; colels[kfree] = yValue ; link[kfree] = ystart ; ystart = kfree ; # if PRESOLVE_DEBUG > 4 std::cout << " link y " << kfree << " row " << i << " coeff " << yValue << " dual " << rowduals[i] << std::endl ; # endif /* Calculate and store the correction to the x coefficient. */ yValue = (yValue*coeffx)/coeffy ; element1[i] = yValue ; index1[nX++] = i ; } # if PRESOLVE_CONSISTENCY > 0 presolve_check_free_list(prob) ; # endif /* Handle the coefficients of the doubleton row. Insert coeffy, coeffx. */ const CoinBigIndex kfree = free_list ; assert(kfree >= 0 && kfree < prob->bulk0_) ; free_list = link[free_list] ; hrow[kfree] = irow ; colels[kfree] = coeffy ; link[kfree] = ystart ; ystart = kfree ; # if PRESOLVE_DEBUG > 4 std::cout << " link y " << kfree << " row " << irow << " coeff " << coeffy << " dual n/a" << std::endl ; # endif element1[irow] = coeffx ; index1[nX++] = irow ; /* Attach the threaded column y to mcstrt and record the length. */ mcstrt[jcoly] = ystart ; hincol[jcoly] = f->ncoly ; /* Now integrate the corrections to column x. Scan the column and correct the existing entries. The correction could cancel the existing coefficient and we don't want to leave an explicit zero. In this case, relink the column around it. The freed slot is linked at the beginning of the free list. */ CoinBigIndex kcs = mcstrt[jcolx] ; CoinBigIndex last_nonzero = NO_LINK ; int numberInColumn = hincol[jcolx] ; const int numberToDo = numberInColumn ; for (int kcol = 0 ; kcol < numberToDo ; ++kcol) { const int i = hrow[kcs] ; assert(i >= 0 && i < nrows && i != irow) ; double value = colels[kcs]+element1[i] ; element1[i] = 0.0 ; if (fabs(value) >= 1.0e-15) { colels[kcs] = value ; last_nonzero = kcs ; kcs = link[kcs] ; djx -= rowduals[i]*value ; # if PRESOLVE_DEBUG > 4 std::cout << " link x " << last_nonzero << " row " << i << " coeff " << value << " dual " << rowduals[i] << std::endl ; # endif } else { # if PRESOLVE_DEBUG > 4 std::cout << " link x skipped row " << i << " dual " << rowduals[i] << std::endl ; # endif numberInColumn-- ; // add to free list int nextk = link[kcs] ; assert(free_list >= 0) ; link[kcs] = free_list ; free_list = kcs ; assert(kcs >= 0) ; kcs = nextk ; if (last_nonzero != NO_LINK) link[last_nonzero] = kcs ; else mcstrt[jcolx] = kcs ; } } if (last_nonzero != NO_LINK) link[last_nonzero] = NO_LINK ; /* We've dealt with the existing nonzeros in column x. Any remaining nonzeros in element1 will be fill in, which we insert at the beginning of the column. */ for (int kcol = 0 ; kcol < nX ; kcol++) { const int i = index1[kcol] ; double xValue = element1[i] ; element1[i] = 0.0 ; if (fabs(xValue) >= 1.0e-15) { if (i != irow) djx -= rowduals[i]*xValue ; numberInColumn++ ; CoinBigIndex kfree = free_list ; assert(kfree >= 0 && kfree < prob->bulk0_) ; free_list = link[free_list] ; hrow[kfree] = i ; PRESOLVEASSERT(rdone[hrow[kfree]] || (hrow[kfree] == irow)) ; colels[kfree] = xValue ; link[kfree] = mcstrt[jcolx] ; mcstrt[jcolx] = kfree ; # if PRESOLVE_DEBUG > 4 std::cout << " link x " << kfree << " row " << i << " coeff " << xValue << " dual " ; if (i != irow) std::cout << rowduals[i] ; else std::cout << "n/a" ; std::cout << std::endl ; # endif } } # if PRESOLVE_CONSISTENCY > 0 presolve_check_free_list(prob) ; # endif /* Whew! Set the column length and we're done. */ assert(numberInColumn) ; hincol[jcolx] = numberInColumn ; } else { /* Of course, we could have saved column x in the action. Now we need to regenerate coefficients of column y. Given coeffx'[k] = coeffx[k]+coeffy[k]*coeff_factor we have coeffy[k] = (coeffx'[k]-coeffx[k])*(1/coeff_factor) where coeff_factor = -coeffx[dblton]/coeffy[dblton]. */ const int ncolx = f->ncolx-1 ; int *indx = reinterpret_cast<int *> (f->colel+ncolx) ; /* Scan existing column x to find the end. While we're at it, accumulate part of the new y coefficients in index1 and element1. */ CoinBigIndex kcs = mcstrt[jcolx] ; int nX = 0 ; for (int kcol = 0 ; kcol < hincol[jcolx]-1 ; ++kcol) { if (colels[kcs]) { const int i = hrow[kcs] ; index1[nX++] = i ; element1[i] = -(colels[kcs]*coeffy)/coeffx ; } kcs = link[kcs] ; } if (colels[kcs]) { const int i = hrow[kcs] ; index1[nX++] = i ; element1[i] = -(colels[kcs]*coeffy)/coeffx ; } /* Replace column x with the the original column x held in the doubleton action (recall that this column does not include coeffx). We first move column x to the free list, then thread a column with the original coefficients, back to front. While we're at it, add the second part of the y coefficients to index1 and element1. */ link[kcs] = free_list ; free_list = mcstrt[jcolx] ; int xstart = NO_LINK ; for (int kcol = 0 ; kcol < ncolx ; ++kcol) { const int i = indx[kcol] ; PRESOLVEASSERT(rdone[i] && i != irow) ; double xValue = f->colel[kcol] ; CoinBigIndex k = free_list ; assert(k >= 0 && k < prob->bulk0_) ; free_list = link[free_list] ; hrow[k] = i ; colels[k] = xValue ; link[k] = xstart ; xstart = k ; djx -= rowduals[i]*xValue ; xValue = (xValue*coeffy)/coeffx ; if (!element1[i]) { element1[i] = xValue ; index1[nX++] = i ; } else { element1[i] += xValue ; } } # if PRESOLVE_CONSISTENCY > 0 presolve_check_free_list(prob) ; # endif /* The same, for the doubleton row. */ { double xValue = coeffx ; CoinBigIndex k = free_list ; assert(k >= 0 && k < prob->bulk0_) ; free_list = link[free_list] ; hrow[k] = irow ; colels[k] = xValue ; link[k] = xstart ; xstart = k ; element1[irow] = coeffy ; index1[nX++] = irow ; } /* Link the new column x to mcstrt and set the length. */ mcstrt[jcolx] = xstart ; hincol[jcolx] = f->ncolx ; /* Now get to work building a threaded column y from the nonzeros in element1. As before, build the thread in reverse. */ int ystart = NO_LINK ; int leny = 0 ; for (int kcol = 0 ; kcol < nX ; kcol++) { const int i = index1[kcol] ; PRESOLVEASSERT(rdone[i] || i == irow) ; double yValue = element1[i] ; element1[i] = 0.0 ; if (fabs(yValue) >= ztolzero) { leny++ ; CoinBigIndex k = free_list ; assert(k >= 0 && k < prob->bulk0_) ; free_list = link[free_list] ; hrow[k] = i ; colels[k] = yValue ; link[k] = ystart ; ystart = k ; } } # if PRESOLVE_CONSISTENCY > 0 presolve_check_free_list(prob) ; # endif /* Tidy up --- link the new column into mcstrt and set the length. */ mcstrt[jcoly] = ystart ; assert(leny) ; hincol[jcoly] = leny ; /* Now that we have the original y, we can scan it and do the corrections to the row bounds and activity, and get a start on a reduced cost for y. */ kcs = mcstrt[jcoly] ; const int ny = hincol[jcoly] ; for (int kcol = 0 ; kcol < ny ; ++kcol) { const int row = hrow[kcs] ; const double coeff = colels[kcs] ; kcs = link[kcs] ; if (row != irow) { // undo elim_doubleton(1) if (-PRESOLVE_INF < rlo[row]) rlo[row] += (coeff*rhs)/coeffy ; // undo elim_doubleton(2) if (rup[row] < PRESOLVE_INF) rup[row] += (coeff*rhs)/coeffy ; acts[row] += (coeff*rhs)/coeffy ; djy -= rowduals[row]*coeff ; } } } # if PRESOLVE_DEBUG > 2 /* Sanity checks. The doubleton coefficients should be linked in the first position of the each column (for no good reason except that it makes it much easier to write these checks). */ # if PRESOLVE_DEBUG > 4 std::cout << " kept: saved " << jcolx << " " << coeffx << ", reconstructed " << hrow[mcstrt[jcolx]] << " " << colels[mcstrt[jcolx]] << "." << std::endl ; std::cout << " elim: saved " << jcoly << " " << coeffy << ", reconstructed " << hrow[mcstrt[jcoly]] << " " << colels[mcstrt[jcoly]] << "." << std::endl ; # endif assert((coeffx == colels[mcstrt[jcolx]]) && (coeffy == colels[mcstrt[jcoly]])) ; # endif /* Time to calculate a dual for the doubleton row, and settle the status of x and y. Ideally, we'll leave x at whatever nonbasic status it currently has and make y basic. There's a potential problem, however: Remember that we transferred bounds from y to x when we eliminated y. If those bounds were tighter than x's original bounds, we may not be able to maintain x at its present status, or even as nonbasic. We'll make two claims here: * If the dual value for the doubleton row is chosen to keep the reduced cost djx of col x at its prior value, then the reduced cost djy of col y will be 0. (Crank through the linear algebra to convince yourself.) * If the bounds on x have loosened, then it must be possible to make y nonbasic, because we've transferred the tight bound back to y. (Yeah, I'm waving my hands. But it sounds good. -- lh, 040907 --) So ... if we can maintain x nonbasic, then we need to set y basic, which means we should calculate rowduals[dblton] so that rcost[jcoly] == 0. We may need to change the status of x (an artifact of loosening a bound when x was previously a fixed variable). If we need to push x into the basis, then we calculate rowduals[dblton] so that rcost[jcolx] == 0 and make y nonbasic. */ # if PRESOLVE_DEBUG > 2 std::cout << " pre status: x(" << jcolx << ") " << prob->columnStatusString(jcolx) << " " << clo[jcolx] << " <= " << sol[jcolx] << " <= " << cup[jcolx] << ", cj " << dcost[jcolx] << ", dj " << djx << "." << std::endl ; std::cout << " pre status: x(" << jcoly << ") " << clo[jcoly] << " <= " << sol[jcoly] << " <= " << cup[jcoly] << ", cj " << dcost[jcoly] << ", dj " << djy << "." << std::endl ; # endif if (colstat) { bool basicx = prob->columnIsBasic(jcolx) ; bool nblbxok = (fabs(lo0 - sol[jcolx]) < ztolzb) && (rcosts[jcolx] >= -ztoldj) ; bool nbubxok = (fabs(up0 - sol[jcolx]) < ztolzb) && (rcosts[jcolx] <= ztoldj) ; if (basicx || nblbxok || nbubxok) { if (!basicx) { if (nblbxok) { prob->setColumnStatus(jcolx, CoinPrePostsolveMatrix::atLowerBound) ; } else if (nbubxok) { prob->setColumnStatus(jcolx, CoinPrePostsolveMatrix::atUpperBound) ; } } prob->setColumnStatus(jcoly,CoinPrePostsolveMatrix::basic) ; rowduals[irow] = djy/coeffy ; rcosts[jcolx] = djx-rowduals[irow]*coeffx ; rcosts[jcoly] = 0.0 ; } else { prob->setColumnStatus(jcolx,CoinPrePostsolveMatrix::basic) ; prob->setColumnStatusUsingValue(jcoly) ; rowduals[irow] = djx/coeffx ; rcosts[jcoly] = djy-rowduals[irow]*coeffy ; rcosts[jcolx] = 0.0 ; } # if PRESOLVE_DEBUG > 2 std::cout << " post status: " << irow << " dual " << rowduals[irow] << " rhs " << rlo[irow] << std::endl ; std::cout << " post status: x(" << jcolx << ") " << prob->columnStatusString(jcolx) << " " << clo[jcolx] << " <= " << sol[jcolx] << " <= " << cup[jcolx] << ", cj " << dcost[jcolx] << ", dj = " << rcosts[jcolx] << "." << std::endl ; std::cout << " post status: x(" << jcoly << ") " << prob->columnStatusString(jcoly) << " " << clo[jcoly] << " <= " << sol[jcoly] << " <= " << cup[jcoly] << ", cj " << dcost[jcoly] << ", dj " << rcosts[jcoly] << "." << std::endl ; /* These asserts are valid but need a scaled tolerance to work well over a range of problems. Occasionally useful for a hard stop while debugging. assert(!prob->columnIsBasic(jcolx) || (fabs(rcosts[jcolx]) < 1.0e-5)) ; assert(!prob->columnIsBasic(jcoly) || (fabs(rcosts[jcoly]) < 1.0e-5)) ; */ # endif } else { // No status array // this is the coefficient we need to force col y's reduced cost to 0.0 ; // for example, this is obviously true if y is a singleton column rowduals[irow] = djy/coeffy ; rcosts[jcoly] = 0.0 ; } # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 /* Mark the column and row as processed by doubleton action. Then check integrity of the threaded matrix. */ cdone[jcoly] = DOUBLETON ; rdone[irow] = DOUBLETON ; presolve_check_threads(prob) ; # endif # if PRESOLVE_DEBUG > 0 /* Confirm accuracy of reduced cost for columns x and y. */ { CoinBigIndex k = mcstrt[jcolx] ; const int nx = hincol[jcolx] ; double dj = maxmin*dcost[jcolx] ; for (int kcol = 0 ; kcol < nx ; ++kcol) { const int row = hrow[k] ; const double coeff = colels[k] ; k = link[k] ; dj -= rowduals[row]*coeff ; } if (!(fabs(rcosts[jcolx]-dj) < 100*ZTOLDP)) printf("BAD DOUBLE X DJ: %d %d %g %g\n", irow,jcolx,rcosts[jcolx],dj) ; rcosts[jcolx] = dj ; } { CoinBigIndex k = mcstrt[jcoly] ; const int ny = hincol[jcoly] ; double dj = maxmin*dcost[jcoly] ; for (int kcol = 0 ; kcol < ny ; ++kcol) { const int row = hrow[k] ; const double coeff = colels[k] ; k = link[k] ; dj -= rowduals[row]*coeff ; } if (!(fabs(rcosts[jcoly]-dj) < 100*ZTOLDP)) printf("BAD DOUBLE Y DJ: %d %d %g %g\n", irow,jcoly,rcosts[jcoly],dj) ; rcosts[jcoly] = dj ; } # endif } /* Done at last. Delete the scratch arrays. */ delete [] index1 ; delete [] element1 ; # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 presolve_check_sol(prob,2,2,2) ; presolve_check_nbasic(prob) ; presolve_check_reduced_costs(prob) ; # if PRESOLVE_DEBUG > 0 std::cout << "Leaving doubleton_action::postsolve." << std::endl ; # endif # endif }
OsiSolverInterface * CglTreeProbingInfo::analyze(const OsiSolverInterface & si,int createSolver, int numberExtraCliques,const int * starts, const CliqueEntry * entries,const char * type) { if (!createSolver) return NULL; convert(); if (!numberIntegers_) return NULL; bool alwaysDo=false; if (numberExtraCliques<0) { alwaysDo=true; numberExtraCliques=0; } bool printit=false; int numberCliques=0; int numberEntries=0; int * cliqueStart = NULL; CliqueEntry * entry = NULL; char * cliqueType=NULL; int * whichP = new int [numberIntegers_]; int * whichM = new int [numberIntegers_]; int *whichClique=NULL; int numberRows=si.getNumRows(); int numberMatrixCliques=0; const CoinPackedMatrix * rowCopy = si.getMatrixByRow(); assert(numberRows&&si.getNumCols()); int iRow; const int * column = rowCopy->getIndices(); const double * elementByRow = rowCopy->getElements(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); const double * lower = si.getColLower(); const double * upper = si.getColUpper(); const double * rowLower = si.getRowLower(); const double * rowUpper = si.getRowUpper(); for (int iPass=0;iPass<2;iPass++) { if (iPass) { int numberExtraEntries=0; if (numberExtraCliques) numberExtraEntries = starts[numberExtraCliques]; cliqueStart = new int [numberCliques+1+numberExtraCliques]; cliqueStart[0]=0; entry = new CliqueEntry [numberEntries+numberExtraEntries]; cliqueType = new char [numberCliques+numberExtraCliques]; whichClique = new int [numberEntries+numberExtraEntries]; numberCliques=0; numberEntries=0; } #if 1 for (iRow=0;iRow<numberRows;iRow++) { int numberP1=0, numberM1=0; int numberTotal=0; CoinBigIndex j; double upperValue=rowUpper[iRow]; double lowerValue=rowLower[iRow]; bool good=true; for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { int iColumn = column[j]; double value = elementByRow[j]; if (upper[iColumn]-lower[iColumn]<1.0e-8) { // fixed upperValue -= lower[iColumn]*value; lowerValue -= lower[iColumn]*value; continue; } else if (backward_[iColumn]<0) { good = false; break; } else { iColumn = backward_[iColumn]; numberTotal++; } if (fabs(value)!=1.0) { good=false; } else if (value>0.0) { assert (numberP1<numberIntegers_); whichP[numberP1++]=iColumn;; } else { assert (numberM1<numberIntegers_); whichM[numberM1++]=iColumn; } } int iUpper = static_cast<int> (floor(upperValue+1.0e-5)); int iLower = static_cast<int> (ceil(lowerValue-1.0e-5)); int state=0; if (upperValue<1.0e6) { if (iUpper==1-numberM1) state=1; else if (iUpper==-numberM1) state=2; else if (iUpper<-numberM1) state=3; if (fabs(static_cast<double> (iUpper)-upperValue)>1.0e-9) state =-1; } if (!state&&lowerValue>-1.0e6) { if (-iLower==1-numberP1) state=-1; else if (-iLower==-numberP1) state=-2; else if (-iLower<-numberP1) state=-3; if (fabs(static_cast<double> (iLower)-lowerValue)>1.0e-9) state =-1; } if (numberP1+numberM1<2) state=-1; if (good&&state>0) { if (abs(state)==3) { // infeasible printf("FFF Infeasible\n");; //feasible=false; break; } else if (abs(state)==2) { // we can fix all //numberFixed += numberP1+numberM1; printf("FFF can fix %d\n",numberP1+numberM1); } else { for (j=0;j<numberP1;j++) { int iColumn = whichP[j]; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; } for (j=0;j<numberM1;j++) { int iColumn = whichM[j]; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; } if (iPass) { if (iLower!=iUpper) { // slack cliqueType[numberCliques]='S'; } else { cliqueType[numberCliques]='E'; } cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } } } #endif if (numberExtraCliques) { int numberExtraEntries = starts[numberExtraCliques]; memcpy(entry+numberEntries,entries,numberExtraEntries*sizeof(CliqueEntry)); for (int iClique=0;iClique<numberExtraCliques;iClique++) { cliqueType[numberCliques] = type[iClique]; numberCliques++; cliqueStart[numberCliques]=starts[iClique]+numberEntries; } numberEntries += numberExtraEntries; } numberMatrixCliques=numberCliques; //int size = toZero_[numberIntegers_]; //char * used = new char [size]; //memset(used,0,size); // find two cliques int nFix=0; for (int iColumn=0;iColumn<static_cast<int> (numberIntegers_);iColumn++) { int j; for ( j=toZero_[iColumn];j<toOne_[iColumn];j++) { int jColumn=sequenceInCliqueEntry(fixEntry_[j]); // just look at ones beore (this also skips non 0-1) if (jColumn<iColumn) { int k; for ( k=toZero_[jColumn];k<toOne_[jColumn];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); //0-0 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } else { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 1 } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn is 1 } else { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn=iColumn } } } } for ( k=toOne_[jColumn];k<toZero_[jColumn+1];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; //iColumn is 1 } else { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn+jcolumn=1 } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); // 0-1 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } else { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 0 } } } } } } for ( j=toOne_[iColumn];j<toZero_[iColumn+1];j++) { int jColumn=sequenceInCliqueEntry(fixEntry_[j]); if (jColumn<iColumn) { int k; for ( k=toZero_[jColumn];k<toOne_[jColumn];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to one and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 1 } else { if (printit&&!iPass) printf("%d to one implies %d to one and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); // 1-0 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn+jColumn=1 } else { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn is 0 } } } } for ( k=toOne_[jColumn];k<toZero_[jColumn+1];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to one and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn == jColumn } else { if (printit&&!iPass) printf("%d to one implies %d to one and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn is 0 } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 0 } else { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); // 1-1 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } } } } } } } if (!iPass) printf("%d cliques and %d fixed (%d already from matrix))\n", numberCliques-numberMatrixCliques,nFix,numberMatrixCliques); } int iClique; outDupsEtc(numberIntegers_, numberCliques, numberMatrixCliques, cliqueStart, cliqueType, entry, -1, printit ? 2 : 1); printf("%d matrix cliques and %d found by probing\n",numberMatrixCliques,numberCliques-numberMatrixCliques); int * zeroStart = new int [numberIntegers_+1]; int * oneStart = new int [numberIntegers_]; int * zeroCount = new int [numberIntegers_]; int * oneCount = new int [numberIntegers_]; char * mark = new char [numberIntegers_]; memset(mark,0,numberIntegers_); int nStrengthen=-1; int iPass=0; while (nStrengthen&&iPass<20) { iPass++; int numberLastTime = numberCliques; int * count = new int [numberCliques]; int i,iColumn; for (i=0;i<numberCliques;i++) { count[i]=0; } int * whichCount = new int [numberCliques]; CoinZeroN(zeroCount,numberIntegers_); CoinZeroN(oneCount,numberIntegers_); for (iClique=0;iClique<numberCliques;iClique++) { for (int j=cliqueStart[iClique];j<cliqueStart[iClique+1];j++) { int iColumn = static_cast<int> (sequenceInCliqueEntry(entry[j])); if (oneFixesInCliqueEntry(entry[j])) { oneCount[iColumn]++; } else { zeroCount[iColumn]++; } } } int j; zeroStart[0]=0; cliqueStart[0]=0; for (j=0;j<numberIntegers_;j++) { int n; n=zeroCount[j]; zeroCount[j]=0; oneStart[j] = zeroStart[j]+n; n=oneCount[j]; oneCount[j]=0; zeroStart[j+1] = oneStart[j]+n; } for (iClique=0;iClique<numberCliques;iClique++) { for (int j=cliqueStart[iClique];j<cliqueStart[iClique+1];j++) { int iColumn = static_cast<int> (sequenceInCliqueEntry(entry[j])); if (oneFixesInCliqueEntry(entry[j])) { int k=oneCount[iColumn]; oneCount[iColumn]++; int put = oneStart[iColumn]+k; whichClique[put]=iClique; } else { int k=zeroCount[iColumn]; zeroCount[iColumn]++; int put = zeroStart[iColumn]+k; whichClique[put]=iClique; } } } nStrengthen=0; int numberEntries=cliqueStart[numberCliques]; int maximumEntries=numberEntries; int maximumCliques=numberCliques; for (iColumn=0;iColumn<numberIntegers_;iColumn++) { int i; int n; int nCount=0; n=0; for (i=zeroStart[iColumn];i<oneStart[iColumn];i++) { int jClique = whichClique[i]; //if (jClique<numberMatrixCliques) //continue; int j = cliqueStart[jClique]; //assert (cliqueStart[jClique+1]==j+2); for (;j<cliqueStart[jClique+1];j++) { CliqueEntry eJ = entry[j]; int jColumn = sequenceInCliqueEntry(eJ); if (jColumn>iColumn&&!mark[jColumn]) { mark[jColumn]=1; whichP[n++]=jColumn; assert (n<numberIntegers_); if (oneFixesInCliqueEntry(eJ)) { for (int k=oneStart[jColumn];k<zeroStart[jColumn+1];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } else { for (int k=zeroStart[jColumn];k<oneStart[jColumn];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } } } } std::sort(whichP,whichP+n); for (i=0;i<nCount;i++) { int jClique = whichCount[i]; int jCount = count[jClique]; count[jClique]=0; if (jCount==cliqueStart[jClique+1]-cliqueStart[jClique]) { printf("Zero can extend %d [ ",jClique); for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i])); printf("] by %d(0)\n",iColumn); nStrengthen++; if (numberEntries+jCount+1>maximumEntries) { maximumEntries = CoinMax(numberEntries+jCount+1,(maximumEntries*12)/10+100); CliqueEntry * temp = new CliqueEntry [maximumEntries]; memcpy(temp,entry,numberEntries*sizeof(CliqueEntry)); delete [] entry; entry=temp; int * tempI = new int [maximumEntries]; memcpy(tempI,whichClique,numberEntries*sizeof(int)); delete [] whichClique; whichClique=tempI; } if (numberCliques==maximumCliques) { maximumCliques = (maximumCliques*12)/10+100; int * temp = new int [maximumCliques+1]; memcpy(temp,cliqueStart,(numberCliques+1)*sizeof(int)); delete [] cliqueStart; cliqueStart=temp; char * tempT = new char [maximumCliques]; memcpy(tempT,cliqueType,numberCliques); delete [] cliqueType; cliqueType=tempT; } CliqueEntry eI; eI.fixes=0; setSequenceInCliqueEntry(eI,iColumn); setOneFixesInCliqueEntry(eI,false); entry[numberEntries++]=eI; whichM[0]=iColumn; int n=1; for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) { entry[numberEntries++]=entry[i]; whichM[n++]=sequenceInCliqueEntry(entry[i]); } CoinSort_2(whichM,whichM+n,(reinterpret_cast<int *>(entry))+numberEntries-n); cliqueType[numberCliques]='S'; numberCliques++; cliqueStart[numberCliques]=numberEntries; } } for (i=0;i<n;i++) mark[whichP[i]]=0; nCount=0; n=0; for (i=oneStart[iColumn];i<zeroStart[iColumn+1];i++) { int jClique = whichClique[i]; //if (jClique<numberMatrixCliques) //continue; int j = cliqueStart[jClique]; //assert (cliqueStart[jClique+1]==j+2); for (;j<cliqueStart[jClique+1];j++) { CliqueEntry eJ = entry[j]; int jColumn = sequenceInCliqueEntry(eJ); if (jColumn>iColumn&&!mark[jColumn]) { mark[jColumn]=1; whichP[n++]=jColumn; assert (n<numberIntegers_); if (oneFixesInCliqueEntry(eJ)) { for (int k=oneStart[jColumn];k<zeroStart[jColumn+1];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } else { for (int k=zeroStart[jColumn];k<oneStart[jColumn];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } } } } std::sort(whichP,whichP+n); for (i=0;i<nCount;i++) { int jClique = whichCount[i]; int jCount = count[jClique]; count[jClique]=0; if (jCount==cliqueStart[jClique+1]-cliqueStart[jClique]) { #if 1 if (printit) { printf("One can extend %d [ ",jClique); for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i])); printf("] by %d(1)\n",iColumn); } #endif nStrengthen++; if (numberEntries+jCount+1>maximumEntries) { maximumEntries = CoinMax(numberEntries+jCount+1,(maximumEntries*12)/10+100); CliqueEntry * temp = new CliqueEntry [maximumEntries]; memcpy(temp,entry,numberEntries*sizeof(CliqueEntry)); delete [] entry; entry=temp; int * tempI = new int [maximumEntries]; memcpy(tempI,whichClique,numberEntries*sizeof(int)); delete [] whichClique; whichClique=tempI; } if (numberCliques==maximumCliques) { maximumCliques = (maximumCliques*12)/10+100; int * temp = new int [maximumCliques+1]; memcpy(temp,cliqueStart,(numberCliques+1)*sizeof(int)); delete [] cliqueStart; cliqueStart=temp; char * tempT = new char [maximumCliques]; memcpy(tempT,cliqueType,numberCliques); delete [] cliqueType; cliqueType=tempT; } CliqueEntry eI; eI.fixes=0; setSequenceInCliqueEntry(eI,iColumn); setOneFixesInCliqueEntry(eI,true); entry[numberEntries++]=eI; whichM[0]=iColumn; int n=1; for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) { entry[numberEntries++]=entry[i]; whichM[n++]=sequenceInCliqueEntry(entry[i]); } CoinSort_2(whichM,whichM+n,(reinterpret_cast<int *>(entry))+numberEntries-n); cliqueType[numberCliques]='S'; numberCliques++; cliqueStart[numberCliques]=numberEntries; } } for (i=0;i<n;i++) mark[whichP[i]]=0; } if (nStrengthen) { int numberDeleted = outDupsEtc(numberIntegers_, numberCliques, numberMatrixCliques, cliqueStart, cliqueType, entry, numberLastTime,printit ? 2 : 1); if (numberDeleted<0||(iPass>1&&numberCliques-numberDeleted>5000)) nStrengthen=0; } delete [] count; delete [] whichCount; } #if 0 if (numberCliques>numberMatrixCliques) { // should keep as cliques and also use in branching ?? double * element = new double [numberIntegers_]; for (iClique=numberMatrixCliques;iClique<numberCliques;iClique++) { int n=0; double rhs=1.0; for (int i=cliqueStart[iClique];i<cliqueStart[iClique+1];i++) { CliqueEntry eI=entry[i]; int iColumn = integerVariable_[sequenceInCliqueEntry(eI)]; whichP[n]=iColumn; if (oneFixesInCliqueEntry(eI)) { element[n++]=1.0; } else { element[n++]=-1.0; rhs -= 1.0; } } stored->addCut(-COIN_DBL_MAX,rhs,n,whichP,element); } delete [] element; } #endif OsiSolverInterface * newSolver=NULL; if (numberCliques>numberMatrixCliques||alwaysDo) { newSolver = si.clone(); // Delete all rows int * start = new int [ CoinMax(numberRows,numberCliques+1)]; int i; for (i=0;i<numberRows;i++) start[i]=i; newSolver->deleteRows(numberRows,start); start[0]=0; int numberElements = cliqueStart[numberCliques]; int * column = new int [numberElements]; double * element = new double [numberElements]; double * lower = new double [numberCliques]; double * upper = new double [numberCliques]; numberElements=0; for (iClique=0;iClique<numberCliques;iClique++) { double rhs=1.0; for (int i=cliqueStart[iClique];i<cliqueStart[iClique+1];i++) { CliqueEntry eI=entry[i]; int iColumn = integerVariable_[sequenceInCliqueEntry(eI)]; column[numberElements]=iColumn; if (oneFixesInCliqueEntry(eI)) { element[numberElements++]=1.0; } else { element[numberElements++]=-1.0; rhs -= 1.0; } } start[iClique+1]=numberElements; assert (cliqueType[iClique]=='S'|| cliqueType[iClique]=='E'); if (cliqueType[iClique]=='S') lower[iClique]=-COIN_DBL_MAX; else lower[iClique] = rhs; upper[iClique]=rhs; } newSolver->addRows(numberCliques,start,column,element,lower,upper); delete [] start; delete [] column; delete [] element; delete [] lower; delete [] upper; } delete [] mark; delete [] whichP; delete [] whichM; delete [] cliqueStart; delete [] entry; delete [] cliqueType; delete [] zeroStart; delete [] oneStart; delete [] zeroCount; delete [] oneCount; delete [] whichClique; return newSolver; }
/* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyMumps::order(ClpInterior * model) { numberRows_ = model->numberRows(); if (doKKT_) { numberRows_ += numberRows_ + model->numberColumns(); printf("finish coding MUMPS KKT!\n"); abort(); } rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // NOT COMPRESSED FOR NOW ??? - Space for starts mumps_->ICNTL(5) = 0; // say NOT compressed format try { choleskyStart_ = new CoinBigIndex[numberRows_+1+sizeFactor_]; } catch (...) { // no memory return -1; } // Now we have size - create arrays and fill in try { choleskyRow_ = new int [sizeFactor_]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } try { sparseFactor_ = new double[sizeFactor_]; } catch (...) { // no memory delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } sizeFactor_ = 0; which = choleskyRow_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStart_[iRow] = sizeFactor_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStart_[numberRows_] = sizeFactor_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; // To Fortran and fake for (iRow = 0; iRow < numberRows_ + 1; iRow++) { int k = choleskyStart_[iRow]; int kEnd = choleskyStart_[iRow+1]; k += numberRows_ + 1; kEnd += numberRows_ + 1; for (; k < kEnd; k++) choleskyStart_[k] = iRow + 1; choleskyStart_[iRow]++; } mumps_->nz = sizeFactor_; mumps_->irn = choleskyStart_ + numberRows_ + 1; mumps_->jcn = choleskyRow_; mumps_->a = NULL; for (CoinBigIndex i = 0; i < sizeFactor_; i++) { choleskyRow_[i]++; #ifndef NDEBUG assert (mumps_->irn[i] >= 1 && mumps_->irn[i] <= numberRows_); assert (mumps_->jcn[i] >= 1 && mumps_->jcn[i] <= numberRows_); #endif } // validate //mumps code here mumps_->n = numberRows_; mumps_->nelt = numberRows_; mumps_->eltptr = choleskyStart_; mumps_->eltvar = choleskyRow_; mumps_->a_elt = NULL; mumps_->rhs = NULL; mumps_->job = 1; // order dmumps_c(mumps_); mumps_->a = sparseFactor_; if (mumps_->infog[0]) { COIN_DETAIL_PRINT(printf("MUMPS ordering failed -error %d %d\n", mumps_->infog[0], mumps_->infog[1])); return 1; } else { double size = mumps_->infog[19]; if (size < 0) size *= -1000000; COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", size, mumps_->rinfog[0])); } for (iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[iRow] = iRow; permute_[iRow] = iRow; } return 0; }
// As some computation is needed in more than one place - returns row int CbcFollowOn::gutsOfFollowOn(int & otherRow, int & preferredWay) const { int whichRow = -1; otherRow = -1; int numberRows = matrix_.getNumRows(); int i; // For sorting int * sort = new int [numberRows]; int * isort = new int [numberRows]; // Column copy //const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); const double * solution = solver->getColSolution(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); int nSort = 0; for (i = 0; i < numberRows; i++) { if (rhs_[i]) { // check elements double smallest = 1.0e10; double largest = 0.0; int rhsValue = rhs_[i]; int number1 = 0; int numberUnsatisfied = 0; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; double value = elementByRow[j]; double solValue = solution[iColumn]; if (columnLower[iColumn] != columnUpper[iColumn]) { smallest = CoinMin(smallest, value); largest = CoinMax(largest, value); if (value == 1.0) number1++; if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) numberUnsatisfied++; } else { rhsValue -= static_cast<int>(value * floor(solValue + 0.5)); } } if (numberUnsatisfied > 1) { if (smallest < largest) { // probably no good but check a few things assert (largest <= rhsValue); if (number1 == 1 && largest == rhsValue) printf("could fix\n"); } else if (largest == rhsValue) { sort[nSort] = i; isort[nSort++] = -numberUnsatisfied; } } } } if (nSort > 1) { CoinSort_2(isort, isort + nSort, sort); CoinZeroN(isort, numberRows); double * other = new double[numberRows]; CoinZeroN(other, numberRows); int * which = new int[numberRows]; //#define COUNT #ifndef COUNT bool beforeSolution = model_->getSolutionCount() == 0; #endif for (int k = 0; k < nSort - 1; k++) { i = sort[k]; int numberUnsatisfied = 0; int n = 0; int j; for (j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (columnLower[iColumn] != columnUpper[iColumn]) { double solValue = solution[iColumn] - columnLower[iColumn]; if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) { numberUnsatisfied++; for (int jj = columnStart[iColumn]; jj < columnStart[iColumn] + columnLength[iColumn]; jj++) { int iRow = row[jj]; if (rhs_[iRow]) { other[iRow] += solValue; if (isort[iRow]) { isort[iRow]++; } else { isort[iRow] = 1; which[n++] = iRow; } } } } } } double total = 0.0; // Take out row double sumThis = other[i]; other[i] = 0.0; assert (numberUnsatisfied == isort[i]); // find one nearest half if solution, one if before solution int iBest = -1; double dtarget = 0.5 * total; #ifdef COUNT int target = (numberUnsatisfied + 1) >> 1; int best = numberUnsatisfied; #else double best; if (beforeSolution) best = dtarget; else best = 1.0e30; #endif for (j = 0; j < n; j++) { int iRow = which[j]; double dvalue = other[iRow]; other[iRow] = 0.0; #ifdef COUNT int value = isort[iRow]; #endif isort[iRow] = 0; if (fabs(dvalue) < 1.0e-8 || fabs(sumThis - dvalue) < 1.0e-8) continue; if (dvalue < integerTolerance || dvalue > 1.0 - integerTolerance) continue; #ifdef COUNT if (abs(value - target) < best && value != numberUnsatisfied) { best = abs(value - target); iBest = iRow; if (dvalue < dtarget) preferredWay = 1; else preferredWay = -1; } #else if (beforeSolution) { if (fabs(dvalue - dtarget) > best) { best = fabs(dvalue - dtarget); iBest = iRow; if (dvalue < dtarget) preferredWay = 1; else preferredWay = -1; } } else { if (fabs(dvalue - dtarget) < best) { best = fabs(dvalue - dtarget); iBest = iRow; if (dvalue < dtarget) preferredWay = 1; else preferredWay = -1; } } #endif } if (iBest >= 0) { whichRow = i; otherRow = iBest; break; } } delete [] which; delete [] other; }
const CoinPresolveAction *subst_constraint_action::presolve ( CoinPresolveMatrix *prob, const int *implied_free, const int *whichFree, int numberFree, const CoinPresolveAction *next, int maxLook) { # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 # if PRESOLVE_DEBUG > 0 std::cout << "Entering subst_constraint_action::presolve, fill level " << maxLook << ", " << numberFree << " candidates." << std::endl ; # endif presolve_consistent(prob) ; presolve_links_ok(prob) ; presolve_check_sol(prob) ; presolve_check_nbasic(prob) ; # endif # if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0 int startEmptyRows = 0 ; int startEmptyColumns = 0 ; startEmptyRows = prob->countEmptyRows() ; startEmptyColumns = prob->countEmptyCols() ; # if COIN_PRESOLVE_TUNING > 0 double startTime = 0.0 ; if (prob->tuning_) startTime = CoinCpuTime() ; # endif # endif /* Unpack the row- and column-major representations. */ const int ncols = prob->ncols_ ; const int nrows = prob->nrows_ ; CoinBigIndex *rowStarts = prob->mrstrt_ ; int *rowLengths = prob->hinrow_ ; double *rowCoeffs = prob->rowels_ ; int *colIndices = prob->hcol_ ; presolvehlink *rlink = prob->rlink_ ; CoinBigIndex *colStarts = prob->mcstrt_ ; int *colLengths = prob->hincol_ ; double *colCoeffs = prob->colels_ ; int *rowIndices = prob->hrow_ ; presolvehlink *clink = prob->clink_ ; /* Row bounds and activity, objective. */ double *rlo = prob->rlo_ ; double *rup = prob->rup_ ; double *acts = prob->acts_ ; double *cost = prob->cost_ ; const double tol = prob->feasibilityTolerance_ ; action *actions = new action [ncols] ; # ifdef ZEROFAULT CoinZeroN(reinterpret_cast<char *>(actions),ncols*sizeof(action)) ; # endif int nactions = 0 ; /* This array is used to hold the indices of columns involved in substitutions, where we have the potential for cancellation. At the end they'll be checked to eliminate any actual zeros that may result. At the end of processing of each target row, the column indices of the target row are copied into zerocols. NOTE that usefulColumnInt_ is already in use for parameters implied_free and whichFree when this routine is called from implied_free. */ int *zerocols = new int[ncols] ; int nzerocols = 0 ; int *x_to_y = new int[ncols] ; int *rowsUsed = &prob->usefulRowInt_[0] ; int nRowsUsed = 0 ; /* Open a loop to process the (equality r, implied free variable t) pairs in whichFree and implied_free. It can happen that removal of (row, natural singleton) pairs back in implied_free will reduce the length of column t. It can also happen that previous processing here has resulted in fillin or cancellation. So check again for column length and exclude natural singletons and overly dense columns. */ for (int iLook = 0 ; iLook < numberFree ; iLook++) { const int tgtcol = whichFree[iLook] ; const int tgtcol_len = colLengths[tgtcol] ; const int tgtrow = implied_free[iLook] ; const int tgtrow_len = rowLengths[tgtrow] ; assert(fabs(rlo[tgtrow]-rup[tgtrow]) < tol) ; if (colLengths[tgtcol] < 2 || colLengths[tgtcol] > maxLook) { # if PRESOLVE_DEBUG > 3 std::cout << " skipping eqn " << tgtrow << " x(" << tgtcol << "); length now " << colLengths[tgtcol] << "." << std::endl ; # endif continue ; } CoinBigIndex tgtcs = colStarts[tgtcol] ; CoinBigIndex tgtce = tgtcs+colLengths[tgtcol] ; /* A few checks to make sure that the candidate pair is still suitable. Processing candidates earlier in the list can eliminate coefficients. * Don't use this pair if any involved row i has become a row singleton or empty. * Don't use this pair if any involved row has been modified as part of the processing for a previous candidate pair on this call. * Don't use this pair if a(i,tgtcol) has become zero. The checks on a(i,tgtcol) seem superfluous but it's possible that implied_free identified two candidate pairs to eliminate the same column. If we've already processed one of them, we could be in trouble. */ double tgtcoeff = 0.0 ; bool dealBreaker = false ; for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) { const int i = rowIndices[kcol] ; if (rowLengths[i] < 2 || prob->rowUsed(i)) { dealBreaker = true ; break ; } const double aij = colCoeffs[kcol] ; if (fabs(aij) <= ZTOLDP2) { dealBreaker = true ; break ; } if (i == tgtrow) tgtcoeff = aij ; } if (dealBreaker == true) { # if PRESOLVE_DEBUG > 3 std::cout << " skipping eqn " << tgtrow << " x(" << tgtcol << "); deal breaker (1)." << std::endl ; # endif continue ; } /* Check for numerical stability.A large coeff_factor will inflate the coefficients in the substitution formula. */ dealBreaker = false ; for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) { const double coeff_factor = fabs(colCoeffs[kcol]/tgtcoeff) ; if (coeff_factor > 10.0) dealBreaker = true ; } /* Given enough target rows with sufficient overlap, there's an outside chance we could overflow zerocols. Unlikely to ever happen. */ if (!dealBreaker && nzerocols+rowLengths[tgtrow] >= ncols) dealBreaker = true ; if (dealBreaker == true) { # if PRESOLVE_DEBUG > 3 std::cout << " skipping eqn " << tgtrow << " x(" << tgtcol << "); deal breaker (2)." << std::endl ; # endif continue ; } /* If c(t) != 0, we will need to modify the objective coefficients and remember the original objective. */ const bool nonzero_cost = (fabs(cost[tgtcol]) > tol) ; double *costsx = (nonzero_cost?new double[rowLengths[tgtrow]]:0) ; # if PRESOLVE_DEBUG > 1 std::cout << " Eliminating row " << tgtrow << ", col " << tgtcol ; if (nonzero_cost) std::cout << ", cost " << cost[tgtcol] ; std::cout << "." << std::endl ; # endif /* Count up the total number of coefficients in entangled rows and mark them as contaminated. */ int ntotels = 0 ; for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) { const int i = rowIndices[kcol] ; ntotels += rowLengths[i] ; PRESOLVEASSERT(!prob->rowUsed(i)) ; prob->setRowUsed(i) ; rowsUsed[nRowsUsed++] = i ; } /* Create the postsolve object. Copy in all the affected rows. Take the opportunity to mark the entangled rows as changed and put them on the list of rows to process in the next round. coeffxs in particular holds the coefficients of the target column. */ action *ap = &actions[nactions++] ; ap->col = tgtcol ; ap->rowy = tgtrow ; PRESOLVE_DETAIL_PRINT(printf("pre_subst %dC %dR E\n",tgtcol,tgtrow)) ; ap->nincol = tgtcol_len ; ap->rows = new int[tgtcol_len] ; ap->rlos = new double[tgtcol_len] ; ap->rups = new double[tgtcol_len] ; ap->costsx = costsx ; ap->coeffxs = new double[tgtcol_len] ; ap->ninrowxs = new int[tgtcol_len] ; ap->rowcolsxs = new int[ntotels] ; ap->rowelsxs = new double[ntotels] ; ntotels = 0 ; for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) { const int ndx = kcol-tgtcs ; const int i = rowIndices[kcol] ; const CoinBigIndex krs = rowStarts[i] ; prob->addRow(i) ; ap->rows[ndx] = i ; ap->ninrowxs[ndx] = rowLengths[i] ; ap->rlos[ndx] = rlo[i] ; ap->rups[ndx] = rup[i] ; ap->coeffxs[ndx] = colCoeffs[kcol] ; CoinMemcpyN(&colIndices[krs],rowLengths[i],&ap->rowcolsxs[ntotels]) ; CoinMemcpyN(&rowCoeffs[krs],rowLengths[i],&ap->rowelsxs[ntotels]) ; ntotels += rowLengths[i] ; } CoinBigIndex tgtrs = rowStarts[tgtrow] ; CoinBigIndex tgtre = tgtrs+rowLengths[tgtrow] ; /* Adjust the objective coefficients based on the substitution formula c'(j) = c(j) - a(rj)c(t)/a(rt) */ if (nonzero_cost) { const double tgtcost = cost[tgtcol] ; for (CoinBigIndex krow = tgtrs ; krow < tgtre ; krow ++) { const int j = colIndices[krow] ; prob->addCol(j) ; costsx[krow-tgtrs] = cost[j] ; double coeff = rowCoeffs[krow] ; cost[j] -= (tgtcost*coeff)/tgtcoeff ; } prob->change_bias(tgtcost*rlo[tgtrow]/tgtcoeff) ; cost[tgtcol] = 0.0 ; } # if PRESOLVE_DEBUG > 1 std::cout << " tgt (" << tgtrow << ") (" << tgtrow_len << "): " ; for (CoinBigIndex krow = tgtrs ; krow < tgtre ; ++krow) { const int j = colIndices[krow] ; const double arj = rowCoeffs[krow] ; std::cout << "x(" << j << ") = " << arj << " (" << colLengths[j] << ") " ; } std::cout << std::endl ; # endif // kill small if wanted int relax= (prob->presolveOptions()&0x60000)>>17; double tolerance = 1.0e-12; for (int i=0;i<relax;i++) tolerance *= 10.0; /* Sort the target row for efficiency when doing elimination. */ CoinSort_2(colIndices+tgtrs,colIndices+tgtre,rowCoeffs+tgtrs) ; /* Get down to the business of substituting for tgtcol in the entangled rows. Open a loop to walk the target column. We walk the saved column because the bulk store can change as we work. We don't want to repeat or miss a row. */ for (int colndx = 0 ; colndx < tgtcol_len ; ++colndx) { int i = ap->rows[colndx] ; if (i == tgtrow) continue ; double ait = ap->coeffxs[colndx] ; double coeff_factor = -ait/tgtcoeff ; CoinBigIndex krs = rowStarts[i] ; CoinBigIndex kre = krs+rowLengths[i] ; # if PRESOLVE_DEBUG > 1 std::cout << " subst pre (" << i << ") (" << rowLengths[i] << "): " ; for (CoinBigIndex krow = krs ; krow < kre ; ++krow) { const int j = colIndices[krow] ; const double aij = rowCoeffs[krow] ; std::cout << "x(" << j << ") = " << aij << " (" << colLengths[j] << ") " ; } std::cout << std::endl ; # endif /* Sort the row for efficiency and call add_row to do the actual business of changing coefficients due to substitution. This has the potential to trigger compaction of the row-major bulk store, so update bulk store indices. */ CoinSort_2(colIndices+krs,colIndices+kre,rowCoeffs+krs) ; bool outOfSpace = add_row(rowStarts,rlo,acts,rup,rowCoeffs,colIndices, rowLengths,rlink,nrows,coeff_factor,tolerance,i,tgtrow, x_to_y) ; if (outOfSpace) throwCoinError("out of memory","CoinImpliedFree::presolve") ; krs = rowStarts[i] ; kre = krs+rowLengths[i] ; tgtrs = rowStarts[tgtrow] ; tgtre = tgtrs+rowLengths[tgtrow] ; # if PRESOLVE_DEBUG > 1 std::cout << " subst aft (" << i << ") (" << rowLengths[i] << "): " ; for (CoinBigIndex krow = krs ; krow < kre ; ++krow) { const int j = colIndices[krow] ; const double aij = rowCoeffs[krow] ; std::cout << "x(" << j << ") = " << aij << " (" << colLengths[j] << ") " ; } std::cout << std::endl ; # endif /* Now update the column-major representation from the row-major representation. This is easy if the coefficient already exists, but painful if there's fillin. presolve_find_row1 will return the index of the row in the column vector, or one past the end if it's missing. If the coefficient is fill, presolve_expand_col will make sure that there's room in the column for one more coefficient. This may require that the column be moved in the bulk store, so we need to update kcs and kce. Once we're done, a(it) = 0 (i.e., we've eliminated x(t) from row i). Physically remove the explicit zero from the row-major representation with presolve_delete_from_row. */ for (CoinBigIndex rowndx = 0 ; rowndx < tgtrow_len ; ++rowndx) { const CoinBigIndex ktgt = tgtrs+rowndx ; const int j = colIndices[ktgt] ; CoinBigIndex kcs = colStarts[j] ; CoinBigIndex kce = kcs+colLengths[j] ; assert(colIndices[krs+x_to_y[rowndx]] == j) ; const double coeff = rowCoeffs[krs+x_to_y[rowndx]] ; CoinBigIndex kcol = presolve_find_row1(i,kcs,kce,rowIndices) ; if (kcol < kce) { colCoeffs[kcol] = coeff ; } else { outOfSpace = presolve_expand_col(colStarts,colCoeffs,rowIndices, colLengths,clink,ncols,j) ; if (outOfSpace) throwCoinError("out of memory","CoinImpliedFree::presolve") ; kcs = colStarts[j] ; kce = kcs+colLengths[j] ; rowIndices[kce] = i ; colCoeffs[kce] = coeff ; colLengths[j]++ ; } } presolve_delete_from_row(i,tgtcol, rowStarts,rowLengths,colIndices,rowCoeffs) ; # if PRESOLVE_DEBUG > 1 kre-- ; std::cout << " subst fin (" << i << ") (" << rowLengths[i] << "): " ; for (CoinBigIndex krow = krs ; krow < kre ; ++krow) { const int j = colIndices[krow] ; const double aij = rowCoeffs[krow] ; std::cout << "x(" << j << ") = " << aij << " (" << colLengths[j] << ") " ; } std::cout << std::endl ; # endif } /* End of the substitution loop. Record the column indices of the target row so we can groom these columns later to remove possible explicit zeros. */ CoinMemcpyN(&colIndices[rowStarts[tgtrow]],rowLengths[tgtrow], &zerocols[nzerocols]) ; nzerocols += rowLengths[tgtrow] ; /* Remove the target equality from the column- and row-major representations Somewhat painful in the colum-major representation. We have to walk the target row in the row-major representation and look up each coefficient in the column-major representation. */ for (CoinBigIndex krow = tgtrs ; krow < tgtre ; ++krow) { const int j = colIndices[krow] ; # if PRESOLVE_DEBUG > 1 std::cout << " removing row " << tgtrow << " from col " << j << std::endl ; # endif presolve_delete_from_col(tgtrow,j, colStarts,colLengths,rowIndices,colCoeffs) ; if (colLengths[j] == 0) { PRESOLVE_REMOVE_LINK(clink,j) ; } } /* Finally, physically remove the column from the column-major representation and the row from the row-major representation. */ PRESOLVE_REMOVE_LINK(clink, tgtcol) ; colLengths[tgtcol] = 0 ; PRESOLVE_REMOVE_LINK(rlink, tgtrow) ; rowLengths[tgtrow] = 0 ; rlo[tgtrow] = 0.0 ; rup[tgtrow] = 0.0 ; # if PRESOLVE_CONSISTENCY > 0 presolve_links_ok(prob) ; presolve_consistent(prob) ; # endif } /* That's it, we've processed all the candidate pairs. Clear the row used flags. */ for (int i = 0 ; i < nRowsUsed ; i++) prob->unsetRowUsed(rowsUsed[i]) ; /* Trim the array of substitution transforms and queue up objects for postsolve. Also groom the problem representation to remove explicit zeros. */ if (nactions) { # if PRESOLVE_SUMMARY > 0 std::cout << "NSUBSTS: " << nactions << std::endl ; # endif next = new subst_constraint_action(nactions, CoinCopyOfArray(actions,nactions),next) ; next = drop_zero_coefficients_action::presolve(prob,zerocols, nzerocols, next) ; # if PRESOLVE_CONSISTENCY > 0 presolve_links_ok(prob) ; presolve_consistent(prob) ; # endif } deleteAction(actions,action*) ; delete [] x_to_y ; delete [] zerocols ; # if COIN_PRESOLVE_TUNING > 0 if (prob->tuning_) double thisTime = CoinCpuTime() ; # endif # if PRESOLVE_CONSISTENCY > 0 || PRESOLVE_DEBUG > 0 presolve_check_sol(prob) ; # endif # if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0 int droppedRows = prob->countEmptyRows()-startEmptyRows ; int droppedColumns = prob->countEmptyCols()-startEmptyColumns ; std::cout << "Leaving subst_constraint_action::presolve, " << droppedRows << " rows, " << droppedColumns << " columns dropped" ; # if COIN_PRESOLVE_TUNING > 0 std::cout << " in " << thisTime-startTime << "s" ; # endif std::cout << "." << std::endl ; # endif return (next) ; }
// Infeasibility - large is 0.5 double CbcLink::infeasibility(int & preferredWay) const { int j; int firstNonZero=-1; int lastNonZero = -1; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); //const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double weight = 0.0; double sum =0.0; // check bounds etc double lastWeight=-1.0e100; int base=0; for (j=0;j<numberMembers_;j++) { for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; //if (lower[iColumn]) //throw CoinError("Non zero lower bound in CBCLink","infeasibility","CbcLink"); if (lastWeight>=weights_[j]-1.0e-7) throw CoinError("Weights too close together in CBCLink","infeasibility","CbcLink"); double value = CoinMax(0.0,solution[iColumn]); sum += value; if (value>integerTolerance&&upper[iColumn]) { // Possibly due to scaling a fixed variable might slip through if (value>upper[iColumn]+1.0e-8) { // Could change to #ifdef CBC_DEBUG #ifndef NDEBUG if (model_->messageHandler()->logLevel()>1) printf("** Variable %d (%d) has value %g and upper bound of %g\n", iColumn,j,value,upper[iColumn]); #endif } value = CoinMin(value,upper[iColumn]); weight += weights_[j]*value; if (firstNonZero<0) firstNonZero=j; lastNonZero=j; } } base += numberLinks_; } double valueInfeasibility; preferredWay=1; if (lastNonZero-firstNonZero>=sosType_) { // find where to branch assert (sum>0.0); weight /= sum; valueInfeasibility = lastNonZero-firstNonZero+1; valueInfeasibility *= 0.5/((double) numberMembers_); //#define DISTANCE #ifdef DISTANCE assert (sosType_==1); // code up /* may still be satisfied. For LOS type 2 we might wish to move coding around and keep initial info in model_ for speed */ int iWhere; bool possible=false; for (iWhere=firstNonZero;iWhere<=lastNonZero;iWhere++) { if (fabs(weight-weights_[iWhere])<1.0e-8) { possible=true; break; } } if (possible) { // One could move some of this (+ arrays) into model_ const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getMutableElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * rowSolution = solver->getRowActivity(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = matrix->getNumRows(); double * array = new double [numberRows]; CoinZeroN(array,numberRows); int * which = new int [numberRows]; int n=0; int base=numberLinks_*firstNonZero; for (j=firstNonZero;j<=lastNonZero;j++) { for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; double value = CoinMax(0.0,solution[iColumn]); if (value>integerTolerance&&upper[iColumn]) { value = CoinMin(value,upper[iColumn]); for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a += value*element[j]; if (!a) a = 1.0e-100; } else { which[n++]=iRow; a=value*element[j]; assert (a); } array[iRow]=a; } } } base += numberLinks_; } base=numberLinks_*iWhere; for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; const double value = 1.0; for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a -= value*element[j]; if (!a) a = 1.0e-100; } else { which[n++]=iRow; a=-value*element[j]; assert (a); } array[iRow]=a; } } for (j=0;j<n;j++) { int iRow = which[j]; // moving to point will increase row solution by this double distance = array[iRow]; if (distance>1.0e-8) { if (distance+rowSolution[iRow]>rowUpper[iRow]+1.0e-8) { possible=false; break; } } else if (distance<-1.0e-8) { if (distance+rowSolution[iRow]<rowLower[iRow]-1.0e-8) { possible=false; break; } } } for (j=0;j<n;j++) array[which[j]]=0.0; delete [] array; delete [] which; if (possible) { valueInfeasibility=0.0; printf("possible %d %d %d\n",firstNonZero,lastNonZero,iWhere); } } #endif } else { valueInfeasibility = 0.0; // satisfied } return valueInfeasibility; }
// This looks at solution and sets bounds to contain solution void CbcLink::feasibleRegion() { int j; int firstNonZero=-1; int lastNonZero = -1; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double weight = 0.0; double sum =0.0; int base=0; for (j=0;j<numberMembers_;j++) { for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; double value = CoinMax(0.0,solution[iColumn]); sum += value; if (value>integerTolerance&&upper[iColumn]) { weight += weights_[j]*value; if (firstNonZero<0) firstNonZero=j; lastNonZero=j; } } base += numberLinks_; } #ifdef DISTANCE if (lastNonZero-firstNonZero>sosType_-1) { /* may still be satisfied. For LOS type 2 we might wish to move coding around and keep initial info in model_ for speed */ int iWhere; bool possible=false; for (iWhere=firstNonZero;iWhere<=lastNonZero;iWhere++) { if (fabs(weight-weights_[iWhere])<1.0e-8) { possible=true; break; } } if (possible) { // One could move some of this (+ arrays) into model_ const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getMutableElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * rowSolution = solver->getRowActivity(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = matrix->getNumRows(); double * array = new double [numberRows]; CoinZeroN(array,numberRows); int * which = new int [numberRows]; int n=0; int base=numberLinks_*firstNonZero; for (j=firstNonZero;j<=lastNonZero;j++) { for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; double value = CoinMax(0.0,solution[iColumn]); if (value>integerTolerance&&upper[iColumn]) { value = CoinMin(value,upper[iColumn]); for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a += value*element[j]; if (!a) a = 1.0e-100; } else { which[n++]=iRow; a=value*element[j]; assert (a); } array[iRow]=a; } } } base += numberLinks_; } base=numberLinks_*iWhere; for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; const double value = 1.0; for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a -= value*element[j]; if (!a) a = 1.0e-100; } else { which[n++]=iRow; a=-value*element[j]; assert (a); } array[iRow]=a; } } for (j=0;j<n;j++) { int iRow = which[j]; // moving to point will increase row solution by this double distance = array[iRow]; if (distance>1.0e-8) { if (distance+rowSolution[iRow]>rowUpper[iRow]+1.0e-8) { possible=false; break; } } else if (distance<-1.0e-8) { if (distance+rowSolution[iRow]<rowLower[iRow]-1.0e-8) { possible=false; break; } } } for (j=0;j<n;j++) array[which[j]]=0.0; delete [] array; delete [] which; if (possible) { printf("possible feas region %d %d %d\n",firstNonZero,lastNonZero,iWhere); firstNonZero=iWhere; lastNonZero=iWhere; } } } #else assert (lastNonZero-firstNonZero<sosType_) ; #endif base=0; for (j=0;j<firstNonZero;j++) { for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; solver->setColUpper(iColumn,0.0); } base += numberLinks_; } // skip base += numberLinks_; for (j=lastNonZero+1;j<numberMembers_;j++) { for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; solver->setColUpper(iColumn,0.0); } base += numberLinks_; } }
void drop_empty_rows_action::postsolve(CoinPostsolveMatrix *prob) const { const int nactions = nactions_; const action *const actions = actions_; int ncols = prob->ncols_; CoinBigIndex *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; int *hrow = prob->hrow_; double *rlo = prob->rlo_; double *rup = prob->rup_; unsigned char *rowstat = prob->rowstat_; double *rowduals = prob->rowduals_; double *acts = prob->acts_; # if PRESOLVE_DEBUG char *rdone = prob->rdone_; # endif int nrows0 = prob->nrows0_; int nrows = prob->nrows_; int * rowmapping = new int [nrows0]; CoinZeroN(rowmapping,nrows0) ; int i, action_i; for (action_i = 0; action_i<nactions; action_i++) { const action *e = &actions[action_i]; int hole = e->row; rowmapping[hole]=-1; } // move data for (i=nrows0-1; i>=0; i--) { if (!rowmapping[i]) { // not a hole nrows--; rlo[i]=rlo[nrows]; rup[i]=rup[nrows]; acts[i]=acts[nrows]; rowduals[i]=rowduals[nrows]; if (rowstat) rowstat[i] = rowstat[nrows]; # if PRESOLVE_DEBUG rdone[i] = rdone[nrows] ; # endif } } assert (!nrows); // set up mapping for matrix for (i=0;i<nrows0;i++) { if (!rowmapping[i]) rowmapping[nrows++]=i; } for (int j=0; j<ncols; j++) { CoinBigIndex start = mcstrt[j]; CoinBigIndex end = start + hincol[j]; for (CoinBigIndex k=start; k<end; ++k) { hrow[k] = rowmapping[hrow[k]]; } } delete [] rowmapping; for (action_i = 0; action_i < nactions; action_i++) { const action *e = &actions[action_i]; int irow = e->row; // Now recreate irow rlo[irow] = e->rlo; rup[irow] = e->rup; if (rowstat) prob->setRowStatus(irow,CoinPrePostsolveMatrix::basic); rowduals[irow] = 0.0; // ??? acts[irow] = 0.0; # if PRESOLVE_DEBUG rdone[irow] = DROP_ROW; # endif } prob->nrows_ = prob->nrows_+nactions; # if PRESOLVE_DEBUG presolve_check_threads(prob) ; # endif }
/* Physically remove empty columns, compressing mcstrt and hincol. The major side effect is that columns are renumbered, thus clink_ is no longer valid and must be rebuilt. It's necessary to rebuild clink_ in order to do direct conversion of a CoinPresolveMatrix to a CoinPostsolveMatrix by transferring the data arrays. Without clink_, it's impractical to build link_ to match the transferred bulk storage. */ const CoinPresolveAction *drop_empty_cols_action::presolve (CoinPresolveMatrix *prob, int *ecols, int necols, const CoinPresolveAction *next) { int ncols = prob->ncols_; CoinBigIndex *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; presolvehlink *clink = prob->clink_; double *clo = prob->clo_; double *cup = prob->cup_; double *dcost = prob->cost_; const double ztoldj = prob->ztoldj_; unsigned char * integerType = prob->integerType_; int * originalColumn = prob->originalColumn_; const double maxmin = prob->maxmin_; double * sol = prob->sol_; unsigned char * colstat = prob->colstat_; action *actions = new action[necols]; int * colmapping = new int [ncols+1]; bool fixInfeasibility = (prob->presolveOptions_&16384)!=0; CoinZeroN(colmapping,ncols); int i; for (i=necols-1; i>=0; i--) { int jcol = ecols[i]; colmapping[jcol]=-1; action &e = actions[i]; e.jcol = jcol; e.clo = clo[jcol]; e.cup = cup[jcol]; // adjust if integer if (integerType[jcol]) { e.clo = ceil(e.clo-1.0e-9); e.cup = floor(e.cup+1.0e-9); if (e.clo>e.cup&&!fixInfeasibility) { // infeasible prob->status_|= 1; prob->messageHandler()->message(COIN_PRESOLVE_COLINFEAS, prob->messages()) <<jcol <<e.clo <<e.cup <<CoinMessageEol; } } e.cost = dcost[jcol]; // there are no more constraints on this variable, // so we had better be able to compute the answer now if (fabs(dcost[jcol])<ztoldj) dcost[jcol]=0.0; if (dcost[jcol] * maxmin == 0.0) { // hopefully, we can make this non-basic // what does OSL currently do in this case??? e.sol = (-PRESOLVE_INF < e.clo ? e.clo : e.cup < PRESOLVE_INF ? e.cup : 0.0); } else if (dcost[jcol] * maxmin > 0.0) { if (-PRESOLVE_INF < e.clo) e.sol = e.clo; else { prob->messageHandler()->message(COIN_PRESOLVE_COLUMNBOUNDB, prob->messages()) <<jcol <<CoinMessageEol; prob->status_ |= 2; break; } } else { if (e.cup < PRESOLVE_INF) e.sol = e.cup; else { prob->messageHandler()->message(COIN_PRESOLVE_COLUMNBOUNDA, prob->messages()) <<jcol <<CoinMessageEol; prob->status_ |= 2; break; } } #if PRESOLVE_DEBUG if (e.sol * dcost[jcol]) { //printf("\a>>>NON-ZERO COST FOR EMPTY COL %d: %g\n", jcol, dcost[jcol]); } #endif prob->change_bias(e.sol * dcost[jcol]); } int ncols2=0; // now move remaining ones down for (i=0;i<ncols;i++) { if (!colmapping[i]) { mcstrt[ncols2] = mcstrt[i]; hincol[ncols2] = hincol[i]; clo[ncols2] = clo[i]; cup[ncols2] = cup[i]; dcost[ncols2] = dcost[i]; if (sol) { sol[ncols2] = sol[i]; colstat[ncols2] = colstat[i]; } integerType[ncols2] = integerType[i]; originalColumn[ncols2] = originalColumn[i]; colmapping[i] = ncols2++; } } mcstrt[ncols2] = mcstrt[ncols] ; colmapping[ncols] = ncols2 ; /* Rebuild clink_. At this point, all empty columns are linked out, so the only columns left are columns that are to be saved, hence available in colmapping. All we need to do is walk clink_ and write the new entries into a new array. */ { presolvehlink *newclink = new presolvehlink [ncols2+1] ; for (int oldj = ncols ; oldj >= 0 ; oldj = clink[oldj].pre) { presolvehlink &oldlnk = clink[oldj] ; int newj = colmapping[oldj] ; assert(newj >= 0 && newj <= ncols2) ; presolvehlink &newlnk = newclink[newj] ; if (oldlnk.suc >= 0) { newlnk.suc = colmapping[oldlnk.suc] ; } else { newlnk.suc = NO_LINK ; } if (oldlnk.pre >= 0) { newlnk.pre = colmapping[oldlnk.pre] ; } else { newlnk.pre = NO_LINK ; } } delete [] clink ; prob->clink_ = newclink ; } delete [] colmapping; prob->ncols_ = ncols2; return (new drop_empty_cols_action(necols, actions, next)); }
void drop_empty_cols_action::postsolve(CoinPostsolveMatrix *prob) const { const int nactions = nactions_; const action *const actions = actions_; int ncols = prob->ncols_; CoinBigIndex *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; // int *hrow = prob->hrow_; double *clo = prob->clo_; double *cup = prob->cup_; double *sol = prob->sol_; double *cost = prob->cost_; double *rcosts = prob->rcosts_; unsigned char *colstat = prob->colstat_; const double maxmin = prob->maxmin_; int ncols2 = ncols+nactions; int * colmapping = new int [ncols2]; CoinZeroN(colmapping,ncols2); # if PRESOLVE_DEBUG char *cdone = prob->cdone_; # endif int action_i; for (action_i = 0; action_i < nactions; action_i++) { const action *e = &actions[action_i]; int jcol = e->jcol; colmapping[jcol]=-1; } int i; // now move remaining ones up for (i=ncols2-1;i>=0;i--) { if (!colmapping[i]) { ncols--; mcstrt[i] = mcstrt[ncols]; hincol[i] = hincol[ncols]; clo[i] = clo[ncols]; cup[i] = cup[ncols]; cost[i] = cost[ncols]; if (sol) sol[i] = sol[ncols]; if (rcosts) rcosts[i] = rcosts[ncols]; if (colstat) colstat[i] = colstat[ncols]; # if PRESOLVE_DEBUG cdone[i] = cdone[ncols]; # endif } } assert (!ncols); delete [] colmapping; for (action_i = 0; action_i < nactions; action_i++) { const action *e = &actions[action_i]; int jcol = e->jcol; // now recreate jcol clo[jcol] = e->clo; cup[jcol] = e->cup; if (sol) sol[jcol] = e->sol; cost[jcol] = e->cost; if (rcosts) rcosts[jcol] = maxmin*cost[jcol]; hincol[jcol] = 0; mcstrt[jcol] = NO_LINK ; # if PRESOLVE_DEBUG cdone[jcol] = DROP_COL; # endif if (colstat) prob->setColumnStatusUsingValue(jcol); } prob->ncols_ += nactions; # if PRESOLVE_CONSISTENCY presolve_check_threads(prob) ; # endif }
//############################################################################# void MibSBilevel::checkBilevelFeasiblity(bool isRoot) { int cutStrategy = model_->MibSPar_->entry(MibSParams::cutStrategy); bool warmStartLL = model_->MibSPar_->entry(MibSParams::warmStartLL); int maxThreadsLL = model_->MibSPar_->entry(MibSParams::maxThreadsLL); int whichCutsLL = model_->MibSPar_->entry(MibSParams::whichCutsLL); int probType = model_->MibSPar_->entry(MibSParams::bilevelProblemType); std::string feasCheckSolver = model_->MibSPar_->entry(MibSParams::feasCheckSolver); if (warmStartLL && (feasCheckSolver == "SYMPHONY") && solver_){ solver_ = setUpModel(model_->getSolver(), false); }else{ if (solver_){ delete solver_; } solver_ = setUpModel(model_->getSolver(), true); } OsiSolverInterface *lSolver = solver_; //CoinWarmStart * ws = getWarmStart(); //if (ws != NULL){ // lSolver->setWarmStart(ws); //} //delete ws; if(1) lSolver->writeLp("lowerlevel"); if (feasCheckSolver == "Cbc"){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); }else if (feasCheckSolver == "SYMPHONY"){ //dynamic_cast<OsiSymSolverInterface *> // (lSolver)->setSymParam("prep_level", -1); sym_environment *env = dynamic_cast<OsiSymSolverInterface *> (lSolver)->getSymphonyEnvironment(); if (warmStartLL){ sym_set_int_param(env, "keep_warm_start", TRUE); if (probType == 1){ //Interdiction sym_set_int_param(env, "should_use_rel_br", FALSE); sym_set_int_param(env, "use_hot_starts", FALSE); sym_set_int_param(env, "should_warmstart_node", TRUE); sym_set_int_param(env, "sensitivity_analysis", TRUE); sym_set_int_param(env, "sensitivity_bounds", TRUE); sym_set_int_param(env, "set_obj_upper_lim", FALSE); } } //Always uncomment for debugging!! sym_set_int_param(env, "do_primal_heuristic", FALSE); sym_set_int_param(env, "verbosity", -2); sym_set_int_param(env, "prep_level", -1); sym_set_int_param(env, "max_active_nodes", maxThreadsLL); sym_set_int_param(env, "tighten_root_bounds", FALSE); sym_set_int_param(env, "max_sp_size", 100); sym_set_int_param(env, "do_reduced_cost_fixing", FALSE); if (whichCutsLL == 0){ sym_set_int_param(env, "generate_cgl_cuts", FALSE); }else{ sym_set_int_param(env, "generate_cgl_gomory_cuts", GENERATE_DEFAULT); } if (whichCutsLL == 1){ sym_set_int_param(env, "generate_cgl_knapsack_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_probing_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_clique_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_twomir_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_flowcover_cuts", DO_NOT_GENERATE); } }else if (feasCheckSolver == "CPLEX"){ #ifdef USE_CPLEX lSolver->setHintParam(OsiDoReducePrint); lSolver->messageHandler()->setLogLevel(0); CPXENVptr cpxEnv = dynamic_cast<OsiCpxSolverInterface*>(lSolver)->getEnvironmentPtr(); assert(cpxEnv); CPXsetintparam(cpxEnv, CPX_PARAM_SCRIND, CPX_OFF); CPXsetintparam(cpxEnv, CPX_PARAM_THREADS, maxThreadsLL); #endif } if (warmStartLL && feasCheckSolver == "SYMPHONY"){ lSolver->resolve(); setWarmStart(lSolver->getWarmStart()); }else{ lSolver->branchAndBound(); } const double * sol = model_->solver()->getColSolution(); double objVal(lSolver->getObjValue() * model_->getLowerObjSense()); MibSTreeNode * node = static_cast<MibSTreeNode *>(model_->activeNode_); MibSTreeNode * parent = static_cast<MibSTreeNode *>(model_->activeNode_->getParent()); if((!node->isBoundSet()) && (node->getIndex() != 0)){ double parentBound = parent->getLowerUB(); node->setLowerUB(parentBound); node->setIsBoundSet(true); } if(objVal > node->getLowerUB()){ node->setLowerUB(objVal); node->setIsBoundSet(true); } double etol(model_->etol_); double lowerObj = getLowerObj(sol, model_->getLowerObjSense()); int lN(model_->lowerDim_); // lower-level dimension int uN(model_->upperDim_); // lower-level dimension if(!optLowerSolution_) optLowerSolution_ = new double[lN]; if(!optLowerSolutionOrd_) optLowerSolutionOrd_ = new double[lN]; CoinZeroN(optLowerSolution_, lN); CoinZeroN(optLowerSolutionOrd_, lN); int * lowerColInd = model_->getLowerColInd(); int * upperColInd = model_->getUpperColInd(); int index(0); if(0){ std::cout << "objVal: " << objVal << std::endl; std::cout << "lowerObj: " << lowerObj << std::endl; } if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ const double * values = lSolver->getColSolution(); int lN(model_->getLowerDim()); int i(0); // May want to take out this update and keep current - both optimal // changed this 7/1 to allow for continuous vars /* for(i = 0; i < lN; i++){ lowerSolution_[i] = (double) floor(values[i] + 0.5); } */ for(i = 0; i < lN; i++){ if(lSolver->isInteger(i)) lowerSolution_[i] = (double) floor(values[i] + 0.5); else lowerSolution_[i] = (double) values[i]; } isBilevelFeasible_ = true; useBilevelBranching_ = false; }else if (lSolver->isProvenOptimal()){ /** Current solution is not bilevel feasible, but we may still have a solution **/ //std::cout << "Solution is not bilevel feasible." << std::endl; const double * values = lSolver->getColSolution(); int lN(model_->getLowerDim()); int i(0); //added this 7/1 to store y* for val func cut for(i = 0; i < lN; i++){ if(lSolver->isInteger(i)) optLowerSolution_[i] = (double) floor(values[i] + 0.5); else optLowerSolution_[i] = (double) values[i]; } int numCols = model_->solver()->getNumCols(); int pos(0); #if 1 for(i = 0; i < numCols; i++){ if ((pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd)) >= 0){ optLowerSolutionOrd_[pos] = optLowerSolution_[pos]; } } #else double upperObj(0); double * newSolution = new double[numCols]; const double * upperObjCoeffs = model_->solver()->getObjCoefficients(); for(i = 0; i < numCols; i++){ pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd); if(pos < 0){ pos = model_->bS_->binarySearch(0, uN - 1, i, upperColInd); newSolution[i] = sol[i]; } else{ newSolution[i] = optLowerSolution_[pos]; optLowerSolutionOrd_[pos] = optLowerSolution_[pos]; } upperObj += newSolution[i] * upperObjCoeffs[i]; } if(model_->checkUpperFeasibility(newSolution)){ MibSSolution *mibsSol = new MibSSolution(numCols, newSolution, upperObj, model_); model_->storeSolution(BlisSolutionTypeHeuristic, mibsSol); } delete [] newSolution; #endif /* run a heuristic to find a better feasible solution */ heuristic_->findHeuristicSolutions(); isBilevelFeasible_ = false; if(cutStrategy != 1) useBilevelBranching_ = true; } //delete lSolver; }
/* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyUfl::order(ClpInterior * model) { numberRows_ = model->numberRows(); if (doKKT_) { numberRows_ += numberRows_ + model->numberColumns(); printf("finish coding UFL KKT!\n"); abort(); } rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); // 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 CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // Now we have size - create arrays and fill in try { choleskyRow_ = new int [sizeFactor_]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } try { sparseFactor_ = new double[sizeFactor_]; } catch (...) { // no memory delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } sizeFactor_ = 0; which = choleskyRow_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStart_[iRow] = sizeFactor_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStart_[numberRows_] = sizeFactor_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; cholmod_sparse A ; A.nrow = numberRows_; A.ncol = numberRows_; A.nzmax = choleskyStart_[numberRows_]; A.p = choleskyStart_; A.i = choleskyRow_; A.x = NULL; A.stype = -1; A.itype = CHOLMOD_INT; A.xtype = CHOLMOD_PATTERN; A.dtype = CHOLMOD_DOUBLE; A.sorted = 1; A.packed = 1; c_->nmethods = 9; c_->postorder = true; //c_->dbound=1.0e-20; L_ = cholmod_analyze (&A, c_) ; if (c_->status) { COIN_DETAIL_PRINT(std::cout << "CHOLMOD ordering failed" << std::endl); return 1; } else { COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", c_->lnz, c_->fl)); } for (iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[iRow] = iRow; permute_[iRow] = iRow; } return 0; }
//############################################################################# void MibSBilevel::createBilevel(CoinPackedVector* sol, MibSModel *mibs) { /** Splits sol into two parts, upper- and lower-level components **/ if(!mibs) return; model_ = mibs; heuristic_ = new MibSHeuristic(mibs); int i(0); int N(model_->numVars_); int lN(model_->lowerDim_); // lower-level dimension //int uN(N - lN); // upper-level dimension int uN(model_->upperDim_); // upper-level dimension double etol(model_->BlisPar()->entry(BlisParams::integerTol)); //double etol(model_->etol_); assert(N == model_->solver()->getNumCols()); int *indices = sol->getIndices(); double *values = sol->getElements(); int numElements(sol->getNumElements()); // number of nonzero elements //FIXME: These don't seem to be used anymore. if(!lowerSolution_) lowerSolution_ = new double[lN]; if(!upperSolution_) upperSolution_ = new double[uN]; CoinZeroN(lowerSolution_, lN); CoinZeroN(upperSolution_, uN); if(!lowerSolutionOrd_) lowerSolutionOrd_ = new double[lN]; if(!upperSolutionOrd_) upperSolutionOrd_ = new double[uN]; CoinZeroN(lowerSolutionOrd_, lN); CoinZeroN(upperSolutionOrd_, uN); isIntegral_ = true; isUpperIntegral_ = true; isBilevelFeasible_ = true; int * lowerColInd = mibs->getLowerColInd(); int * upperColInd = mibs->getUpperColInd(); int index(0), uCount(0), lCount(0); /* for(i = 0; i < numElements; i ++){ index = indices[i]; if(binarySearch(0, lN - 1, index, lowerColInd) < 0){ if(fabs(floor(values[i] + 0.5) - values[i]) > etol){ isIntegral_ = false; isBilevelFeasible_ = false; upperSolution_[uCount++] = values[i]; } else{ upperSolution_[uCount++] = floor(values[i] + 0.5); } } else{ if(fabs(floor(values[i] + 0.5) - values[i]) > etol){ isIntegral_ = false; isBilevelFeasible_ = false; lowerSolution_[lCount++] = values[i]; } else{ lowerSolution_[lCount++] = floor(values[i] + 0.5); } } } */ //changed this 5/12 to allow for continuous variables //FIXME: THIS IS WRONG. //VALUES SHOULD EITHER BE PLACED DIFFERENTLY OR VECTORS MADE SMALLER //PROBABLY PLACE THEM DIFFERENTLY AS BELOW, KEEPING NONZERO PLACES /* for(i = 0; i < numElements; i ++){ index = indices[i]; if(binarySearch(0, lN - 1, index, lowerColInd) < 0){ if(fabs(floor(values[i] + 0.5) - values[i]) > etol){ if(mibs->solver()->isInteger(i)){ isIntegral_ = false; isBilevelFeasible_ = false; } upperSolution_[uCount++] = values[i]; } else{ if(mibs->solver()->isInteger(i)) upperSolution_[uCount++] = floor(values[i] + 0.5); else upperSolution_[uCount++] = values[i]; } } else{ if(fabs(floor(values[i] + 0.5) - values[i]) > etol){ if(mibs->solver()->isInteger(i)){ isIntegral_ = false; isBilevelFeasible_ = false; } lowerSolution_[lCount++] = values[i]; } else{ if(mibs->solver()->isInteger(i)) lowerSolution_[lCount++] = floor(values[i] + 0.5); else lowerSolution_[lCount++] = values[i]; } } } */ const double *lower = model_->solver()->getColLower(); const double *upper = model_->solver()->getColUpper(); double value; for(i = 0; i < numElements; i ++){ index = indices[i]; value = CoinMax(values[i], lower[index]); value = CoinMin(value, upper[index]); if(binarySearch(0, uN - 1, index, upperColInd) >= 0){ if(fabs(floor(value + 0.5) - value) > etol){ #if 1 //This check is failing when Blis has already declared the solution integral //It's not really needed if(mibs->solver()->isInteger(index)){ isUpperIntegral_ = false; isIntegral_ = false; isBilevelFeasible_ = false; } #endif } } else{ if(fabs(floor(value + 0.5) - value) > etol){ #if 1 //This check is failing when Blis has already declared the solution integral //It's not really needed if(mibs->solver()->isInteger(index)){ isIntegral_ = false; isBilevelFeasible_ = false; } #endif } } } /* put the solution in order by integers first */ int pos(0); for(i = 0; i < numElements; i ++){ index = indices[i]; pos = binarySearch(0, lN - 1, index, lowerColInd); if(pos < 0){ pos = binarySearch(0, uN - 1, index, upperColInd); upperSolutionOrd_[pos] = values[i]; } else lowerSolutionOrd_[pos] = values[i]; } if(isUpperIntegral_) checkBilevelFeasiblity(mibs->isRoot_); }
void presolve_check_reduced_costs (const CoinPostsolveMatrix *postObj) { static bool warned = false ; static double *warned_rcosts = 0 ; static int allocSize = 0 ; static const CoinPostsolveMatrix *lastObj = 0 ; /* Is the client asking for reinitialisation only? */ if (postObj == 0) { warned = false ; if (warned_rcosts != 0) { delete[] warned_rcosts ; warned_rcosts = 0 ; } allocSize = 0 ; lastObj = 0 ; return ; } /* *Should* the client have asked for reinitialisation? */ int ncols0 = postObj->ncols0_ ; if (allocSize < ncols0 || postObj != lastObj) { warned = false ; delete[] warned_rcosts ; warned_rcosts = 0 ; allocSize = 0 ; lastObj = postObj ; } double *rcosts = postObj->rcosts_ ; /* By tracking values in warned_rcosts, we can produce a single message the first time a value is determined to be incorrect. */ if (!warned) { warned = true ; std::cout << "reduced cost" << std::endl ; warned_rcosts = new double[ncols0] ; CoinZeroN(warned_rcosts,ncols0) ; } double *colels = postObj->colels_ ; int *hrow = postObj->hrow_ ; int *mcstrt = postObj->mcstrt_ ; int *hincol = postObj->hincol_ ; CoinBigIndex *link = postObj->link_ ; double *clo = postObj->clo_ ; double *cup = postObj->cup_ ; double *dcost = postObj->cost_ ; double *sol = postObj->sol_ ; char *cdone = postObj->cdone_ ; char *rdone = postObj->rdone_ ; const double ztoldj = postObj->ztoldj_ ; const double ztolzb = postObj->ztolzb_ ; double *rowduals = postObj->rowduals_ ; double maxmin = postObj->maxmin_ ; std::string strMaxmin((maxmin < 0)?"max":"min") ; int checkCol=-1; /* Scan all columns, but only check the ones that are marked as having been postprocessed. */ for (int j = 0 ; j < ncols0 ; j++) { if (cdone[j] == 0) continue ; const char *statjstr = postObj->columnStatusString(j) ; /* Check the stored reduced cost for accuracy. See note above w.r.t. maxmin. */ double dj = rcosts[j] ; double wrndj = warned_rcosts[j] ; { int ndx ; CoinBigIndex k = mcstrt[j] ; int len = hincol[j] ; double chkdj = maxmin*dcost[j] ; if (j==checkCol) printf("dj for %d is %g - cost is %g\n", j,dj,chkdj); for (ndx = 0 ; ndx < len ; ndx++) { int row = hrow[k] ; PRESOLVEASSERT(rdone[row] != 0) ; chkdj -= rowduals[row]*colels[k] ; if (j==checkCol) printf("row %d coeff %g dual %g => dj %g\n", row,colels[k],rowduals[row],chkdj); k = link[k] ; } if (fabs(dj-chkdj) > ztoldj && wrndj != dj) { std::cout << "Inacc rcost: " << j << " " << statjstr << " " << strMaxmin << " have " << dj << " should be " << chkdj << " err " << fabs(dj-chkdj) << std::endl ; } } /* Check the stored reduced cost for consistency with the variable's status. The cases are * basic: (reduced cost) == 0 * at upper bound and not at lower bound: (reduced cost)*(maxmin) <= 0 * at lower bound and not at upper bound: (reduced cost)*(maxmin) >= 0 * not at either bound: any sign is correct (the variable can move either way) but superbasic status is sufficiently exotic that it always deserves a message. (There should be no superbasic variables at the completion of postsolve.) As a courtesy, show the reduced cost with the proper sign. */ { double xj = sol[j] ; double lj = clo[j] ; double uj = cup[j] ; if (postObj->columnIsBasic(j)) { if (fabs(dj) > ztoldj && wrndj != dj) { std::cout << "Bad rcost: " << j << " " << maxmin*dj << " " << statjstr << " " << strMaxmin << std::endl ; } } else if (fabs(xj-uj) < ztolzb && fabs(xj-lj) > ztolzb) { if (dj >= ztoldj && wrndj != dj) { std::cout << "Bad rcost: " << j << " " << maxmin*dj << " " << statjstr << " " << strMaxmin << std::endl ; } } else if (fabs(xj-lj) < ztolzb && fabs(xj-uj) > ztolzb) { if (dj <= -ztoldj && wrndj != dj) { std::cout << "Bad rcost: " << j << " " << maxmin*dj << " " << statjstr << " " << strMaxmin << std::endl ; } } else if (fabs(xj-lj) > ztolzb && fabs(xj-uj) > ztolzb) { if (fabs(dj) > ztoldj && wrndj != dj) { std::cout << "Superbasic rcost: " << j << " " << maxmin*dj << " " << statjstr << " " << strMaxmin << " lb "<< lj << " val " << xj << " ub "<< uj << std::endl ; } } } warned_rcosts[j] = rcosts[j] ; } }
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 ; }
//############################################################################# bfSol* MibSHeuristic::getBilevelSolution1(const double * sol) { /* Find a bilevel feasible solution by solving the LL problem for a fixed UL solution, given by the UL portion of sol */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * lSolver = new OsiCbcSolverInterface(oSolver); //double uObjSense(model->getSolver()->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int uRowNum = model->getUpperRowNum(); int lRowNum = model->getLowerRowNum(); int * uRowIndices = model->getUpperRowInd(); int * lRowIndices = model->getLowerRowInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); int tCols(uCols + lCols); int i(0), index(0); /* delete the UL rows */ lSolver->deleteRows(uRowNum, uRowIndices); /* Fix the UL variables to their current value in sol */ for(i = 0; i < uCols; i++){ index = uColIndices[i]; lSolver->setColLower(index, sol[index]); lSolver->setColUpper(index, sol[index]); } /* Set the objective to the LL objective coefficients */ double * nObjCoeffs = new double[tCols]; CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i] * lObjSense; } lSolver->setObjective(nObjCoeffs); #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); #endif lSolver->branchAndBound(); if(lSolver->isProvenOptimal()){ double objVal(0.0); for(i = 0; i < tCols; i++) objVal += lSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; double * colsol = new double[tCols]; CoinCopyN(lSolver->getColSolution(), tCols, colsol); bfSol * bfsol = new bfSol(objVal, colsol); delete lSolver; return bfsol; } else{ delete lSolver; return NULL; } }
/* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyMumps::factorize(const double * diagonal, int * rowsDropped) { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); const double * elementByRow = rowCopy_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); int iRow; double * work = new double[numberRows_]; CoinZeroN(work, numberRows_); const double * diagonalSlack = diagonal + numberColumns; int newDropped = 0; double largest; //double smallest; //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = 0.0; 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; } double delta2 = model_->delta(); // add delta*delta to diagonal delta2 *= delta2; for (iRow = 0; iRow < numberRows_; iRow++) { double * put = sparseFactor_ + choleskyStart_[iRow] - 1; // Fortran int * which = choleskyRow_ + choleskyStart_[iRow] - 1; // Fortran int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; if (!rowLength[iRow]) rowsDropped_[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; work[iRow] = diagonalSlack[iRow] + delta2; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; double multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { double value = element[j] * multiplier; work[jRow] += value; } } } } int j; for (j = 0; j < number; j++) { int jRow = which[j] - 1; // to Fortran put[j] = work[jRow]; work[jRow] = 0.0; } } else { // dropped int j; for (j = 1; j < number; j++) { put[j] = 0.0; } put[0] = 1.0; } } //check sizes double largest2 = maximumAbsElement(sparseFactor_, sizeFactor_); largest2 *= 1.0e-20; largest = CoinMin(largest2, 1.0e-11); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinBigIndex start = choleskyStart_[iRow] - 1; // to Fortran double diagonal = sparseFactor_[start]; if (diagonal > largest2) { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); } else { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); rowsDropped[iRow] = 2; numberDroppedBefore++; } } } delete [] work; // code here mumps_->a_elt = sparseFactor_; mumps_->rhs = NULL; mumps_->job = 2; // factorize dmumps_c(mumps_); if (mumps_->infog[0]) { COIN_DETAIL_PRINT(printf("MUMPS factorization failed -error %d %d\n", mumps_->infog[0], mumps_->infog[1])); } choleskyCondition_ = 1.0; bool cleanCholesky; if (model_->numberIterations() < 2000) cleanCholesky = true; else cleanCholesky = false; if (cleanCholesky) { //drop fresh makes some formADAT easier //int oldDropped=numberRowsDropped_; if (newDropped || numberRowsDropped_) { //std::cout <<"Rank "<<numberRows_-newDropped<<" ( "<< // newDropped<<" dropped)"; //if (newDropped>oldDropped) //std::cout<<" ( "<<newDropped-oldDropped<<" dropped this time)"; //std::cout<<std::endl; newDropped = 0; for (int i = 0; i < numberRows_; i++) { int dropped = rowsDropped[i]; rowsDropped_[i] = (char)dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 0; } } numberRowsDropped_ = newDropped; newDropped = -(2 + newDropped); } } else { if (newDropped) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { int dropped = rowsDropped[i]; rowsDropped_[i] = (char)dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 1; } } } numberRowsDropped_ += newDropped; if (numberRowsDropped_ && 0) { std::cout << "Rank " << numberRows_ - numberRowsDropped_ << " ( " << numberRowsDropped_ << " dropped)"; if (newDropped) { std::cout << " ( " << newDropped << " dropped this time)"; } std::cout << std::endl; } } status_ = 0; return newDropped; }
//############################################################################# mcSol MibSHeuristic::solveSubproblem(double beta) { /* optimize wrt to weighted upper-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * sSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface* sSolver = new OsiSymSolverInterface(); //sSolver = oSolver->clone(); //OsiSolverInterface * sSolver = tmpSolver; //OsiSolverInterface * tmpSolver = new OsiSolverInterface(oSolver); #endif double uObjSense(oSolver->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); const double * uObjCoeffs = oSolver->getObjCoefficients(); double etol(etol_); int tCols(uCols + lCols); assert(tCols == oSolver->getNumCols()); sSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) sSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); /* Multiply the UL columns of the UL objective by beta */ for(i = 0; i < uCols; i++){ index = uColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta * uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Multiply the LL columns of the UL objective by beta */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta* uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Add the LL columns of the LL objective multiplied by (1 - beta) */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(lObjCoeffs[i]) > etol) nObjCoeffs[index] += (1 - beta) * lObjCoeffs[i] * lObjSense; } sSolver->setObjective(nObjCoeffs); //int i(0); if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "betaobj " << sSolver->getObjCoefficients()[i] << std::endl; } } if(0){ sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "obj " << sSolver->getObjCoefficients()[i] << std::endl; std::cout << "upper " << sSolver->getColUpper()[i] << std::endl; std::cout << "lower " << sSolver->getColLower()[i] << std::endl; } } #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (sSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("max_active_nodes", 1); #endif //dynamic_cast<OsiSymSolverInterface *> (sSolver)->branchAndBound(); sSolver->branchAndBound(); if(sSolver->isProvenOptimal()){ if(0){ std::cout << "writing lp file." << std::endl; sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } double upperObjVal(0.0); double lowerObjVal(0.0); for(i = 0; i < tCols; i++){ upperObjVal += sSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; if(0){ std::cout << "sSolver->getColSolution()[" << i << "] :" << sSolver->getColSolution()[i] << std::endl; } } lowerObjVal = getLowerObj(sSolver->getColSolution(), lObjSense); if(beta == 1.0){ /* fix upper-level objective to current value and reoptimize wrt to lower-level objective */ #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface * nSolver = new OsiSymSolverInterface(); #endif nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i] * lObjSense; } nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < tCols; i++){ objCon.insert(i, uObjCoeffs[i] * uObjSense); } nSolver->addRow(objCon, upperObjVal, upperObjVal); nSolver->writeLp("beta1"); #ifndef COIN_HAS_SYMPHONY 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 nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ lowerObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ //just take the current solution lowerObjVal = sSolver->getObjValue(); CoinCopyN(sSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else if(beta == 0.0){ /* fix lower-level objective to current value and reoptimize wrt to upper-level objective */ #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface * nSolver = new OsiSymSolverInterface(); #endif nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < tCols; i++) nObjCoeffs[i] = uObjCoeffs[i] * uObjSense; nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * lObjSense); } nSolver->addRow(objCon, lowerObjVal, lowerObjVal); #ifndef COIN_HAS_SYMPHONY 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 if(0) nSolver->writeLp("nSolver"); nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else{ //no optimality cut needed here. all solutions are supported. double * colsol = new double[tCols]; CoinCopyN(sSolver->getColSolution(), tCols, colsol); delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } } else{ //FIXME:SHOULD JUST TAKE THIS OUT. DELETE sSolver and remove it from above nObjCoeffs = 0; delete[] nObjCoeffs; delete sSolver; std::cout << "Subproblem is not proven optimal." << std::endl; //return NULL; //abort(); } }
DSP_RTN_CODE BlkModel::updateBlocks() { #define FREE_MEMORY \ FREE_ARRAY_PTR(ncols_coupled); int* ncols_coupled = NULL; BGN_TRY_CATCH std::vector<int> blockids; for (Blocks::iterator it = blocks_.begin(); it != blocks_.end(); ++it) blockids.push_back(it->first); double stime = CoinGetTimeOfDay(); /** number of blocks */ if (blockids.size() > 0) { /** coupling columns and rows */ std::vector<int> master_coupling_cols; /** retrieve master information */ DetBlock* master = block(blockids[0]); if (master == NULL) return DSP_RTN_ERR; const CoinPackedMatrix* master_mat = master->getConstraintMatrix(); /** get number of columns, rows and integers */ ncols_full_ = master->getNumCols(); nrows_full_ = master->getNumRows(); nints_full_ = master->getNumIntegers(); /** to count how many subproblems are coupled with each column of the master. */ ncols_coupled = new int [master->getNumCols()]; CoinZeroN(ncols_coupled, master->getNumCols()); for (unsigned i = 1; i < blockids.size(); ++i) { /** coupling columns and rows */ std::vector<int> sub_coupling_cols; std::vector<int> sub_coupling_rows; /** retrieve subproblem */ int id = blockids[i]; DetBlock* sub = block(id); if (sub == NULL) return DSP_RTN_ERR; /** mark it is a dual block angular matrix */ if (sub->getNumCols() > master->getNumCols()) dual_block_angular_ = true; /** retrieve subproblem column indices */ const CoinPackedMatrix* sub_mat = sub->getConstraintMatrix(); int sub_num_col_indices = sub_mat->isColOrdered() ? sub_mat->getNumCols() : sub_mat->getNumElements(); int* sub_col_indices = new int [sub_num_col_indices]; if (sub_mat->isColOrdered()) CoinCopyN(sub_mat->getVectorStarts(), sub_num_col_indices, sub_col_indices); else CoinCopyN(sub_mat->getIndices(), sub_num_col_indices, sub_col_indices); /** add number of columns, rows and integers */ ncols_full_ += sub->getNumCols() - master->getNumCols(); nrows_full_ += sub->getNumRows() - master->getNumRows(); nints_full_ += sub->getNumIntegers() - master->getNumIntegers(); /** sort indices to speed up the search */ std::sort(sub_col_indices, sub_col_indices + sub_num_col_indices); /** find coupling columns and rows */ for (int j = 0; j < sub_num_col_indices; ++j) { if (j > 0 && sub_col_indices[j-1] == sub_col_indices[j]) continue; if (sub_col_indices[j] < master_mat->getNumCols()) { master_coupling_cols.push_back(sub_col_indices[j]); sub_coupling_cols.push_back(sub_col_indices[j]); /** find all the coupling rows */ for (int row = 0; row < master->getNumRows(); ++row) { if (fabs(master_mat->getCoefficient(row, sub_col_indices[j])) > 1.0e-8) sub_coupling_rows.push_back(row); } } } /** erase duplicates */ std::sort(sub_coupling_cols.begin(), sub_coupling_cols.end()); sub_coupling_cols.erase( std::unique(sub_coupling_cols.begin(), sub_coupling_cols.end()), sub_coupling_cols.end()); std::sort(sub_coupling_rows.begin(), sub_coupling_rows.end()); sub_coupling_rows.erase( std::unique(sub_coupling_rows.begin(), sub_coupling_rows.end()), sub_coupling_rows.end()); /** set coupling columns and rows */ sub->setCouplingCols(sub_coupling_cols.size(), &sub_coupling_cols[0]); sub->setCouplingRows(sub_coupling_rows.size(), &sub_coupling_rows[0]); DSPdebugMessage("Coupling columns of block %d:\n", id); DSPdebug(DspMessage::printArray(sub->getNumCouplingCols(), sub->getCouplingCols())); DSPdebugMessage("Coupling rows of block %d:\n", id); DSPdebug(DspMessage::printArray(sub->getNumCouplingRows(), sub->getCouplingRows())); /** count the master columns coupled */ for (unsigned j = 0; j < sub_coupling_cols.size(); ++j) ncols_coupled[sub_coupling_cols[j]]++; } /** erase duplicates */ std::sort(master_coupling_cols.begin(), master_coupling_cols.end()); master_coupling_cols.erase( std::unique(master_coupling_cols.begin(), master_coupling_cols.end()), master_coupling_cols.end()); /** set coupling columns */ master->setCouplingCols(master_coupling_cols.size(), &master_coupling_cols[0]); /** set coupling rows */ int* master_coupling_rows = new int [master->getNumRows()]; for (int i = 0; i < master->getNumRows(); ++i) master_coupling_rows[i] = i; master->setCouplingRows(master->getNumRows(), master_coupling_rows); FREE_ARRAY_PTR(master_coupling_rows); #if 0 /** check if the full matrix is of a primal block angular form. */ primal_block_angular_ = true; for (int j = 0; j < master->getNumCols(); ++j) if (ncols_coupled[j] > 1) primal_block_angular_ = false; if (primal_block_angular_ == true) printf("The constraint matrix is of a primal block angular.\n"); if (dual_block_angular_ == true) printf("The constraint matrix is of a dual block angular.\n"); #endif } DSPdebugMessage("Update block time: %.4f\n", CoinGetTimeOfDay() - stime); END_TRY_CATCH_RTN(FREE_MEMORY,DSP_RTN_ERR) FREE_MEMORY return DSP_RTN_OK; #undef FREE_MEMORY }
//############################################################################# void MibSHeuristic::objCutHeuristic() { /* Solve the LP relaxation with the new constraint d^2 y <= d^y* */ MibSModel * model = MibSModel_; //OsiSolverInterface * oSolver = model->origLpSolver_; OsiSolverInterface * oSolver = model->getSolver(); #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface * hSolver = new OsiSymSolverInterface(); #endif double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int tCols(lCols + uCols); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); hSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) hSolver->setInteger(j); } double * optLowerSolutionOrd = model->bS_->optLowerSolutionOrd_; CoinPackedVector objCon; int i(0), index(0); double rhs(0.0); for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * objSense); //should this be ordered? and should lObjCoeffs by at index? //rhs += optLowerSolutionOrd_[i] * lObjCoeffs[i] * objSense; rhs += optLowerSolutionOrd[i] * lObjCoeffs[i] * objSense; } //Hmm, I think this was wrong before...? // hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); hSolver->addRow(objCon, rhs, hSolver->getInfinity()); /* optimize w.r.t. to the UL objective with the new row */ #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); #endif hSolver->branchAndBound(); if(0) hSolver->writeLp("objcutheuristic"); if(hSolver->isProvenOptimal()){ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); #endif lSolver->branchAndBound(); const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), hSolver->getObjValue(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); //int numElements(lSolver->getNumCols()); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? for(i = 0; i < numElements; i++){ //index = indices[i]; pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); //optUpperSolutionOrd[pos] = values[i]; //optUpperSolutionOrd[pos] = uSol[pos]; if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ //optLowerSolutionOrd[pos] = lSol[i]; optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * hSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } delete lSolver; } delete hSolver; }
/* 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_); 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; }
//############################################################################# void MibSHeuristic::greedyHeuristic() { MibSModel * model = MibSModel_; //OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * oSolver = model->solver(); double uObjSense(oSolver->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * uColIndices = model->getUpperColInd(); int * lColIndices = model->getLowerColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); double * intCost = model->getInterdictCost(); double intBudget = model->getInterdictBudget(); int tCols(uCols + lCols); assert(tCols == oSolver->getNumCols()); int i(0), ind_min_wt(0); double usedBudget(0.0); double * fixedVars = new double[lCols]; double * testsol = new double[tCols]; CoinZeroN(fixedVars, lCols); CoinZeroN(testsol, tCols); std::multimap<double, int> lObjCoeffsOrd; for(i = 0; i < lCols; i++) lObjCoeffsOrd.insert(std::pair<double, int>(lObjCoeffs[i] * lObjSense, i)); if(!bestSol_) bestSol_ = new double[tCols]; //initialize the best solution information //bestObjVal_ = model->getSolver()->getInfinity() * uObjSense; //CoinZeroN(bestSol_, tCols); std::multimap<double, int>::iterator iter; //std::multimap<double, int>::iterator first; //std::multimap<double, int>::iterator last; //int dist = std::distance(first, last); SRANDOM((unsigned) time(NULL)); int randchoice(0); if(0) std::cout << "randchoice " << randchoice << std::endl; double cost(0.0); //starting from the largest, fix corr upper-level variables //then, with these fixed, solve the lower-level problem //this yields a feasible solution iter = lObjCoeffsOrd.begin(); while((usedBudget < intBudget) && (iter != lObjCoeffsOrd.end())){ ind_min_wt = iter->second; cost = intCost[ind_min_wt]; testsol[uColIndices[ind_min_wt]] = 1.0; double min_wt = iter->first; if(0){ std::cout << "upper: " << ind_min_wt << " " << uColIndices[ind_min_wt] << " " << oSolver->getColUpper()[uColIndices[ind_min_wt]] << " " << oSolver->getColLower()[uColIndices[ind_min_wt]] << std::endl; std::cout << "lower: " << ind_min_wt << " " << lColIndices[ind_min_wt] << " " << oSolver->getColUpper()[lColIndices[ind_min_wt]] << std::endl; } //if((oSolver->getColUpper()[uColIndices[ind_min_wt]] == 1.0) //&& (oSolver->getColUpper()[lColIndices[ind_min_wt]] > 0)){ if(oSolver->getColUpper()[uColIndices[ind_min_wt]] > etol_){ //if(((usedBudget + cost) <= intBudget) // && checkLowerFeasibility(oSolver, testsol)){ if((usedBudget + cost) <= intBudget){ //FIXME: SHOULD BE CHECKING FOR CURRENT BOUNDS HERE //fix the corresponding upper-level variable to 1 randchoice = RANDOM() % 2; if(0) std::cout << "randchoice " << randchoice << std::endl; if(randchoice){ fixedVars[ind_min_wt] = 1.0; usedBudget += intCost[ind_min_wt]; } } } else{ testsol[uColIndices[ind_min_wt]] = 0; //break; } iter++; } /* now we find a feasible solution by fixing upper-level vars and solving the lower-level problem */ double * incumbentSol = new double[tCols]; double * colsol = new double[tCols]; CoinZeroN(colsol, tCols); for(i = 0; i < uCols; i++){ colsol[uColIndices[i]] = fixedVars[i]; if(fixedVars[i] == 1.0) if(0) std::cout << "fixed " << i << std::endl; } bfSol * sol = getBilevelSolution(colsol, lObjSense * oSolver->getInfinity()); if(sol){ double incumbentObjVal = sol->getObjVal(); CoinCopyN(sol->getColumnSol(), tCols, incumbentSol); MibSSolution * mibSol = new MibSSolution(tCols, incumbentSol, incumbentObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); } //bestObjVal_ = incumbentObjVal; //CoinCopyN(incumbentSol, tCols, bestSol_); delete [] incumbentSol; delete [] testsol; //delete [] colsol; //delete [] fixedVars; //delete sol; }
void OsiPresolve::postsolve(bool updateStatus) { // Messages CoinMessages messages = CoinMessage(presolvedModel_->messages().language()); if (!presolvedModel_->isProvenOptimal()) { presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NONOPTIMAL, messages) <<CoinMessageEol; } // this is the size of the original problem const int ncols0 = ncols_; const int nrows0 = nrows_; const CoinBigIndex nelems0 = nelems_; // reality check assert(ncols0==originalModel_->getNumCols()); assert(nrows0==originalModel_->getNumRows()); // this is the reduced problem int ncols = presolvedModel_->getNumCols(); int nrows = presolvedModel_->getNumRows(); double *acts = new double [nrows0]; double *sol = new double [ncols0]; CoinZeroN(acts,nrows0); CoinZeroN(sol,ncols0); unsigned char * rowstat=NULL; unsigned char * colstat = NULL; CoinWarmStartBasis * presolvedBasis = dynamic_cast<CoinWarmStartBasis*>(presolvedModel_->getWarmStart()); if (!presolvedBasis) updateStatus=false; if (updateStatus) { colstat = new unsigned char[ncols0+nrows0]; # ifdef ZEROFAULT memset(colstat,0,((ncols0+nrows0)*sizeof(char))) ; # endif rowstat = colstat + ncols0; int i; for (i=0;i<ncols;i++) { colstat[i] = presolvedBasis->getStructStatus(i); } for (i=0;i<nrows;i++) { rowstat[i] = presolvedBasis->getArtifStatus(i); } } delete presolvedBasis; # if PRESOLVE_CONSISTENCY > 0 if (updateStatus) { int basicCnt = 0 ; int i ; for (i = 0 ; i < ncols ; i++) { if (colstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; } for (i = 0 ; i < nrows ; i++) { if (rowstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; } assert (basicCnt == nrows) ; } # endif /* Postsolve back to the original problem. The CoinPostsolveMatrix object assumes ownership of sol, acts, colstat, and rowstat. */ CoinPostsolveMatrix prob(presolvedModel_, ncols0, nrows0, nelems0, presolvedModel_->getObjSense(), sol, acts, colstat, rowstat); postsolve(prob); # if PRESOLVE_CONSISTENCY > 0 if (updateStatus) { int basicCnt = 0 ; int i ; for (i = 0 ; i < ncols0 ; i++) { if (prob.getColumnStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; } for (i = 0 ; i < nrows0 ; i++) { if (prob.getRowStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; } assert (basicCnt == nrows0) ; } # endif originalModel_->setColSolution(sol); if (updateStatus) { CoinWarmStartBasis *basis = dynamic_cast<CoinWarmStartBasis *>(presolvedModel_->getEmptyWarmStart()); basis->setSize(ncols0,nrows0); int i; for (i=0;i<ncols0;i++) { CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getColumnStatus(i)); /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */ // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getColLower()[i] > -originalModel_->getInfinity()); // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getColUpper()[i] < originalModel_->getInfinity()); basis->setStructStatus(i,status); } for (i=0;i<nrows0;i++) { CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getRowStatus(i)); /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */ // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getRowLower()[i] > -originalModel_->getInfinity()); // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getRowUpper()[i] < originalModel_->getInfinity()); basis->setArtifStatus(i,status); } originalModel_->setWarmStart(basis); delete basis ; } }
//############################################################################# void MibSHeuristic::lowerObjHeuristic() { /* optimize wrt to lower-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface* hSolver = new OsiSymSolverInterface(); #endif double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); //int tCols(lCols + uCols); int tCols(oSolver->getNumCols()); //assert(tCols == oSolver->getNumCols()); hSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) hSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i]; } //MibS objective sense is the opposite of OSI's! hSolver->setObjSense(objSense); hSolver->setObjective(nObjCoeffs); //double cutoff(model->getCutoff()); double cutoff(model->getKnowledgeBroker()->getIncumbentValue()); if(model->getNumSolutions()){ CoinPackedVector objCon; //double rhs(cutoff * objSense); //double smlTol(1.0); double rhs(cutoff); for(i = 0; i < tCols; i++){ objCon.insert(i, oSolver->getObjCoefficients()[i] * oSolver->getObjSense()); } hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); } if(0) hSolver->writeLp("lobjheurstic"); #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); #endif hSolver->branchAndBound(); if(hSolver->isProvenOptimal()){ double upperObjVal(0.0); /*****************NEW ******************/ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); if(0){ lSolver->writeLp("tmp"); } #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); #endif lSolver->branchAndBound(); if (lSolver->isProvenOptimal()){ const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ for(i = 0; i < tCols; i++) upperObjVal += hSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), upperObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? //this may be an old comment for(i = 0; i < numElements; i++){ pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * oSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } } delete lSolver; } delete hSolver; }
bool ClpInterior::createWorkingData() { bool goodMatrix = true; //check matrix if (!matrix_->allElementsInRange(this, 1.0e-12, 1.0e20)) { problemStatus_ = 4; goodMatrix = false; } int nTotal = numberRows_ + numberColumns_; delete [] solution_; solution_ = new CoinWorkDouble[nTotal]; CoinMemcpyN(columnActivity_, numberColumns_, solution_); CoinMemcpyN(rowActivity_, numberRows_, solution_ + numberColumns_); delete [] cost_; cost_ = new CoinWorkDouble[nTotal]; int i; CoinWorkDouble direction = optimizationDirection_ * objectiveScale_; // direction is actually scale out not scale in if (direction) direction = 1.0 / direction; const double * obj = objective(); for (i = 0; i < numberColumns_; i++) cost_[i] = direction * obj[i]; memset(cost_ + numberColumns_, 0, numberRows_ * sizeof(CoinWorkDouble)); // do scaling if needed if (scalingFlag_ > 0 && !rowScale_) { if (matrix_->scale(this)) scalingFlag_ = -scalingFlag_; // not scaled after all } delete [] lower_; delete [] upper_; lower_ = new CoinWorkDouble[nTotal]; upper_ = new CoinWorkDouble[nTotal]; rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; CoinMemcpyN(rowLower_, numberRows_, rowLowerWork_); CoinMemcpyN(rowUpper_, numberRows_, rowUpperWork_); CoinMemcpyN(columnLower_, numberColumns_, columnLowerWork_); CoinMemcpyN(columnUpper_, numberColumns_, columnUpperWork_); // clean up any mismatches on infinity for (i = 0; i < numberColumns_; i++) { if (columnLowerWork_[i] < -1.0e30) columnLowerWork_[i] = -COIN_DBL_MAX; if (columnUpperWork_[i] > 1.0e30) columnUpperWork_[i] = COIN_DBL_MAX; } // clean up any mismatches on infinity for (i = 0; i < numberRows_; i++) { if (rowLowerWork_[i] < -1.0e30) rowLowerWork_[i] = -COIN_DBL_MAX; if (rowUpperWork_[i] > 1.0e30) rowUpperWork_[i] = COIN_DBL_MAX; } // check rim of problem okay if (!sanityCheck()) goodMatrix = false; if(rowScale_) { for (i = 0; i < numberColumns_; i++) { CoinWorkDouble multiplier = rhsScale_ / columnScale_[i]; cost_[i] *= columnScale_[i]; if (columnLowerWork_[i] > -1.0e50) columnLowerWork_[i] *= multiplier; if (columnUpperWork_[i] < 1.0e50) columnUpperWork_[i] *= multiplier; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble multiplier = rhsScale_ * rowScale_[i]; if (rowLowerWork_[i] > -1.0e50) rowLowerWork_[i] *= multiplier; if (rowUpperWork_[i] < 1.0e50) rowUpperWork_[i] *= multiplier; } } else if (rhsScale_ != 1.0) { for (i = 0; i < numberColumns_ + numberRows_; i++) { if (lower_[i] > -1.0e50) lower_[i] *= rhsScale_; if (upper_[i] < 1.0e50) upper_[i] *= rhsScale_; } } assert (!errorRegion_); errorRegion_ = new CoinWorkDouble [numberRows_]; assert (!rhsFixRegion_); rhsFixRegion_ = new CoinWorkDouble [numberRows_]; assert (!deltaY_); deltaY_ = new CoinWorkDouble [numberRows_]; CoinZeroN(deltaY_, numberRows_); assert (!upperSlack_); upperSlack_ = new CoinWorkDouble [nTotal]; assert (!lowerSlack_); lowerSlack_ = new CoinWorkDouble [nTotal]; assert (!diagonal_); diagonal_ = new CoinWorkDouble [nTotal]; assert (!deltaX_); deltaX_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaX_, nTotal); assert (!deltaZ_); deltaZ_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaZ_, nTotal); assert (!deltaW_); deltaW_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaW_, nTotal); assert (!deltaSU_); deltaSU_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaSU_, nTotal); assert (!deltaSL_); deltaSL_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaSL_, nTotal); assert (!primalR_); assert (!dualR_); // create arrays if we are doing KKT if (cholesky_->type() >= 20) { primalR_ = new CoinWorkDouble [nTotal]; CoinZeroN(primalR_, nTotal); dualR_ = new CoinWorkDouble [numberRows_]; CoinZeroN(dualR_, numberRows_); } assert (!rhsB_); rhsB_ = new CoinWorkDouble [numberRows_]; CoinZeroN(rhsB_, numberRows_); assert (!rhsU_); rhsU_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsU_, nTotal); assert (!rhsL_); rhsL_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsL_, nTotal); assert (!rhsZ_); rhsZ_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsZ_, nTotal); assert (!rhsW_); rhsW_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsW_, nTotal); assert (!rhsC_); rhsC_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsC_, nTotal); assert (!workArray_); workArray_ = new CoinWorkDouble [nTotal]; CoinZeroN(workArray_, nTotal); assert (!zVec_); zVec_ = new CoinWorkDouble [nTotal]; CoinZeroN(zVec_, nTotal); assert (!wVec_); wVec_ = new CoinWorkDouble [nTotal]; CoinZeroN(wVec_, nTotal); assert (!dj_); dj_ = new CoinWorkDouble [nTotal]; if (!status_) status_ = new unsigned char [numberRows_+numberColumns_]; memset(status_, 0, numberRows_ + numberColumns_); return goodMatrix; }
// Returns gradient int ClpConstraintQuadratic::gradient(const ClpSimplex * model, const double * solution, double * gradient, double & functionValue, double & offset, bool useScaling, bool refresh) const { if (refresh || !lastGradient_) { offset_ = 0.0; functionValue_ = 0.0; if (!lastGradient_) lastGradient_ = new double[numberColumns_]; CoinZeroN(lastGradient_, numberColumns_); bool scaling = (model && model->rowScale() && useScaling); if (!scaling) { int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { double valueJ = solution[jColumn]; double elementValue = coefficient_[j]; if (iColumn != jColumn) { offset_ -= valueI * valueJ * elementValue; double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; lastGradient_[iColumn] += gradientI; lastGradient_[jColumn] += gradientJ; } else { offset_ -= 0.5 * valueI * valueI * elementValue; double gradientI = valueI * elementValue; lastGradient_[iColumn] += gradientI; } } else { // linear part lastGradient_[iColumn] += coefficient_[j]; functionValue_ += valueI * coefficient_[j]; } } } functionValue_ -= offset_; } else { abort(); // do scaling const double * columnScale = model->columnScale(); for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; double value = solution[iColumn]; // already scaled double coefficient = coefficient_[i] * columnScale[iColumn]; functionValue_ += value * coefficient; lastGradient_[iColumn] = coefficient; } } } functionValue = functionValue_; offset = offset_; CoinMemcpyN(lastGradient_, numberColumns_, gradient); return 0; }