Exemple #1
0
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");
}
Exemple #2
0
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]));
        }
    }
}
Exemple #3
0
/*
 * 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");
  }
}
Exemple #5
0
   /** 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) );
  }
}
Exemple #7
0
//===========================================================================//
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;
}