Logo Search packages:      
Sourcecode: rsymphony version File versions  Download package

CoinLpIO.cpp

/* $Id: CoinLpIO.cpp 1240 2009-12-10 17:07:20Z ladanyi $ */
// Last edit: 11/5/08
//
// Name:     CoinLpIO.cpp; Support for Lp files
// Author:   Francois Margot
//           Tepper School of Business
//           Carnegie Mellon University, Pittsburgh, PA 15213
// Date:     12/28/03
//-----------------------------------------------------------------------------
// Copyright (C) 2003, Francois Margot, International Business Machines
// Corporation and others.  All Rights Reserved.

#include <cfloat>
#include <cctype>
#include <cassert>
#include <string>
#include <cstdarg>

#include "CoinError.hpp"
#include "CoinHelperFunctions.hpp"
#include "CoinPackedMatrix.hpp"
#include "CoinLpIO.hpp"

using namespace std;

//#define LPIO_DEBUG

/************************************************************************/

00030 CoinLpIO::CoinLpIO() :
  problemName_(CoinStrdup("")),
  numberRows_(0),
  numberColumns_(0),
  numberElements_(0),
  matrixByColumn_(NULL),
  matrixByRow_(NULL),
  rowlower_(NULL),
  rowupper_(NULL),
  collower_(NULL),
  colupper_(NULL),
  rhs_(NULL),
  rowrange_(NULL),
  rowsense_(NULL),
  objective_(NULL),
  objectiveOffset_(0),
  integerType_(NULL),
  fileName_(NULL),
  infinity_(DBL_MAX),
  epsilon_(1e-5),
  numberAcross_(10),
  decimals_(5),
  objName_(NULL)
{
  card_previous_names_[0] = 0;
  card_previous_names_[1] = 0;
  previous_names_[0] = NULL;
  previous_names_[1] = NULL;

  maxHash_[0]=0;
  numberHash_[0]=0;
  hash_[0] = NULL;
  names_[0] = NULL;
  maxHash_[1] = 0;
  numberHash_[1] = 0;
  hash_[1] = NULL;
  names_[1] = NULL;
}

/************************************************************************/
00070 CoinLpIO::~CoinLpIO() {
  stopHash(0);
  stopHash(1);
  freeAll();
}

/************************************************************************/
void
00078 CoinLpIO::freePreviousNames(const int section) {

  int j;

  if(previous_names_[section] != NULL) {
    for(j=0; j<card_previous_names_[section]; j++) {
      free(previous_names_[section][j]);
    }
    free(previous_names_[section]);
  }
  previous_names_[section] = NULL;
  card_previous_names_[section] = 0;
} /* freePreviousNames */

/************************************************************************/
void
00094 CoinLpIO::freeAll() {

  delete matrixByColumn_;
  delete matrixByRow_;
  free(rowupper_);
  rowupper_ = NULL;
  free(rowlower_);
  rowlower_ = NULL;
  free(colupper_);
  colupper_ = NULL;
  free(collower_);
  collower_ = NULL;
  free(rhs_);
  rhs_ = NULL;
  free(rowrange_);
  rowrange_ = NULL;
  free(rowsense_);
  rowsense_ = NULL;
  free(objective_);
  objective_ = NULL;
  free(integerType_);
  integerType_ = NULL;
  free(problemName_);
  problemName_ = NULL;
  free(fileName_);
  fileName_ = NULL;

  freePreviousNames(0);
  freePreviousNames(1);
}

/*************************************************************************/
00126 const char * CoinLpIO::getProblemName() const
{
  return problemName_;
}

void
00132 CoinLpIO::setProblemName (const char *name)
{
  free(problemName_) ;
  problemName_ = CoinStrdup(name);
}

/*************************************************************************/
00139 int CoinLpIO::getNumCols() const
{
  return numberColumns_;
}

/*************************************************************************/
00145 int CoinLpIO::getNumRows() const
{
  return numberRows_;
}

/*************************************************************************/
00151 int CoinLpIO::getNumElements() const
{
  return numberElements_;
}

/*************************************************************************/
00157 const double * CoinLpIO::getColLower() const
{
  return collower_;
}

/*************************************************************************/
00163 const double * CoinLpIO::getColUpper() const
{
  return colupper_;
}

/*************************************************************************/
00169 const double * CoinLpIO::getRowLower() const
{
  return rowlower_;
}

/*************************************************************************/
00175 const double * CoinLpIO::getRowUpper() const
{
  return rowupper_;
}

/*************************************************************************/
/** A quick inlined function to convert from lb/ub style constraint
    definition to sense/rhs/range style */
inline void
00184 CoinLpIO::convertBoundToSense(const double lower, const double upper,
                        char& sense, double& right,
                        double& range) const
{
  range = 0.0;
  if (lower > -infinity_) {
    if (upper < infinity_) {
      right = upper;
      if (upper==lower) {
        sense = 'E';
      } else {
        sense = 'R';
        range = upper - lower;
      }
    } else {
      sense = 'G';
      right = lower;
    }
  } else {
    if (upper < infinity_) {
      sense = 'L';
      right = upper;
    } else {
      sense = 'N';
      right = 0.0;
    }
  }
}

/*************************************************************************/
00214  const char * CoinLpIO::getRowSense() const
{
  if(rowsense_  == NULL) {
    int nr=numberRows_;
    rowsense_ = reinterpret_cast<char *> (malloc(nr*sizeof(char)));
    
    double dum1,dum2;
    int i;
    for(i=0; i<nr; i++) {
      convertBoundToSense(rowlower_[i],rowupper_[i],rowsense_[i],dum1,dum2);
    }
  }
  return rowsense_;
}

/*************************************************************************/
00230 const double * CoinLpIO::getRightHandSide() const
{
  if(rhs_==NULL) {
    int nr=numberRows_;
    rhs_ = reinterpret_cast<double *> (malloc(nr*sizeof(double)));

    char dum1;
    double dum2;
    int i;
    for (i=0; i<nr; i++) {
      convertBoundToSense(rowlower_[i],rowupper_[i],dum1,rhs_[i],dum2);
    }
  }
  return rhs_;
}

/*************************************************************************/
00247 const double * CoinLpIO::getRowRange() const
{
  if (rowrange_ == NULL) {
    int nr=numberRows_;
    rowrange_ = reinterpret_cast<double *> (malloc(nr*sizeof(double)));
    std::fill(rowrange_,rowrange_+nr,0.0);

    char dum1;
    double dum2;
    int i;
    for (i=0; i<nr; i++) {
      convertBoundToSense(rowlower_[i],rowupper_[i],dum1,dum2,rowrange_[i]);
    }
  }
  return rowrange_;
}

/*************************************************************************/
00265 const double * CoinLpIO::getObjCoefficients() const
{
  return objective_;
}
 
/*************************************************************************/
00271 const CoinPackedMatrix * CoinLpIO::getMatrixByRow() const
{
  return matrixByRow_;
}

/*************************************************************************/
00277 const CoinPackedMatrix * CoinLpIO::getMatrixByCol() const
{
  if (matrixByColumn_ == NULL && matrixByRow_) {
    matrixByColumn_ = new CoinPackedMatrix(*matrixByRow_);
    matrixByColumn_->reverseOrdering();
  }
  return matrixByColumn_;
}

/*************************************************************************/
00287 const char * CoinLpIO::getObjName() const
{
  return objName_;
}
 
/*************************************************************************/
00293 void CoinLpIO::checkRowNames() {

  int i, nrow = getNumRows();

  if(numberHash_[0] != nrow+1) {
    setDefaultRowNames();
    printf("### WARNING: CoinLpIO::checkRowNames(): non distinct or missing row names or objective function name.\nNow using default row names.\n");
  }

  char const * const * rowNames = getRowNames();
  const char *rSense = getRowSense();
  char rName[256];

  // Check that row names and objective function name are all distinct, 
  /// even after adding "_low" to ranged constraint names

  for(i=0; i<nrow; i++) {
    if(rSense[i] == 'R') {
      sprintf(rName, "%s_low", rowNames[i]);
      if(findHash(rName, 0) != -1) {
      setDefaultRowNames();
      printf("### WARNING: CoinLpIO::checkRowNames(): ranged constraint %d hasa name %s identical to another constraint name or objective function name.\nUse getPreviousNames() to get the old row names.\nNow using default row names.\n", i, rName);
      break;
      }
    }
  }
} /* checkRowNames */

