Ejemplo n.º 1
0
// --------------------------------------------------------------------- //
//THINK: this is specific to PC and DC??
void DecompVarPool::reExpand(const DecompConstraintSet& modelCore,
                             const double                tolZero)
{
   //THIS IS WRONG...
   //in masterSI, we have
   //A'', convexity, cuts
   //in modelCore.M we have A'', cuts
   //the sparseCol that you come out with the end here has things in the wrong
   //order: //A'', cuts, convexity
   double* denseCol = new double[modelCore.getNumRows() + 1];
   vector<DecompWaitingCol>::iterator vi;

   for (vi = begin(); vi != end(); vi++) {
      // ---
      // --- get dense column = A''s, append convexity constraint on end
      // ---
      modelCore.M->times((*vi).getVarPtr()->m_s, denseCol);
      denseCol[modelCore.getNumRows()] = 1.0;
      // ---
      // --- create a sparse column from the dense column
      // ---
      CoinPackedVector* sparseCol
      = UtilPackedVectorFromDense(modelCore.getNumRows() + 1,
                                  denseCol, tolZero);
      (*vi).deleteCol();
      (*vi).setCol(sparseCol);
   }

   setColsAreValid(true);
   UTIL_DELARR(denseCol);
}
Ejemplo n.º 2
0
//===========================================================================//
DecompConstraintSet * ATM_DecompApp::createModelCoreCount(){

   UtilPrintFuncBegin(m_osLog, m_classTag,
		      "createModelCoreCount()", m_appParam.LogLevel, 2);

   int                 a, nRows;
   const int           nAtms      = m_instance.getNAtms();
   const int           nAtmsSteps = getNAtmsSteps();
   const int           nCols      = numCoreCols();
   if(m_appParam.UseTightModel)
      nRows = 3*nAtms +   nAtmsSteps;
   else
      nRows = 2*nAtms + 3*nAtmsSteps;
   int                 rowCnt     = 0;

   //---
   //--- A'' (core):
   //---    for a in A:
   //---       sum{d in D} v[a,d]  <= K[a]
   //---
   
   DecompConstraintSet * model = new DecompConstraintSet();
   CoinAssertHint(model, "Error: Out of Memory");

   //---
   //--- create new matrix
   //---
   model->M = new CoinPackedMatrix(false, 0.0, 0.0);
   CoinAssertHint(model->M, "Error: Out of Memory");
   model->M->setDimensions(0, nCols);
   model->reserve(nRows, nCols);

   //---
   //--- create model constraints
   //---
   for(a = 0; a < nAtms; a++){
      rowCnt += createConCount  (model, a);
      rowCnt += createConZtoX   (model, a);//OPT
      rowCnt += createConPickOne(model, a);//OPT
   }
   //THINK - add conZtoX to core and remove from relax?
   printf("nRows = %d, rowCnt = %d\n", nRows, rowCnt);
   assert(rowCnt == nRows);
   
   //---
   //--- create model variables/columns
   //---
   createModelColumns(model);

   UtilPrintFuncEnd(m_osLog, m_classTag,
		    "createModelCoreCount()", m_appParam.LogLevel, 2);
   
   return model;
}
Ejemplo n.º 3
0
//===========================================================================//
DecompConstraintSet * ATM_DecompApp::createModelCore2(){

   UtilPrintFuncBegin(m_osLog, m_classTag,
		      "createModelCore2()", m_appParam.LogLevel, 2);

   int                 a;
   const int           nAtms   = m_instance.getNAtms();
   const int           nCols   = numCoreCols();
   const int           nRows   = (2*nAtms);
   int                 rowCnt  = 0;

   //---
   //--- A'' (core):
   //---    for a in A:
   //---       sum{t in T} x1[a,t] <= 1
   //---       sum{d in D} v[a,d]  <= K[a]
   //---    for a in A, t in T:
   //---       z[a,t] <= x1[a,t],            
   //---       z[a,t] <= x2[a],              
   //---       z[a,t] >= x1[a,t] + x2[a] - 1.
   //---
   
   DecompConstraintSet * model = new DecompConstraintSet();
   CoinAssertHint(model, "Error: Out of Memory");

   //---
   //--- create new matrix
   //---
   model->M = new CoinPackedMatrix(false, 0.0, 0.0);
   CoinAssertHint(model->M, "Error: Out of Memory");
   model->M->setDimensions(0, nCols);
   model->reserve(nRows, nCols);

   //---
   //--- create model constraints
   //---
   for(a = 0; a < nAtms; a++){
      rowCnt += createConPickOne(model, a);
      rowCnt += createConCount  (model, a);
   }
   printf("nRows = %d, rowCnt = %d\n", nRows, rowCnt);
   assert(rowCnt == nRows);
   
   //---
   //--- create model variables/columns
   //---
   createModelColumns(model);

   UtilPrintFuncEnd(m_osLog, m_classTag,
		    "createModelCore2()", m_appParam.LogLevel, 2);
   
   return model;
}
Ejemplo n.º 4
0
//===========================================================================//
DecompConstraintSet * ATM_DecompApp::createModelRelaxCount(){
   
   UtilPrintFuncBegin(m_osLog, m_classTag,
		      "createModelRelaxCount()", m_appParam.LogLevel, 2);
   
   int                a, d, t, nRows, pairIndex, nRowsMax;
   double             rhs, coefA, coefC;
   pair<int,int>      adP;
   vector<int>::const_iterator vi;
   
   const int           nSteps     = m_appParam.NumSteps;
   const int           nAtms      = m_instance.getNAtms();
   const int           nDates     = m_instance.getNDates();
   const int           nPairs     = m_instance.getNPairs();
   const int           nAtmsSteps = getNAtmsSteps();
   const vector<int> & pairsAD    = m_instance.getPairsAD();   

   const double      * a_ad      = m_instance.get_a_ad(); //dense storage
   const double      * b_ad      = m_instance.get_b_ad(); //dense storage
   const double      * c_ad      = m_instance.get_c_ad(); //dense storage
   const double      * d_ad      = m_instance.get_d_ad(); //dense storage
   const double      * e_ad      = m_instance.get_e_ad(); //dense storage
   const double      * w_ad      = m_instance.get_w_ad(); //dense storage
   const double      * B_d       = m_instance.get_B_d();

   const int           nCols     = numCoreCols();
   if(m_appParam.UseTightModel)
      nRowsMax  = nDates + 2*nAtms +   nAtmsSteps + 2*nPairs;
   else
      nRowsMax  = nDates +   nAtms + 3*nAtmsSteps + 2*nPairs;

   //TODO:
   // try the nested idea - so master has ConZtoX and we price without that
   //   but we solve with gap the harder oracle with those constraints

   //---
   //--- A' (relax):
   //---    for d in D:
   //---       sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]  <---- makes it hard
   //OPT
   //---    for a in A:
   //---       sum{t in T}  x1[a,t] <= 1
   //OPT
   //---    for a in A, t in T:
   //---       z[a,t] <= x1[a,t],            
   //---       z[a,t] <= x2[a],              
   //---       z[a,t] >= x1[a,t] + x2[a] - 1.      

   //---    for a in A, d in D:
   //---       f+[a,d] - f-[a,d] =  
   //---         a[a,d] sum{t in T} (t/n) x1[a,t] +
   //---         b[a,d] x2[a]                     +     
   //---         c[a,d] sum{t in T} (t/n) z[a,t]  + 
   //---         d[a,d] x3[a]                     +
   //---         e[a,d]
   //---       f-[a,d] <= w[a,d] * v[a,d]
   //---
   
   DecompConstraintSet * model = new DecompConstraintSet();
   CoinAssertHint(model, "Error: Out of Memory");

   model->M = new CoinPackedMatrix(false, 0.0, 0.0);
   CoinAssertHint(model->M, "Error: Out of Memory");
   model->M->setDimensions(0, nCols);
   model->reserve(nRowsMax, nCols);

   //---
   //--- create nDates empty rowBudget packed vectors
   //---
   vector<CoinPackedVector> rowBudget;
   for(d = 0; d < nDates; d++){
      CoinPackedVector row;
      rowBudget.push_back(row);
   }

   nRows     = 0;
   pairIndex = 0;
   for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){
      adP = m_instance.getIndexADInv(*vi);
      a = adP.first;
      d = adP.second;

      //---
      //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]
      //---
      rowBudget[d].insert(getColOffset_fp() + pairIndex,  1.0);
      rowBudget[d].insert(getColOffset_fm() + pairIndex, -1.0);


      //---
      //---       f+[a,d] - f-[a,d] =  
      //---         a[a,d] sum{t in T} (t/n) x1[a,t] +
      //---         b[a,d] x2[a]                     +     
      //---         c[a,d] sum{t in T} (t/n) z[a,t]  + 
      //---         d[a,d] x3[a]                     +
      //---         e[a,d]
      //---
      CoinPackedVector row;
      string rowName = "demand_def(a_" 
	 + m_instance.getAtmName(a) + ",d_" 
	 + m_instance.getDateName(d) + ")";
      row.insert(colIndex_fp(pairIndex),  1.0);
      row.insert(colIndex_fm(pairIndex), -1.0);
      coefA = -a_ad[*vi] / nSteps;
      coefC = -c_ad[*vi] / nSteps;
      if(m_appParam.UseTightModel){
	 for(t = 0; t <= nSteps; t++){ 
	    row.insert(colIndex_x1(a,t), t * coefA);
	    row.insert(colIndex_z (a,t), t * coefC);
	 }
      }
      else{
	 for(t = 0; t < nSteps; t++){ 
	    row.insert(colIndex_x1(a,t), (t+1) * coefA);
	    row.insert(colIndex_z (a,t), (t+1) * coefC);
	 }
      }
      row.insert(colIndex_x2(a), -b_ad[*vi]);
      row.insert(colIndex_x3(a), -d_ad[*vi]);
      
      rhs = e_ad[*vi];
      model->appendRow(row, rhs, rhs, rowName);
      nRows++;

      //---
      //---       f-[a,d] <= w[a,d] * v[a,d]      
      //---
      CoinPackedVector rowLink;
      string rowNameLink = "linkv(a_" 
         + m_instance.getAtmName(a) + ",d_" 
         + m_instance.getDateName(d) + ")";	 
      rowLink.insert(colIndex_fm(pairIndex), 1.0);
      rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]);
      model->appendRow(rowLink, -DecompInf, 0.0, rowNameLink);
      nRows++;	 

      pairIndex++;
   }

   for(d = 0; d < nDates; d++){   
      string rowNameBudget = "budget(d_" + m_instance.getDateName(d) + ")";
      model->appendRow(rowBudget[d], -DecompInf, B_d[d], rowNameBudget);
      nRows++;
   }

   //---
   //---    for a in A:
   //---       sum{t in T}  x1[a,t] <= 1
   //---    for a in A, t in T:
   //---       z[a,t] <= x1[a,t],            
   //---       z[a,t] <= x2[a],              
   //---       z[a,t] >= x1[a,t] + x2[a] - 1.      
   //---   
   //THINK: if you use this, shouldn't we postprocess z=x1*x2?
   //  putting those constaints in master are unneccessary... 
   //  in fact, why not just do that in block version too... 
   //for(a = 0; a < nAtms; a++){
      //nRows += createConZtoX(model, a);
      //nRows += createConPickOne(model, a);
   //}
   assert(nRows <= nRowsMax);
   
   //---
   //--- create model columns
   //---
   createModelColumns(model);
   
   UtilPrintFuncEnd(m_osLog, m_classTag,
		    "createModelRelaxCount()", m_appParam.LogLevel, 2);

   return model;
}
Ejemplo n.º 5
0
//===========================================================================//
DecompConstraintSet * ATM_DecompApp::createModelRelax2(const int d){
   
   UtilPrintFuncBegin(m_osLog, m_classTag,
		      "createModelRelax2()", m_appParam.LogLevel, 2);
   
   int                a, t, nRows, pairIndex, nRowsMax;
   double             rhs, coefA, coefC;
   pair<int,int>      adP;
   vector<int>::const_iterator vi;
   
   const int           nSteps    = m_appParam.NumSteps;
   const int           nAtms     = m_instance.getNAtms();
   const vector<int> & pairsAD   = m_instance.getPairsAD();   

   const double      * a_ad      = m_instance.get_a_ad(); //dense storage
   const double      * b_ad      = m_instance.get_b_ad(); //dense storage
   const double      * c_ad      = m_instance.get_c_ad(); //dense storage
   const double      * d_ad      = m_instance.get_d_ad(); //dense storage
   const double      * e_ad      = m_instance.get_e_ad(); //dense storage
   const double      * w_ad      = m_instance.get_w_ad(); //dense storage
   const double      * B_d       = m_instance.get_B_d();

   const int           nCols     = numCoreCols();
   if(m_appParam.UseTightModel)
      nRowsMax  = 3*nAtms + 1 + getNAtmsSteps();
   else
      nRowsMax  = 2*nAtms + 1 + (3*getNAtmsSteps());

   //---
   //--- A'[d] for d in D (independent blocks)
   //---    for a in A
   //---       f+[a,d] - f-[a,d] =  
   //---         a[a,d] sum{t in T} (t/n) x1[a,t] +
   //---         b[a,d] x2[a]                     +     
   //---         c[a,d] sum{t in T} (t/n) z[a,t]  + 
   //---         d[a,d] x3[a]                     +
   //---         e[a,d]
   //---       f-[a,d] <= w[a,d] * v[a,d]
   //---    sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]
   //---    for a in A, t in T:
   //---       z[a,t] <= x1[a,t],            
   //---       z[a,t] <= x2[a],              
   //---       z[a,t] >= x1[a,t] + x2[a] - 1.
   //---
   
   DecompConstraintSet * model = new DecompConstraintSet();
   CoinAssertHint(model, "Error: Out of Memory");

   model->M = new CoinPackedMatrix(false, 0.0, 0.0);
   CoinAssertHint(model->M, "Error: Out of Memory");
   model->M->setDimensions(0, nCols);
   model->reserve(nRowsMax, nCols);

   CoinPackedVector rowBudget;
   nRows     = 0;
   pairIndex = 0;
   for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){
      adP = m_instance.getIndexADInv(*vi);
      if(d != adP.second){
	 pairIndex++;
	 continue;      
      }
      a = adP.first;

      //---
      //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]
      //---
      rowBudget.insert(getColOffset_fp() + pairIndex,  1.0);
      rowBudget.insert(getColOffset_fm() + pairIndex, -1.0);


      //---
      //---       f+[a,d] - f-[a,d] =  
      //---         a[a,d] sum{t in T} (t/n) x1[a,t] +
      //---         b[a,d] x2[a]                     +     
      //---         c[a,d] sum{t in T} (t/n) z[a,t]  + 
      //---         d[a,d] x3[a]                     +
      //---         e[a,d]
      //---
      CoinPackedVector row;
      string rowName = "demand_def(a_" 
	 + m_instance.getAtmName(a) + ",d_" 
	 + m_instance.getDateName(d) + ")";
      row.insert(colIndex_fp(pairIndex),  1.0);
      row.insert(colIndex_fm(pairIndex), -1.0);
      coefA = -a_ad[*vi] / nSteps;
      coefC = -c_ad[*vi] / nSteps;
      if(m_appParam.UseTightModel){
	 for(t = 0; t <= nSteps; t++){ 
	    row.insert(colIndex_x1(a,t), t * coefA);
	    row.insert(colIndex_z (a,t), t * coefC);
	 }
      }
      else{
	 for(t = 0; t < nSteps; t++){ 
	    row.insert(colIndex_x1(a,t), (t+1) * coefA);
	    row.insert(colIndex_z (a,t), (t+1) * coefC);
	 }
      }
      row.insert(colIndex_x2(a), -b_ad[*vi]);
      row.insert(colIndex_x3(a), -d_ad[*vi]);

      rhs = e_ad[*vi];
      model->appendRow(row, rhs, rhs, rowName);
      nRows++;

      //---
      //---       f-[a,d] <= w[a,d] * v[a,d]      
      //---      
      CoinPackedVector rowLink;
      string rowNameLink = "linkv(a_" 
         + m_instance.getAtmName(a) + ",d_" 
         + m_instance.getDateName(d) + ")";	 
      rowLink.insert(colIndex_fm(pairIndex), 1.0);
      rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]);
      model->appendRow(rowLink, -DecompInf, 0.0, rowNameLink);
      nRows++;	 
   
      pairIndex++;
   }
   
   string rowNameBudget = "budget(d_" + m_instance.getDateName(d) + ")";
   model->appendRow(rowBudget, -DecompInf, B_d[d], rowNameBudget);
   nRows++;

  for(a = 0; a < nAtms; a++)
     nRows += createConZtoX(model, a);
   assert(nRows <= nRowsMax);
   
   //---
   //--- create model columns
   //---
   createModelColumns(model, -1, d);
   
   UtilPrintFuncEnd(m_osLog, m_classTag,
		    "createModelRelax2()", m_appParam.LogLevel, 2);

   return model;
}
Ejemplo n.º 6
0
//===========================================================================//
DecompConstraintSet * ATM_DecompApp::createModelCore1(bool includeCount){

   UtilPrintFuncBegin(m_osLog, m_classTag,
		      "createModelCore1()", m_appParam.LogLevel, 2);

   int   a, d, pairIndex;

   pair<int,int>               adP;
   vector<int>::const_iterator vi;

   const int           nAtms   = m_instance.getNAtms();
   const int           nDates  = m_instance.getNDates();
   const vector<int> & pairsAD = m_instance.getPairsAD();   
   const double      * B_d     = m_instance.get_B_d();
   const int           nCols   = numCoreCols();
   int                 nRows   = nDates; 

   if(includeCount)
      nRows += nAtms;

   DecompConstraintSet * model = new DecompConstraintSet();
   CoinAssertHint(model, "Error: Out of Memory");

   model->M = new CoinPackedMatrix(false, 0.0, 0.0);
   CoinAssertHint(model->M, "Error: Out of Memory");
   model->M->setDimensions(0, nCols);
   model->reserve(nRows, nCols);

   //---
   //---    for d in D:
   //---      sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]
   //---
   CoinPackedVector * rowsD = new CoinPackedVector[nDates];   
   pairIndex = 0;
   for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){
      adP = m_instance.getIndexADInv(*vi);
      a   = adP.first;
      d   = adP.second;
      rowsD[d].insert(getColOffset_fp() + pairIndex,  1.0);
      rowsD[d].insert(getColOffset_fm() + pairIndex, -1.0);
      pairIndex++;
   }

   for(d = 0; d < nDates; d++){
      string rowName = "budget(d_" 
	 + m_instance.getDateName(d) + ")";
      model->appendRow(rowsD[d], -DecompInf, B_d[d], rowName);
   }
   UTIL_DELARR(rowsD);

   if(includeCount){
      //---  for a in A:
      //---    sum{d in D} v[a,d] <= K[a]
      //---   
      for(a = 0; a < nAtms; a++){
	 createConCount(model, a);
      }
   }
   
   //---
   //--- create model columns
   //---
   createModelColumns(model);
   
   UtilPrintFuncEnd(m_osLog, m_classTag,
		    "createModelCore1()", m_appParam.LogLevel, 2);

   return model;
}
Ejemplo n.º 7
0
//===========================================================================//
void DecompAlgoRC::phaseDone()
{
   //take the current set of variables and solve DW master to get primal
   //TODO: right now, creating from scratch each time -- really need
   //      to append and warm start - esp if doing alot of branching
   //delete m_masterSI;
   //m_masterSI = NULL;
   //m_masterSI = new OsiLpSolverInterface();
   //CoinAssertHint(m_masterSI, "Error: Out of Memory");
   //m_masterSI->messageHandler()->setLogLevel(m_param.LogLpLevel);
   DecompConstraintSet*           modelCore   = m_modelCore.getModel();
#if 0
   //---
   //--- Initialize the solver interface for the master problem.
   //--- PC: min c(s lam)
   //---     A''s   lam   >= b'',
   //---     sum{s} lam_s  = 1  ,
   //---            lam_s >= 0  , s in F'[0]
   //--- modelCore contains [A'', b''], from the original model in
   //--- terms of x. In this function we create the DW-LP in terms of
   //--- lambda, [[A''s, 1], [b'', 1]] and load that into the OSI
   //--- interface m_masterSI.
   //---
   //--- NOTE: if 0 is feasible to subproblem, we can relax convexity to <= 1
   //---
   UtilPrintFuncBegin(m_osLog, m_classTag,
                      "phaseDone()", m_param.LogDebugLevel, 2);
   CoinAssert(m_vars.size() > 0);
   int nColsCore = modelCore->getNumCols();
   int nRowsCore = modelCore->getNumRows();
   modelCore->nBaseRowsOrig = modelCore->nBaseRows;
   modelCore->nBaseRows     = nRowsCore;
   //THINK? should initVars be in pool and do addVarsFromPool here?
   CoinPackedMatrix* M = new CoinPackedMatrix(true, 0, 0);
   M->setDimensions(nRowsCore + 1, 0);
   const int n_cols  = static_cast<int>(m_vars.size());
   double* colLB    = new double[n_cols];
   double* colUB    = new double[n_cols];
   double* obj      = new double[n_cols];
   double* denseCol = new double[nRowsCore + 1];
   CoinAssertHint(colLB && colUB && obj && denseCol, "Error: Out of Memory");
   int col_index     = 0;
   DecompVarList::iterator li;

   for (li = m_vars.begin(); li != m_vars.end(); li++) {
      UTIL_DEBUG(m_param.LogDebugLevel, 5,
                 (*li)->print(m_osLog, m_app);
                );
      //---
      //--- get dense column = A''s, append convexity constraint on end
      //---
      modelCore->M->times((*li)->m_s, denseCol);
      denseCol[nRowsCore] = 1.0;
      //---
      //--- create a sparse column from the dense column
      //---
      // THINK: do i need a DecompCol?
      // THINK: does this allocate memory for coinpackedvec twice?
      CoinPackedVector* sparseCol
      = UtilPackedVectorFromDense(nRowsCore + 1,
                                  denseCol, m_param.TolZero);
      UTIL_DEBUG(m_param.LogDebugLevel, 5,
                 (*m_osLog) << "\nSparse Col: \n";
                 UtilPrintPackedVector(*sparseCol, m_osLog);
                );
Ejemplo n.º 8
0
//===========================================================================//
bool DecompAlgoModel::isPointFeasible(const double* x,
                                      const bool     isXSparse,
                                      const int      logLevel,
                                      const double   feasVarTol,
                                      const double   feasConTol)
{
   DecompConstraintSet*     model    = getModel();

   if (!model) {
      return true;
   }

   const CoinPackedMatrix* M        = model->getMatrix();

   if (!M) {
      return true;
   }

   const  vector<string>&   colNames = model->getColNames();

   const  vector<string>&   rowNames = model->getRowNames();

   int    c, r, i;

   bool   isFeas      = true;

   bool   hasColNames = false;

   bool   hasRowNames = false;

   double xj          = 0.0;

   double ax          = 0.0;

   double clb         = 0.0;

   double cub         = 0.0;

   double rlb         = 0.0;

   double rub         = 0.0;

   double actViol     = 0.0;

   double relViol     = 0.0;

   if (colNames.size()) {
      hasColNames = true;
   }

   if (rowNames.size()) {
      hasRowNames = true;
   }

   double feasVarTol10 = 10 * feasVarTol;
   double feasConTol10 = 10 * feasConTol;
   //---
   //--- do we satisfy all (active) column bounds
   //---
   vector<int> ::const_iterator it;
   map<int, int>::const_iterator mcit;
   const vector<int>&   activeColumns  = model->getActiveColumns();
   bool                 isSparse       = model->isSparse();
   const map<int, int>& origToSparse   = model->getMapOrigToSparse();
   const map<int, int>& sparseToOrig   = model->getMapSparseToOrig();

   for (it = activeColumns.begin(); it != activeColumns.end(); it++) {
      if (isSparse) {
         mcit = origToSparse.find(*it);
         c    = mcit->second;
         xj   = isXSparse ? x[c] : x[*it];
      } else {
         c  = *it;
         xj = x[c];
         assert(!isXSparse);
      }

      clb      = model->colLB[c];
      cub      = model->colUB[c];
      UTIL_DEBUG(logLevel, 5,
                 int    precision   = 7;

      if (!UtilIsZero(xj)) {
      cout << "Point " << c;

      if (hasColNames) {
            cout << " -> " << colNames[c];
         }

         cout << " LB= " << UtilDblToStr(clb, precision)
         << " x= "  << UtilDblToStr(xj, precision)
         << " UB= " << UtilDblToStr(cub, precision)
         << endl;
      }
                );
      actViol = std::max<double>(clb - xj, xj - cub);
      actViol = std::max<double>(actViol, 0.0);

      if (UtilIsZero(xj, feasVarTol) ||
            (xj < 0 && UtilIsZero(clb)) ||
            (xj > 0 && UtilIsZero(cub))) {
         relViol = actViol;
      } else {
         relViol = actViol / std::fabs(xj);
      }

      if (relViol > feasVarTol) {
         //Notify, but don't mark in feasible unless 10x worse.
         UTIL_DEBUG(logLevel, 4,
                    int    precision   = 7;
                    cout << "Point violates column " << c;

                    if (hasColNames)
                    cout << " -> " << colNames[c];
                    cout << " LB= " << UtilDblToStr(clb, precision)
                    << " x= "  << UtilDblToStr(xj, precision)
                    << " UB= " << UtilDblToStr(cub, precision)
                    << " RelViol= " << UtilDblToStr(relViol, precision)
                    << endl;
                   );