void OsiSolver::printModel() { printf("########\nMODEL:\nVARS :\n"); printf("V%d(%.2lf, %.2lf)", 0, col_lb[0], col_ub[0]); for (int i = 1; i < n_cols; i++) { printf(", V%d(%.2lf,%.2lf)", i, col_lb[i], col_ub[i]); } printf("\n\nObjective : Maximise(%s): ", (_obj_coef == -1 ? "Minimise" : "Maximise")); printf("%.2lf * V%d", objective[0], 0); for (int i = 1; i < n_cols; i++) { printf(" + %.2lf * V%d", objective[i], i); } printf("\n\nMatrix:\n"); for (int i = 0; i < matrix->getNumRows(); i++) { CoinShallowPackedVector row = matrix->getVector(i); const double* elements = row.getElements(); const int* indices = row.getIndices(); int n = row.getNumElements(); if (row_lb[i] == -1.0 * si->getInfinity()) printf("-infinity <= "); else printf("%.2lf <= ", row_lb[i]); printf("%.2lf * V%d", elements[0], indices[0]); for (int j = 1; j < n; j++) printf(" + %.2lf * V%d", elements[j], indices[j]); if (row_ub[i] == si->getInfinity()) printf(" <= infinity\n"); else printf(" <= %.2lf\n", row_ub[i]); } printf("########\n"); }
void OsiSolver::build_expressions() { // build expressions*, first element is Sum() for the objective // every pair after that ((1,2),(3,4)) is a le and ge over a // common Sum const double*objCoef = si->getObjCoefficients(); const int ncols = si->getNumCols(); const int nrows = si->getNumRows(); const double* col_ubs = si->getColUpper(); const double* col_lbs = si->getColLower(); const double* row_ubs = si->getRowUpper(); const double* row_lbs = si->getRowLower(); const CoinPackedMatrix* mtx = si->getMatrixByRow(); // Build objective expression. OsiExpArray vars; OsiDoubleArray coefs; double sum = 0; for (int i = 0; i < ncols; i++) { Osi_Expression* var; if (si->isContinuous(i)) var = new Osi_DoubleVar(col_lbs[i], col_ubs[i], i); else var = new Osi_IntVar(col_lbs[i], col_ubs[i], i); var->varname = si->getColName(i, 255); vars.add(var); expressions.push_back(var); coefs.add(objCoef[i]); sum += objCoef[i]; } /* Only return an objective if there is one! (Empty objectives were not * working with some solvers */ if (sum != 0) { expressions.push_back(new Osi_Minimise(new Osi_Sum(vars, coefs, 0))); } // Build remaining expressions, expr <= upper, expr >= lower for (int i = 0; i < nrows; i++) { CoinShallowPackedVector row = mtx->getVector(i); if (row.getNumElements() > 0) { const double* elements = row.getElements(); const int* indices = row.getIndices(); OsiExpArray sumvars; OsiDoubleArray coefs; for (int j = 0; j < row.getNumElements(); j++) { sumvars.add(vars.get_item(indices[j])); coefs.add(elements[j]); } Osi_Sum* expr = new Osi_Sum(sumvars, coefs, 0); if (!(row_ubs[i] == si->getInfinity())) expressions.push_back(new Osi_le(expr, row_ubs[i])); if (!(row_lbs[i] == -1.0 * si->getInfinity())) expressions.push_back(new Osi_ge(expr, row_lbs[i])); } } }
/* * split_ranged_rows finds rows that are bounded on both sides and creates * two separate rows for each. This is added since OsiVol doesn't like * ranged rows. */ void OsiSolver::splitRangedRows() { std::vector<double> row_ubs_new; std::vector<double> row_lbs_new; CoinPackedMatrix* matrix_new = new CoinPackedMatrix(false, 0, 0); for (int i = 0; i < n_rows; i++) { double ub_coef = row_ub[i] < 0.0 ? -1.0 : 1.0; double lb_coef = row_lb[i] < -1.0e20 ? 1.0 : (row_lb[i] < 0.0 ? -1.0 : 1.0); const CoinShallowPackedVector row = matrix->getVector(i); const double* elements = row.getElements(); const int* indices = row.getIndices(); if (row_lb[i] > -1.0e20 && row_ub[i] < 1.0e20 && row_lb[i] != row_ub[i]) { CoinPackedVector row_with_ub; CoinPackedVector row_with_lb; row_ubs_new.push_back(si->getInfinity()); row_ubs_new.push_back(ub_coef * row_ub[i]); row_lbs_new.push_back(lb_coef * row_lb[i]); row_lbs_new.push_back(-1.0 * si->getInfinity()); for (int j = 0; j < row.getNumElements(); j++) { row_with_ub.insert(indices[j], ub_coef * elements[j]); row_with_lb.insert(indices[j], lb_coef * elements[j]); } matrix_new->appendRow(row_with_ub); matrix_new->appendRow(row_with_lb); } else { CoinPackedVector new_row; row_ubs_new.push_back(ub_coef * row_ub[i]); row_lbs_new.push_back(lb_coef * row_lb[i]); double row_coef = row_ub[i] < 1.0e20 ? (row_ub[i] < 0.0 ? -1.0 : 1.0) : (row_lb[i] < 0.0 ? -1.0 : 1.0); for (int j = 0; j < row.getNumElements(); j++) { new_row.insert(indices[j], row_coef * elements[j]); } matrix_new->appendRow(new_row); } } n_rows = row_ubs_new.size(); delete matrix; delete[] row_lb; delete[] row_ub; row_lb = new double[n_rows]; row_ub = new double[n_rows]; for (int i = 0; i < n_rows; i++) { row_lb[i] = row_lbs_new.at(i); row_ub[i] = row_ubs_new.at(i); } matrix = matrix_new; }
//------------------------------------------------------------------- // Copy //------------------------------------------------------------------- CoinShallowPackedVector::CoinShallowPackedVector(const CoinShallowPackedVector &x) : CoinPackedVectorBase() , indices_(x.getIndices()) , elements_(x.getElements()) , nElements_(x.getNumElements()) { CoinPackedVectorBase::copyMaxMinIndex(x); try { CoinPackedVectorBase::setTestForDuplicateIndex(x.testForDuplicateIndex()); } catch (CoinError &e) { throw CoinError("duplicate index", "copy constructor", "CoinShallowPackedVector"); } }
/** Equivalence. Two matrices are equivalent if they are both by rows or both by columns, they have the same dimensions, and each vector is equivalent. In this method the FloatEqual function operator can be specified. */ template <class FloatEqual> bool isEquivalent(const CoinPackedMatrix& rhs, const FloatEqual& eq) const { // Both must be column order or both row ordered and must be of same size if ((isColOrdered() ^ rhs.isColOrdered()) || (getNumCols() != rhs.getNumCols()) || (getNumRows() != rhs.getNumRows()) || (getNumElements() != rhs.getNumElements())) return false; for (int i=getMajorDim()-1; i >= 0; --i) { CoinShallowPackedVector pv = getVector(i); CoinShallowPackedVector rhsPv = rhs.getVector(i); if ( !pv.isEquivalent(rhsPv,eq) ) return false; } return true; }
void CoinShallowPackedVectorUnitTest() { CoinRelFltEq eq; int i; // Test default constructor { CoinShallowPackedVector r; assert( r.indices_==NULL ); assert( r.elements_==NULL ); assert( r.nElements_==0 ); } // Test set and get methods const int ne = 4; int inx[ne] = { 1, 3, 4, 7 }; double el[ne] = { 1.2, 3.4, 5.6, 7.8 }; { CoinShallowPackedVector r; assert( r.getNumElements()==0 ); // Test setting/getting elements with int* & double* vectors r.setVector( ne, inx, el ); assert( r.getNumElements()==ne ); for ( i=0; i<ne; i++ ) { assert( r.getIndices()[i] == inx[i] ); assert( r.getElements()[i] == el[i] ); } assert ( r.getMaxIndex()==7 ); assert ( r.getMinIndex()==1 ); // try to clear it r.clear(); assert( r.indices_==NULL ); assert( r.elements_==NULL ); assert( r.nElements_==0 ); // Test setting/getting elements with indices out of order const int ne2 = 5; int inx2[ne2] = { 2, 4, 8, 14, 3 }; double el2[ne2] = { 2.2, 4.4, 6.6, 8.8, 3.3 }; r.setVector(ne2,inx2,el2); assert( r.getNumElements()==ne2 ); for (i = 0; i < ne2; ++i) { assert( r.getIndices()[i]==inx2[i] ); assert( r.getElements()[i]==el2[i] ); } assert ( r.getMaxIndex()==14 ); assert ( r.getMinIndex()==2 ); // try to call it once more assert ( r.getMaxIndex()==14 ); assert ( r.getMinIndex()==2 ); CoinShallowPackedVector r1(ne2,inx2,el2); assert( r == r1 ); // assignment operator r1.clear(); r1 = r; assert( r == r1 ); // assignment from packed vector CoinPackedVector pv1(ne2,inx2,el2); r1 = pv1; assert( r == r1 ); // construction CoinShallowPackedVector r2(r1); assert( r2 == r ); // construction from packed vector CoinShallowPackedVector r3(pv1); assert( r3 == r ); // test duplicate indices { const int ne3 = 4; int inx3[ne3] = { 2, 4, 2, 3 }; double el3[ne3] = { 2.2, 4.4, 8.8, 6.6 }; r.setVector(ne3,inx3,el3, false); assert(r.testForDuplicateIndex() == false); bool errorThrown = false; try { r.setTestForDuplicateIndex(true); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); r.clear(); errorThrown = false; try { r.setVector(ne3,inx3,el3); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); errorThrown = false; try { CoinShallowPackedVector r1(ne3,inx3,el3); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); } } // Test copy constructor and assignment operator { CoinShallowPackedVector rhs; { CoinShallowPackedVector r; { CoinShallowPackedVector rC1(r); assert( 0==r.getNumElements() ); assert( 0==rC1.getNumElements() ); r.setVector( ne, inx, el ); assert( ne==r.getNumElements() ); assert( 0==rC1.getNumElements() ); } CoinShallowPackedVector rC2(r); assert( ne==r.getNumElements() ); assert( ne==rC2.getNumElements() ); for ( i=0; i<ne; i++ ) { assert( r.getIndices()[i] == rC2.getIndices()[i] ); assert( r.getElements()[i] == rC2.getElements()[i] ); } rhs=rC2; } // Test that rhs has correct values even though lhs has gone out of scope assert( rhs.getNumElements()==ne ); for ( i=0; i<ne; i++ ) { assert( inx[i] == rhs.getIndices()[i] ); assert( el[i] == rhs.getElements()[i] ); } } // Test operator== { CoinShallowPackedVector v1,v2; assert( v1==v2 ); assert( v2==v1 ); assert( v1==v1 ); assert( !(v1!=v2) ); v1.setVector( ne, inx, el ); assert ( !(v1==v2) ); assert ( v1!=v2 ); CoinShallowPackedVector v3(v1); assert( v3==v1 ); assert( v3!=v2 ); CoinShallowPackedVector v4(v2); assert( v4!=v1 ); assert( v4==v2 ); } { // Test operator[] and isExistingIndex() const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r; assert( r[1]==0. ); r.setVector(ne,inx,el); assert( r[-1]==0. ); assert( r[ 0]==1. ); assert( r[ 1]==10.); assert( r[ 2]==50.); assert( r[ 3]==0. ); assert( r[ 4]==40.); assert( r[ 5]==0. ); assert( r.isExistingIndex(2) ); assert( !r.isExistingIndex(3) ); assert( !r.isExistingIndex(-1) ); assert( r.isExistingIndex(0) ); assert( !r.isExistingIndex(3) ); assert( r.isExistingIndex(4) ); assert( !r.isExistingIndex(5) ); assert ( r.getMaxIndex()==4 ); assert ( r.getMinIndex()==0 ); } // Test that attemping to get min/max index of a 0, // length vector { CoinShallowPackedVector nullVec; assert( nullVec.getMaxIndex() == -COIN_INT_MAX/*0*/ ); assert( nullVec.getMinIndex() == COIN_INT_MAX/*0*/ ); } { // test dense vector const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r; r.setVector(ne,inx,el); double * dense = r.denseVector(6); assert(dense[0] == 1.); assert(dense[1] == 10.); assert(dense[2] == 50.); assert(dense[3] == 0.); assert(dense[4] == 40.); assert(dense[5] == 0.); delete[] dense; // try once more dense = r.denseVector(7); assert(dense[0] == 1.); assert(dense[1] == 10.); assert(dense[2] == 50.); assert(dense[3] == 0.); assert(dense[4] == 40.); assert(dense[5] == 0.); assert(dense[6] == 0.); delete[] dense; } #if 0 // what happens when someone sets // the number of elements to be a negative number { const int ne = 4; int inx1[ne] = { 1, 3, 4, 7 }; double el1[ne] = { 1.2, 3.4, 5.6, 7.8 }; CoinShallowPackedVector v1; v1.setVector(-ne,inx1,el1); } #endif // Test adding vectors { const int ne1 = 5; int inx1[ne1] = { 1, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 + v2; const int ner = 6; int inxr[ner] = { 1, 2, 3, 4, 5, 7 }; double elr[ner] = { 1.+1., 0.+2., 5.+0., 6.+4., 9.+0., 2.+7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( rV != r ); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1+3.1415; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]+3.1415) ); CoinPackedVector p2=(-3.1415) + p1; assert( p2.isEquivalent(v1) ); } // Test subtracting vectors { const int ne1 = 5; int inx1[ne1] = { 1, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 - v2; const int ner = 6; int inxr[ner] = { 1, 2, 3, 4, 5, 7 }; double elr[ner] = { 1.-1., 0.-2., 5.-0., 6.-4., 9.-0., 2.-7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1-3.1415; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]-3.1415) ); } // Test multiplying vectors { const int ne1 = 5; int inx1[ne1] = { 1, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 * v2; const int ner = 6; int inxr[ner] = { 1, 2, 3, 4, 5, 7 }; double elr[ner] = { 1.*1., 0.*2., 5.*0., 6.*4., 9.*0., 2.*7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1*3.3; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]*3.3) ); CoinPackedVector p2=(1./3.3) * p1; assert( p2.isEquivalent(v1) ); } // Test dividing vectors { const int ne1 = 3; int inx1[ne1] = { 1, 4, 7 }; double el1[ne1] = { 1., 6., 2. }; const int ne2 = 4; int inx2[ne2] = { 7, 4, 2, 1 }; double el2[ne2] = { 7., 4., 2., 1. }; CoinShallowPackedVector v1; v1.setVector(ne1,inx1,el1); CoinShallowPackedVector v2; v2.setVector(ne2,inx2,el2); CoinPackedVector r = v1 / v2; const int ner = 4; int inxr[ner] = { 1, 2, 4, 7 }; double elr[ner] = { 1./1., 0./2., 6./4., 2./7. }; CoinPackedVector rV; rV.setVector(ner,inxr,elr); assert( r.isEquivalent(rV) ); CoinPackedVector p1=v1/3.1415; for ( i=0; i<p1.getNumElements(); i++ ) assert( eq( p1.getElements()[i], v1.getElements()[i]/3.1415) ); } // Test sum { CoinShallowPackedVector s; assert( s.sum() == 0 ); int inx = 25; double value = 45.; s.setVector(1, &inx, &value); assert(s.sum()==45.); const int ne1 = 5; int inx1[ne1] = { 10, 3, 4, 7, 5 }; double el1[ne1] = { 1., 5., 6., 2., 9. }; s.setVector(ne1,inx1,el1); assert(s.sum()==1.+5.+6.+2.+9.); } // Just another interesting test { // Create numerator vector const int ne1 = 2; int inx1[ne1] = { 1, 4 }; double el1[ne1] = { 1., 6. }; CoinShallowPackedVector v1(ne1,inx1,el1); // create denominator vector const int ne2 = 3; int inx2[ne2] = { 1, 2, 4 }; double el2[ne2] = { 1., 7., 4.}; CoinShallowPackedVector v2(ne2,inx2,el2); // Compute ratio CoinPackedVector ratio = v1 / v2; // Sort ratios ratio.sortIncrElement(); // Test that the sort really worked assert( ratio.getElements()[0] == 0.0/7.0 ); assert( ratio.getElements()[1] == 1.0/1.0 ); assert( ratio.getElements()[2] == 6.0/4.0 ); // Get numerator of of sorted ratio vector assert( v1[ ratio.getIndices()[0] ] == 0.0 ); assert( v1[ ratio.getIndices()[1] ] == 1.0 ); assert( v1[ ratio.getIndices()[2] ] == 6.0 ); // Get denominator of of sorted ratio vector assert( v2[ ratio.getIndices()[0] ] == 7.0 ); assert( v2[ ratio.getIndices()[1] ] == 1.0 ); assert( v2[ ratio.getIndices()[2] ] == 4.0 ); } { // Test that sample usage works const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r(ne,inx,el); assert( r.getIndices()[0]== 1 ); assert( r.getElements()[0]==10. ); assert( r.getIndices()[1]== 4 ); assert( r.getElements()[1]==40. ); assert( r.getIndices()[2]== 0 ); assert( r.getElements()[2]== 1. ); assert( r.getIndices()[3]== 2 ); assert( r.getElements()[3]==50. ); assert( r[ 0]==1. ); assert( r[ 1]==10.); assert( r[ 2]==50.); assert( r[ 3]==0. ); assert( r[ 4]==40.); CoinShallowPackedVector r1; r1=r; assert( r==r1 ); CoinPackedVector add = r + r1; assert( add[0] == 1.+ 1. ); assert( add[1] == 10.+10. ); assert( add[2] == 50.+50. ); assert( add[3] == 0.+ 0. ); assert( add[4] == 40.+40. ); assert( r.sum() == 10.+40.+1.+50. ); } { // Test findIndex const int ne = 4; int inx[ne] = { 1, -4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r(ne,inx,el); assert( r.findIndex(2) == 3 ); assert( r.findIndex(0) == 2 ); assert( r.findIndex(-4) == 1 ); assert( r.findIndex(1) == 0 ); assert( r.findIndex(3) == -1 ); } { // Test construction with testing for duplicates as false const int ne = 4; int inx[ne] = { 1, -4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinShallowPackedVector r(ne,inx,el,false); assert( r.isExistingIndex(1) ); assert( r.isExistingIndex(-4) ); assert( r.isExistingIndex(0) ); assert( r.isExistingIndex(2) ); assert( !r.isExistingIndex(3) ); assert( !r.isExistingIndex(-3) ); } }
//===========================================================================// bool DecompAlgo::checkPointFeasible(const DecompConstraintSet* model, const double* x) { //--- //--- sanity check //--- Does the recomposed solution (x*) satisfy the core //--- constraints. If not, but in master solver OR in the //--- process of recomposed (the map). //--- const CoinPackedMatrix* M = model->getMatrix(); if (!M) { return true; } int i; double actViol; double relViol; int precision = 7; bool isFeas = true; bool hasColNames = false; bool hasRowNames = false; const int nCols = model->getNumCols(); const int nRows = model->getNumRows(); const double* colLB = model->getColLB(); const double* colUB = model->getColUB(); const double* rowLB = model->getRowLB(); const double* rowUB = model->getRowUB(); const vector<string>& colNames = model->getColNames(); const vector<string>& rowNames = model->getRowNames(); double* ax = new double[nRows]; assert(M); assert(ax); if (colNames.size()) { hasColNames = true; } if (rowNames.size()) { hasRowNames = true; } //--- //--- check column bounds //--- for (i = 0; i < nCols; i++) { actViol = std::max<double>(colLB[i] - x[i], x[i] - colUB[i]); actViol = std::max<double>(actViol, 0.0); if (UtilIsZero(x[i], 1.0e-3) || (x[i] < 0 && UtilIsZero(colLB[i])) || (x[i] > 0 && UtilIsZero(colUB[i]))) { relViol = actViol; } else { relViol = actViol / std::fabs(x[i]); } if (relViol > 0.0001) { //0.01% violated (*m_osLog) << "Point violates column " << i; if (hasColNames) { (*m_osLog) << " -> " << colNames[i]; } (*m_osLog) << " LB= " << UtilDblToStr(colLB[i], precision) << " x= " << UtilDblToStr(x[i], precision) << " UB= " << UtilDblToStr(colUB[i], precision) << " RelViol= " << UtilDblToStr(relViol, precision) << endl; //>1% violation is probably a bug, but <1% could be just // round off error??? not sure about that if (relViol > 0.01) { isFeas = false; } } } //--- //--- M * x = ax //--- M->times(x, ax); //--- //--- check row bounds //--- //--- Need to deal with masterOnly variable for (i = 0; i < nRows; i++) { actViol = std::max<double>(rowLB[i] - ax[i], ax[i] - rowUB[i]); //printf("ax=%12.10f, actViol=%12.10f\n", ax[i], actViol); actViol = std::max<double>(actViol, 0.0); //printf(" actViol=%12.10f\n", actViol); if (m_param.LogDebugLevel >= 4) { CoinShallowPackedVector row = M->getVector(i); (*m_osLog) << "Row i: " << i; if (hasRowNames) { (*m_osLog) << " -> " << rowNames[i]; } (*m_osLog) << " LB= " << UtilDblToStr(rowLB[i], precision) << " ax= " << UtilDblToStr(ax[i], precision) << " UB= " << UtilDblToStr(rowUB[i], precision) << endl; //UtilPrintPackedVector(row); } if (UtilIsZero(ax[i], 1.0e-3) || (ax[i] < 0 && UtilIsZero(rowLB[i])) || (ax[i] > 0 && UtilIsZero(rowUB[i]))) { relViol = actViol; } else { relViol = actViol / std::fabs(ax[i]); } if (relViol > 0.005) { //0.5% violated (*m_osLog) << "Point violates row " << i; if (hasRowNames) { (*m_osLog) << " -> " << rowNames[i]; } (*m_osLog) << " LB= " << UtilDblToStr(rowLB[i], precision) << " ax= " << UtilDblToStr(ax[i], precision) << " UB= " << UtilDblToStr(rowUB[i], precision) << " RelViol= " << UtilDblToStr(relViol, precision) << endl; //>5% violation is probably a bug, but <5% could be just // round off error??? not sure about that if (relViol > 0.05) { isFeas = false; //--- //--- if special case of relViol=actViol, //--- then check to see if possible round off issues //--- e.g., harp2 a[j]=1.0e9, actViol=1.0e3 is OK //--- if (UtilIsZero(ax[i], 1.0e-3) || (ax[i] < 0 && UtilIsZero(rowLB[i])) || (ax[i] > 0 && UtilIsZero(rowUB[i]))) { int k; CoinShallowPackedVector row = M->getVector(i); const int numNZ = row.getNumElements(); const double* els = row.getElements(); for (k = 0; k < numNZ; k++) { if (fabs(els[k]) > 1.0e7) { (*m_osLog) << " row has a big coefficient " << els[k] << endl; isFeas = true; break; } } } } } } UTIL_DELARR(ax); return isFeas; }