/*************************************************************************/
00322 void CoinLpIO::checkColNames() {

  int ncol = getNumCols();

  if(numberHash_[1] != ncol) {
    setDefaultColNames();
    printf("### WARNING: CoinLpIO::checkColNames(): non distinct or missing column names.\nNow using default column names.\n");
  }
} /* checkColNames */

/*************************************************************************/
00333 void CoinLpIO::getPreviousRowNames(char const * const * prev, 
                           int *card_prev) const
{
  *card_prev = card_previous_names_[0];
  prev = previous_names_[0];
}
 
/*************************************************************************/
00341 void CoinLpIO::getPreviousColNames(char const * const * prev, 
                           int *card_prev) const
{
  *card_prev = card_previous_names_[1];
  prev = previous_names_[1];
}
 
/*************************************************************************/
00349 char const * const * CoinLpIO::getRowNames() const
{
  return names_[0];
}
 
/*************************************************************************/
00355 char const * const * CoinLpIO::getColNames() const
{
  return names_[1];
}
 
/*************************************************************************/
00361 const char * CoinLpIO::rowName(int index) const {

  if((names_[0] != NULL) && (index >= 0) && (index < numberRows_+1)) {
    return names_[0][index];
  } 
  else {
    return NULL;
  }
}

/*************************************************************************/
00372 const char * CoinLpIO::columnName(int index) const {

  if((names_[1] != NULL) && (index >= 0) && (index < numberColumns_)) {
    return names_[1][index];
  } 
  else {
    return NULL;
  }
}

/*************************************************************************/
00383 int CoinLpIO::rowIndex(const char * name) const {

  if (!hash_[0]) {
    return -1;
  }
  return findHash(name , 0);
}

/*************************************************************************/
00392 int CoinLpIO::columnIndex(const char * name) const {

  if (!hash_[1]) {
    return -1;
  }
  return findHash(name , 1);
}

/************************************************************************/
00401 double CoinLpIO::getInfinity() const
{
  return infinity_;
}

/************************************************************************/
00407 void CoinLpIO::setInfinity(const double value) 
{
  if (value >= 1.0e20) {
    infinity_ = value;
  } 
  else {
    char str[8192];
    sprintf(str,"### ERROR: value: %f\n", value);
    throw CoinError(str, "setInfinity", "CoinLpIO", __FILE__, __LINE__);
  }
}

/************************************************************************/
00420 double CoinLpIO::getEpsilon() const
{
  return epsilon_;
}

/************************************************************************/
00426 void CoinLpIO::setEpsilon(const double value) 
{
  if (value < 0.1) {
    epsilon_ = value;
  } 
  else {
    char str[8192];
    sprintf(str,"### ERROR: value: %f\n", value);
    throw CoinError(str, "setEpsilon", "CoinLpIO", __FILE__, __LINE__);
  }
}

/************************************************************************/
00439 int CoinLpIO::getNumberAcross() const
{
  return numberAcross_;
}

/************************************************************************/
00445 void CoinLpIO::setNumberAcross(const int value) 
{
  if (value > 0) {
    numberAcross_ = value;
  } 
  else {
    char str[8192];
    sprintf(str,"### ERROR: value: %d\n", value);
    throw CoinError(str, "setNumberAcross", "CoinLpIO", __FILE__, __LINE__);
  }
}

/************************************************************************/
00458 int CoinLpIO::getDecimals() const
{
  return decimals_;
}

/************************************************************************/
00464 void CoinLpIO::setDecimals(const int value) 
{
  if (value > 0) {
    decimals_ = value;
  } 
  else {
    char str[8192];
    sprintf(str,"### ERROR: value: %d\n", value);
    throw CoinError(str, "setDecimals", "CoinLpIO", __FILE__, __LINE__);
  }
}

/************************************************************************/
00477 double CoinLpIO::objectiveOffset() const
{
  return objectiveOffset_;
}

/************************************************************************/
00483 bool CoinLpIO::isInteger(int columnNumber) const
{
  const char * intType = integerType_;
  if (intType == NULL) return false;
  assert (columnNumber >= 0 && columnNumber < numberColumns_);
  if (intType[columnNumber] != 0) return true;
  return false;
}

/************************************************************************/
00493 const char * CoinLpIO::integerColumns() const
{
  return integerType_;
}

/************************************************************************/
void
00500 CoinLpIO::setLpDataWithoutRowAndColNames(
                        const CoinPackedMatrix& m,
                        const double *collb, const double *colub,
                        const double *obj_coeff,
                        const char *is_integer,
                        const double *rowlb, const double *rowub) {

  freeAll();
  problemName_ = CoinStrdup("");

  if (m.isColOrdered()) {
    matrixByRow_ = new CoinPackedMatrix();
    matrixByRow_->reverseOrderedCopyOf(m);
  } 
  else {
    matrixByRow_ = new CoinPackedMatrix(m);
  }
  numberColumns_ = matrixByRow_->getNumCols();
  numberRows_ = matrixByRow_->getNumRows();
  
  rowlower_ = reinterpret_cast<double *> (malloc (numberRows_ * sizeof(double)));
  rowupper_ = reinterpret_cast<double *> (malloc (numberRows_ * sizeof(double)));
  collower_ = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
  colupper_ = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
  objective_ = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
  std::copy(rowlb, rowlb + numberRows_, rowlower_);
  std::copy(rowub, rowub + numberRows_, rowupper_);
  std::copy(collb, collb + numberColumns_, collower_);
  std::copy(colub, colub + numberColumns_, colupper_);
  std::copy(obj_coeff, obj_coeff + numberColumns_, objective_);

  if (is_integer) {
    integerType_ = reinterpret_cast<char *> (malloc (numberColumns_ * sizeof(char)));
    std::copy(is_integer, is_integer + numberColumns_, integerType_);
  } 
  else {
    integerType_ = 0;
  }

  if((numberHash_[0] > 0) && (numberHash_[0] != numberRows_+1)) {
    stopHash(0);
  }
  if((numberHash_[1] > 0) && (numberHash_[1] != numberColumns_)) {
    stopHash(1);
  }
} /* SetLpDataWithoutRowAndColNames */

/*************************************************************************/
00548 void CoinLpIO::setDefaultRowNames() {

  int i, nrow = getNumRows();
  char **defaultRowNames = reinterpret_cast<char **> (malloc ((nrow+1) * sizeof(char *)));
  char buff[1024];

  for(i=0; i<nrow; i++) {
    sprintf(buff, "cons%d", i);
    defaultRowNames[i] = CoinStrdup(buff);
  }
  sprintf(buff, "obj");
  defaultRowNames[nrow] = CoinStrdup(buff);

  stopHash(0);
  startHash(defaultRowNames, nrow+1, 0);
  objName_ = CoinStrdup("obj");

  for(i=0; i<nrow+1; i++) {
    free(defaultRowNames[i]);
  }
  free(defaultRowNames);

} /* setDefaultRowNames */

/*************************************************************************/
00573 void CoinLpIO::setDefaultColNames() {

  int j, ncol = getNumCols();
  char **defaultColNames = reinterpret_cast<char **> (malloc (ncol * sizeof(char *)));
  char buff[256];

  for(j=0; j<ncol; j++) {
    sprintf(buff, "x%d", j);
    defaultColNames[j] = CoinStrdup(buff);
  }
  stopHash(1);
  startHash(defaultColNames, ncol, 1);

  for(j=0; j<ncol; j++) {
    free(defaultColNames[j]);
  }
  free(defaultColNames);

} /* setDefaultColNames */

