// ----------------------------------------------------------------- void SPxSolver::perturbMax( const UpdateVector& uvec, Vector& p_low, Vector& p_up, Real eps, Real delta, int start, int incr) { METHOD( "SPxSolver::perturbMax()" ); assert(uvec.dim() == p_low.dim()); assert(uvec.dim() == p_up.dim()); const Real* vec = uvec.get_const_ptr(); const Real* upd = uvec.delta().values(); const IdxSet& idx = uvec.delta().indices(); Random mult(10.0 * delta, 100.0 * delta); Real x, l, u; int i, j; #ifdef FULL_SHIFT eps = delta; for (i = uvec.dim() - start - 1; i >= 0; i -= incr) { u = p_up[i]; l = p_low[i]; if (p_up[i] <= vec[i] + eps) { p_up[i] = vec[i] + Real(mult); theShift += p_up[i] - u; } if (p_low[i] >= vec[i] - eps) { p_low[i] = vec[i] - Real(mult); theShift -= p_low[i] - l; } } #else // !FULL_SHIFT for (j = uvec.delta().size() - start - 1; j >= 0; j -= incr) { i = idx.index(j); x = upd[i]; u = p_up[i]; l = p_low[i]; if (x > epsilon()) { if (u != l && vec[i] >= u - eps) { p_up[i] = vec[i] + Real(mult); theShift += p_up[i] - u; } } else if (x < epsilon()) { if (u != l && vec[i] <= l + eps) { p_low[i] = vec[i] - Real(mult); theShift -= p_low[i] - l; } } } #endif // !FULL_SHIFT }
/* See maxDelta() */ int SPxFastRT::minDelta( Real& val, Real& maxabs, UpdateVector& update, const Vector& lowBound, const Vector& upBound, int start, int incr) const { int i, sel; Real x, y, max; Real u, l; bool columnleaving = thesolver->rep() == SPxSolver::COLUMN && m_type == SPxSolver::LEAVE; Real mabs = maxabs; const Real* up = upBound.get_const_ptr(); const Real* low = lowBound.get_const_ptr(); const Real* vec = update.get_const_ptr(); const Real* upd = update.delta().values(); const int* idx = update.delta().indexMem(); sel = -1; max = val; if (update.delta().isSetup()) { const int* last = idx + update.delta().size(); for (idx += start; idx < last; idx += incr) { i = *idx; x = upd[i]; /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */ if( columnleaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) ) continue; if (x > epsilon) { // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below mabs = (x > mabs) ? x : mabs; l = low[i]; if (l > -infinity) { y = l - vec[i]; if ( y >= 0 ) x = - fastDelta / x; else x = ( y - fastDelta ) / x; if (x > max) { max = x; sel = i; } } } else if (x < -epsilon) { // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below mabs = (-x > mabs) ? -x : mabs; u = up[i]; if (u < infinity) { y = u - vec[i]; if (y <= 0) x = fastDelta / x; else x = (y + fastDelta) / x; if (x > max) { max = x; sel = i; } } } } } else { /* In this case, the indices of the semi-sparse vector update.delta() are not set up and are filled below. */ int* l_idx = update.delta().altIndexMem(); Real* uval = update.delta().altValues(); const Real* uend = uval + update.dim(); assert( uval == upd ); for (i = 0; uval < uend; ++uval, ++i) { x = *uval; if (x) { if (x >= -epsilon && x <= epsilon) { *uval = 0.0; continue; } else *l_idx++ = i; /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */ if( columnleaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) ) continue; if (x > epsilon) { mabs = (x > mabs) ? x : mabs; l = low[i]; if (l > -infinity) { y = l - vec[i]; if ( y >= 0 ) x = - fastDelta / x; else x = ( y - fastDelta ) / x; if (x > max) { max = x; sel = i; } } } else if (x < -epsilon) { mabs = (-x > mabs) ? -x : mabs; u = up[i]; if (u < infinity) { y = u - vec[i]; if (y <= 0) x = fastDelta / x; else x = (y + fastDelta) / x; if (x > max) { max = x; sel = i; } } } } } update.delta().setSize(int(l_idx - update.delta().indexMem())); update.delta().forceSetup(); } val = max; maxabs = mabs; return sel; }
/* See minSelect() */ int SPxFastRT::maxSelect( Real& val, Real& stab, Real& best, Real& bestDelta, Real max, const UpdateVector& update, const Vector& lowBound, const Vector& upBound, int start, int incr) const { int i; Real x, y; bool columnleaving = thesolver->rep() == SPxSolver::COLUMN && m_type == SPxSolver::LEAVE; const Real* up = upBound.get_const_ptr(); const Real* low = lowBound.get_const_ptr(); const Real* vec = update.get_const_ptr(); const Real* upd = update.delta().values(); const int* idx = update.delta().indexMem(); const int* last = idx + update.delta().size(); int nr = -1; int bestNr = -1; for (idx += start; idx < last; idx += incr) { i = *idx; x = upd[i]; // in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables if( columnleaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) ) continue; if (x > stab) { y = (up[i] - vec[i]) / x; if (y <= max) { val = y; nr = i; stab = x; } else if (y > best) { best = y; bestNr = i; } } else if (x < -stab) { y = (low[i] - vec[i]) / x; if (y <= max) { val = y; nr = i; stab = -x; } else if (y > best) { best = y; bestNr = i; } } } if (nr < 0 && bestNr > 0) { if (upd[bestNr] > 0) bestDelta = up[bestNr] - vec[bestNr]; else bestDelta = vec[bestNr] - low[bestNr]; } return nr; }
// ----------------------------------------------------------------- void SPxSolver::perturbMax( const UpdateVector& uvec, Vector& p_low, Vector& p_up, Real eps, Real p_delta, int start, int incr) { assert(uvec.dim() == p_low.dim()); assert(uvec.dim() == p_up.dim()); const Real* vec = uvec.get_const_ptr(); const Real* upd = uvec.delta().values(); const IdxSet& idx = uvec.delta().indices(); Random mult(10.0 * p_delta, 100.0 * p_delta); Real x, l, u; int i, j; #ifdef FULL_SHIFT eps = p_delta; for (i = uvec.dim() - start - 1; i >= 0; i -= incr) { u = p_up[i]; l = p_low[i]; if (p_up[i] <= vec[i] + eps) { p_up[i] = vec[i] + Real(mult); theShift += p_up[i] - u; } if (p_low[i] >= vec[i] - eps) { p_low[i] = vec[i] - Real(mult); theShift -= p_low[i] - l; } } #else // !FULL_SHIFT for (j = uvec.delta().size() - start - 1; j >= 0; j -= incr) { i = idx.index(j); x = upd[i]; u = p_up[i]; l = p_low[i]; // do not permute these bounds! c.f. computeFrhs2() in spxvecs.cpp if( dualStatus(baseId(i)) == SPxBasis::Desc::D_ON_BOTH ) { continue; } if (x > eps) { if (u != l && vec[i] >= u - eps) { p_up[i] = vec[i] + Real(mult); theShift += p_up[i] - u; } } else if (x < -eps) { if (u != l && vec[i] <= l + eps) { p_low[i] = vec[i] - Real(mult); theShift -= p_low[i] - l; } } } #endif // !FULL_SHIFT }