int MC_components(const int n, const int m, const MC_graph_edge* edges, int* component) { // See the MC_kruskal.cpp file. // This is the same algorithm, just here we don't need all those things that // are computed there int * first_on_chain = component; int * last_on_chain = new int[n]; int * next_on_chain = new int[n]; int * size_of_chain = new int[n]; CoinIotaN(first_on_chain, n, 0); CoinIotaN(last_on_chain, n, 0); CoinFillN(next_on_chain, n, -1); CoinFillN(size_of_chain, n, 1); int tree_size = 0; int label_s = -1; // shorter chain head int label_l = -1; // longer chain head for (int k = 0; k < m; ++k) { const int i = edges[k].tail; const int j = edges[k].head; const int label_i = first_on_chain[i]; const int label_j = first_on_chain[j]; if (label_i == label_j) continue; if (size_of_chain[label_i] > size_of_chain[label_j]) { label_s = label_j; label_l = label_i; } else { label_s = label_i; label_l = label_j; } ++tree_size; for (int l = label_s; l != -1; l = next_on_chain[l]) { first_on_chain[l] = label_l; } next_on_chain[last_on_chain[label_l]] = label_s; last_on_chain[label_l] = last_on_chain[label_s]; size_of_chain[label_l] += size_of_chain[label_s]; } delete[] last_on_chain; delete[] next_on_chain; delete[] size_of_chain; return tree_size; }
void CoinPackedVector::assignVector(int size, int*& inds, double*& elems, bool testForDuplicateIndex) { clear(); // Allocate storage if ( size != 0 ) { //reserve(size); //This is a BUG!!! nElements_ = size; if (indices_ != NULL) delete[] indices_; indices_ = inds; inds = NULL; if (elements_ != NULL) delete[] elements_; elements_ = elems; elems = NULL; if (origIndices_ != NULL) delete[] origIndices_; origIndices_ = new int[size]; CoinIotaN(origIndices_, size, 0); capacity_ = size; } if (testForDuplicateIndex) { try { CoinPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } catch (CoinError e) { throw CoinError("duplicate index", "assignVector", "CoinPackedVector"); } } else { setTestsOff(); } }
void CoinPackedVector::append(const CoinPackedVectorBase & caboose) { const int cs = caboose.getNumElements(); if (cs == 0) { return; } if (testForDuplicateIndex()) { // Just to initialize the index heap indexSet("append (1st call)", "CoinPackedVector"); } const int s = nElements_; // Make sure there is enough room for the caboose if ( capacity_ < s + cs) reserve(CoinMax(s + cs, 2 * capacity_)); const int * cind = caboose.getIndices(); const double * celem = caboose.getElements(); CoinDisjointCopyN(cind, cs, indices_ + s); CoinDisjointCopyN(celem, cs, elements_ + s); CoinIotaN(origIndices_ + s, cs, s); nElements_ += cs; if (testForDuplicateIndex()) { std::set<int>& is = *indexSet("append (2nd call)", "CoinPackedVector"); for (int i = 0; i < cs; ++i) { if (!is.insert(cind[i]).second) throw CoinError("duplicate index", "append", "CoinPackedVector"); } } }
void CoinPackedVector::setFull(int size, const double * elems, bool testForDuplicateIndex) { // Clear out any values presently stored clear(); // Allocate storage if ( size!=0 ) { reserve(size); nElements_ = size; CoinIotaN(origIndices_, size, 0); CoinIotaN(indices_, size, 0); CoinDisjointCopyN(elems, size, elements_); } // Full array can not have duplicates CoinPackedVectorBase::setTestForDuplicateIndexWhenTrue(testForDuplicateIndex); }
CoinPackedVector::CoinPackedVector(int capacity, int size, int *&inds, double *&elems, bool /*testForDuplicateIndex*/) : CoinPackedVectorBase(), indices_(inds), elements_(elems), nElements_(size), origIndices_(NULL), capacity_(capacity) { assert( size <= capacity ); inds = NULL; elems = NULL; origIndices_ = new int[capacity_]; CoinIotaN(origIndices_, size, 0); }
void CoinPackedVector::assignVector(int size, int*& inds, double*& elems, bool testForDuplicateIndex) { clear(); // Allocate storage if ( size != 0 ) { reserve(size); nElements_ = size; indices_ = inds; inds = NULL; elements_ = elems; elems = NULL; CoinIotaN(origIndices_, size, 0); } try { CoinPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } catch (CoinError e) { throw CoinError("duplicate index", "assignVector", "CoinPackedVector"); } }
void CoinPackedVector::gutsOfSetConstant(int size, const int * inds, double value, bool testForDuplicateIndex, const char * method) { if ( size != 0 ) { reserve(size); nElements_ = size; CoinDisjointCopyN(inds, size, indices_); CoinFillN(elements_, size, value); CoinIotaN(origIndices_, size, 0); } try { CoinPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } catch (CoinError e) { throw CoinError("duplicate index", method, "CoinPackedVector"); } }
void CoinPackedVector::gutsOfSetVector(int size, const int * inds, const double * elems, bool testForDuplicateIndex, const char * method) { if ( size != 0 ) { reserve(size); nElements_ = size; CoinDisjointCopyN(inds, size, indices_); CoinDisjointCopyN(elems, size, elements_); CoinIotaN(origIndices_, size, 0); } if (testForDuplicateIndex) { try { CoinPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } catch (CoinError& e) { throw CoinError("duplicate index", method, "CoinPackedVector"); } } else { setTestsOff(); } }
const CoinPresolveAction *implied_free_action::presolve ( CoinPresolveMatrix *prob, const CoinPresolveAction *next, int &fill_level) { # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 # if PRESOLVE_DEBUG > 0 std::cout << "Entering implied_free_action::presolve, fill level " << fill_level << "." << 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 const int startEmptyRows = prob->countEmptyRows() ; const int 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 m = prob->nrows_ ; const int n = prob->ncols_ ; const CoinBigIndex *rowStarts = prob->mrstrt_ ; int *rowLengths = prob->hinrow_ ; const int *colIndices = prob->hcol_ ; const double *rowCoeffs = prob->rowels_ ; presolvehlink *rlink = prob->rlink_ ; CoinBigIndex *colStarts = prob->mcstrt_ ; int *colLengths = prob->hincol_ ; int *rowIndices = prob->hrow_ ; double *colCoeffs = prob->colels_ ; presolvehlink *clink = prob->clink_ ; /* Column bounds, row bounds, cost, integrality. */ double *clo = prob->clo_ ; double *cup = prob->cup_ ; double *rlo = prob->rlo_ ; double *rup = prob->rup_ ; double *cost = prob->cost_ ; const unsigned char *integerType = prob->integerType_ ; /* Documented as `inhibit x+y+z = 1 mods'. From the code below, it's clear that this is intended to avoid removing SOS equalities with length >= 5 (hardcoded). */ const bool stopSomeStuff = ((prob->presolveOptions()&0x04) != 0) ; /* Ignore infeasibility. `Fix' is overly optimistic. */ const bool fixInfeasibility = ((prob->presolveOptions_&0x4000) != 0) ; /* Defaults to 0.0. */ const double feasTol = prob->feasibilityTolerance_ ; # if 0 /* Tentatively moved to be a front-end function for useless_constraint_action, much as make_fixed is a front-end for make_fixed_action. This bit of code left for possible tuning. -- lh, 121127 -- Original comment: This needs to be made faster. */ # ifdef COIN_LIGHTWEIGHT_PRESOLVE if (prob->pass_ == 1) { #else if (prob->presolveOptions_&0x10) { # endif next = testRedundant(prob,next) ; if (prob->status_&0x01 != 0) { if ((prob->presolveOptions_&0x4000) != 0) prob->status_ &= !0x01 ; else return (next) ; } # if 1 //def COIN_LIGHTWEIGHT_PRESOLVE } # endif # endif /* implied_free and subst take a fair bit of effort to scan for candidates. This is a hook to allow a presolve driver to avoid that work. */ if (prob->pass_ > 15 && (prob->presolveOptions_&0x10000) != 0) { fill_level = 2 ; return (next) ; } /* Set up to collect implied_free actions. */ action *actions = new action [n] ; # ifdef ZEROFAULT CoinZeroN(reinterpret_cast<char *>(actions),n*sizeof(action)) ; # endif int nactions = 0 ; int *implied_free = prob->usefulColumnInt_ ; int *whichFree = implied_free+n ; int numberFree = 0 ; /* Arrays to hold row activity (row lhs) min and max values. Each row lhs bound is held as two components: a sum of finite column bounds and a count of infinite column bounds. */ int *infiniteDown = new int[m] ; int *infiniteUp = new int[m] ; double *maxDown = new double[m] ; double *maxUp = new double[m] ; /* Overload infiniteUp with row status codes: -1: L(i)/U(i) not yet computed, -2: do not use (empty or useless row), -3: give up (infeasible) -4: chosen as implied free row */ for (int i = 0 ; i < m ; i++) { if (rowLengths[i] > 1) infiniteUp[i] = -1 ; else infiniteUp[i] = -2 ; } // Get rid of rows with prohibited columns if (prob->anyProhibited_) { for (int i = 0 ; i < m ; i++) { CoinBigIndex rStart = rowStarts[i]; CoinBigIndex rEnd = rStart+rowLengths[i]; bool badRow=false; for (CoinBigIndex j = rStart; j < rEnd; ++j) { if (prob->colProhibited(colIndices[j])) { badRow=true; break; } } if (badRow) infiniteUp[i] = -2 ; } } // Can't go on without a suitable finite infinity, can we? #ifdef USE_SMALL_LARGE const double large = 1.0e10 ; #else const double large = 1.0e20 ; #endif /* Decide which columns we're going to look at. There are columns already queued in colsToDo_, but sometimes we want to look at all of them. Don't suck in prohibited columns. See comments at the head of the routine for fill_level. NOTE the overload on usefulColumnInt_. It was assigned above to whichFree (indices of interesting columns). We'll be ok because columns are consumed out of look at one per main loop iteration, but not all columns are interesting. Original comment: if gone from 2 to 3 look at all */ int numberLook = prob->numberColsToDo_ ; int iLook ; int *look = prob->colsToDo_ ; if (fill_level < 0) { look = prob->usefulColumnInt_+n ; if (!prob->anyProhibited()) { CoinIotaN(look,n,0) ; numberLook = n ; } else { numberLook = 0 ; for (iLook = 0 ; iLook < n ; iLook++) if (!prob->colProhibited(iLook)) look[numberLook++] = iLook ; } } /* Step through the columns of interest looking for suitable x(tgt). Interesting columns are limited by number of nonzeros to minimise fill-in during substitution. */ bool infeas = false ; const int maxLook = abs(fill_level) ; for (iLook = 0 ; iLook < numberLook ; iLook++) { const int tgtcol = look[iLook] ; const int tgtcol_len = colLengths[tgtcol] ; if (tgtcol_len <= 0 || tgtcol_len > maxLook) continue ; /* Set up to reconnoiter the column. The initial value for ait_max is chosen to make sure that anything that satisfies the stability check is big enough to use (though we'd clearly like something better). */ const CoinBigIndex kcs = colStarts[tgtcol] ; const CoinBigIndex kce = kcs+tgtcol_len ; const bool singletonCol = (tgtcol_len == 1) ; bool possibleRow = false ; bool singletonRow = false ; double ait_max = 20*ZTOLDP2 ; /* If this is a singleton column, the only concern is that the row is not a singleton row (that has its own, simpler, transform: slack_doubleton). But make sure we're not dealing with some tiny a(it). Note that there's no point in marking a singleton row. By definition, we won't encounter it again. */ if (singletonCol) { const int i = rowIndices[kcs] ; singletonRow = (rowLengths[i] == 1) ; possibleRow = (fabs(colCoeffs[kcs]) > ZTOLDP2) ; } else { /* If the column is not a singleton, we'll need a numerically stable substitution formula. Check that this is possible. One of the entangled rows must be an equality with a numerically stable coefficient, at least .1*MAX{i}a(it). */ for (CoinBigIndex kcol = kcs ; kcol < kce ; ++kcol) { const int i = rowIndices[kcol] ; if (rowLengths[i] == 1) { singletonRow = true ; break ; } const double abs_ait = fabs(colCoeffs[kcol]) ; ait_max = CoinMax(ait_max,abs_ait) ; if (fabs(rlo[i]-rup[i]) < feasTol && abs_ait > .1*ait_max) { possibleRow = true ; } } } if (singletonRow || !possibleRow) continue ; /* The column has possibilities. Walk the column, calculate row activity bounds L(i) and U(i) for suitable entangled rows, then calculate the improvement (if any) on the column bounds for l(j) and u(j). The goal is to satisfy the implied free condition over all entangled rows and find at least one row suitable for a substitution formula (if the column is not a natural singleton). Suitable: If this is a natural singleton, we need to look at the single entangled constraint. If we're attempting to create a singleton by substitution, only look at equalities with stable coefficients. If x(t) is integral, make sure the scaled rhs will be integral. */ # if PRESOLVE_DEBUG > 2 std::cout << " Checking x(" << tgtcol << "), " << tgtcol_len << " nonzeros" << ", l(" << tgtcol << ") " << clo[tgtcol] << ", u(" << tgtcol << ") " << cup[tgtcol] << ", c(" << tgtcol << ") " << cost[tgtcol] << "." << std::endl ; # endif const double lt = clo[tgtcol] ; const double ut = cup[tgtcol] ; double impliedLow = -COIN_DBL_MAX ; double impliedHigh = COIN_DBL_MAX ; int subst_ndx = -1 ; int subst_len = n ; for (CoinBigIndex kcol = kcs ; kcol < kce ; ++kcol) { const int i = rowIndices[kcol] ; assert(infiniteUp[i] != -3) ; if (infiniteUp[i] <= -2) continue ; const double ait = colCoeffs[kcol] ; const int leni = rowLengths[i] ; const double rloi = rlo[i] ; const double rupi = rup[i] ; /* A suitable row for substitution must * be an equality; * the entangled coefficient must be large enough to be numerically stable; * if x(t) is integer, the constant term in the substitution formula must be integer. */ bool rowiOK = (fabs(rloi-rupi) < feasTol) && (fabs(ait) > .1*ait_max) ; rowiOK = rowiOK && ((integerType[tgtcol] == 0) || (fabs((rloi/ait)-floor((rloi/ait)+0.5)) < feasTol)) ; /* If we don't already have L(i) and U(i), calculate now. Check for useless and infeasible constraints when that's done. */ int infUi = 0 ; int infLi = 0 ; double maxUi = 0.0 ; double maxLi = 0.0 ; const CoinBigIndex krs = rowStarts[i] ; const CoinBigIndex kre = krs+leni ; if (infiniteUp[i] == -1) { for (CoinBigIndex krow = krs ; krow < kre ; ++krow) { const double aik = rowCoeffs[krow] ; const int k = colIndices[krow] ; const double lk = clo[k] ; const double uk = cup[k] ; if (aik > 0.0) { if (uk < large) maxUi += uk*aik ; else ++infUi ; if (lk > -large) maxLi += lk*aik ; else ++infLi ; } else if (aik < 0.0) { if (uk < large) maxLi += uk*aik ; else ++infLi ; if (lk > -large) maxUi += lk*aik ; else ++infUi ; } } const double maxUinf = maxUi+infUi*1.0e31 ; const double maxLinf = maxLi-infLi*1.0e31 ; if (maxUinf <= rupi+feasTol && maxLinf >= rloi-feasTol) { infiniteUp[i] = -2 ; } else if (maxUinf < rloi-feasTol && !fixInfeasibility) { prob->status_|= 1 ; infeas = true ; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) << i << rloi << rupi << CoinMessageEol ; infiniteUp[i] = -3 ; } else if (maxLinf > rupi+feasTol && !fixInfeasibility) { prob->status_|= 1 ; infeas = true ; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) << i << rloi << rupi << CoinMessageEol ; infiniteUp[i] = -3 ; } else { infiniteUp[i] = infUi ; infiniteDown[i] = infLi ; maxUp[i] = maxUi ; maxDown[i] = maxLi ; } } else { infUi = infiniteUp[i] ; infLi = infiniteDown[i] ; maxUi = maxUp[i] ; maxLi = maxDown[i] ; } # if PRESOLVE_DEBUG > 2 std::cout << " row(" << i << ") " << leni << " nonzeros, blow " << rloi << ", L (" << infLi << "," << maxLi << "), U (" << infUi << "," << maxUi << "), b " << rupi ; if (infeas) std::cout << " infeas" ; if (infiniteUp[i] == -2) std::cout << " useless" ; std::cout << "." << std::endl ; # endif /* If we're infeasible, no sense checking further; escape the implied bound loop. The other possibility is that we've just discovered the constraint is useless, in which case we just move on to the next one in the column. */ if (infeas) break ; if (infiniteUp[i] == -2) continue ; assert(infiniteUp[i] >= 0 && infiniteUp[i] <= leni) ; /* At this point we have L(i) and U(i), expressed as finite and infinite components, and constraint i is neither useless or infeasible. Calculate the implied bounds l'(t) and u'(t) on x(t). The calculation (for a(it) > 0) is u'(t) <= (b(i) - (L(i)-a(it)l(t)))/a(it) = l(t)+(b(i)-L(i))/a(it) l'(t) >= (blow(i) - (U(i)-a(it)u(t)))/a(it) = u(t)+(blow(i)-U(i))/a(it) Insert the appropriate flips for a(it) < 0. Notice that if there's exactly one infinite contribution to L(i) or U(i) and x(t) is responsible, then the finite portion of L(i) or U(i) is already correct. Cut some slack for possible numerical inaccuracy if the finite portion of L(i) or U(i) is very large. If the new bound is very large, force it to infinity. */ double ltprime = -COIN_DBL_MAX ; double utprime = COIN_DBL_MAX ; if (ait > 0.0) { if (rloi > -large) { if (!infUi) { assert(ut < large) ; ltprime = ut+(rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxUi) ; } else if (infUi == 1 && ut > large) { ltprime = (rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxUi) ; } else { ltprime = -COIN_DBL_MAX ; } impliedLow = CoinMax(impliedLow,ltprime) ; } if (rupi < large) { if (!infLi) { assert(lt > -large) ; utprime = lt+(rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxLi) ; } else if (infLi == 1 && lt < -large) { utprime = (rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxLi) ; } else { utprime = COIN_DBL_MAX ; } impliedHigh = CoinMin(impliedHigh,utprime) ; } } else { if (rloi > -large) { if (!infUi) { assert(lt > -large) ; utprime = lt+(rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxUi) ; } else if (infUi == 1 && lt < -large) { utprime = (rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxUi) ; } else { utprime = COIN_DBL_MAX ; } impliedHigh = CoinMin(impliedHigh,utprime) ; } if (rupi < large) { if (!infLi) { assert(ut < large) ; ltprime = ut+(rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxLi) ; } else if (infLi == 1 && ut > large) { ltprime = (rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxLi) ; } else { ltprime = -COIN_DBL_MAX ; } impliedLow = CoinMax(impliedLow,ltprime) ; } } # if PRESOLVE_DEBUG > 2 std::cout << " row(" << i << ") l'(" << tgtcol << ") " << ltprime << ", u'(" << tgtcol << ") " << utprime ; if (lt <= impliedLow && impliedHigh <= ut) std::cout << "; implied free satisfied" ; std::cout << "." << std::endl ; # endif /* For x(t) integral, see if a substitution formula based on row i will preserve integrality. The final check in this clause aims to preserve SOS equalities (i.e., don't eliminate a non-trivial SOS equality from the system using this transform). Note that this can't be folded into the L(i)/U(i) loop because the answer changes with x(t). Original comment: can only accept if good looking row */ if (integerType[tgtcol]) { possibleRow = true ; bool allOnes = true ; for (CoinBigIndex krow = krs ; krow < kre ; ++krow) { const int j = colIndices[krow] ; const double scaled_aij = rowCoeffs[krow]/ait ; if (fabs(scaled_aij) != 1.0) allOnes = false ; if (!integerType[j] || fabs(scaled_aij-floor(scaled_aij+0.5)) > feasTol) { possibleRow = false ; break ; } } if (rloi == 1.0 && leni >= 5 && stopSomeStuff && allOnes) possibleRow = false ; rowiOK = rowiOK && possibleRow ; } /* Do we have a winner? If we have an incumbent, prefer the one with fewer coefficients. */ if (rowiOK) { if (subst_ndx < 0 || (leni < subst_len)) { # if PRESOLVE_DEBUG > 2 std::cout << " row(" << i << ") now candidate for x(" << tgtcol << ")." << std::endl ; # endif subst_ndx = i ; subst_len = leni ; } } } if (infeas) break ; /* Can we do the transform? If so, subst_ndx will have a valid row. Record the implied free variable and the equality we'll use to substitute it out. Take the row out of the running --- we can't use the same row for two substitutions. */ if (lt <= impliedLow && impliedHigh <= ut && (subst_ndx >= 0 || singletonRow)) { implied_free[numberFree] = subst_ndx ; infiniteUp[subst_ndx] = -4 ; whichFree[numberFree++] = tgtcol ; # if PRESOLVE_DEBUG > 1 std::cout << " x(" << tgtcol << ") implied free by row " << subst_ndx << std::endl ; # endif } } delete[] infiniteDown ; delete[] infiniteUp ; delete[] maxDown ; delete[] maxUp ; /* If we're infeasible, there's nothing more to be done. */ if (infeas) { # if PRESOLVE_SUMMARY > 0 || PRESOLVE_DEBUG > 0 std::cout << " IMPLIED_FREE: infeasible." << std::endl ; # endif return (next) ; } /* We have a list of implied free variables, each with a row that can be used to substitute the variable to singleton status if the variable is not a natural singleton. The loop here will only process natural singletons. We'll hand the remainder to subst_constraint_action below, if there is a remainder. The natural singletons processed here are compressed out of whichFree and implied_free. */ int unprocessed = 0 ; for (iLook = 0 ; iLook < numberFree ; iLook++) { const int tgtcol = whichFree[iLook] ; if (colLengths[tgtcol] != 1) { whichFree[unprocessed] = whichFree[iLook] ; implied_free[unprocessed] = implied_free[iLook] ; unprocessed++ ; continue ; } const int tgtrow = implied_free[iLook] ; const int tgtrow_len = rowLengths[tgtrow] ; const CoinBigIndex kcs = colStarts[tgtcol] ; const double tgtcol_coeff = colCoeffs[kcs] ; const double tgtcol_cost = cost[tgtcol] ; const CoinBigIndex krs = rowStarts[tgtrow] ; const CoinBigIndex kre = krs+tgtrow_len ; if (tgtcol_cost != 0.0) { // Check costs don't make unstable //double minOldCost=COIN_DBL_MAX; double maxOldCost=0.0; //double minNewCost=COIN_DBL_MAX; double maxNewCost=0.0; for (CoinBigIndex krow = krs ; krow < kre ; krow++) { const int j = colIndices[krow] ; if (j != tgtcol) { double oldCost = cost[j] ; double newCost = oldCost - (tgtcol_cost*rowCoeffs[krow])/tgtcol_coeff ; oldCost = fabs(oldCost); newCost = fabs(newCost); //minOldCost=CoinMin(minOldCost,oldCost); maxOldCost=CoinMax(maxOldCost,oldCost); //minNewCost=CoinMin(minNewCost,newCost); maxNewCost=CoinMax(maxNewCost,newCost); } } if (maxNewCost>1000.0*(maxOldCost+1.0) && maxOldCost) { //printf("too big %d tgtcost %g maxOld %g maxNew %g\n", // tgtcol,tgtcol_cost,maxOldCost,maxNewCost); continue; } } /* Initialise the postsolve action. We need to remember the row and column. */ action *s = &actions[nactions++] ; s->row = tgtrow ; s->col = tgtcol ; s->clo = clo[tgtcol] ; s->cup = cup[tgtcol] ; s->rlo = rlo[tgtrow] ; s->rup = rup[tgtrow] ; s->ninrow = tgtrow_len ; s->rowels = presolve_dupmajor(rowCoeffs,colIndices,tgtrow_len,krs) ; s->costs = NULL ; /* We're processing a singleton, hence no substitutions in the matrix, but we do need to fix up the cost vector. The substitution formula is x(t) = (rhs(i) - SUM{j\t}a(ik)x(k))/a(it) hence c'(k) = c(k)-c(t)a(ik)/a(it) and there's a constant offset c(t)rhs(i)/a(it). where rhs(i) is one of blow(i) or b(i). For general constraints where blow(i) != b(i), we need to take a bit of care. If only one of blow(i) or b(i) is finite, that's the one to use. Where we have two finite but unequal bounds, choose the bound that will result in the most favourable value for x(t). For minimisation, if c(t) < 0 we want to maximise x(t), so choose b(i) if a(it) > 0, blow(i) if a(it) < 0. A bit of case analysis says choose b(i) when c(t)a(it) < 0, blow(i) when c(t)a(it) > 0. We shouldn't be here if both row bounds are infinite. Fortunately, the objective coefficients are not affected by this. */ if (tgtcol_cost != 0.0) { double tgtrow_rhs = rup[tgtrow] ; if (fabs(rlo[tgtrow]-rup[tgtrow]) > feasTol) { const double rlot = rlo[tgtrow] ; const double rupt = rup[tgtrow] ; if (rlot > -COIN_DBL_MAX && rupt < COIN_DBL_MAX) { if ((tgtcol_cost*tgtcol_coeff) > 0) tgtrow_rhs = rlot ; else tgtrow_rhs = rupt ; } else if (rupt >= COIN_DBL_MAX) { tgtrow_rhs = rlot ; } } assert(fabs(tgtrow_rhs) <= large) ; double *save_costs = new double[tgtrow_len] ; for (CoinBigIndex krow = krs ; krow < kre ; krow++) { const int j = colIndices[krow] ; save_costs[krow-krs] = cost[j] ; cost[j] -= (tgtcol_cost*rowCoeffs[krow])/tgtcol_coeff ; } prob->change_bias((tgtcol_cost*tgtrow_rhs)/tgtcol_coeff) ; cost[tgtcol] = 0.0 ; s->costs = save_costs ; } /* Remove the row from the column-major representation, queuing up each column for reconsideration. Then remove the row from the row-major representation. */ for (CoinBigIndex krow = krs ; krow < kre ; krow++) { const int j = colIndices[krow] ; presolve_delete_from_col(tgtrow,j,colStarts,colLengths,rowIndices, colCoeffs) ; if (colLengths[j] == 0) { PRESOLVE_REMOVE_LINK(prob->clink_,j) ; } else { prob->addCol(j) ; } } PRESOLVE_REMOVE_LINK(clink,tgtcol) ; colLengths[tgtcol] = 0 ; PRESOLVE_REMOVE_LINK(rlink,tgtrow) ; rowLengths[tgtrow] = 0 ; rlo[tgtrow] = 0.0 ; rup[tgtrow] = 0.0 ; } /* We're done with the natural singletons. Trim actions to length and create the postsolve object. */ if (nactions) { # if PRESOLVE_SUMMARY > 0 || PRESOLVE_DEBUG > 0 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 PRESOLVE_DEBUG > 0 std::cout << " IMPLIED_FREE: identified " << numberFree << " implied free transforms, processed " << numberFree-unprocessed << " natural singletons." << std::endl ; # endif /* Now take a stab at the columns that aren't natural singletons, if there are any left. */ if (unprocessed != 0) { // if not integer - don't allow much fill if (!prob->anyInteger()) { int numberFree=unprocessed; int nBad=0; unprocessed=0; // Take out ones that make much denser or might lead to instability /* Unpack the row- and column-major representations. */ CoinBigIndex *rowStarts = prob->mrstrt_ ; int *rowLengths = prob->hinrow_ ; double *rowCoeffs = prob->rowels_ ; int *colIndices = prob->hcol_ ; CoinBigIndex *colStarts = prob->mcstrt_ ; int *colLengths = prob->hincol_ ; double *colCoeffs = prob->colels_ ; int *rowIndices = prob->hrow_ ; /* 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. NOTE that usefulColumnInt_ is already in use for parameters implied_free and whichFree when this routine is called from implied_free. */ 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 tgtrow = implied_free[iLook] ; 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 ; } if (dealBreaker == true) { # if PRESOLVE_DEBUG > 3 std::cout << " skipping eqn " << tgtrow << " x(" << tgtcol << "); deal breaker (2)." << std::endl ; # endif continue ; } /* 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 ; } CoinBigIndex tgtrs = rowStarts[tgtrow] ; CoinBigIndex tgtre = tgtrs+rowLengths[tgtrow] ; // 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 */ CoinSort_2(colIndices+tgtrs,colIndices+tgtre,rowCoeffs+tgtrs) ; CoinBigIndex start=colStarts[tgtcol]; CoinBigIndex end = start+colLengths[tgtcol]; numberBadElements=0; int numberFill=-rowLengths[tgtrow]; for (int colndx = start ; colndx < end ; ++colndx) { int i = rowIndices[colndx] ; if (i == tgtrow) continue ; double ait = colCoeffs[colndx] ; double coeff_factor = -ait/tgtcoeff ; CoinBigIndex krs = rowStarts[i] ; CoinBigIndex kre = krs+rowLengths[i] ; /* 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) ; numberFill += check_row(rowStarts,rowCoeffs,colIndices, rowLengths,coeff_factor,tolerance,i,tgtrow); } if (numberBadElements||3*numberFill>2*(colLengths[tgtcol]+rowLengths[tgtrow])) { //printf("Bad subst col %d row %d - %d small elements, fill %d\n", // tgtcol,tgtrow,numberBadElements,numberFill); if (numberBadElements) nBad++; } else { whichFree[unprocessed]=tgtcol; implied_free[unprocessed++]=tgtrow; //printf("Good subst col %d row %d - fill %d\n", // tgtcol,tgtrow,numberFill); } } /* 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]) ; #if CLP_USEFUL_PRINTOUT printf("%d allowed through out of %d - %d on coefficient\n", unprocessed,numberFree,nBad); #endif } next = subst_constraint_action::presolve(prob,implied_free,whichFree, unprocessed,next,maxLook) ; } /* Give some feedback to the presolve driver. If we aren't finding enough candidates and haven't reached the limit, bump fill_level and return a negated value. The presolve driver can tweak this value or simply return it on the next call. See the top of the routine for a full explanation. */ if (numberFree < 30 && maxLook < prob->maxSubstLevel_) { fill_level = -(maxLook+1) ; } else { fill_level = maxLook ; } # if COIN_PRESOLVE_TUNING > 0 double thisTime ; if (prob->tuning_) thisTime = CoinCpuTime() ; # endif # if PRESOLVE_CONSISTENCY > 0 || PRESOLVE_DEBUG > 0 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 droppedRows = prob->countEmptyRows()-startEmptyRows ; int droppedColumns = prob->countEmptyCols()-startEmptyColumns ; std::cout << "Leaving implied_free_action::presolve, fill level " << fill_level << ", " << droppedRows << " rows, " << droppedColumns << " columns dropped" ; # if COIN_PRESOLVE_TUNING > 0 std::cout << " in " << thisTime-startTime << "s" ; # endif std::cout << "." << std::endl ; # endif return (next) ; }
//----------------------------------------------------------------------------- // Generate Lift-and-Project cuts //------------------------------------------------------------------- void CglLiftAndProject::generateCuts(const OsiSolverInterface& si, OsiCuts& cs, const CglTreeInfo /*info*/) { // Assumes the mixed 0-1 problem // // min {cx: <Atilde,x> >= btilde} // // is in canonical form with all bounds, // including x_t>=0, -x_t>=-1 for x_t binary, // explicitly stated in the constraint matrix. // See ~/COIN/Examples/Cgl2/cgl2.cpp // for a general purpose "convert" function. // Reference [BCC]: Balas, Ceria, and Corneujols, // "A lift-and-project cutting plane algorithm // for mixed 0-1 program", Math Prog 58, (1993) // 295-324. // This implementation uses Normalization 1. // Given canonical problem and // the lp-relaxation solution, x, // the LAP cut generator attempts to construct // a cut for every x_j such that 0<x_j<1 // [BCC:307] // x_j is the strictly fractional binary variable // the cut is generated from int j = 0; // Get basic problem information // let Atilde be an m by n matrix const int m = si.getNumRows(); const int n = si.getNumCols(); const double * x = si.getColSolution(); // Remember - Atildes may have gaps.. const CoinPackedMatrix * Atilde = si.getMatrixByRow(); const double * AtildeElements = Atilde->getElements(); const int * AtildeIndices = Atilde->getIndices(); const CoinBigIndex * AtildeStarts = Atilde->getVectorStarts(); const int * AtildeLengths = Atilde->getVectorLengths(); const int AtildeFullSize = AtildeStarts[m]; const double * btilde = si.getRowLower(); // Set up memory for system (10) [BCC:307] // (the problem over the norm intersected // with the polar cone) // // min <<x^T,Atilde^T>,u> + x_ju_0 // s.t. // <B,w> = (0,...,0,beta_,beta)^T // w is nonneg for all but the // last two entries, which are free. // where // w = (u,v,v_0,u_0)in BCC notation // u and v are m-vectors; u,v >=0 // v_0 and u_0 are free-scalars, and // // B = Atilde^T -Atilde^T -e_j e_j // btilde^T e_0^T 0 0 // e_0^T btilde^T 1 0 // ^T indicates Transpose // e_0 is a (AtildeNCols x 1) vector of all zeros // e_j is e_0 with a 1 in the jth position // Storing B in column order. B is a (n+2 x 2m+2) matrix // But need to allow for possible gaps in Atilde. // At each iteration, only need to change 2 cols and objfunc // Sane design of OsiSolverInterface does not permit mucking // with matrix. // Because we must delete and add cols to alter matrix, // and we can only add columns on the end of the matrix // put the v_0 and u_0 columns on the end. // rather than as described in [BCC] // Initially allocating B with space for v_0 and u_O cols // but not populating, for efficiency. // B without u_0 and v_0 is a (n+2 x 2m) size matrix. int twoM = 2*m; int BNumRows = n+2; int BNumCols = twoM+2; int BFullSize = 2*AtildeFullSize+twoM+3; double * BElements = new double[BFullSize]; int * BIndices = new int[BFullSize]; CoinBigIndex * BStarts = new CoinBigIndex [BNumCols+1]; int * BLengths = new int[BNumCols]; int i, ij, k=0; int nPlus1=n+1; int offset = AtildeStarts[m]+m; for (i=0; i<m; i++){ for (ij=AtildeStarts[i];ij<AtildeStarts[i]+AtildeLengths[i];ij++){ BElements[k]=AtildeElements[ij]; BElements[k+offset]=-AtildeElements[ij]; BIndices[k]= AtildeIndices[ij]; BIndices[k+offset]= AtildeIndices[ij]; k++; } BElements[k]=btilde[i]; BElements[k+offset]=btilde[i]; BIndices[k]=n; BIndices[k+offset]=nPlus1; BStarts[i]= AtildeStarts[i]+i; BStarts[i+m]=offset+BStarts[i];// = AtildeStarts[m]+m+AtildeStarts[i]+i BLengths[i]= AtildeLengths[i]+1; BLengths[i+m]= AtildeLengths[i]+1; k++; } BStarts[twoM]=BStarts[twoM-1]+BLengths[twoM-1]; // Cols that will be deleted each iteration int BNumColsLessOne=BNumCols-1; int BNumColsLessTwo=BNumCols-2; const int delCols[2] = {BNumColsLessOne, BNumColsLessTwo}; // Set lower bound on u and v // u_0, v_0 will be reset as free const double solverINFINITY = si.getInfinity(); double * BColLowers = new double[BNumCols]; double * BColUppers = new double[BNumCols]; CoinFillN(BColLowers,BNumCols,0.0); CoinFillN(BColUppers,BNumCols,solverINFINITY); // Set row lowers and uppers. // The rhs is zero, for but the last two rows. // For these the rhs is beta_ double * BRowLowers = new double[BNumRows]; double * BRowUppers = new double[BNumRows]; CoinFillN(BRowLowers,BNumRows,0.0); CoinFillN(BRowUppers,BNumRows,0.0); BRowLowers[BNumRows-2]=beta_; BRowUppers[BNumRows-2]=beta_; BRowLowers[BNumRows-1]=beta_; BRowUppers[BNumRows-1]=beta_; // Calculate base objective <<x^T,Atilde^T>,u> // Note: at each iteration coefficient u_0 // changes to <x^T,e_j> // w=(u,v,beta,v_0,u_0) size 2m+3 // So, BOjective[2m+2]=x[j] double * BObjective= new double[BNumCols]; double * Atildex = new double[m]; CoinFillN(BObjective,BNumCols,0.0); Atilde->times(x,Atildex); // Atildex is size m, x is size n CoinDisjointCopyN(Atildex,m,BObjective); // Number of cols and size of Elements vector // in B without the v_0 and u_0 cols int BFullSizeLessThree = BFullSize-3; // Load B matrix into a column orders CoinPackedMatrix CoinPackedMatrix * BMatrix = new CoinPackedMatrix(true, BNumRows, BNumColsLessTwo, BFullSizeLessThree, BElements,BIndices, BStarts,BLengths); // Assign problem into a solver interface // Note: coneSi will cleanup the memory itself OsiSolverInterface * coneSi = si.clone(false); coneSi->assignProblem (BMatrix, BColLowers, BColUppers, BObjective, BRowLowers, BRowUppers); // Problem sense should default to "min" by default, // but just to be virtuous... coneSi->setObjSense(1.0); // The plot outline from here on down: // coneSi has been assigned B without the u_0 and v_0 columns // Calculate base objective <<x^T,Atilde^T>,u> // bool haveWarmStart = false; // For (j=0; j<n, j++) // if (!isBinary(x_j) || x_j<=0 || x_j>=1) continue; // // IMPROVEME: if(haveWarmStart) check if j attractive // add {-e_j,0,-1} matrix column for v_0 // add {e_j,0,0} matrix column for u_0 // objective coefficient for u_0 is x_j // if (haveWarmStart) // set warmstart info // solve min{objw:Bw=0; w>=0,except v_0, u_0 free} // if (bounded) // get warmstart info // haveWarmStart=true; // ustar = optimal u solution // ustar_0 = optimal u_0 solution // alpha^T= <ustar^T,Atilde> -ustar_0e_j^T // (double check <alpha^T,x> >= beta_ should be violated) // add <alpha^T,x> >= beta_ to cutset // endif // delete column for u_0 // this deletes all column info. // delete column for v_0 // endFor // clean up memory // return 0; int * nVectorIndices = new int[n]; CoinIotaN(nVectorIndices, n, 0); bool haveWarmStart = false; bool equalObj1, equalObj2; CoinRelFltEq eq; double v_0Elements[2] = {-1,1}; double u_0Elements[1] = {1}; CoinWarmStart * warmStart = 0; double * ustar = new double[m]; CoinFillN(ustar, m, 0.0); double* alpha = new double[n]; CoinFillN(alpha, n, 0.0); for (j=0;j<n;j++){ if (!si.isBinary(j)) continue; // Better to ask coneSi? No! // coneSi has no binInfo. equalObj1=eq(x[j],0); equalObj2=eq(x[j],1); if (equalObj1 || equalObj2) continue; // IMPROVEME: if (haveWarmStart) check if j attractive; // AskLL:wanted to declare u_0 and v_0 packedVec outside loop // and setIndices, but didn't see a method to do that(?) // (Could "insert". Seems inefficient) int v_0Indices[2]={j,nPlus1}; int u_0Indices[1]={j}; // CoinPackedVector v_0(2,v_0Indices,v_0Elements,false); CoinPackedVector u_0(1,u_0Indices,u_0Elements,false); #if CGL_DEBUG const CoinPackedMatrix *see1 = coneSi->getMatrixByRow(); #endif coneSi->addCol(v_0,-solverINFINITY,solverINFINITY,0); coneSi->addCol(u_0,-solverINFINITY,solverINFINITY,x[j]); if(haveWarmStart) { coneSi->setWarmStart(warmStart); coneSi->resolve(); } else { #if CGL_DEBUG const CoinPackedMatrix *see2 = coneSi->getMatrixByRow(); #endif coneSi->initialSolve(); } if(coneSi->isProvenOptimal()){ warmStart = coneSi->getWarmStart(); haveWarmStart=true; const double * wstar = coneSi->getColSolution(); CoinDisjointCopyN(wstar, m, ustar); Atilde->transposeTimes(ustar,alpha); alpha[j]+=wstar[BNumCols-1]; #if debug int p; double sum; for(p=0;p<n;p++)sum+=alpha[p]*x[p]; if (sum<=beta_){ throw CoinError("Cut not violated", "cutGeneration", "CglLiftAndProject"); } #endif // add <alpha^T,x> >= beta_ to cutset OsiRowCut rc; rc.setRow(n,nVectorIndices,alpha); rc.setLb(beta_); rc.setUb(solverINFINITY); cs.insert(rc); } // delete col for u_o and v_0 coneSi->deleteCols(2,delCols); // clean up memory } // clean up delete [] alpha; delete [] ustar; delete [] nVectorIndices; // BMatrix, BColLowers,BColUppers, BObjective, BRowLowers, BRowUppers // are all freed by OsiSolverInterface destructor (?) delete [] BLengths; delete [] BStarts; delete [] BIndices; delete [] BElements; }
int MilpRounding::solution(double &solutionValue, double *betterSolution) { if(model_->getCurrentPassNumber() > 1) return 0; if (model_->currentDepth() > 2 && (model_->getNodeCount()%howOften_)!=0) return 0; int returnCode = 0; // 0 means it didn't find a feasible solution OsiTMINLPInterface * nlp = NULL; if(setup_->getAlgorithm() == B_BB) nlp = dynamic_cast<OsiTMINLPInterface *>(model_->solver()->clone()); else nlp = dynamic_cast<OsiTMINLPInterface *>(setup_->nonlinearSolver()->clone()); TMINLP2TNLP* minlp = nlp->problem(); // set tolerances double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); //double primalTolerance = 1.0e-6; int n; int m; int nnz_jac_g; int nnz_h_lag; Ipopt::TNLP::IndexStyleEnum index_style; minlp->get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style); const Bonmin::TMINLP::VariableType* variableType = minlp->var_types(); const double* x_sol = minlp->x_sol(); const double* g_l = minlp->g_l(); const double* g_u = minlp->g_u(); const double * colsol = model_->solver()->getColSolution(); // Get information about the linear and nonlinear part of the instance TMINLP* tminlp = nlp->model(); vector<Ipopt::TNLP::LinearityType> c_lin(m); tminlp->get_constraints_linearity(m, c_lin()); vector<int> c_idx(m); int n_lin = 0; for (int i=0;i<m;i++) { if (c_lin[i]==Ipopt::TNLP::LINEAR) c_idx[i] = n_lin++; else c_idx[i] = -1; } // Get the structure of the jacobian vector<int> indexRow(nnz_jac_g); vector<int> indexCol(nnz_jac_g); minlp->eval_jac_g(n, x_sol, false, m, nnz_jac_g, indexRow(), indexCol(), 0); // get the jacobian values vector<double> jac_g(nnz_jac_g); minlp->eval_jac_g(n, x_sol, false, m, nnz_jac_g, NULL, NULL, jac_g()); // Sort the matrix to column ordered vector<int> sortedIndex(nnz_jac_g); CoinIotaN(sortedIndex(), nnz_jac_g, 0); MatComp c; c.iRow = indexRow(); c.jCol = indexCol(); std::sort(sortedIndex.begin(), sortedIndex.end(), c); vector<int> row (nnz_jac_g); vector<double> value (nnz_jac_g); vector<int> columnStart(n,0); vector<int> columnLength(n,0); int indexCorrection = (index_style == Ipopt::TNLP::C_STYLE) ? 0 : 1; int iniCol = -1; int nnz = 0; for(int i=0; i<nnz_jac_g; i++) { int thisIndexCol = indexCol[sortedIndex[i]]-indexCorrection; int thisIndexRow = c_idx[indexRow[sortedIndex[i]] - indexCorrection]; if(thisIndexCol != iniCol) { iniCol = thisIndexCol; columnStart[thisIndexCol] = nnz; columnLength[thisIndexCol] = 0; } if(thisIndexRow == -1) continue; columnLength[thisIndexCol]++; row[nnz] = thisIndexRow; value[nnz] = jac_g[i]; nnz++; } // Build the row lower and upper bounds vector<double> newRowLower(n_lin); vector<double> newRowUpper(n_lin); for(int i = 0 ; i < m ; i++){ if(c_idx[i] == -1) continue; newRowLower[c_idx[i]] = g_l[i]; newRowUpper[c_idx[i]] = g_u[i]; } // Get solution array for heuristic solution vector<double> newSolution(n); std::copy(x_sol, x_sol + n, newSolution.begin()); // Define the constraint matrix for MILP CoinPackedMatrix matrix(true,n_lin,n, nnz, value(), row(), columnStart(), columnLength()); // create objective function and columns lower and upper bounds for MILP // and create columns for matrix in MILP //double alpha = 0; double beta = 1; vector<double> objective(n); vector<int> idxIntegers; idxIntegers.reserve(n); for(int i = 0 ; i < n ; i++){ if(variableType[i] != Bonmin::TMINLP::CONTINUOUS){ idxIntegers.push_back(i); objective[i] = beta*(1 - 2*colsol[i]); } } #if 0 // Get dual multipliers and build gradient of the lagrangean const double * duals = nlp->getRowPrice() + 2 *n; vector<double> grad(n, 0); vector<int> indices(n, 0); tminlp->eval_grad_f(n, x_sol, false, grad()); for(int i = 0 ; i < m ; i++){ if(c_lin[i] == Ipopt::TNLP::LINEAR) continue; int nnz; tminlp->eval_grad_gi(n, x_sol, false, i, nnz, indices(), NULL); tminlp->eval_grad_gi(n, x_sol, false, i, nnz, NULL, grad()); for(int k = 0 ; k < nnz ; k++){ objective[indices[k]] += alpha *duals[i] * grad[k]; } } for(int i = 0 ; i < n ; i++){ if(variableType[i] != Bonmin::TMINLP::CONTINUOUS) objective[i] += alpha * grad[i]; //if(fabs(objective[i]) < 1e-4) objective[i] = 0; else objective[i] = 0; } std::copy(objective.begin(), objective.end(), std::ostream_iterator<double>(std::cout, " ")); std::cout<<std::endl; #endif // load the problem to OSI OsiSolverInterface *si = mip_->solver(); assert(si != NULL); CoinMessageHandler * handler = model_->messageHandler()->clone(); si->passInMessageHandler(handler); si->messageHandler()->setLogLevel(1); si->loadProblem(matrix, model_->solver()->getColLower(), model_->solver()->getColUpper(), objective(), newRowLower(), newRowUpper()); si->setInteger(idxIntegers(), static_cast<int>(idxIntegers.size())); si->applyCuts(noGoods); bool hasFractionnal = true; while(hasFractionnal){ mip_->optimize(DBL_MAX, 0, 60); hasFractionnal = false; #if 0 bool feasible = false; if(mip_->getLastSolution()) { const double* solution = mip_->getLastSolution(); std::copy(solution, solution + n, newSolution.begin()); feasible = true; } if(feasible) { // fix the integer variables and solve the NLP // also add no good cut CoinPackedVector v; double lb = 1; for (int iColumn=0;iColumn<n;iColumn++) { if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) { double value=newSolution[iColumn]; if (fabs(floor(value+0.5)-value)>integerTolerance) { #ifdef DEBUG_BON_HEURISTIC_DIVE_MIP cout<<"It should be infeasible because: "<<endl; cout<<"variable "<<iColumn<<" is not integer"<<endl; #endif feasible = false; break; } else { value=floor(newSolution[iColumn]+0.5); if(value > 0.5){ v.insert(iColumn, -1); lb -= value; } minlp->SetVariableUpperBound(iColumn, value); minlp->SetVariableLowerBound(iColumn, value); } } } } #endif } bool feasible = false; if(mip_->getLastSolution()) { const double* solution = mip_->getLastSolution(); std::copy(solution, solution + n, newSolution.begin()); feasible = true; delete handler; } if(feasible) { // fix the integer variables and solve the NLP // also add no good cut CoinPackedVector v; double lb = 1; for (int iColumn=0;iColumn<n;iColumn++) { if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) { double value=newSolution[iColumn]; if (fabs(floor(value+0.5)-value)>integerTolerance) { feasible = false; break; } else { value=floor(newSolution[iColumn]+0.5); if(value > 0.5){ v.insert(iColumn, -1); lb -= value; } minlp->SetVariableUpperBound(iColumn, value); minlp->SetVariableLowerBound(iColumn, value); } } } OsiRowCut c; c.setRow(v); c.setLb(lb); c.setUb(DBL_MAX); noGoods.insert(c); if(feasible) { nlp->initialSolve(); if(minlp->optimization_status() != Ipopt::SUCCESS) { feasible = false; } std::copy(x_sol,x_sol+n, newSolution.begin()); } } if(feasible) { double newSolutionValue; minlp->eval_f(n, newSolution(), true, newSolutionValue); if(newSolutionValue < solutionValue) { std::copy(newSolution.begin(), newSolution.end(), betterSolution); solutionValue = newSolutionValue; returnCode = 1; } } delete nlp; #ifdef DEBUG_BON_HEURISTIC_DIVE_MIP std::cout<<"DiveMIP returnCode = "<<returnCode<<std::endl; #endif return returnCode; }