/*************************************************************************/
00594 void CoinLpIO::setLpDataRowAndColNames(char const * const * const rownames,
                               char const * const * const colnames) {

  int nrow = getNumRows();
  int ncol = getNumCols();

  if(rownames != NULL) {
    if(are_invalid_names(rownames, nrow+1, true)) {
      setDefaultRowNames();
      printf("### WARNING: CoinLpIO::setLpDataRowAndColNames(): Invalid row names\nUse getPreviousNames() to get the old row names.\nNow using default row names.\n");
    } 
    else {
      stopHash(0);
      startHash(rownames, nrow+1, 0);
      objName_ = CoinStrdup(rownames[nrow]);
      checkRowNames();
    }
  }
  else {
    if(objName_ == NULL) {
      objName_ = CoinStrdup("obj");      
    }
  }

  if(colnames != NULL) {
    if(are_invalid_names(colnames, ncol, false)) {
      setDefaultColNames();
      printf("### WARNING: CoinLpIO::setLpDataRowAndColNames(): Invalid column names\nNow using default row names.\n");
    } 
    else {
      stopHash(1);
      startHash(colnames, ncol, 1);
      checkColNames();
    }
  }
} /* setLpDataColAndRowNames */

/************************************************************************/
void
00633 CoinLpIO::out_coeff(FILE *fp, const double v, const int print_1) const {

  double lp_eps = getEpsilon();

  if(!print_1) {
    if(fabs(v-1) < lp_eps) {
      return;
    }
    if(fabs(v+1) < lp_eps) {
      fprintf(fp, " -");
      return;
    }
  }

  double frac = v - floor(v);

  if(frac < lp_eps) {
    fprintf(fp, " %.0f", floor(v));
  }
  else {
    if(frac > 1 - lp_eps) {
      fprintf(fp, " %.0f", floor(v+0.5));
    }
    else {
      int decimals = getDecimals();
      char form[15];
      sprintf(form, " %%.%df", decimals);
      fprintf(fp, form, v);
    }
  }
} /* out_coeff */

/************************************************************************/
int
00667 CoinLpIO::writeLp(const char *filename, const double epsilon,
              const int numberAcross, const int decimals,
              const bool useRowNames) {

  FILE *fp = NULL;
  fp = fopen(filename,"w");
  if (!fp) {
    char str[8192];
    sprintf(str,"### ERROR: unable to open file %s\n", filename);
    throw CoinError(str, "writeLP", "CoinLpIO", __FILE__, __LINE__);
  }
  int nerr = writeLp(fp, epsilon, numberAcross, decimals, useRowNames);
  fclose(fp);
  return(nerr);
}

/************************************************************************/
int
00685 CoinLpIO::writeLp(FILE *fp, const double epsilon,
              const int numberAcross, const int decimals,
              const bool useRowNames) {

  setEpsilon(epsilon);
  setNumberAcross(numberAcross);
  setDecimals(decimals);
  return writeLp(fp, useRowNames);
}

/************************************************************************/
int
00697 CoinLpIO::writeLp(const char *filename, const bool useRowNames)
{
  FILE *fp = NULL;
  fp = fopen(filename,"w");
  if (!fp) {
    char str[8192];
    sprintf(str,"### ERROR: unable to open file %s\n", filename);
    throw CoinError(str, "writeLP", "CoinLpIO", __FILE__, __LINE__);
  }
  int nerr = writeLp(fp, useRowNames);
  fclose(fp);
  return(nerr);
}

/************************************************************************/
int
00713 CoinLpIO::writeLp(FILE *fp, const bool useRowNames)
{
   double lp_eps = getEpsilon();
   double lp_inf = getInfinity();
   int numberAcross = getNumberAcross();

   int i, j, cnt_print, loc_row_names = 0, loc_col_names = 0;
   char **prowNames = NULL, **pcolNames = NULL;

   const int *indices = matrixByRow_->getIndices();
   const double *elements  = matrixByRow_->getElements();
   int ncol = getNumCols();
   int nrow = getNumRows();
   const double *collow = getColLower();
   const double *colup = getColUpper();
   const double *rowlow = getRowLower();
   const double *rowup = getRowUpper();
   const double *obj = getObjCoefficients();
   const char *integerType = integerColumns();
   char const * const * rowNames = getRowNames();
   char const * const * colNames = getColNames();
   
   char buff[256];

   if(rowNames == NULL) {
     loc_row_names = 1;
     prowNames = reinterpret_cast<char **> (malloc ((nrow+1) * sizeof(char *)));

     for (j=0; j<nrow; j++) {
       sprintf(buff, "cons%d", j);
       prowNames[j] = CoinStrdup(buff);
     }
     prowNames[nrow] = CoinStrdup("obj");
     rowNames = prowNames;
   }

   if(colNames == NULL) {
     loc_col_names = 1;
     pcolNames = reinterpret_cast<char **> (malloc (ncol * sizeof(char *)));

     for (j=0; j<ncol; j++) {
       sprintf(buff, "x%d", j);
       pcolNames[j] = CoinStrdup(buff);
     }
     colNames = pcolNames;
   }

#ifdef LPIO_DEBUG
   printf("CoinLpIO::writeLp(): numberRows: %d numberColumns: %d\n", 
        nrow, ncol);
#endif
 
   fprintf(fp, "\\Problem name: %s\n\n", getProblemName());
   fprintf(fp, "Minimize\n");

   if(useRowNames) {
     fprintf(fp, "%s:", objName_);
   }

   cnt_print = 0;
   for(j=0; j<ncol; j++) {
     if((cnt_print > 0) && (objective_[j] > lp_eps)) {
       fprintf(fp, " +");
     }
     if(fabs(obj[j]) > lp_eps) {
       out_coeff(fp, obj[j], 0);
       fprintf(fp, " %s", colNames[j]);
       cnt_print++;
       if(cnt_print % numberAcross == 0) {
       fprintf(fp, "\n");
       }
     }
   }
 
   if((cnt_print > 0) && (objectiveOffset_ > lp_eps)) {
     fprintf(fp, " +");
   }
   if(fabs(objectiveOffset_) > lp_eps) {
     out_coeff(fp, objectiveOffset_, 1);
     cnt_print++;
   }

   if(cnt_print % numberAcross != 0) {
     fprintf(fp, "\n");
   }
   
   fprintf(fp, "Subject To\n");
   
   int cnt_out_rows = 0;

   for(i=0; i<nrow; i++) {
     cnt_print = 0;
     
     if(useRowNames) {
       fprintf(fp, "%s: ", rowNames[i]);
     }
     cnt_out_rows++;

     for(j=matrixByRow_->getVectorFirst(i); 
       j<matrixByRow_->getVectorLast(i); j++) {
       if((cnt_print > 0) && (elements[j] > lp_eps)) {
       fprintf(fp, " +");
       }
       if(fabs(elements[j]) > lp_eps) {
       out_coeff(fp, elements[j], 0);
       fprintf(fp, " %s", colNames[indices[j]]);
       cnt_print++;
       if(cnt_print % numberAcross == 0) {
         fprintf(fp, "\n");
       }
       }
     }

     if(rowup[i] - rowlow[i] < lp_eps) {
          fprintf(fp, " =");
        out_coeff(fp, rowlow[i], 1);
        fprintf(fp, "\n");
     }
     else {
       if(rowup[i] < lp_inf) {
       fprintf(fp, " <=");
       out_coeff(fp, rowup[i], 1);   
       fprintf(fp, "\n");

       if(rowlower_[i] > -lp_inf) {

         cnt_print = 0;

         if(useRowNames) {
           fprintf(fp, "%s_low:", rowNames[i]);
         }
         cnt_out_rows++;
         
         for(j=matrixByRow_->getVectorFirst(i); 
             j<matrixByRow_->getVectorLast(i); j++) {
           if((cnt_print>0) && (elements[j] > lp_eps)) {
             fprintf(fp, " +");
           }
           if(fabs(elements[j]) > lp_eps) {
             out_coeff(fp, elements[j], 0);
             fprintf(fp, " %s", colNames[indices[j]]);
             cnt_print++;
             if(cnt_print % numberAcross == 0) {
             fprintf(fp, "\n");
             }
           }
         }
         fprintf(fp, " >=");
         out_coeff(fp, rowlow[i], 1);
         fprintf(fp, "\n");
       }

       }
       else {
       fprintf(fp, " >=");
       out_coeff(fp, rowlow[i], 1);  
       fprintf(fp, "\n");
       }
     }
   }

#ifdef LPIO_DEBUG
   printf("CoinLpIO::writeLp(): Done with constraints\n");
#endif

   fprintf(fp, "Bounds\n");
   
   for(j=0; j<ncol; j++) {
     if((collow[j] > -lp_inf) && (colup[j] < lp_inf)) {
       out_coeff(fp, collow[j], 1);
       fprintf(fp, " <= %s <=", colNames[j]); 
       out_coeff(fp, colup[j], 1);
       fprintf(fp, "\n");
     }
     if((collow[j] == -lp_inf) && (colup[j] < lp_inf)) {
       fprintf(fp, "%s <=", colNames[j]);
       out_coeff(fp, colup[j], 1);
       fprintf(fp, "\n");
     }
     if((collow[j] > -lp_inf) && (colup[j] == lp_inf)) {
       if(fabs(collow[j]) > lp_eps) { 
       out_coeff(fp, collow[j], 1);
       fprintf(fp, " <= %s\n", colNames[j]);
       }
     }
     if(collow[j] == -lp_inf) {
       fprintf(fp, " %s Free\n", colNames[j]); 
     }
   }

#ifdef LPIO_DEBUG
   printf("CoinLpIO::writeLp(): Done with bounds\n");
#endif

   if(integerType != NULL) {
     int first_int = 1;
     cnt_print = 0;
     for(j=0; j<ncol; j++) {
       if(integerType[j] == 1) {

       if(first_int) {
         fprintf(fp, "Integers\n");
         first_int = 0;
       }

       fprintf(fp, "%s ", colNames[j]);
       cnt_print++;
       if(cnt_print % numberAcross == 0) {
         fprintf(fp, "\n");
       }
       }
     }

     if(cnt_print % numberAcross != 0) {
       fprintf(fp, "\n");
     }
   }

#ifdef LPIO_DEBUG
   printf("CoinLpIO::writeLp(): Done with integers\n");
#endif

   fprintf(fp, "End\n");

   if(loc_row_names) {
     for(j=0; j<nrow+1; j++) {
       free(prowNames[j]);
     }
     free(prowNames);
   }

   if(loc_col_names) {
     for(j=0; j<ncol; j++) {
       free(pcolNames[j]);
     }
     free(pcolNames);
   }
   return 0;
} /* writeLp */

