/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* This file is part of the class library */ /* SoPlex --- the Sequential object-oriented simPlex. */ /* */ /* Copyright 1996-2022 Zuse Institute Berlin */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ /* You may obtain a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* */ /* You should have received a copy of the Apache-2.0 license */ /* along with SoPlex; see the file LICENSE. If not email to soplex@zib.de. */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /**@file spxscaler.hpp * @brief LP scaling base class. */ #include #include #include #include "soplex/dsvector.h" #include "soplex/lprowsetbase.h" #include "soplex/lpcolsetbase.h" #include namespace soplex { template std::ostream& operator<<(std::ostream& s, const SPxScaler& sc) { const DataArray < int >& colscaleExp = *(sc.m_activeColscaleExp); DataArray < int > rowccaleExp = *(sc.m_activeRowscaleExp); s << sc.getName() << " scaler:" << std::endl; s << "colscale = [ "; for(int ci = 0; ci < colscaleExp.size(); ++ci) s << colscaleExp[ci] << " "; s << "]" << std::endl; s << "rowscale = [ "; for(int ri = 0; ri < rowccaleExp.size(); ++ri) s << rowccaleExp[ri] << " "; s << "]" << std::endl; return s; } template SPxScaler::SPxScaler( const char* name, bool colFirst, bool doBoth, SPxOut* outstream) : m_name(name) , m_activeColscaleExp(0) , m_activeRowscaleExp(0) , m_colFirst(colFirst) , m_doBoth(doBoth) , spxout(outstream) { assert(SPxScaler::isConsistent()); } template SPxScaler::SPxScaler(const SPxScaler& old) : m_name(old.m_name) , m_activeColscaleExp(old.m_activeColscaleExp) , m_activeRowscaleExp(old.m_activeRowscaleExp) , m_colFirst(old.m_colFirst) , m_doBoth(old.m_doBoth) , spxout(old.spxout) { assert(SPxScaler::isConsistent()); } template SPxScaler::~SPxScaler() { m_name = 0; } template SPxScaler& SPxScaler::operator=(const SPxScaler& rhs) { if(this != &rhs) { m_name = rhs.m_name; m_activeColscaleExp = rhs.m_activeColscaleExp; m_activeRowscaleExp = rhs.m_activeRowscaleExp; m_colFirst = rhs.m_colFirst; m_doBoth = rhs.m_doBoth; spxout = rhs.spxout; assert(SPxScaler::isConsistent()); } return *this; } template const char* SPxScaler::getName() const { return m_name; } template void SPxScaler::setOrder(bool colFirst) { m_colFirst = colFirst; } template void SPxScaler::setBoth(bool both) { m_doBoth = both; } template void SPxScaler::setRealParam(R param, const char* name) {} template void SPxScaler::setIntParam(int param, const char* name) {} template void SPxScaler::setup(SPxLPBase& lp) { assert(lp.isConsistent()); m_activeColscaleExp = &lp.LPColSetBase::scaleExp; m_activeRowscaleExp = &lp.LPRowSetBase::scaleExp; m_activeColscaleExp->reSize(lp.nCols()); m_activeRowscaleExp->reSize(lp.nRows()); for(int i = 0; i < lp.nCols(); ++i) (*m_activeColscaleExp)[i] = 0; for(int i = 0; i < lp.nRows(); ++i) (*m_activeRowscaleExp)[i] = 0; lp.lp_scaler = this; } template int SPxScaler::computeScaleExp(const SVectorBase& vec, const DataArray& oldScaleExp) const { R maxi = 0.0; // find largest absolute value after applying existing scaling factors for(int i = 0; i < vec.size(); ++i) { R x = spxAbs(spxLdexp(vec.value(i), oldScaleExp[vec.index(i)])); if(GT(x, maxi)) maxi = x; } // empty rows/cols are possible if(maxi == 0.0) return 0; // get exponent corresponding to new scaling factor else { int scaleExp; spxFrexp(R(1.0 / maxi), &(scaleExp)); return scaleExp - 1; } } template void SPxScaler::applyScaling(SPxLPBase& lp) { assert(lp.nCols() == m_activeColscaleExp->size()); assert(lp.nRows() == m_activeRowscaleExp->size()); DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; for(int i = 0; i < lp.nRows(); ++i) { SVectorBase& vec = lp.rowVector_w(i); int exp1; int exp2 = rowscaleExp[i]; for(int j = 0; j < vec.size(); ++j) { exp1 = colscaleExp[vec.index(j)]; vec.value(j) = spxLdexp(vec.value(j), exp1 + exp2); } lp.maxRowObj_w(i) = spxLdexp(lp.maxRowObj(i), exp2); if(lp.rhs(i) < R(infinity)) lp.rhs_w(i) = spxLdexp(lp.rhs_w(i), exp2); if(lp.lhs(i) > R(-infinity)) lp.lhs_w(i) = spxLdexp(lp.lhs_w(i), exp2); MSG_DEBUG(std::cout << "DEBUG: rowscaleExp(" << i << "): " << exp2 << std::endl;) } for(int i = 0; i < lp.nCols(); ++i) { SVectorBase& vec = lp.colVector_w(i); int exp1; int exp2 = colscaleExp[i]; for(int j = 0; j < vec.size(); ++j) { exp1 = rowscaleExp[vec.index(j)]; vec.value(j) = spxLdexp(vec.value(j), exp1 + exp2); } lp.maxObj_w(i) = spxLdexp(lp.maxObj_w(i), exp2); if(lp.upper(i) < R(infinity)) lp.upper_w(i) = spxLdexp(lp.upper_w(i), -exp2); if(lp.lower(i) > R(-infinity)) lp.lower_w(i) = spxLdexp(lp.lower_w(i), -exp2); MSG_DEBUG(std::cout << "DEBUG: colscaleExp(" << i << "): " << exp2 << std::endl;) } lp.setScalingInfo(true); assert(lp.isConsistent()); } /// unscale SPxLP template void SPxScaler::unscale(SPxLPBase& lp) { assert(lp.isScaled()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; for(int i = 0; i < lp.nRows(); ++i) { SVectorBase& vec = lp.rowVector_w(i); int exp1; int exp2 = rowscaleExp[i]; for(int j = 0; j < vec.size(); ++j) { exp1 = colscaleExp[vec.index(j)]; vec.value(j) = spxLdexp(vec.value(j), -exp1 - exp2); } lp.maxRowObj_w(i) = spxLdexp(lp.maxRowObj(i), -exp2); if(lp.rhs(i) < R(infinity)) lp.rhs_w(i) = spxLdexp(lp.rhs_w(i), -exp2); if(lp.lhs(i) > R(-infinity)) lp.lhs_w(i) = spxLdexp(lp.lhs_w(i), -exp2); } for(int i = 0; i < lp.nCols(); ++i) { SVectorBase& vec = lp.colVector_w(i); int exp1; int exp2 = colscaleExp[i]; for(int j = 0; j < vec.size(); ++j) { exp1 = rowscaleExp[vec.index(j)]; vec.value(j) = spxLdexp(vec.value(j), -exp1 - exp2); } lp.maxObj_w(i) = spxLdexp(lp.maxObj_w(i), -exp2); if(lp.upper(i) < R(infinity)) lp.upper_w(i) = spxLdexp(lp.upper_w(i), exp2); if(lp.lower(i) > R(-infinity)) lp.lower_w(i) = spxLdexp(lp.lower_w(i), exp2); } lp._isScaled = false; assert(lp.isConsistent()); } /// returns scaling factor for column \p i /// todo pass the LP?! template int SPxScaler::getColScaleExp(int i) const { return (*m_activeColscaleExp)[i]; } /// returns scaling factor for row \p i /// todo pass the LP?! template int SPxScaler::getRowScaleExp(int i) const { return (*m_activeRowscaleExp)[i]; } /// gets unscaled column \p i template void SPxScaler::getColUnscaled(const SPxLPBase& lp, int i, DSVectorBase& vec) const { assert(lp.isScaled()); assert(i < lp.nCols()); assert(i >= 0); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; vec = lp.LPColSetBase::colVector(i); int exp1; int exp2 = colscaleExp[i]; const SVectorBase& col = lp.colVector(i); vec.setMax(col.size()); vec.clear(); for(int j = 0; j < col.size(); j++) { exp1 = rowscaleExp[col.index(j)]; vec.add(col.index(j), spxLdexp(col.value(j), -exp1 - exp2)); } } /// returns maximum absolute value of unscaled column \p i template R SPxScaler::getColMaxAbsUnscaled(const SPxLPBase& lp, int i) const { assert(i < lp.nCols()); assert(i >= 0); DataArray < int >& colscaleExp = *m_activeColscaleExp; DataArray < int >& rowscaleExp = *m_activeRowscaleExp; const SVectorBase& colVec = lp.LPColSetBase::colVector(i); R max = 0.0; int exp1; int exp2 = colscaleExp[i]; for(int j = 0; j < colVec.size(); j++) { exp1 = rowscaleExp[colVec.index(j)]; R abs = spxAbs(spxLdexp(colVec.value(j), -exp1 - exp2)); if(abs > max) max = abs; } return max; } /// returns minimum absolute value of unscaled column \p i template R SPxScaler::getColMinAbsUnscaled(const SPxLPBase& lp, int i) const { assert(i < lp.nCols()); assert(i >= 0); DataArray < int >& colscaleExp = *m_activeColscaleExp; DataArray < int >& rowscaleExp = *m_activeRowscaleExp; const SVectorBase& colVec = lp.LPColSetBase::colVector(i); R min = R(infinity); int exp1; int exp2 = colscaleExp[i]; for(int j = 0; j < colVec.size(); j++) { exp1 = rowscaleExp[colVec.index(j)]; R abs = spxAbs(spxLdexp(colVec.value(j), -exp1 - exp2)); if(abs < min) min = abs; } return min; } /// returns unscaled upper bound \p i template R SPxScaler::upperUnscaled(const SPxLPBase& lp, int i) const { assert(lp.isScaled()); assert(i < lp.nCols()); assert(i >= 0); if(lp.LPColSetBase::upper(i) < R(infinity)) { const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; return spxLdexp(lp.LPColSetBase::upper(i), colscaleExp[i]); } else return lp.LPColSetBase::upper(i); } /// gets unscaled upper bound vector template void SPxScaler::getUpperUnscaled(const SPxLPBase& lp, VectorBase& vec) const { assert(lp.isScaled()); assert(lp.LPColSetBase::upper().dim() == vec.dim()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; for(int i = 0; i < lp.LPColSetBase::upper().dim(); i++) vec[i] = spxLdexp(lp.LPColSetBase::upper()[i], colscaleExp[i]); } /// returns unscaled upper bound VectorBase of \p lp template R SPxScaler::lowerUnscaled(const SPxLPBase& lp, int i) const { assert(lp.isScaled()); assert(i < lp.nCols()); assert(i >= 0); if(lp.LPColSetBase::lower(i) > R(-infinity)) { const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; return spxLdexp(lp.LPColSetBase::lower(i), colscaleExp[i]); } else return lp.LPColSetBase::lower(i); } /// returns unscaled lower bound VectorBase of \p lp template void SPxScaler::getLowerUnscaled(const SPxLPBase& lp, VectorBase& vec) const { assert(lp.isScaled()); assert(lp.LPColSetBase::lower().dim() == vec.dim()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; for(int i = 0; i < lp.LPColSetBase::lower().dim(); i++) vec[i] = spxLdexp(lp.LPColSetBase::lower()[i], colscaleExp[i]); } /// returns unscaled objective function coefficient of \p i template R SPxScaler::maxObjUnscaled(const SPxLPBase& lp, int i) const { assert(lp.isScaled()); assert(i < lp.nCols()); assert(i >= 0); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; return spxLdexp(lp.LPColSetBase::maxObj(i), -colscaleExp[i]); } /// gets unscaled objective function coefficient of \p i template void SPxScaler::getMaxObjUnscaled(const SPxLPBase& lp, VectorBase& vec) const { assert(lp.isScaled()); assert(lp.LPColSetBase::maxObj().dim() == vec.dim()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; for(int i = 0; i < lp.LPColSetBase::maxObj().dim(); i++) vec[i] = spxLdexp(lp.LPColSetBase::maxObj()[i], -colscaleExp[i]); } /// gets unscaled row \p i template void SPxScaler::getRowUnscaled(const SPxLPBase& lp, int i, DSVectorBase& vec) const { assert(lp.isScaled()); assert(i < lp.nRows()); assert(i >= 0); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; int exp1; int exp2 = rowscaleExp[i]; const SVectorBase& row = lp.rowVector(i); vec.setMax(row.size()); vec.clear(); for(int j = 0; j < row.size(); j++) { exp1 = colscaleExp[row.index(j)]; vec.add(row.index(j), spxLdexp(row.value(j), -exp1 - exp2)); } } /// returns maximum absolute value of unscaled row \p i template R SPxScaler::getRowMaxAbsUnscaled(const SPxLPBase& lp, int i) const { assert(i < lp.nRows()); assert(i >= 0); DataArray < int >& colscaleExp = *m_activeColscaleExp; DataArray < int >& rowscaleExp = *m_activeRowscaleExp; const SVectorBase& rowVec = lp.LPRowSetBase::rowVector(i); R max = 0.0; int exp1; int exp2 = rowscaleExp[i]; for(int j = 0; j < rowVec.size(); j++) { exp1 = colscaleExp[rowVec.index(j)]; R abs = spxAbs(spxLdexp(rowVec.value(j), -exp1 - exp2)); if(GT(abs, max)) max = abs; } return max; } /// returns minimum absolute value of unscaled row \p i template R SPxScaler::getRowMinAbsUnscaled(const SPxLPBase& lp, int i) const { assert(i < lp.nRows()); assert(i >= 0); DataArray < int >& colscaleExp = *m_activeColscaleExp; DataArray < int >& rowscaleExp = *m_activeRowscaleExp; const SVectorBase& rowVec = lp.LPRowSetBase::rowVector(i); R min = R(infinity); int exp1; int exp2 = rowscaleExp[i]; for(int j = 0; j < rowVec.size(); j++) { exp1 = colscaleExp[rowVec.index(j)]; R abs = spxAbs(spxLdexp(rowVec.value(j), -exp1 - exp2)); if(LT(abs, min)) min = abs; } return min; } /// returns unscaled right hand side \p i template R SPxScaler::rhsUnscaled(const SPxLPBase& lp, int i) const { assert(lp.isScaled()); assert(i < lp.nRows()); assert(i >= 0); if(lp.LPRowSetBase::rhs(i) < R(infinity)) { const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; return spxLdexp(lp.LPRowSetBase::rhs(i), -rowscaleExp[i]); } else return lp.LPRowSetBase::rhs(i); } /// gets unscaled right hand side vector template void SPxScaler::getRhsUnscaled(const SPxLPBase& lp, VectorBase& vec) const { assert(lp.isScaled()); assert(lp.LPRowSetBase::rhs().dim() == vec.dim()); for(int i = 0; i < lp.LPRowSetBase::rhs().dim(); i++) { const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; vec[i] = spxLdexp(lp.LPRowSetBase::rhs()[i], -rowscaleExp[i]); } } /// returns unscaled left hand side \p i of \p lp template R SPxScaler::lhsUnscaled(const SPxLPBase& lp, int i) const { assert(lp.isScaled()); assert(i < lp.nRows()); assert(i >= 0); if(lp.LPRowSetBase::lhs(i) > R(-infinity)) { const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; return spxLdexp(lp.LPRowSetBase::lhs(i), -rowscaleExp[i]); } else return lp.LPRowSetBase::lhs(i); } /// returns unscaled left hand side VectorBase of \p lp template void SPxScaler::getLhsUnscaled(const SPxLPBase& lp, VectorBase& vec) const { assert(lp.isScaled()); assert(lp.LPRowSetBase::lhs().dim() == vec.dim()); const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; for(int i = 0; i < lp.LPRowSetBase::lhs().dim(); i++) vec[i] = spxLdexp(lp.LPRowSetBase::lhs()[i], -rowscaleExp[i]); } /// returns unscaled coefficient of \p lp template R SPxScaler::getCoefUnscaled(const SPxLPBase& lp, int row, int col) const { assert(lp.isScaled()); assert(row < lp.nRows()); assert(col < lp.nCols()); const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; return spxLdexp(lp.colVector(col)[row], - rowscaleExp[row] - colscaleExp[col]); } template void SPxScaler::unscalePrimal(const SPxLPBase& lp, VectorBase& x) const { assert(lp.isScaled()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; assert(x.dim() == colscaleExp.size()); for(int j = 0; j < x.dim(); ++j) x[j] = spxLdexp(x[j], colscaleExp[j]); } template void SPxScaler::unscaleSlacks(const SPxLPBase& lp, VectorBase& s) const { assert(lp.isScaled()); const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; assert(s.dim() == rowscaleExp.size()); for(int i = 0; i < s.dim(); ++i) s[i] = spxLdexp(s[i], -rowscaleExp[i]); } template void SPxScaler::unscaleDual(const SPxLPBase& lp, VectorBase& pi) const { assert(lp.isScaled()); const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; assert(pi.dim() == rowscaleExp.size()); for(int i = 0; i < pi.dim(); ++i) pi[i] = spxLdexp(pi[i], rowscaleExp[i]); } template void SPxScaler::unscaleRedCost(const SPxLPBase& lp, VectorBase& r) const { assert(lp.isScaled()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; assert(r.dim() == colscaleExp.size()); for(int j = 0; j < r.dim(); ++j) r[j] = spxLdexp(r[j], -colscaleExp[j]); } template void SPxScaler::unscalePrimalray(const SPxLPBase& lp, VectorBase& ray) const { assert(lp.isScaled()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; assert(ray.dim() == colscaleExp.size()); for(int j = 0; j < ray.dim(); ++j) ray[j] = spxLdexp(ray[j], colscaleExp[j]); } template void SPxScaler::unscaleDualray(const SPxLPBase& lp, VectorBase& ray) const { assert(lp.isScaled()); const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; assert(ray.dim() == rowscaleExp.size()); for(int i = 0; i < ray.dim(); ++i) ray[i] = spxLdexp(ray[i], rowscaleExp[i]); } template void SPxScaler::scaleObj(const SPxLPBase& lp, VectorBase& origObj) const { assert(lp.isScaled()); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; for(int i = 0; i < origObj.dim(); ++i) { origObj[i] = spxLdexp(origObj[i], colscaleExp[i]); } } template R SPxScaler::scaleObj(const SPxLPBase& lp, int i, R origObj) const { assert(lp.isScaled()); assert(i < lp.nCols()); assert(i >= 0); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; int exp = colscaleExp[i]; return spxLdexp(origObj, exp); } template R SPxScaler::scaleElement(const SPxLPBase& lp, int row, int col, R val) const { assert(lp.isScaled()); assert(col < lp.nCols()); assert(col >= 0); assert(row < lp.nRows()); assert(row >= 0); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; return spxLdexp(val, colscaleExp[col] + rowscaleExp[row]); } template R SPxScaler::scaleLower(const SPxLPBase& lp, int col, R lower) const { assert(lp.isScaled()); assert(col < lp.nCols()); assert(col >= 0); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; return spxLdexp(lower, -colscaleExp[col]); } template R SPxScaler::scaleUpper(const SPxLPBase& lp, int col, R upper) const { assert(lp.isScaled()); assert(col < lp.nCols()); assert(col >= 0); const DataArray < int >& colscaleExp = lp.LPColSetBase::scaleExp; return spxLdexp(upper, -colscaleExp[col]); } template R SPxScaler::scaleLhs(const SPxLPBase& lp, int row, R lhs) const { assert(lp.isScaled()); assert(row < lp.nRows()); assert(row >= 0); const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; return spxLdexp(lhs, rowscaleExp[row]); } template R SPxScaler::scaleRhs(const SPxLPBase& lp, int row, R rhs) const { assert(lp.isScaled()); assert(row < lp.nRows()); assert(row >= 0); const DataArray < int >& rowscaleExp = lp.LPRowSetBase::scaleExp; return spxLdexp(rhs, rowscaleExp[row]); } template R SPxScaler::minAbsColscale() const { const DataArray < int >& colscaleExp = *m_activeColscaleExp; R mini = R(infinity); for(int i = 0; i < colscaleExp.size(); ++i) if(spxAbs(spxLdexp(1.0, colscaleExp[i])) < mini) mini = spxAbs(spxLdexp(1.0, colscaleExp[i])); return mini; } template R SPxScaler::maxAbsColscale() const { const DataArray < int >& colscaleExp = *m_activeColscaleExp; R maxi = 0.0; for(int i = 0; i < colscaleExp.size(); ++i) if(spxAbs(spxLdexp(1.0, colscaleExp[i])) > maxi) maxi = spxAbs(spxLdexp(1.0, colscaleExp[i])); return maxi; } template R SPxScaler::minAbsRowscale() const { const DataArray < int >& rowscaleExp = *m_activeRowscaleExp; int mini = std::numeric_limits::max(); for(int i = 0; i < rowscaleExp.size(); ++i) if(rowscaleExp[i] < mini) mini = rowscaleExp[i]; return spxLdexp(1.0, mini); } template R SPxScaler::maxAbsRowscale() const { const DataArray < int >& rowscaleExp = *m_activeRowscaleExp; int maxi = std::numeric_limits::min(); for(int i = 0; i < rowscaleExp.size(); ++i) if(rowscaleExp[i] > maxi) maxi = rowscaleExp[i]; return spxLdexp(1.0, maxi); } /** \f$\max_{j\in\mbox{ cols}} * \left(\frac{\max_{i\in\mbox{ rows}}|a_ij|} * {\min_{i\in\mbox{ rows}}|a_ij|}\right)\f$ */ template R SPxScaler::maxColRatio(const SPxLPBase& lp) const { R pmax = 0.0; for(int i = 0; i < lp.nCols(); ++i) { const SVectorBase& vec = lp.colVector(i); R mini = R(infinity); R maxi = 0.0; for(int j = 0; j < vec.size(); ++j) { R x = spxAbs(vec.value(j)); if(isZero(x)) continue; if(x < mini) mini = x; if(x > maxi) maxi = x; } if(mini == R(infinity)) continue; R p = maxi / mini; if(p > pmax) pmax = p; } return pmax; } /** \f$\max_{i\in\mbox{ rows}} * \left(\frac{\max_{j\in\mbox{ cols}}|a_ij|} * {\min_{j\in\mbox{ cols}}|a_ij|}\right)\f$ */ template R SPxScaler::maxRowRatio(const SPxLPBase& lp) const { R pmax = 0.0; for(int i = 0; i < lp.nRows(); ++i) { const SVectorBase& vec = lp.rowVector(i); R mini = R(infinity); R maxi = 0.0; for(int j = 0; j < vec.size(); ++j) { R x = spxAbs(vec.value(j)); if(isZero(x)) continue; if(x < mini) mini = x; if(x > maxi) maxi = x; } if(mini == R(infinity)) continue; R p = maxi / mini; if(p > pmax) pmax = p; } return pmax; } template void SPxScaler::computeExpVec(const std::vector& vec, DataArray& vecExp) { assert(vec.size() == unsigned(vecExp.size())); for(unsigned i = 0; i < vec.size(); ++i) { spxFrexp(vec[i], &(vecExp[int(i)])); vecExp[int(i)] -= 1; } } template bool SPxScaler::isConsistent() const { #ifdef ENABLE_CONSISTENCY_CHECKS return m_activeColscaleExp->isConsistent() && m_activeRowscaleExp->isConsistent(); #else return true; #endif } } // namespace soplex