// Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. #include #include #include "CoinPresolveMatrix.hpp" #include "CoinPresolveSubst.hpp" #include "CoinPresolveIsolated.hpp" #include "CoinPresolveImpliedFree.hpp" #include "CoinPresolveUseless.hpp" #include "CoinMessage.hpp" #include "CoinHelperFunctions.hpp" #include "CoinSort.hpp" #if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY #include "CoinPresolvePsdebug.hpp" #endif namespace { // begin unnamed file-local namespace const CoinPresolveAction *testRedundant (CoinPresolveMatrix *prob, const CoinPresolveAction *next, int & numberInfeasible) { numberInfeasible=0; int numberColumns = prob->ncols_; double * columnLower = new double[numberColumns]; double * columnUpper = new double[numberColumns]; memcpy(columnLower,prob->clo_,numberColumns*sizeof(double)); memcpy(columnUpper,prob->cup_,numberColumns*sizeof(double)); const double *element = prob->rowels_; const int *column = prob->hcol_; const CoinBigIndex *rowStart = prob->mrstrt_; const int *rowLength = prob->hinrow_; int numberRows = prob->nrows_; const int *hrow = prob->hrow_; const CoinBigIndex *mcstrt = prob->mcstrt_; const int *hincol = prob->hincol_; int *useless_rows = new int[numberRows]; int nuseless_rows = 0; double *rowLower = prob->rlo_; double *rowUpper = prob->rup_; double tolerance = prob->feasibilityTolerance_; int numberChanged=1,iPass=0; double large = 1.0e20; // treat bounds > this as infinite #ifndef NDEBUG double large2= 1.0e10*large; #endif int totalTightened = 0; int iRow, iColumn; int * markRow = new int[numberRows]; for (iRow=0;iRow-large||rowUpper[iRow]0) markRow[iRow]=-1; else markRow[iRow]=1; } #define MAXPASS 10 bool fixInfeasibility = (prob->presolveOptions_&16384)!=0; // Loop round seeing if we can tighten bounds // Would be faster to have a stack of possible rows // and we put altered rows back on stack int numberCheck=-1; while(numberChanged>numberCheck) { numberChanged = 0; // Bounds tightened this pass if (iPass==MAXPASS) break; iPass++; for (iRow = 0; iRow < numberRows; iRow++) { if (markRow[iRow]==-1) { // possible row - but mark as useless next time markRow[iRow]=-2; int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; double newBound; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow]+rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value=element[j]; iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value<0.0) { if (columnUpper[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error maximumUp += 1.0e-8*fabs(maximumUp); maximumDown -= 1.0e-8*fabs(maximumDown); double maxUp = maximumUp+infiniteUpper*1.0e31; double maxDown = maximumDown-infiniteLower*1.0e31; if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) { } else { if (maxUp < rowLower[iRow] -100.0*tolerance || maxDown > rowUpper[iRow]+100.0*tolerance) { if(!fixInfeasibility) { // problem is infeasible - exit at once numberInfeasible++; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) < 0.0) { // positive value if (lower>-large) { if (!infiniteUpper) { assert(nowUpper < large2); newBound = nowUpper + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound -= 1.0e-12*fabs(maximumUp); } else if (infiniteUpper==1&&nowUpper>large) { newBound = (lower -maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound -= 1.0e-12*fabs(maximumUp); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12&&newBound>-large) { // Tighten the lower bound columnLower[iColumn] = newBound; markRow[iRow]=1; numberChanged++; // Mark rows as possible CoinBigIndex kcs = mcstrt[iColumn]; CoinBigIndex kce = kcs + hincol[iColumn]; CoinBigIndex k; for (k=kcs; k- large2); newBound = nowLower + (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown)>1.0e8) newBound += 1.0e-12*fabs(maximumDown); } else if (infiniteLower==1&&nowLower<-large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown)>1.0e8) newBound += 1.0e-12*fabs(maximumDown); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12&&newBoundlarge) { now=0.0; infiniteUpper--; } else { now = nowUpper; } maximumUp += (newBound-now) * value; nowUpper = newBound; } } } else { // negative value if (lower>-large) { if (!infiniteUpper) { assert(nowLower < large2); newBound = nowLower + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound += 1.0e-12*fabs(maximumUp); } else if (infiniteUpper==1&&nowLower<-large) { newBound = (lower -maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound += 1.0e-12*fabs(maximumUp); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12&&newBoundlarge) { now=0.0; infiniteLower--; } else { now = nowUpper; } maximumDown += (newBound-now) * value; nowUpper = newBound; } } if (upper 1.0e8) newBound -= 1.0e-12*fabs(maximumDown); } else if (infiniteLower==1&&nowUpper>large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown)>1.0e8) newBound -= 1.0e-12*fabs(maximumDown); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12&&newBound>-large) { // Tighten the lower bound columnLower[iColumn] = newBound; markRow[iRow]=1; numberChanged++; // Mark rows as possible CoinBigIndex kcs = mcstrt[iColumn]; CoinBigIndex kce = kcs + hincol[iColumn]; CoinBigIndex k; for (k=kcs; k>5); if (numberInfeasible) break; } if (!numberInfeasible) { for (iRow = 0; iRow < numberRows; iRow++) { if (markRow[iRow]<0) { // possible row int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow]+rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value=element[j]; iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value<0.0) { if (columnUpper[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error maximumUp += 1.0e-8*fabs(maximumUp); maximumDown -= 1.0e-8*fabs(maximumDown); double maxUp = maximumUp+infiniteUpper*1.0e31; double maxDown = maximumDown-infiniteLower*1.0e31; if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) { // Row is redundant useless_rows[nuseless_rows++] = iRow; prob->addRow(iRow); } } } } if (nuseless_rows) next = useless_constraint_action::presolve(prob, useless_rows, nuseless_rows, next); delete[]useless_rows; delete [] columnLower; delete [] columnUpper; delete [] markRow; return next; } } // end unnamed file-local namespace // If there is a row with a singleton column such that no matter what // the values of the other variables are, the constraint forces the singleton // column to have a feasible value, then we can drop the column and row, // since we just compute the value of the column from the row in postsolve. // This seems vaguely similar to the case of a useless constraint, but it // is different. For example, if the singleton column is already free, // then this operation will eliminate it, but the constraint is not useless // (assuming the constraint is not trivial), since the variables do not imply an // upper or lower bound. // // If the column is not singleton, we can still do something similar if the // constraint is an equality constraint. In that case, we substitute away // the variable in the other constraints it appears in. This introduces // new coefficients, but the total number of coefficients never increases // if the column has only two constraints, and may not increase much even // if there are more. // // There is nothing to prevent us from substituting away a variable // in an equality from the other constraints it appears in, but since // that causes fill-in, it wouldn't make sense unless we could then // drop the equality itself. We can't do that if the bounds on the // variable in equation aren't implied by the equality. // Another way of thinking of this is that there is nothing special // about an equality; just like one can't always drop an inequality constraint // with a column singleton, one can't always drop an equality. // // It is possible for two singleton columns to be in the same row. // In that case, the other one will become empty. If its bounds and // costs aren't just right, this signals an unbounded problem. // We don't need to check that specially here. // // invariant: loosely packed const CoinPresolveAction *implied_free_action::presolve(CoinPresolveMatrix *prob, const CoinPresolveAction *next, int & fill_level) { double startTime = 0.0; int startEmptyRows=0; int startEmptyColumns = 0; if (prob->tuning_) { startTime = CoinCpuTime(); startEmptyRows = prob->countEmptyRows(); startEmptyColumns = prob->countEmptyCols(); } double *colels = prob->colels_; int *hrow = prob->hrow_; const CoinBigIndex *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; const int ncols = prob->ncols_; const double *clo = prob->clo_; const double *cup = prob->cup_; const double *rowels = prob->rowels_; const int *hcol = prob->hcol_; const CoinBigIndex *mrstrt = prob->mrstrt_; int *hinrow = prob->hinrow_; int nrows = prob->nrows_; /*const*/ double *rlo = prob->rlo_; /*const*/ double *rup = prob->rup_; double *cost = prob->cost_; presolvehlink *rlink = prob->rlink_; presolvehlink *clink = prob->clink_; const unsigned char *integerType = prob->integerType_; bool stopSomeStuff = (prob->presolveOptions()&4)!=0; const double tol = prob->feasibilityTolerance_; #if 1 // This needs to be made faster int numberInfeasible; //if (prob->pass_%2!=1) //return next; next = testRedundant(prob,next,numberInfeasible); if (numberInfeasible) { // infeasible prob->status_|= 1; return (next); } #endif // int nbounds = 0; action *actions = new action [ncols]; # ifdef ZEROFAULT CoinZeroN(reinterpret_cast(actions),ncols*sizeof(action)) ; # endif int nactions = 0; bool fixInfeasibility = (prob->presolveOptions_&16384)!=0; int *implied_free = new int[ncols]; int i; for (i=0;i not computed, -2 give up (singleton), -3 give up (other) for (i=0;i1) infiniteUp[i]=-1; else infiniteUp[i]=-2; } double large=1.0e20; int numberLook = prob->numberColsToDo_; int iLook; int * look = prob->colsToDo_; int * look2 = NULL; // if gone from 2 to 3 look at all // why does this loop not check for prohibited columns? -- lh, 040818 -- // changed 040923 if (fill_level<0) { look2 = new int[ncols]; look=look2; if (!prob->anyProhibited()) { for (iLook=0;iLookcolProhibited(iLook)) look[numberLook++]=iLook; } } int maxLook = CoinAbs(fill_level); if (maxLook==2) maxLook=3; for (iLook=0;iLook1) { CoinBigIndex kcs = mcstrt[j]; CoinBigIndex kce = kcs + hincol[j]; bool possible = false; bool singleton = false; CoinBigIndex k; double largestElement=0.0; for (k=kcs; k 1 ) { if ( fabs(rlo[row] - rup[row]) < tol && fabs(coeffj) > ZTOLDP) { possible=true; } largestElement = CoinMax(largestElement,fabs(coeffj)); } else { singleton=true; } } if (possible&&!singleton) { double low=-COIN_DBL_MAX; double high=COIN_DBL_MAX; // get bound implied by all rows for (k=kcs; k ZTOLDP) { if (infiniteUp[row]==-1) { // compute CoinBigIndex krs = mrstrt[row]; CoinBigIndex kre = krs + hinrow[row]; int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex kk; // Compute possible lower and upper ranges for (kk = krs; kk < kre; ++kk) { double value=rowels[kk]; int iColumn = hcol[kk]; if (value > 0.0) { if (cup[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += cup[iColumn] * value; } if (clo[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += clo[iColumn] * value; } } else if (value<0.0) { if (cup[iColumn] >= large) { ++infiniteLower; } else { maximumDown += cup[iColumn] * value; } if (clo[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += clo[iColumn] * value; } } } double maxUpx = maximumUp+infiniteUpper*1.0e31; double maxDownx = maximumDown-infiniteLower*1.0e31; if (maxUpx <= rup[row] + tol && maxDownx >= rlo[row] - tol) { // Row is redundant infiniteUp[row]=-3; } else if (maxUpx < rlo[row] -tol &&!fixInfeasibility) { /* there is an upper bound and it can't be reached */ prob->status_|= 1; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) < rup[row]+tol&&!fixInfeasibility) { /* there is a lower bound and it can't be reached */ prob->status_|= 1; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) <=0) { double lower = rlo[row]; double upper = rup[row]; double value=coeffj; double nowLower = clo[j]; double nowUpper = cup[j]; double newBound; int infiniteUpper=infiniteUp[row]; int infiniteLower=infiniteDown[row]; double maximumUp = maxUp[row]; double maximumDown = maxDown[row]; if (value > 0.0) { // positive value if (lower>-large) { if (!infiniteUpper) { assert(nowUpper < large); newBound = nowUpper + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound -= 1.0e-12*fabs(maximumUp); } else if (infiniteUpper==1&&nowUpper>large) { newBound = (lower -maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound -= 1.0e-12*fabs(maximumUp); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12) { // Tighten the lower bound // adjust double now; if (nowLower<-large) { now=0.0; infiniteLower--; } else { now = nowLower; } maximumDown += (newBound-now) * value; nowLower = newBound; } low=CoinMax(low,newBound); } if (upper - large); newBound = nowLower + (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown)>1.0e8) newBound += 1.0e-12*fabs(maximumDown); } else if (infiniteLower==1&&nowLower<-large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown)>1.0e8) newBound += 1.0e-12*fabs(maximumDown); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12) { // Tighten the upper bound // adjust double now; if (nowUpper>large) { now=0.0; infiniteUpper--; } else { now = nowUpper; } maximumUp += (newBound-now) * value; nowUpper = newBound; } high=CoinMin(high,newBound); } } else { // negative value if (lower>-large) { if (!infiniteUpper) { assert(nowLower >- large); newBound = nowLower + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound += 1.0e-12*fabs(maximumUp); } else if (infiniteUpper==1&&nowLower<-large) { newBound = (lower -maximumUp) / value; // relax if original was large if (fabs(maximumUp)>1.0e8) newBound += 1.0e-12*fabs(maximumUp); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12) { // Tighten the upper bound // adjust double now; if (nowUpper>large) { now=0.0; infiniteLower--; } else { now = nowUpper; } maximumDown += (newBound-now) * value; nowUpper = newBound; } high=CoinMin(high,newBound); } if (upper 1.0e8) newBound -= 1.0e-12*fabs(maximumDown); } else if (infiniteLower==1&&nowUpper>large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown)>1.0e8) newBound -= 1.0e-12*fabs(maximumDown); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12) { // Tighten the lower bound // adjust double now; if (nowLower<-large) { now=0.0; infiniteUpper--; } else { now = nowLower; } maximumUp += (newBound-now) * value; nowLower = newBound; } low = CoinMax(low,newBound); } } } else if (infiniteUp[row]==-3) { // give up high=COIN_DBL_MAX; low=-COIN_DBL_MAX; break; } } } if (clo[j] <= low && high <= cup[j]) { // both column bounds implied by the constraints of the problem // get row // If more than one equality is present, how do I know the one I // select here will be the one that actually implied tighter // bounds? Seems like I should care. -- lh, 040818 -- largestElement *= 0.1; int krow=-1; int ninrow=ncols+1; double thisValue=0.0; for (k=kcs; k largestElement) { if (hinrow[row]=0) { bool goodRow=true; if (integerType[j]) { // can only accept if good looking row double scaleFactor = 1.0/thisValue; double rhs = rlo[krow]*scaleFactor; if (fabs(rhs-floor(rhs+0.5))tol) { goodRow=false; break; } } if (rlo[krow]==1.0&&hinrow[krow]>=5&&stopSomeStuff&&allOnes) goodRow=false; // may spoil SOS } else { goodRow=false; } } if (goodRow) { implied_free[j] = krow; // And say row no good for further use infiniteUp[krow]=-3; //printf("column %d implied free by row %d hincol %d hinrow %d\n", // j,krow,hincol[j],hinrow[krow]); } } } } } else if (hincol[j]) { // singleton column CoinBigIndex k = mcstrt[j]; int row = hrow[k]; double coeffj = colels[k]; if ((!cost[j]||rlo[row]==rup[row])&&hinrow[row]>1&& fabs(coeffj) > ZTOLDP&&infiniteUp[row]!=-3) { CoinBigIndex krs = mrstrt[row]; CoinBigIndex kre = krs + hinrow[row]; double maxup, maxdown, ilow, iup; implied_bounds(rowels, clo, cup, hcol, krs, kre, &maxup, &maxdown, j, rlo[row], rup[row], &ilow, &iup); if (maxup < PRESOLVE_INF && maxup + tol < rlo[row]&&!fixInfeasibility) { /* there is an upper bound and it can't be reached */ prob->status_|= 1; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) <status_|= 1; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) <tol) { goodRow=false; break; } } if (rlo[row]==1.0&&hinrow[row]>=5&&stopSomeStuff&&allOnes) goodRow=false; // may spoil SOS } else { goodRow=false; } } if (goodRow) { implied_free[j] = row; infiniteUp[row]=-3; //printf("column %d implied free by row %d hincol %d hinrow %d\n", // j,row,hincol[j],hinrow[row]); } } } } } } // this comment is incorrect? implied_free[j] is a row index, not column // length -- lh, 040818 -- // implied_free[j] == hincol[j] && hincol[j] > 0 ==> j is implied free delete [] infiniteDown; delete [] infiniteUp; delete [] maxDown; delete [] maxUp; int isolated_row = -1; // first pick off the easy ones // note that this will only deal with columns that were originally // singleton; it will not deal with doubleton columns that become // singletons as a result of dropping rows. for (iLook=0;iLook=0) { CoinBigIndex kcs = mcstrt[j]; int row = hrow[kcs]; double coeffj = colels[kcs]; CoinBigIndex krs = mrstrt[row]; CoinBigIndex kre = krs + hinrow[row]; // isolated rows are weird { int n = 0; for (CoinBigIndex k=krs; krow = row; s->col = j; s->clo = clo[j]; s->cup = cup[j]; s->rlo = rlo[row]; s->rup = rup[row]; s->ninrow = hinrow[row]; s->rowels = presolve_dupmajor(rowels,hcol,hinrow[row],krs) ; s->costs = save_costs; } if (nonzero_cost) { double rhs = rlo[row]; double costj = cost[j]; # if PRESOLVE_DEBUG printf("FREE COSTS: %g ", costj); # endif for (CoinBigIndex k=krs; kchange_bias(costj * rhs / coeffj); // ?? cost[j] = 0.0; } /* remove the row from the columns in the row */ for (CoinBigIndex k=krs; kaddCol(jcol); presolve_delete_from_col(row,jcol,mcstrt,hincol,hrow,colels) ; if (hincol[jcol] == 0) { PRESOLVE_REMOVE_LINK(prob->clink_,jcol) ; } } PRESOLVE_REMOVE_LINK(rlink, row); hinrow[row] = 0; // just to make things squeeky rlo[row] = 0.0; rup[row] = 0.0; PRESOLVE_REMOVE_LINK(clink, j); hincol[j] = 0; implied_free[j] = -1; // probably unnecessary } } delete [] look2; if (nactions) { # if PRESOLVE_SUMMARY printf("NIMPLIED FREE: %d\n", nactions); # endif action *actions1 = new action[nactions]; CoinMemcpyN(actions, nactions, actions1); next = new implied_free_action(nactions, actions1, next); } delete [] actions; if (isolated_row != -1) { const CoinPresolveAction *nextX = isolated_constraint_action::presolve(prob, isolated_row, next); if (nextX) next = nextX; // may fail } // try more complex ones if (fill_level) { next = subst_constraint_action::presolve(prob, implied_free, next,fill_level); } delete[]implied_free; if (prob->tuning_) { double thisTime=CoinCpuTime(); int droppedRows = prob->countEmptyRows() - startEmptyRows ; int droppedColumns = prob->countEmptyCols() - startEmptyColumns; printf("CoinPresolveImpliedFree(64) - %d rows, %d columns dropped in time %g, total %g\n", droppedRows,droppedColumns,thisTime-startTime,thisTime-prob->startTime_); } return (next); } const char *implied_free_action::name() const { return ("implied_free_action"); } void implied_free_action::postsolve(CoinPostsolveMatrix *prob) const { const action *const actions = actions_; const int nactions = nactions_; double *elementByColumn = prob->colels_; int *hrow = prob->hrow_; CoinBigIndex *columnStart = prob->mcstrt_; int *numberInColumn = prob->hincol_; int *link = prob->link_; double *clo = prob->clo_; double *cup = prob->cup_; double *rlo = prob->rlo_; double *rup = prob->rup_; double *sol = prob->sol_; double *rcosts = prob->rcosts_; double *dcost = prob->cost_; double *acts = prob->acts_; double *rowduals = prob->rowduals_; const double maxmin = prob->maxmin_; # if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY char *cdone = prob->cdone_; char *rdone = prob->rdone_; # endif CoinBigIndex &free_list = prob->free_list_; for (const action *f = &actions[nactions-1]; actions<=f; f--) { int irow = f->row; int icol = f->col; int ninrow = f->ninrow; const double *rowels = f->rowels; const int *rowcols = reinterpret_cast(rowels+ninrow) ; const double *save_costs = f->costs; // put back coefficients in the row // this includes recreating the singleton column { for (int k = 0; k= 0 && kk < prob->bulk0_) ; free_list = link[free_list]; link[kk] = columnStart[jcol]; columnStart[jcol] = kk; elementByColumn[kk] = coeff; hrow[kk] = irow; } if (jcol == icol) { // initialize the singleton column numberInColumn[jcol] = 1; clo[icol] = f->clo; cup[icol] = f->cup; # if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY cdone[icol] = IMPLIED_FREE; # endif } else { numberInColumn[jcol]++; } } # if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY rdone[irow] = IMPLIED_FREE; # endif # if PRESOLVE_CONSISTENCY presolve_check_free_list(prob) ; # endif rlo[irow] = f->rlo; rup[irow] = f->rup; } //deleteAction( f->costs,double*); do on delete // coeff has now been initialized // compute solution { double act = 0.0; double coeff = 0.0; for (int k = 0; k ZTOLDP); double thisCost = maxmin*dcost[icol]; double loActivity,upActivity; if (coeff>0) { loActivity = (rlo[irow]-act)/coeff; upActivity = (rup[irow]-act)/coeff; } else { loActivity = (rup[irow]-act)/coeff; upActivity = (rlo[irow]-act)/coeff; } loActivity = CoinMax(loActivity,clo[icol]); upActivity = CoinMin(upActivity,cup[icol]); int where; //0 in basis, -1 at lb, +1 at ub const double tolCheck = 0.1*prob->ztolzb_; if (loActivity=0.0) where=-1; else if (upActivity>cup[icol]-tolCheck/fabs(coeff)&&thisCost<0.0) where=1; else where =0; // But we may need to put in basis to stay dual feasible double possibleDual = thisCost/coeff; if (where) { double worst= prob->ztoldj_; for (int k = 0; kgetColumnStatus(jcol); // can only trust basic if (status==CoinPrePostsolveMatrix::basic) { if (fabs(rcosts[jcol])>worst) worst=fabs(rcosts[jcol]); } else if (sol[jcol]worst) worst=-rcosts[jcol]; } else if (sol[jcol]>cup[jcol]-ZTOLDP) { if (rcosts[jcol]>worst) worst=rcosts[jcol]; } } } if (worst>prob->ztoldj_) { // see if better if in basis double worst2 = prob->ztoldj_; for (int k = 0; kgetColumnStatus(jcol); // can only trust basic if (status==CoinPrePostsolveMatrix::basic) { if (fabs(newDj)>worst2) worst2=fabs(newDj); } else if (sol[jcol]worst2) worst2=-newDj; } else if (sol[jcol]>cup[jcol]-ZTOLDP) { if (newDj>worst2) worst2=newDj; } } } if (worst2ZTOLDP) printf("IMP %g %g %g\n",rlo[irow],rup[irow],rowduals[irow]); sol[icol] = (rup[irow] - act) / coeff; //assert (sol[icol]>=clo[icol]-1.0e-5&&sol[icol]<=cup[icol]+1.0e-5); acts[irow] = rup[irow]; prob->setRowStatus(irow,CoinPrePostsolveMatrix::atUpperBound); } else { sol[icol] = (rlo[irow] - act) / coeff; //assert (sol[icol]>=clo[icol]-1.0e-5&&sol[icol]<=cup[icol]+1.0e-5); acts[irow] = rlo[irow]; prob->setRowStatus(irow,CoinPrePostsolveMatrix::atLowerBound); } prob->setColumnStatus(icol,CoinPrePostsolveMatrix::basic); for (int k = 0; ksetRowStatus(irow,CoinPrePostsolveMatrix::basic); if (where<0) { // to lb prob->setColumnStatus(icol,CoinPrePostsolveMatrix::atLowerBound); sol[icol]=clo[icol]; } else { // to ub prob->setColumnStatus(icol,CoinPrePostsolveMatrix::atUpperBound); sol[icol]=cup[icol]; } acts[irow] = act + sol[icol]*coeff; //assert (acts[irow]>=rlo[irow]-1.0e-5&&acts[irow]<=rup[irow]+1.0e-5); } # if PRESOLVE_DEBUG { double *colels = prob->colels_; int *hrow = prob->hrow_; const CoinBigIndex *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; for (int j = 0; j1.0e-3) printf("changed\n"); } } # endif } } return ; } /* Why do we delete costs during postsolve() execution, but none of the other components of the action? */ implied_free_action::~implied_free_action() { int i; for (i=0;i