/*************************************************************************/
int 
00955 CoinLpIO::find_obj(FILE *fp) const {

  char buff[1024];

  sprintf(buff, "aa");
  size_t lbuff = strlen(buff);

  while(((lbuff != 8) || (CoinStrNCaseCmp(buff, "minimize", 8) != 0)) &&
      ((lbuff != 3) || (CoinStrNCaseCmp(buff, "min", 3) != 0)) &&
      ((lbuff != 8) || (CoinStrNCaseCmp(buff, "maximize", 8) != 0)) &&
      ((lbuff != 3) || (CoinStrNCaseCmp(buff, "max", 3) != 0))) {

    scan_next(buff, fp);
    lbuff = strlen(buff);
    
    if(feof(fp)) {
      char str[8192];
      sprintf(str,"### ERROR: Unable to locate objective function\n");
      throw CoinError(str, "find_obj", "CoinLpIO", __FILE__, __LINE__);
    }
  }

  if(((lbuff == 8) && (CoinStrNCaseCmp(buff, "minimize", 8) == 0)) ||
     ((lbuff == 3) && (CoinStrNCaseCmp(buff, "min", 3) == 0))) {
    return(1);
  }
  return(-1);
} /* find_obj */

/*************************************************************************/
int
00986 CoinLpIO::is_subject_to(const char *buff) const {

  size_t lbuff = strlen(buff);

  if(((lbuff == 4) && (CoinStrNCaseCmp(buff, "s.t.", 4) == 0)) ||
     ((lbuff == 3) && (CoinStrNCaseCmp(buff, "st.", 3) == 0)) ||
     ((lbuff == 2) && (CoinStrNCaseCmp(buff, "st", 2) == 0))) {
    return(1);
  }
  if((lbuff == 7) && (CoinStrNCaseCmp(buff, "subject", 7) == 0)) {
    return(2);
  }
  return(0);
} /* is_subject_to */

/*************************************************************************/
int 
01003 CoinLpIO::first_is_number(const char *buff) const {

  size_t pos;
  char str_num[] = "1234567890";

  pos = strcspn (buff, str_num);
  if (pos == 0) {
    return(1);
  }
  return(0);
} /* first_is_number */

/*************************************************************************/
int 
01017 CoinLpIO::is_sense(const char *buff) const {

  size_t pos;
  char str_sense[] = "<>=";

  pos = strcspn(buff, str_sense);
  if(pos == 0) {
    if(strcmp(buff, "<=") == 0) {
      return(0);
    }
    if(strcmp(buff, "=") == 0) {
      return(1);
    }
    if(strcmp(buff, ">=") == 0) {
      return(2);
    }
    
    printf("### ERROR: CoinLpIO: is_sense(): string: %s \n", buff);
  }
  return(-1);
} /* is_sense */

/*************************************************************************/
int 
01041 CoinLpIO::is_free(const char *buff) const {

  size_t lbuff = strlen(buff);

  if((lbuff == 4) && (CoinStrNCaseCmp(buff, "free", 4) == 0)) {
    return(1);
  }
  return(0);
} /* is_free */

/*************************************************************************/
int 
01053 CoinLpIO::is_inf(const char *buff) const {

  size_t lbuff = strlen(buff);

  if((lbuff == 3) && (CoinStrNCaseCmp(buff, "inf", 3) == 0)) {
    return(1);
  }
  return(0);
} /* is_inf */

/*************************************************************************/
int 
01065 CoinLpIO::is_comment(const char *buff) const {

  if((buff[0] == '/') || (buff[0] == '\\')) {
    return(1);
  }
  return(0);
} /* is_comment */

/*************************************************************************/
void
01075 CoinLpIO::skip_comment(char *buff, FILE *fp) const {

  while(strcspn(buff, "\n") == strlen(buff)) { // end of line not read yet
    if(feof(fp)) {
      char str[8192];
      sprintf(str,"### ERROR: end of file reached while skipping comment\n");
      throw CoinError(str, "skip_comment", "CoinLpIO", __FILE__, __LINE__);
    }
    if(ferror(fp)) {
      char str[8192];
      sprintf(str,"### ERROR: error while skipping comment\n");
      throw CoinError(str, "skip_comment", "CoinLpIO", __FILE__, __LINE__);
    }
    char * x=fgets(buff, sizeof(buff), fp);    
    if (!x)
      throw("bad fgets");
  } 
} /* skip_comment */

/*************************************************************************/
void
01096 CoinLpIO::scan_next(char *buff, FILE *fp) const {

  int x=fscanf(fp, "%s", buff);
  if (x<=0)
    throw("bad fscanf");
  while(is_comment(buff)) {
    skip_comment(buff, fp);
    x=fscanf(fp, "%s", buff);
    if (x<=0)
      throw("bad fscanf");
  }

#ifdef LPIO_DEBUG
  printf("CoinLpIO::scan_next: (%s)\n", buff);
#endif

} /* scan_next */

/*************************************************************************/
int 
01116 CoinLpIO::is_invalid_name(const char *name, 
                    const bool ranged) const {

  size_t pos, lname, valid_lname = 100;
  char str_valid[] = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"!#$%&(),.;?@_'`{}~";

  if(ranged) {
    valid_lname -= 4; // will add "_low" when writing the Lp file
  }

  if(name == NULL) {
    lname = 0;
  }
  else {
    lname = strlen(name);
  }
  if(lname < 1) {
    printf("### WARNING: CoinLpIO::is_invalid_name(): Name is empty\n");
    return(5);
  }
  if(lname > valid_lname) {
    printf("### WARNING: CoinLpIO::is_invalid_name(): Name %s is too long\n", 
         name);
    return(1);
  }
  if(first_is_number(name)) {
    printf("### WARNING: CoinLpIO::is_invalid_name(): Name %s should not start with a number\n", name);
    return(2);
  }
  pos = strspn(name, str_valid);
  if(pos != lname) {
    printf("### WARNING: CoinLpIO::is_invalid_name(): Name %s contains illegal character '%c'\n", name, name[pos]);
    return(3);
  }

  if((is_keyword(name)) || (is_free(name) || (is_inf(name)))) {
    return(4);
  }

  return(0);
} /* is_invalid_name */

