// Last edit: 2/10/07 // // 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 #include #include #include "CoinHelperFunctions.hpp" #include "CoinPackedMatrix.hpp" #include "CoinLpIO.hpp" using namespace std; //#define LPIO_DEBUG /************************************************************************/ CoinLpIO::CoinLpIO() : problemName_(strdup("")), 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; } /************************************************************************/ CoinLpIO::~CoinLpIO() { stopHash(0); stopHash(1); freeAll(); } /************************************************************************/ void CoinLpIO::freePreviousNames(const int section) { int j; if(previous_names_[section] != NULL) { for(j=0; j -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; } } } /*************************************************************************/ const char * CoinLpIO::getRowSense() const { if(rowsense_ == NULL) { int nr=numberRows_; rowsense_ = (char *) malloc(nr*sizeof(char)); double dum1,dum2; int i; for(i=0; ireverseOrdering(); } return matrixByColumn_; } /*************************************************************************/ const char * CoinLpIO::getObjName() const { return objName_; } /*************************************************************************/ 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= 0) && (index < numberRows_+1)) { return names_[0][index]; } else { return NULL; } } /*************************************************************************/ const char * CoinLpIO::columnName(int index) const { if((names_[1] != NULL) && (index >= 0) && (index < numberColumns_)) { return names_[1][index]; } else { return NULL; } } /*************************************************************************/ int CoinLpIO::rowIndex(const char * name) const { if (!hash_[0]) { return -1; } return findHash(name , 0); } /*************************************************************************/ int CoinLpIO::columnIndex(const char * name) const { if (!hash_[1]) { return -1; } return findHash(name , 1); } /************************************************************************/ double CoinLpIO::getInfinity() const { return infinity_; } /************************************************************************/ void CoinLpIO::setInfinity(const double value) { if (value >= 1.020) { infinity_ = value; } else { printf("### ERROR: CoinLpIO::setInfinity(): value: %f\n", value); exit(1); } } /************************************************************************/ double CoinLpIO::getEpsilon() const { return epsilon_; } /************************************************************************/ void CoinLpIO::setEpsilon(const double value) { if (value < 0.1) { epsilon_ = value; } else { printf("### ERROR: CoinLpIO::setEpsilon(): value: %f\n", value); exit(1); } } /************************************************************************/ int CoinLpIO::getNumberAcross() const { return numberAcross_; } /************************************************************************/ void CoinLpIO::setNumberAcross(const int value) { if (value > 0) { numberAcross_ = value; } else { printf("### ERROR: CoinLpIO::setNumberAcross(): value: %d\n", value); exit(1); } } /************************************************************************/ int CoinLpIO::getDecimals() const { return decimals_; } /************************************************************************/ void CoinLpIO::setDecimals(const int value) { if (value > 0) { decimals_ = value; } else { printf("### ERROR: CoinLpIO::setDecimals(): value: %d\n", value); exit(1); } } /************************************************************************/ double CoinLpIO::objectiveOffset() const { return objectiveOffset_; } /************************************************************************/ 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; } /************************************************************************/ const char * CoinLpIO::integerColumns() const { return integerType_; } /************************************************************************/ void 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_ = strdup(""); if (m.isColOrdered()) { matrixByRow_ = new CoinPackedMatrix(); matrixByRow_->reverseOrderedCopyOf(m); } else { matrixByRow_ = new CoinPackedMatrix(m); } numberColumns_ = matrixByRow_->getNumCols(); numberRows_ = matrixByRow_->getNumRows(); rowlower_ = (double *) malloc (numberRows_ * sizeof(double)); rowupper_ = (double *) malloc (numberRows_ * sizeof(double)); collower_ = (double *) malloc (numberColumns_ * sizeof(double)); colupper_ = (double *) malloc (numberColumns_ * sizeof(double)); objective_ = (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_ = (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 */ /*************************************************************************/ void CoinLpIO::setDefaultRowNames() { int i, nrow = getNumRows(); char **defaultRowNames = (char **) malloc ((nrow+1) * sizeof(char *)); char buff[1024]; for(i=0; i 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 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) { printf("### ERROR: in CoinLpIO::writeLP(): unable to open file %s\n", filename); exit(1); } int nerr = writeLp(fp, epsilon, numberAcross, decimals, useRowNames); fclose(fp); return(nerr); } /************************************************************************/ int 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 CoinLpIO::writeLp(const char *filename, const bool useRowNames) { FILE *fp = NULL; fp = fopen(filename,"w"); if (!fp) { printf("### ERROR: in CoinLpIO::writeLP(): unable to open file %s\n", filename); exit(1); } int nerr = writeLp(fp, useRowNames); fclose(fp); return(nerr); } /************************************************************************/ int 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 = (char **) malloc ((nrow+1) * sizeof(char *)); for (j=0; j 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; igetVectorFirst(i); jgetVectorLast(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); jgetVectorLast(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 -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=") == 0) { return(2); } printf("### ERROR: CoinLpIO: is_sense(): string: %s \n", buff); } return(-1); } /* is_sense */ /*************************************************************************/ int CoinLpIO::is_free(const char *buff) const { unsigned lbuff = strlen(buff); if((lbuff == 4) && (CoinStrNCaseCmp(buff, "free", 4) == 0)) { return(1); } return(0); } /* is_free */ /*************************************************************************/ int CoinLpIO::is_comment(const char *buff) const { if((buff[0] == '/') || (buff[0] == '\\')) { return(1); } return(0); } /* is_comment */ /*************************************************************************/ void CoinLpIO::skip_comment(char *buff, FILE *fp) const { while(strcspn(buff, "\n") == strlen(buff)) { // end of line not read yet if(feof(fp)) { printf("### ERROR: CoinLpIO::skip_comment(): end of file reached while skipping comment\n"); exit(1); } if(ferror(fp)) { printf("### ERROR: CoinLpIO::skip_comment(): error while skipping comment\n"); exit(1); } fgets(buff, sizeof(buff), fp); } } /* skip_comment */ /*************************************************************************/ void CoinLpIO::scan_next(char *buff, FILE *fp) const { fscanf(fp, "%s", buff); while(is_comment(buff)) { skip_comment(buff, fp); fscanf(fp, "%s", buff); } #ifdef LPIO_DEBUG printf("CoinLpIO::scan_next: (%s)\n", buff); #endif } /* scan_next */ /*************************************************************************/ int CoinLpIO::is_invalid_name(const char *name, const bool ranged) const { unsigned 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))) { return(4); } return(0); } /* is_invalid_name */ /*************************************************************************/ int 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)) { printf("### ERROR: CoinLpIO::are_invalid_names(): card_vnames: %d number of rows: %d\n", card_vnames, getNumRows()); exit(1); } for(i=0; i 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] = strdup(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 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, 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] = strdup(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 CoinLpIO::realloc_coeff(double **coeff, char ***colNames, int *maxcoeff) const { *maxcoeff *= 5; *colNames = (char **) realloc ((*colNames), (*maxcoeff+1) * sizeof(char *)); *coeff = (double *) realloc ((*coeff), (*maxcoeff+1) * sizeof(double)); } /* realloc_coeff */ /*************************************************************************/ void CoinLpIO::realloc_row(char ***rowNames, int **start, double **rhs, double **rowlow, double **rowup, int *maxrow) const { *maxrow *= 5; *rowNames = (char **) realloc ((*rowNames), (*maxrow+1) * sizeof(char *)); *start = (int *) realloc ((*start), (*maxrow+1) * sizeof(int)); *rhs = (double *) realloc ((*rhs), (*maxrow+1) * sizeof(double)); *rowlow = (double *) realloc ((*rowlow), (*maxrow+1) * sizeof(double)); *rowup = (double *) realloc ((*rowup), (*maxrow+1) * sizeof(double)); } /* realloc_row */ /*************************************************************************/ void CoinLpIO::realloc_col(double **collow, double **colup, char **is_int, int *maxcol) const { *maxcol += 100; *collow = (double *) realloc ((*collow), (*maxcol+1) * sizeof(double)); *colup = (double *) realloc ((*colup), (*maxcol+1) * sizeof(double)); *is_int = (char *) realloc ((*is_int), (*maxcol+1) * sizeof(char)); } /* realloc_col */ /*************************************************************************/ void 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, 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)) { printf("### ERROR: CoinLpIO: read_monom_row(): Unable to read row monomial\n"); exit(1); } } (*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 CoinLpIO::is_keyword(const char *buff) const { unsigned 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 CoinLpIO::readLp(const char *filename, const double epsilon) { setEpsilon(epsilon); readLp(filename); } /*************************************************************************/ void CoinLpIO::readLp(const char *filename) { FILE *fp = fopen(filename, "r"); if(!fp) { printf("### ERROR: CoinLpIO: Unable to open file %s for reading\n", filename); exit(1); } readLp(fp); fclose(fp); } /*************************************************************************/ void CoinLpIO::readLp(FILE* fp, const double epsilon) { setEpsilon(epsilon); readLp(fp); } /*************************************************************************/ void 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 = (char **) malloc ((maxcoeff+1) * sizeof(char *)); double *coeff = (double *) malloc ((maxcoeff+1) * sizeof(double)); char **rowNames = (char **) malloc ((maxrow+1) * sizeof(char *)); int *start = (int *) malloc ((maxrow+1) * sizeof(int)); double *rhs = (double *) malloc ((maxrow+1) * sizeof(double)); double *rowlow = (double *) malloc ((maxrow+1) * sizeof(double)); double *rowup = (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) { fscanf(fp, "%s", buff); unsigned lbuff = strlen(buff); if((lbuff != 2) || (CoinStrNCaseCmp(buff, "to", 2) != 0)) { printf("### ERROR: CoinLpIO::readLp(): Can not locate keyword 'Subject To'\n"); exit(1); } } 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] = strdup(buff); scan_next(buff, fp); } else { char rname[15]; sprintf(rname, "cons%d", cnt_row); rowNames[cnt_row] = strdup(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 = (double *) malloc ((maxcol+1) * sizeof(double)); double *colup = (double *) malloc ((maxcol+1) * sizeof(double)); char *is_int = (char *) malloc ((maxcol+1) * sizeof(char)); int has_int = 0; for (i=0; i -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 (strncmp(start_str,"inf",3)&&strncmp(start_str,"Inf",3)) { printf("### ERROR: CoinLpIO::readLp(): lost in Bounds section; expect a number, get: %s\n", buff); exit(1); } else { // infinity bnd2 = DBL_MAX; scan_next(buff, fp); } } } if((read_sense1 > -1) && (read_sense2 > -1)) { if(read_sense1 != read_sense2) { printf("### ERROR: CoinLpIO::readLp(): lost in Bounds section; \n\ variable: %s read_sense1: %d read_sense2: %d\n", buff, read_sense1, read_sense2); exit(1); } else { if(read_sense1 == 1) { if(fabs(bnd1 - bnd2) > lp_eps) { printf("### ERROR: CoinLpIO::readLp(): lost in Bounds section; \nvariable: %s read_sense1: %d read_sense2: %d bnd1: %f bnd2: %f\n", buff, read_sense1, read_sense2, bnd1, bnd2); exit(1); } 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: printf("### ERROR: CoinLpIO::readLp(): Lost while reading: (%s)\n", buff); exit(1); break; } } #ifdef LPIO_DEBUG printf("CoinLpIO::readLp(): Done with reading the Lp file\n"); #endif int *ind = (int *) malloc ((maxcoeff+1) * sizeof(int)); for(i=0; idumpMatrix(); #endif setLpDataWithoutRowAndColNames(*matrix, collow, colup, obj, has_int ? is_int : 0, rowlow, rowup); if(objName == NULL) { rowNames[cnt_row] = strdup("obj"); } else { rowNames[cnt_row] = strdup(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; idumpMatrix(); int i; printf("rowlower_:\n"); for(i=0; i i) { printf("### ERROR: CoinLpIO::startHash(): j1: %d i: %d\n", j1, i); exit(1); } #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) { printf ( "### ERROR: CoinLpIO::startHash(): too many names\n"); exit(1); break; } if (hashThis[iput].index == -1) { break; } } hashThis[ipos].next = iput; hashThis[iput].index = cnt_distinct; hashNames[cnt_distinct] = strdup(thisName); cnt_distinct++; break; } else { ipos = k; // continue the check with names in collision } } } } } numberHash_[section] = cnt_distinct; } /* startHash */ /**************************************************************************/ // stopHash. Deletes hash storage void 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 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 = strlen (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 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 = strlen (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) { printf ( "### ERROR: CoinLpIO::insertHash(): too many names\n"); exit(1); 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] = strdup(thisName); (numberHash_[section])++; }