/*************************************************************************/
int 
01160 CoinLpIO::are_invalid_names(char const * const * const vnames, 
                      const int card_vnames, 
                      const bool check_ranged) const {

  int i, invalid = 0, flag, nrows = getNumRows();
  bool is_ranged = 0;
  const char * rSense = getRowSense();

  if((check_ranged) && (card_vnames != nrows+1)) {
    char str[8192];
    sprintf(str,"### ERROR: card_vnames: %d   number of rows: %d\n",
          card_vnames, getNumRows());
    throw CoinError(str, "are_invalid_names", "CoinLpIO", __FILE__, __LINE__);
  }

  for(i=0; i<card_vnames; i++) {

    if((check_ranged) && (i < nrows) && (rSense[i] == 'R')) {
      is_ranged = true;
    }
    else {
      is_ranged = false;
    }
    flag = is_invalid_name(vnames[i], is_ranged);
    if(flag) {
      printf("### WARNING: CoinLpIO::are_invalid_names(): Invalid name: vnames[%d]: %s\n",
           i, vnames[i]);
      invalid = flag;
    }
  }
  return(invalid);
} /* are_invalid_names */

/*************************************************************************/
int 
01195 CoinLpIO::read_monom_obj(FILE *fp, double *coeff, char **name, int *cnt, 
                                     char **obj_name) {

  double mult;
  char buff[1024] = "aa", loc_name[1024], *start;
  int read_st = 0;

  scan_next(buff, fp);

  if(feof(fp)) {
    char str[8192];
    sprintf(str,"### ERROR: Unable to read objective function\n");
    throw CoinError(str, "read_monom_obj", "CoinLpIO", __FILE__, __LINE__);
  }

  if(buff[strlen(buff)-1] == ':') {
    buff[strlen(buff)-1] = '\0';

#ifdef LPIO_DEBUG
    printf("CoinLpIO: read_monom_obj(): obj_name: %s\n", buff);
#endif

    *obj_name = CoinStrdup(buff);
    return(0);
  }


  read_st = is_subject_to(buff);

#ifdef LPIO_DEBUG
  printf("read_monom_obj: first buff: (%s)\n", buff);
#endif

  if(read_st > 0) {
    return(read_st);
  }

  start = buff;
  mult = 1;
  if(buff[0] == '+') {
    mult = 1;
    if(strlen(buff) == 1) {
      scan_next(buff, fp);
      start = buff;
    }
    else {
      start = &(buff[1]);
    }
  }
  
  if(buff[0] == '-') {
    mult = -1;
    if(strlen(buff) == 1) {
      scan_next(buff, fp);
      start = buff;
    }
    else {
      start = &(buff[1]);
    }
  }
  
  if(first_is_number(start)) {
    coeff[*cnt] = atof(start);       
    sprintf(loc_name, "aa");
    scan_next(loc_name, fp);
  }
  else {
    coeff[*cnt] = 1;
    strcpy(loc_name, start);
  }

  read_st = is_subject_to(loc_name);

#ifdef LPIO_DEBUG
  printf("read_monom_obj: second buff: (%s)\n", buff);
#endif

  if(read_st > 0) {
    setObjectiveOffset(mult * coeff[*cnt]);

#ifdef LPIO_DEBUG
  printf("read_monom_obj: objectiveOffset: %f\n", objectiveOffset_);
#endif

    return(read_st);
  }

  coeff[*cnt] *= mult;
  name[*cnt] = CoinStrdup(loc_name);

#ifdef LPIO_DEBUG
  printf("read_monom_obj: (%f)  (%s)\n", coeff[*cnt], name[*cnt]);
#endif

  (*cnt)++;

  return(read_st);
} /* read_monom_obj */

/*************************************************************************/
int 
01296 CoinLpIO::read_monom_row(FILE *fp, char *start_str, 
                   double *coeff, char **name, 
                   int cnt_coeff) const {

  double mult;
  char buff[1024], loc_name[1024], *start;
  int read_sense = -1;

  sprintf(buff, "%s", start_str);
  read_sense = is_sense(buff);
  if(read_sense > -1) {
    return(read_sense);
  }

  start = buff;
  mult = 1;
  if(buff[0] == '+') {
    mult = 1;
    if(strlen(buff) == 1) {
      scan_next(buff, fp);
      start = buff;
    }
    else {
      start = &(buff[1]);
    }
  }
  
  if(buff[0] == '-') {
    mult = -1;
    if(strlen(buff) == 1) {
      scan_next(buff, fp);
      start = buff;
    }
    else {
      start = &(buff[1]);
    }
  }
  
  if(first_is_number(start)) {
    coeff[cnt_coeff] = atof(start);       
    scan_next(loc_name, fp);
  }
  else {
    coeff[cnt_coeff] = 1;
    strcpy(loc_name, start);
  }

  coeff[cnt_coeff] *= mult;
  name[cnt_coeff] = CoinStrdup(loc_name);

#ifdef LPIO_DEBUG
  printf("CoinLpIO: read_monom_row: (%f)  (%s)\n", 
       coeff[cnt_coeff], name[cnt_coeff]);
#endif  
  return(read_sense);
} /* read_monom_row */

/*************************************************************************/
void
01355 CoinLpIO::realloc_coeff(double **coeff, char ***colNames, 
                  int *maxcoeff) const {
  
  *maxcoeff *= 5;

  *colNames = reinterpret_cast<char **> (realloc ((*colNames), (*maxcoeff+1) * sizeof(char *)));
  *coeff = reinterpret_cast<double *> (realloc ((*coeff), (*maxcoeff+1) * sizeof(double)));

} /* realloc_coeff */

/*************************************************************************/
void
01367 CoinLpIO::realloc_row(char ***rowNames, int **start, double **rhs, 
                  double **rowlow, double **rowup, int *maxrow) const {

  *maxrow *= 5;
  *rowNames = reinterpret_cast<char **> (realloc ((*rowNames), (*maxrow+1) * sizeof(char *)));
  *start = reinterpret_cast<int *> (realloc ((*start), (*maxrow+1) * sizeof(int)));
  *rhs = reinterpret_cast<double *> (realloc ((*rhs), (*maxrow+1) * sizeof(double)));
  *rowlow = reinterpret_cast<double *> (realloc ((*rowlow), (*maxrow+1) * sizeof(double)));
  *rowup = reinterpret_cast<double *> (realloc ((*rowup), (*maxrow+1) * sizeof(double)));

} /* realloc_row */

/*************************************************************************/
void
01381 CoinLpIO::realloc_col(double **collow, double **colup, char **is_int,
                  int *maxcol) const {
  
  *maxcol += 100;
  *collow = reinterpret_cast<double *> (realloc ((*collow), (*maxcol+1) * sizeof(double)));
  *colup = reinterpret_cast<double *> (realloc ((*colup), (*maxcol+1) * sizeof(double)));
  *is_int = reinterpret_cast<char *> (realloc ((*is_int), (*maxcol+1) * sizeof(char)));

} /* realloc_col */

/*************************************************************************/
void 
01393 CoinLpIO::read_row(FILE *fp, char *buff,
               double **pcoeff, char ***pcolNames, 
               int *cnt_coeff,
               int *maxcoeff,
               double *rhs, double *rowlow, double *rowup, 
               int *cnt_row, double inf) const {

  int read_sense = -1;
  char start_str[1024];
  
  sprintf(start_str, "%s", buff);

  while(read_sense < 0) {

    if((*cnt_coeff) == (*maxcoeff)) {
      realloc_coeff(pcoeff, pcolNames, maxcoeff);
    }
    read_sense = read_monom_row(fp, start_str, 
                        *pcoeff, *pcolNames, *cnt_coeff);

    (*cnt_coeff)++;

    scan_next(start_str, fp);

    if(feof(fp)) {
      char str[8192];
      sprintf(str,"### ERROR: Unable to read row monomial\n");
      throw CoinError(str, "read_monom_row", "CoinLpIO", __FILE__, __LINE__);
    }
  }
  (*cnt_coeff)--;

  rhs[*cnt_row] = atof(start_str);

  switch(read_sense) {
  case 0: rowlow[*cnt_row] = -inf; rowup[*cnt_row] = rhs[*cnt_row];
    break;
  case 1: rowlow[*cnt_row] = rhs[*cnt_row]; rowup[*cnt_row] = rhs[*cnt_row];
    break;
  case 2: rowlow[*cnt_row] = rhs[*cnt_row]; rowup[*cnt_row] = inf; 
    break;
  default: break;
  }
  (*cnt_row)++;

} /* read_row */

/*************************************************************************/
int 
01442 CoinLpIO::is_keyword(const char *buff) const {

  size_t lbuff = strlen(buff);

  if(((lbuff == 5) && (CoinStrNCaseCmp(buff, "bound", 5) == 0)) ||
     ((lbuff == 6) && (CoinStrNCaseCmp(buff, "bounds", 6) == 0))) {
    return(1);
  }

  if(((lbuff == 7) && (CoinStrNCaseCmp(buff, "integer", 7) == 0)) ||
     ((lbuff == 8) && (CoinStrNCaseCmp(buff, "integers", 8) == 0))) {
    return(2);
  }
  
  if(((lbuff == 7) && (CoinStrNCaseCmp(buff, "general", 7) == 0)) ||
     ((lbuff == 8) && (CoinStrNCaseCmp(buff, "generals", 8) == 0))) {
    return(2);
  }

  if(((lbuff == 6) && (CoinStrNCaseCmp(buff, "binary", 6) == 0)) ||
     ((lbuff == 8) && (CoinStrNCaseCmp(buff, "binaries", 8) == 0))) {
    return(3);
  }
  
  if((lbuff == 3) && (CoinStrNCaseCmp(buff, "end", 3) == 0)) {
    return(4);
  }

  return(0);

} /* is_keyword */

/*************************************************************************/
void
01476 CoinLpIO::readLp(const char *filename, const double epsilon)
{
  setEpsilon(epsilon);
  readLp(filename);
}

/*************************************************************************/
void
01484 CoinLpIO::readLp(const char *filename)
{
  FILE *fp = fopen(filename, "r");
  if(!fp) {
    char str[8192];
    sprintf(str,"### ERROR: Unable to open file %s for reading\n", filename);
    throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
  }
  readLp(fp);
  fclose(fp);
}

/*************************************************************************/
void
01498 CoinLpIO::readLp(FILE* fp, const double epsilon)
{
  setEpsilon(epsilon);
  readLp(fp);
}

/*************************************************************************/
void
01506 CoinLpIO::readLp(FILE* fp)
{

  int maxrow = 1000;
  int maxcoeff = 40000;
  double lp_eps = getEpsilon();
  double lp_inf = getInfinity();

  char buff[1024];

  int objsense, cnt_coeff = 0, cnt_row = 0, cnt_obj = 0;
  char *objName = NULL;

  char **colNames = reinterpret_cast<char **> (malloc ((maxcoeff+1) * sizeof(char *)));
  double *coeff = reinterpret_cast<double *> (malloc ((maxcoeff+1) * sizeof(double)));

  char **rowNames = reinterpret_cast<char **> (malloc ((maxrow+1) * sizeof(char *)));
  int *start = reinterpret_cast<int *> (malloc ((maxrow+1) * sizeof(int)));
  double *rhs = reinterpret_cast<double *> (malloc ((maxrow+1) * sizeof(double)));
  double *rowlow = reinterpret_cast<double *> (malloc ((maxrow+1) * sizeof(double)));
  double *rowup = reinterpret_cast<double *> (malloc ((maxrow+1) * sizeof(double)));

  int i;

  objsense = find_obj(fp);

  int read_st = 0;
  while(!read_st) {
    read_st = read_monom_obj(fp, coeff, colNames, &cnt_obj, &objName);

    if(cnt_obj == maxcoeff) {
      realloc_coeff(&coeff, &colNames, &maxcoeff);
    }
  }
  
  start[0] = cnt_obj;
  cnt_coeff = cnt_obj;

  if(read_st == 2) {
    int x=fscanf(fp, "%s", buff);
    if (x<=0)
      throw("bad fscanf");
    size_t lbuff = strlen(buff);

    if((lbuff != 2) || (CoinStrNCaseCmp(buff, "to", 2) != 0)) {
      char str[8192];
      sprintf(str,"### ERROR: Can not locate keyword 'Subject To'\n");
      throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
    }
  }
  
  scan_next(buff, fp);

  while(!is_keyword(buff)) {
    if(buff[strlen(buff)-1] == ':') {
      buff[strlen(buff)-1] = '\0';

#ifdef LPIO_DEBUG
      printf("CoinLpIO::readLp(): rowName[%d]: %s\n", cnt_row, buff);
#endif

      rowNames[cnt_row] = CoinStrdup(buff);
      scan_next(buff, fp);
    }
    else {
      char rname[15];
      sprintf(rname, "cons%d", cnt_row); 
      rowNames[cnt_row] = CoinStrdup(rname);
    }
    read_row(fp, buff, 
           &coeff, &colNames, &cnt_coeff, &maxcoeff, rhs, rowlow, rowup, 
           &cnt_row, lp_inf);
    scan_next(buff, fp);
    start[cnt_row] = cnt_coeff;

    if(cnt_row == maxrow) {
      realloc_row(&rowNames, &start, &rhs, &rowlow, &rowup, &maxrow);
    }

  }

  numberRows_ = cnt_row;

  stopHash(1);
  startHash(colNames, cnt_coeff, 1);
  
  COINColumnIndex icol;
  int read_sense1,  read_sense2;
  double bnd1 = 0, bnd2 = 0;

  int maxcol = numberHash_[1] + 100;

  double *collow = reinterpret_cast<double *> (malloc ((maxcol+1) * sizeof(double)));
  double *colup = reinterpret_cast<double *> (malloc ((maxcol+1) * sizeof(double)));
  char *is_int = reinterpret_cast<char *> (malloc ((maxcol+1) * sizeof(char)));
  int has_int = 0;

  for (i=0; i<maxcol; i++) {
    collow[i] = 0;
    colup[i] = lp_inf;
    is_int[i] = 0;
  }

  int done = 0;

  while(!done) {
    switch(is_keyword(buff)) {

    case 1: /* Bounds section */ 
      scan_next(buff, fp);

      while(is_keyword(buff) == 0) {

      read_sense1 = -1;
      read_sense2 = -1;
      int mult = 1;
      char *start_str = buff;

      if(buff[0] == '-' || buff[0] == '+') {
        mult = (buff[0] == '-') ? -1 : +1;
        if(strlen(buff) == 1) {
          scan_next(buff, fp);
          start_str = buff;
        }
        else {
          start_str = &(buff[1]);
        }
      }

      int scan_sense = 0;
      if(first_is_number(start_str)) {
        bnd1 = mult * atof(start_str);
        scan_sense = 1;
      }
      else {
        if(is_inf(start_str)) {
          bnd1 = mult * lp_inf;
          scan_sense = 1;
        }
      }
      if(scan_sense) {
        scan_next(buff, fp);
        read_sense1 = is_sense(buff);
        if(read_sense1 < 0) {
          char str[8192];
          sprintf(str,"### ERROR: Bounds; expect a sense, get: %s\n", buff);
          throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
        }
        scan_next(buff, fp);
      }

      icol = findHash(buff, 1);
      if(icol < 0) {
        printf("### WARNING: CoinLpIO::readLp(): Variable %s does not appear in objective function or constraints\n", buff);
        insertHash(buff, 1);
        icol = findHash(buff, 1);
        if(icol == maxcol) {
          realloc_col(&collow, &colup, &is_int, &maxcol);
        }
      }

      scan_next(buff, fp);
      if(is_free(buff)) {
        collow[icol] = -lp_inf;
        scan_next(buff, fp);
      }
            else {
        read_sense2 = is_sense(buff);
        if(read_sense2 > -1) {
          scan_next(buff, fp);
          mult = 1;
          start_str = buff;

          if(buff[0] == '-'||buff[0] == '+') {
            mult = (buff[0] == '-') ? -1 : +1;
            if(strlen(buff) == 1) {
            scan_next(buff, fp);
            start_str = buff;
            }
            else {
            start_str = &(buff[1]);
            }
          }
          if(first_is_number(start_str)) {
            bnd2 = mult * atof(start_str);
            scan_next(buff, fp);
          }
          else {
            if(is_inf(start_str)) {
            bnd2 = mult * lp_inf;
            scan_next(buff, fp);
            }
            else {
            char str[8192];
            sprintf(str,"### ERROR: Bounds; expect a number, get: %s\n",
                  buff);
            throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
            }
          }
        }

        if((read_sense1 > -1) && (read_sense2 > -1)) {
          if(read_sense1 != read_sense2) {
            char str[8192];
            sprintf(str,"### ERROR: Bounds; variable: %s read_sense1: %d  read_sense2: %d\n",
                  buff, read_sense1, read_sense2);
            throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
          }
          else {
            if(read_sense1 == 1) {
            if(fabs(bnd1 - bnd2) > lp_eps) {
              char str[8192];
              sprintf(str,"### ERROR: Bounds; variable: %s read_sense1: %d  read_sense2: %d  bnd1: %f  bnd2: %f\n", 
                    buff, read_sense1, read_sense2, bnd1, bnd2);
              throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
            }
            collow[icol] = bnd1;
            colup[icol] = bnd1;
            }
            if(read_sense1 == 0) {
            collow[icol] = bnd1;
            colup[icol] = bnd2;         
            }
            if(read_sense1 == 2) {
            colup[icol] = bnd1;
            collow[icol] = bnd2;        
            }
          }
        }
        else {
          if(read_sense1 > -1) {
            switch(read_sense1) {
            case 0: collow[icol] = bnd1; break;
            case 1: collow[icol] = bnd1; colup[icol] = bnd1; break;
            case 2: colup[icol] = bnd1; break;
            }
          }
          if(read_sense2 > -1) {
            switch(read_sense2) {
            case 0: colup[icol] = bnd2; break;
            case 1: collow[icol] = bnd2; colup[icol] = bnd2; break;
            case 2: collow[icol] = bnd2; break;
            }
          }
        }
      }
      }
      break;

    case 2: /* Integers/Generals section */

      scan_next(buff, fp);
    
      while(is_keyword(buff) == 0) {
      
      icol = findHash(buff, 1);

#ifdef LPIO_DEBUG
      printf("CoinLpIO::readLp(): Integer: colname: (%s)  icol: %d\n", 
             buff, icol);
#endif

      if(icol < 0) {
        printf("### WARNING: CoinLpIO::readLp(): Integer variable %s does not appear in objective function or constraints\n", buff);
        insertHash(buff, 1);
        icol = findHash(buff, 1);
        if(icol == maxcol) {
          realloc_col(&collow, &colup, &is_int, &maxcol);
        }
        
#ifdef LPIO_DEBUG
        printf("CoinLpIO::readLp(): Integer: colname: (%s)  icol: %d\n", 
             buff, icol);
#endif
        
      }
      is_int[icol] = 1;
      has_int = 1;
      scan_next(buff, fp);
      };
      break;

    case 3: /* Binaries section */
  
      scan_next(buff, fp);
      
      while(is_keyword(buff) == 0) {

      icol = findHash(buff, 1);

#ifdef LPIO_DEBUG
      printf("CoinLpIO::readLp(): binary: colname: (%s)  icol: %d\n", 
             buff, icol);
#endif

      if(icol < 0) {
        printf("### WARNING: CoinLpIO::readLp(): Binary variable %s does not appear in objective function or constraints\n", buff);
        insertHash(buff, 1);
        icol = findHash(buff, 1);
        if(icol == maxcol) {
          realloc_col(&collow, &colup, &is_int, &maxcol);
        }
#ifdef LPIO_DEBUG
        printf("CoinLpIO::readLp(): binary: colname: (%s)  icol: %d\n", 
             buff, icol);
#endif
        
      }

      is_int[icol] = 1;
      has_int = 1;
      if(collow[icol] < 0) {
        collow[icol] = 0;
      }
      if(colup[icol] > 1) {
        colup[icol] = 1;
      }
      scan_next(buff, fp);
      }
      break;
      
    case 4: done = 1; break;
      
    default: 
      char str[8192];
      sprintf(str,"### ERROR: Lost while reading: (%s)\n", buff);
      throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
      break;
    }
  }

#ifdef LPIO_DEBUG
  printf("CoinLpIO::readLp(): Done with reading the Lp file\n");
#endif

  int *ind = reinterpret_cast<int *> (malloc ((maxcoeff+1) * sizeof(int)));

  for(i=0; i<cnt_coeff; i++) {
    ind[i] = findHash(colNames[i], 1);

#ifdef LPIO_DEBUG
    printf("CoinLpIO::readLp(): name[%d]: (%s)   ind: %d\n", 
         i, colNames[i], ind[i]);
#endif

    if(ind[i] < 0) {
      char str[8192];
      sprintf(str,"### ERROR: Hash table: %s not found\n", colNames[i]);
      throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
    }
  }
  
  numberColumns_ = numberHash_[1];
  numberElements_ = cnt_coeff - start[0];

  double *obj = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
  memset(obj, 0, numberColumns_ * sizeof(double));

  for(i=0; i<cnt_obj; i++) {
    icol = findHash(colNames[i], 1);
    if(icol < 0) {
      char str[8192];
      sprintf(str,"### ERROR: Hash table: %s (obj) not found\n", colNames[i]);
      throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
    }
    obj[icol] = objsense * coeff[i];
  }

  if (objsense == -1) {
    printf("### WARNING: CoinLpIO::readLp(): Maximization problem reformulated as minimization\n");
    objectiveOffset_ = -objectiveOffset_;
  }


  for(i=0; i<cnt_row+1; i++) {
    start[i] -= cnt_obj;
  }

  CoinPackedMatrix *matrix = 
    new CoinPackedMatrix(false,
                   numberColumns_, numberRows_, numberElements_,
                   &(coeff[cnt_obj]), &(ind[cnt_obj]), start, NULL);

#ifdef LPIO_DEBUG
  matrix->dumpMatrix();  
#endif

  setLpDataWithoutRowAndColNames(*matrix, collow, colup,
                         obj, has_int ? is_int : 0, rowlow, rowup);


  if(objName == NULL) {
    rowNames[cnt_row] = CoinStrdup("obj");
  }
  else {
    rowNames[cnt_row] = CoinStrdup(objName);
  }

  // Hash tables for column names are already set up
  setLpDataRowAndColNames(rowNames, NULL);

  if(are_invalid_names(names_[1], numberHash_[1], false)) {
    setDefaultColNames();
    printf("### WARNING: CoinLpIO::readLp(): Invalid column names\nNow using default column names.\n");
  } 
  
  for(i=0; i<cnt_coeff; i++) {
    free(colNames[i]);
  }
  free(colNames);

  for(i=0; i<cnt_row+1; i++) {
    free(rowNames[i]);
  }
  free(rowNames);

  free(objName);

#ifdef LPIO_DEBUG
  writeLp("readlp.xxx");
  printf("CoinLpIO::readLp(): read Lp file written in file readlp.xxx\n");
#endif

  free(coeff);
  free(start);
  free(ind);
  free(colup);
  free(collow);
  free(rhs);
  free(rowlow);
  free(rowup);
  free(is_int);
  free(obj);
  delete matrix;

} /* readLp */

/*************************************************************************/
void
01945 CoinLpIO::print() const {

  printf("problemName_: %s\n", problemName_);
  printf("numberRows_: %d\n", numberRows_);
  printf("numberColumns_: %d\n", numberColumns_);

  printf("matrixByRows_:\n");
  matrixByRow_->dumpMatrix();  

  int i;
  printf("rowlower_:\n");
  for(i=0; i<numberRows_; i++) {
    printf("%.5f ", rowlower_[i]);
  }
  printf("\n");

  printf("rowupper_:\n");
  for(i=0; i<numberRows_; i++) {
    printf("%.5f ", rowupper_[i]);
  }
  printf("\n");
  
  printf("collower_:\n");
  for(i=0; i<numberColumns_; i++) {
    printf("%.5f ", collower_[i]);
  }
  printf("\n");

  printf("colupper_:\n");
  for(i=0; i<numberColumns_; i++) {
    printf("%.5f ", colupper_[i]);
  }
  printf("\n");
  
  printf("objective_:\n");
  for(i=0; i<numberColumns_; i++) {
    printf("%.5f ", objective_[i]);
  }
  printf("\n");
  
  if(integerType_ != NULL) {
    printf("integerType_:\n");
    for(i=0; i<numberColumns_; i++) {
      printf("%c ", integerType_[i]);
    }
  }
  else {
    printf("integerType_: NULL\n");
  }

  printf("\n");
  if(fileName_ != NULL) {
    printf("fileName_: %s\n", fileName_);
  }
  printf("infinity_: %.5f\n", infinity_);
} /* print */


/*************************************************************************/
// Hash functions slightly modified from CoinMpsIO.cpp

static int
hash(const char *name, int maxsiz, int length)
{
  static int mmult[] = {
    262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
    241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829,
    221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773,
    201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761,
    181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871,
    161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299,
    141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853,
    122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727,
    103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521,
    82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103
  };
  int n = 0;
  int j;

  for ( j = 0; j < length; ++j ) {
    int iname = name[j];

    n += mmult[j] * iname;
  }
  return ( abs ( n ) % maxsiz );    /* integer abs */
}

/************************************************************************/
//  startHash.  Creates hash list for names
//  setup names_[section] with names in the same order as in the parameter, 
//  but removes duplicates

void
02038 CoinLpIO::startHash(char const * const * const names, 
                const COINColumnIndex number, int section)
{
  maxHash_[section] = 4 * number;
  int maxhash = maxHash_[section];
  COINColumnIndex i, ipos, iput;

  names_[section] = reinterpret_cast<char **> (malloc(maxhash * sizeof(char *)));
  hash_[section] = new CoinHashLink[maxhash];
  
  CoinHashLink * hashThis = hash_[section];
  char **hashNames = names_[section];
  
  for ( i = 0; i < maxhash; i++ ) {
    hashThis[i].index = -1;
    hashThis[i].next = -1;
  }
  
  /*
   * Initialize the hash table.  Only the index of the first name that
   * hashes to a value is entered in the table; subsequent names that
   * collide with it are not entered.
   */
  
  for (i=0; i<number; i++) {
    const char *thisName = names[i];
    int length = CoinStrlenAsInt(thisName);
    
    ipos = hash(thisName, maxhash, length);
    if (hashThis[ipos].index == -1) {
      hashThis[ipos].index = i; // will be changed below
    }
  }
  
  /*
   * Now take care of the names that collided in the preceding loop,
   * by finding some other entry in the table for them.
   * Since there are as many entries in the table as there are names,
   * there must be room for them.
   * Also setting up hashNames.
   */

  int cnt_distinct = 0;
  
  iput = -1;
  for (i=0; i<number; i++) {
    const char *thisName = names[i];
    int length = CoinStrlenAsInt(thisName);
    
    ipos = hash(thisName, maxhash, length);
    
    while (1) {
      COINColumnIndex j1 = hashThis[ipos].index;
      
      if(j1 == i) {

      // first occurence of thisName in the parameter "names"

      hashThis[ipos].index = cnt_distinct;
      hashNames[cnt_distinct] = CoinStrdup(thisName);
      cnt_distinct++;
      break;
      }
      else {

#ifdef LPIO_DEBUG
      if(j1 > i) {
        char str[8192];
        sprintf(str,"### ERROR: Hash table: j1: %d  i: %d\n", j1, i);
        throw CoinError(str, "startHash", "CoinLpIO", __FILE__, __LINE__);
      }
#endif

      if (strcmp(thisName, hashNames[j1]) == 0) {

        // thisName already entered

        break;
      }
      else {
        // Collision; check if thisName already entered

        COINColumnIndex k = hashThis[ipos].next;

        if (k == -1) {

          // thisName not found; enter it

          while (1) {
            ++iput;
            if (iput > maxhash) {
            char str[8192];
            sprintf(str,"### ERROR: Hash table: too many names\n");
            throw CoinError(str, "startHash", "CoinLpIO", __FILE__, __LINE__);
            break;
            }
            if (hashThis[iput].index == -1) {
            break;
            }
          }
          hashThis[ipos].next = iput;
          hashThis[iput].index = cnt_distinct;
          hashNames[cnt_distinct] = CoinStrdup(thisName);
          cnt_distinct++;
          break;
        } 
        else {
          ipos = k;

          // continue the check with names in collision 

        }
      }
      }
    }
  }

  numberHash_[section] = cnt_distinct;

} /* startHash */

/**************************************************************************/
//  stopHash.  Deletes hash storage
void
02162 CoinLpIO::stopHash(int section)
{
  char **names = names_[section];

  freePreviousNames(section);
  previous_names_[section] = names_[section];
  card_previous_names_[section] = numberHash_[section];

  delete[] hash_[section];
  hash_[section] = NULL;

  names = NULL;

  maxHash_[section] = 0;
  numberHash_[section] = 0;

  if(section == 0) {
    free(objName_);
    objName_ = NULL;
  }
} /* stopHash */

/**********************************************************************/
//  findHash.  -1 not found
COINColumnIndex
02187 CoinLpIO::findHash(const char *name, int section) const
{
  COINColumnIndex found = -1;

  char ** names = names_[section];
  CoinHashLink * hashThis = hash_[section];
  COINColumnIndex maxhash = maxHash_[section];
  COINColumnIndex ipos;

  /* default if we don't find anything */
  if (!maxhash)
    return -1;

  int length = CoinStrlenAsInt(name);

  ipos = hash (name, maxhash, length);
  while (1) {
    COINColumnIndex j1 = hashThis[ipos].index;

    if (j1 >= 0) {
      char *thisName2 = names[j1];

      if (strcmp (name, thisName2) != 0) {
      COINColumnIndex k = hashThis[ipos].next;

      if (k != -1)
        ipos = k;
      else
        break;
      } 
      else {
      found = j1;
      break;
      }
    } 
    else {
      found = -1;
      break;
    }
  }
  return found;
} /* findHash */

/*********************************************************************/
void
02232 CoinLpIO::insertHash(const char *thisName, int section)
{

  int number = numberHash_[section];
  int maxhash = maxHash_[section];

  CoinHashLink * hashThis = hash_[section];
  char **hashNames = names_[section];

  int iput = -1;
  int length = CoinStrlenAsInt(thisName);

  int ipos = hash (thisName, maxhash, length);

  while (1) {
    COINColumnIndex j1 = hashThis[ipos].index;
    
    if (j1 == -1) {
      hashThis[ipos].index = number;
      break;
    }
    else {
      char *thisName2 = hashNames[j1];
      
      if ( strcmp (thisName, thisName2) != 0 ) {
      COINColumnIndex k = hashThis[ipos].next;

      if (k == -1) {
        while (1) {
          ++iput;
          if (iput == maxhash) {
            char str[8192];
            sprintf(str,"### ERROR: Hash table: too many names\n");
            throw CoinError(str, "insertHash", "CoinLpIO", __FILE__, __LINE__);
            break;
          }
          if (hashThis[iput].index == -1) {
            break;
          }
        }
        hashThis[ipos].next = iput;
        hashThis[iput].index = number;
        break;
      } 
      else {
        ipos = k;
        /* nothing worked - try it again */
      }
      }
    }
  }

  hashNames[number] = CoinStrdup(thisName);
  (numberHash_[section])++;

}


Generated by  Doxygen 1.6.0   Back to index