// Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CoinUtilsConfig.h" #include #include #include #include #include #include #include "CoinMpsIO.hpp" #include "CoinMessage.hpp" #include "CoinHelperFunctions.hpp" #include "CoinModel.hpp" //############################################################################# // type - 0 normal, 1 INTEL IEEE, 2 other IEEE double CoinMpsCardReader::osi_strtod(char * ptr, char ** output, int type) { static const double fraction[]= {1.0,1.0e-1,1.0e-2,1.0e-3,1.0e-4,1.0e-5,1.0e-6,1.0e-7,1.0e-8, 1.0e-9,1.0e-10,1.0e-11,1.0e-12,1.0e-13,1.0e-14,1.0e-15,1.0e-16, 1.0e-17,1.0e-18,1.0e-19,1.0e-20,1.0e-21,1.0e-22,1.0e-23}; static const double exponent[]= {1.0e-9,1.0e-8,1.0e-7,1.0e-6,1.0e-5,1.0e-4,1.0e-3,1.0e-2,1.0e-1, 1.0,1.0e1,1.0e2,1.0e3,1.0e4,1.0e5,1.0e6,1.0e7,1.0e8,1.0e9}; double value = 0.0; char * save = ptr; // take off leading white space while (*ptr==' '||*ptr=='\t') ptr++; if (!type) { double sign1=1.0; // do + or - if (*ptr=='-') { sign1=-1.0; ptr++; } else if (*ptr=='+') { ptr++; } // more white space while (*ptr==' '||*ptr=='\t') ptr++; char thisChar=0; while (value<1.0e30) { thisChar = *ptr; ptr++; if (thisChar>='0'&&thisChar<='9') value = value*10.0+thisChar-'0'; else break; } if (value<1.0e30) { if (thisChar=='.') { // do fraction double value2 = 0.0; int nfrac=0; while (nfrac<24) { thisChar = *ptr; ptr++; if (thisChar>='0'&&thisChar<='9') { value2 = value2*10.0+thisChar-'0'; nfrac++; } else { break; } } if (nfrac<24) { value += value2*fraction[nfrac]; } else { thisChar='x'; // force error } } if (thisChar=='e'||thisChar=='E') { // exponent int sign2=1; // do + or - if (*ptr=='-') { sign2=-1; ptr++; } else if (*ptr=='+') { ptr++; } int value3 = 0; while (value3<100) { thisChar = *ptr; ptr++; if (thisChar>='0'&&thisChar<='9') { value3 = value3*10+thisChar-'0'; } else { break; } } if (value3<200) { value3 *= sign2; // power of 10 if (abs(value3)<10) { // do most common by lookup (for accuracy?) value *= exponent[value3+9]; } else { value *= pow(10.0,value3); } } else { thisChar='x'; // force error } } if (thisChar==0||thisChar=='\t'||thisChar==' ') { // okay *output=ptr; } else { value = osi_strtod(save,output); sign1=1.0; } } else { // bad value value = osi_strtod(save,output); sign1=1.0; } value *= sign1; } else { // ieee - 3 bytes go to 2 assert (sizeof(double)==8*sizeof(char)); assert (sizeof(unsigned short) == 2*sizeof(char)); unsigned short shortValue[4]; *output = ptr+12; // say okay if (type==1) { // INTEL for (int i=3;i>=0;i--) { int integerValue=0; char * three = (char *) &integerValue; three[1]=ptr[0]; three[2]=ptr[1]; three[3]=ptr[2]; unsigned short thisValue=0; // decode 6 bits at a time for (int j=2;j>=0;j--) { thisValue = thisValue<<6; char thisChar = ptr[j]; if (thisChar >= '0' && thisChar <= '0' + 9) { thisValue |= thisChar - '0'; } else if (thisChar >= 'a' && thisChar <= 'a' + 25) { thisValue |= thisChar - 'a' + 10; } else if (thisChar >= 'A' && thisChar <= 'A' + 25) { thisValue |= thisChar - 'A' + 36; } else if (thisChar >= '*' && thisChar <= '*' + 1) { thisValue |= thisChar - '*' + 62; } else { // error *output=save; } } ptr+=3; shortValue[i]=thisValue; } } else { // not INTEL for (int i=0;i<4;i++) { int integerValue=0; char * three = (char *) &integerValue; three[1]=ptr[0]; three[2]=ptr[1]; three[3]=ptr[2]; unsigned short thisValue=0; // decode 6 bits at a time for (int j=2;j>=0;j--) { thisValue = thisValue<<6; char thisChar = ptr[j]; if (thisChar >= '0' && thisChar <= '0' + 9) { thisValue |= thisChar - '0'; } else if (thisChar >= 'a' && thisChar <= 'a' + 25) { thisValue |= thisChar - 'a' + 10; } else if (thisChar >= 'A' && thisChar <= 'A' + 25) { thisValue |= thisChar - 'A' + 36; } else if (thisChar >= '*' && thisChar <= '*' + 1) { thisValue |= thisChar - '*' + 62; } else { // error *output=save; } } ptr+=3; shortValue[i]=thisValue; } } memcpy(&value,shortValue,sizeof(double)); } return value; } // for strings double CoinMpsCardReader::osi_strtod(char * ptr, char ** output) { char * save = ptr; double value=-1.0e100; if (!stringsAllowed_) { *output=save; } else { // take off leading white space while (*ptr==' '||*ptr=='\t') ptr++; if (*ptr=='=') { strcpy(valueString_,ptr); #define STRING_VALUE -1.234567e-101 value = STRING_VALUE; *output=ptr+strlen(ptr); } else { *output=save; } } return value; } //############################################################################# // sections const static char *section[] = { "", "NAME", "ROW", "COLUMN", "RHS", "RANGES", "BOUNDS", "ENDATA", " ","QSECTION", "CSECTION", "QUADOBJ" , "SOS", "BASIS", " " }; // what is allowed in each section - must line up with COINSectionType const static COINMpsType startType[] = { COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE, COIN_N_ROW, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_UP_BOUND, COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_S1_BOUND, COIN_BS_BASIS, COIN_UNKNOWN_MPS_TYPE }; const static COINMpsType endType[] = { COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE, COIN_BLANK_COLUMN, COIN_UNSET_BOUND, COIN_S1_COLUMN, COIN_S1_COLUMN, COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_BS_BASIS, COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE }; const static int allowedLength[] = { 0, 0, 1, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0 }; // names of types const static char *mpsTypes[] = { "N", "E", "L", "G", " ", "S1", "S2", "S3", " ", " ", " ", " ", "UP", "FX", "LO", "FR", "MI", "PL", "BV", "UI", "LI", "SC", "X1", "X2", "BS", "XL", "XU", "LL", "UL", " " }; int CoinMpsCardReader::cleanCard() { char * getit; getit = input_->gets ( card_, MAX_CARD_LENGTH); if ( getit ) { cardNumber_++; unsigned char * lastNonBlank = (unsigned char *) card_-1; unsigned char * image = (unsigned char *) card_; bool tabs=false; while ( *image != '\0' ) { if ( *image != '\t' && *image < ' ' ) { break; } else if ( *image != '\t' && *image != ' ') { lastNonBlank = image; } else if (*image == '\t') { tabs=true; } image++; } *(lastNonBlank+1)='\0'; if (tabs&§ion_ == COIN_BOUNDS_SECTION&&!freeFormat_&&eightChar_) { int length=lastNonBlank+1-(unsigned char *)card_; assert (length<81); memcpy(card_+82,card_,length); int pos[]={1,4,14,24,1000}; int put=0; int tab=0; for (int i=0;imessage(COIN_MPS_LINE,messages_)<message(COIN_MPS_LINE,messages_)<messageHandler(); messages_ = reader_->messages(); memset ( valueString_, 0, COIN_MAX_FIELD_LENGTH ); stringsAllowed_=false; } // ~CoinMpsCardReader. Destructor CoinMpsCardReader::~CoinMpsCardReader ( ) { delete input_; } void CoinMpsCardReader::strcpyAndCompress ( char *to, const char *from ) { int n = strlen ( from ); int i; int nto = 0; for ( i = 0; i < n; i++ ) { if ( from[i] != ' ' ) { to[nto++] = from[i]; } } if ( !nto ) to[nto++] = ' '; to[nto] = '\0'; } // nextField COINSectionType CoinMpsCardReader::nextField ( ) { mpsType_ = COIN_BLANK_COLUMN; // find next non blank character char *next = position_; while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } bool gotCard; if ( next == eol_ ) { gotCard = false; } else { gotCard = true; } while ( !gotCard ) { // need new image if ( cleanCard() ) { return COIN_EOF_SECTION; } if ( card_[0] == ' ' || card_[0] == '\0') { // not a section or comment position_ = card_; eol_ = card_ + strlen ( card_ ); // get mps type and column name // scan to first non blank next = card_; while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } if ( next != eol_ ) { char *nextBlank = nextBlankOr ( next ); int nchar; if ( nextBlank ) { nchar = nextBlank - next; } else { nchar = -1; } mpsType_ = COIN_BLANK_COLUMN; // special coding if RHS or RANGES, not free format and blanks if ( ( section_ != COIN_RHS_SECTION && section_ != COIN_RANGES_SECTION ) || freeFormat_ || strncmp ( card_ + 4, " ", 8 ) ) { // if columns section only look for first field if MARKER if ( section_ == COIN_COLUMN_SECTION && !strstr ( next, "'MARKER'" ) ) nchar = -1; if (section_ == COIN_SOS_SECTION) { if (!strncmp(card_," S1",3)) { mpsType_ = COIN_S1_BOUND; break; } else if (!strncmp(card_," S2",3)) { mpsType_ = COIN_S2_BOUND; break; } } if ( nchar == allowedLength[section_] ) { //could be a type int i; for ( i = startType[section_]; i < endType[section_]; i++ ) { if ( !strncmp ( next, mpsTypes[i], nchar ) ) { mpsType_ = ( COINMpsType ) i; break; } } if ( mpsType_ != COIN_BLANK_COLUMN ) { //we know all we need so we can skip over next = nextBlank; while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } if ( next == eol_ ) { // error position_ = eol_; mpsType_ = COIN_UNKNOWN_MPS_TYPE; } else { nextBlank = nextBlankOr ( next ); } } else if (section_ == COIN_BOUNDS_SECTION) { // should have been something - but just fix LI problem // set to something illegal if (card_[0]==' '&&card_[3]==' '&&(card_[1]!=' '||card_[2]!=' ')) { mpsType_ = COIN_S3_COLUMN; //we know all we need so we can skip over next = nextBlank; while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } if ( next == eol_ ) { // error position_ = eol_; mpsType_ = COIN_UNKNOWN_MPS_TYPE; } else { nextBlank = nextBlankOr ( next ); } } } } if ( mpsType_ != COIN_UNKNOWN_MPS_TYPE ) { // special coding if BOUND, not free format and blanks if ( section_ != COIN_BOUNDS_SECTION || freeFormat_ || strncmp ( card_ + 4, " ", 8 ) ) { char save = '?'; if ( !freeFormat_ && eightChar_ && next == card_ + 4 ) { if ( eol_ - next >= 8 ) { if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) { eightChar_ = false; } else { nextBlank = next + 8; } if (nextBlank) { save = *nextBlank; *nextBlank = '\0'; } } else { nextBlank = NULL; } } else { if ( nextBlank ) { save = *nextBlank; *nextBlank = '\0'; } } strcpyAndCompress ( columnName_, next ); if ( nextBlank ) { *nextBlank = save; // on to next next = nextBlank; } else { next = eol_; } } else { // blank bounds name strcpy ( columnName_, " " ); } while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } if ( next == eol_ ) { // error unless row section or conic section position_ = eol_; value_ = -1.0e100; if ( section_ != COIN_ROW_SECTION && section_!= COIN_CONIC_SECTION) mpsType_ = COIN_UNKNOWN_MPS_TYPE; else return section_; } else { nextBlank = nextBlankOr ( next ); //if (section_==COIN_CONIC_SECTION) } if ( section_ != COIN_ROW_SECTION ) { char save = '?'; if ( !freeFormat_ && eightChar_ && next == card_ + 14 ) { if ( eol_ - next >= 8 ) { if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) { eightChar_ = false; } else { nextBlank = next + 8; } save = *nextBlank; *nextBlank = '\0'; } else { nextBlank = NULL; } } else { if ( nextBlank ) { save = *nextBlank; *nextBlank = '\0'; } } strcpyAndCompress ( rowName_, next ); if ( nextBlank ) { *nextBlank = save; // on to next next = nextBlank; } else { next = eol_; } while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } // special coding for markers if ( section_ == COIN_COLUMN_SECTION && !strncmp ( rowName_, "'MARKER'", 8 ) && next != eol_ ) { if ( !strncmp ( next, "'INTORG'", 8 ) ) { mpsType_ = COIN_INTORG; } else if ( !strncmp ( next, "'INTEND'", 8 ) ) { mpsType_ = COIN_INTEND; } else if ( !strncmp ( next, "'SOSORG'", 8 ) ) { if ( mpsType_ == COIN_BLANK_COLUMN ) mpsType_ = COIN_S1_COLUMN; } else if ( !strncmp ( next, "'SOSEND'", 8 ) ) { mpsType_ = COIN_SOSEND; } else { mpsType_ = COIN_UNKNOWN_MPS_TYPE; } position_ = eol_; return section_; } if ( next == eol_ ) { // error unless bounds or basis position_ = eol_; if ( section_ != COIN_BOUNDS_SECTION ) { if ( section_ != COIN_BASIS_SECTION ) mpsType_ = COIN_UNKNOWN_MPS_TYPE; value_ = -1.0e100; } else { value_ = 0.0; } } else { nextBlank = nextBlankOr ( next ); if ( nextBlank ) { save = *nextBlank; *nextBlank = '\0'; } char * after; value_ = osi_strtod(next,&after,ieeeFormat_); // see if error if (after>next) { if ( nextBlank ) { *nextBlank = save; position_ = nextBlank; } else { position_ = eol_; } } else { // error position_ = eol_; mpsType_ = COIN_UNKNOWN_MPS_TYPE; value_ = -1.0e100; } } } } } else { //blank name in RHS or RANGES strcpy ( columnName_, " " ); char save = '?'; if ( !freeFormat_ && eightChar_ && next == card_ + 14 ) { if ( eol_ - next >= 8 ) { if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) { eightChar_ = false; } else { nextBlank = next + 8; } save = *nextBlank; *nextBlank = '\0'; } else { nextBlank = NULL; } } else { if ( nextBlank ) { save = *nextBlank; *nextBlank = '\0'; } } strcpyAndCompress ( rowName_, next ); if ( nextBlank ) { *nextBlank = save; // on to next next = nextBlank; } else { next = eol_; } while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } if ( next == eol_ ) { // error position_ = eol_; value_ = -1.0e100; mpsType_ = COIN_UNKNOWN_MPS_TYPE; } else { nextBlank = nextBlankOr ( next ); value_ = -1.0e100; if ( nextBlank ) { save = *nextBlank; *nextBlank = '\0'; } char * after; value_ = osi_strtod(next,&after,ieeeFormat_); // see if error if (after>next) { if ( nextBlank ) { *nextBlank = save; position_ = nextBlank; } else { position_ = eol_; } } else { // error position_ = eol_; mpsType_ = COIN_UNKNOWN_MPS_TYPE; value_ = -1.0e100; } } } } else { // blank continue; } return section_; } else if ( card_[0] != '*' ) { // not a comment int i; handler_->message(COIN_MPS_LINE,messages_)<= 8 ) { if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) { eightChar_ = false; } else { nextBlank = next + 8; } save = *nextBlank; *nextBlank = '\0'; } else { nextBlank = NULL; } } else { if ( nextBlank ) { save = *nextBlank; *nextBlank = '\0'; } } strcpyAndCompress ( rowName_, next ); // on to next if ( nextBlank ) { *nextBlank = save; next = nextBlank; } else { next = eol_; } while ( next != eol_ ) { if ( *next == ' ' || *next == '\t' ) { next++; } else { break; } } if ( next == eol_ && section_ != COIN_SOS_SECTION) { // error position_ = eol_; mpsType_ = COIN_UNKNOWN_MPS_TYPE; } else { nextBlank = nextBlankOr ( next ); } if ( nextBlank ) { save = *nextBlank; *nextBlank = '\0'; } //value_ = -1.0e100; char * after; value_ = osi_strtod(next,&after,ieeeFormat_); // see if error if (after>next) { if ( nextBlank ) { *nextBlank = save; position_ = nextBlank; } else { position_ = eol_; } } else { // error position_ = eol_; mpsType_ = COIN_UNKNOWN_MPS_TYPE; value_ = -1.0e100; } } return section_; } static char * nextNonBlank ( char *image ) { while ( 1 ) { if ( *image != ' ' && *image != '\t' ) break; else image++; } if ( *image == '\0' ) image=NULL; return image; } /** Gets next field for .gms file and returns type. -1 - EOF 0 - what we expected (and processed so pointer moves past) 1 - not what we expected 2 - equation type when expecting value name pair leading blanks always ignored input types 0 - anything - stops on non blank card 1 - name (in columnname) 2 - value 3 - value name pair 4 - equation type 5 - ; */ int CoinMpsCardReader::nextGmsField ( int expectedType ) { int returnCode=-1; bool good=false; switch(expectedType) { case 0: // 0 - May get * in first column or anything if ( cleanCard()) return -1; while(!strlen(card_)) { if ( cleanCard()) return -1; } eol_ = card_+strlen(card_); position_=card_; returnCode=0; break; case 1: // 1 - expect name while (!good) { position_ = nextNonBlank(position_); if (position_==NULL) { if ( cleanCard()) return -1; eol_ = card_+strlen(card_); position_=card_; } else { good=true; char nextChar =*position_; if ((nextChar>='a'&&nextChar<='z')|| (nextChar>='A'&&nextChar<='Z')) { returnCode=0; char * next=position_; while (*next!=','&&*next!=';'&&*next!='='&&*next!=' ' &&*next!='\t'&&*next!='-'&&*next!='+'&&*next>=32) next++; if (next) { int length = next-position_; strncpy(columnName_,position_,length); columnName_[length]='\0'; } else { strcpy(columnName_,position_); next=eol_; } position_=next; } else { returnCode=1; } } } break; case 2: // 2 - expect value while (!good) { position_ = nextNonBlank(position_); if (position_==NULL) { if ( cleanCard()) return -1; eol_ = card_+strlen(card_); position_=card_; } else { good=true; char nextChar =*position_; if ((nextChar>='0'&&nextChar<='9')||nextChar=='+'||nextChar=='-') { returnCode=0; char * next=position_; while (*next!=','&&*next!=';'&&*next!='='&&*next!=' ' &&*next!='\t'&&*next>=32) next++; if (next) { int length = next-position_; strncpy(rowName_,position_,length); rowName_[length]='\0'; } else { strcpy(rowName_,position_); next=eol_; } value_=-1.0e100; sscanf(rowName_,"%lg",&value_); position_=next; } else { returnCode=1; } } } break; case 3: // 3 - expect value name pair while (!good) { position_ = nextNonBlank(position_); char * savePosition = position_; if (position_==NULL) { if ( cleanCard()) return -1; eol_ = card_+strlen(card_); position_=card_; savePosition = position_; } else { good=true; value_=1.0; char nextChar =*position_; returnCode=0; if ((nextChar>='0'&&nextChar<='9')||nextChar=='+'||nextChar=='-') { char * next; int put=0; if (nextChar=='+'||nextChar=='-') { rowName_[0]=nextChar; put=1; next=position_+1; while (*next==' '||*next=='\t') next++; if ((*next>='a'&&*next<='z')|| (*next>='A'&&*next<='Z')) { // name - set value if (nextChar=='+') value_=1.0; else value_=-1.0; position_=next; } else if ((*next>='0'&&*next<='9')||*next=='+'||*next=='-') { rowName_[put++]=*next; next++; while (*next!=' '&&*next!='\t'&&*next!='*') { rowName_[put++]=*next; next++; } assert (*next=='*'); next ++; rowName_[put]='\0'; value_=-1.0e100; sscanf(rowName_,"%lg",&value_); position_=next; } else { returnCode=1; } } else { // number char * next = nextBlankOr(position_); // but could be * char * next2 = strchr(position_,'*'); if (next2&&next2-position_='a'&&nextChar<='z')|| (nextChar>='A'&&nextChar<='Z')) { // name so take value as 1.0 } else if (nextChar=='=') { returnCode=2; position_=savePosition; } else { returnCode=1; position_=savePosition; } if ((*position_)=='*') position_++; position_= nextNonBlank(position_); if (!returnCode) { char nextChar =*position_; if ((nextChar>='a'&&nextChar<='z')|| (nextChar>='A'&&nextChar<='Z')) { char * next = nextBlankOr(position_); if (next) { int length = next-position_; strncpy(columnName_,position_,length); columnName_[length]='\0'; } else { strcpy(columnName_,position_); next=eol_; } position_=next; } else { returnCode=1; position_=savePosition; } } } } break; case 4: // 4 - expect equation type while (!good) { position_ = nextNonBlank(position_); if (position_==NULL) { if ( cleanCard()) return -1; eol_ = card_+strlen(card_); position_=card_; } else { good=true; char nextChar =*position_; if (nextChar=='=') { returnCode=0; char * next = nextBlankOr(position_); int length = next-position_; strncpy(rowName_,position_,length); rowName_[length]='\0'; position_=next; } else { returnCode=1; } } } break; case 5: // 5 - ; expected while (!good) { position_ = nextNonBlank(position_); if (position_==NULL) { if ( cleanCard()) return -1; eol_ = card_+strlen(card_); position_=card_; } else { good=true; char nextChar =*position_; if (nextChar==';') { returnCode=0; char * next = nextBlankOr(position_); if (!next) next=eol_; position_=next; } else { returnCode=1; } } } break; } return returnCode; } //############################################################################# 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 */ } // Define below if you are reading a Cnnnnnn file // Will not do row names (for electricfence) //#define NONAMES #ifndef NONAMES // startHash. Creates hash list for names void CoinMpsIO::startHash ( char **names, const COINColumnIndex number , int section ) { names_[section] = names; numberHash_[section] = number; startHash(section); } void CoinMpsIO::startHash ( int section ) const { char ** names = names_[section]; COINColumnIndex number = numberHash_[section]; COINColumnIndex i; COINColumnIndex maxhash = 4 * number; COINColumnIndex ipos, iput; //hash_=(CoinHashLink *) malloc(maxhash*sizeof(CoinHashLink)); hash_[section] = new CoinHashLink[maxhash]; CoinHashLink * hashThis = hash_[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 ) { char *thisName = names[i]; int length = strlen ( thisName ); ipos = hash ( thisName, maxhash, length ); if ( hashThis[ipos].index == -1 ) { hashThis[ipos].index = i; } } /* * 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. */ iput = -1; for ( i = 0; i < number; ++i ) { char *thisName = names[i]; int length = strlen ( thisName ); ipos = hash ( thisName, maxhash, length ); while ( 1 ) { COINColumnIndex j1 = hashThis[ipos].index; if ( j1 == i ) break; else { char *thisName2 = names[j1]; if ( strcmp ( thisName, thisName2 ) == 0 ) { printf ( "** duplicate name %s\n", names[i] ); break; } else { COINColumnIndex k = hashThis[ipos].next; if ( k == -1 ) { while ( 1 ) { ++iput; if ( iput > number ) { printf ( "** too many names\n" ); break; } if ( hashThis[iput].index == -1 ) { break; } } hashThis[ipos].next = iput; hashThis[iput].index = i; break; } else { ipos = k; /* nothing worked - try it again */ } } } } } } // stopHash. Deletes hash storage void CoinMpsIO::stopHash ( int section ) { delete [] hash_[section]; hash_[section] = NULL; } // findHash. -1 not found COINColumnIndex CoinMpsIO::findHash ( const char *name , int section ) const { COINColumnIndex found = -1; char ** names = names_[section]; CoinHashLink * hashThis = hash_[section]; COINColumnIndex maxhash = 4 * numberHash_[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; } #else // Version when we know images are C/Rnnnnnn // startHash. Creates hash list for names void CoinMpsIO::startHash ( char **names, const COINColumnIndex number , int section ) { numberHash_[section] = number; names_[section] = names; } void CoinMpsIO::startHash ( int section ) const { } // stopHash. Deletes hash storage void CoinMpsIO::stopHash ( int section ) { } // findHash. -1 not found COINColumnIndex CoinMpsIO::findHash ( const char *name , int section ) const { COINColumnIndex found = atoi(name+1); if (!strcmp(name,"OBJROW")) found = numberHash_[section]-1; return found; } #endif //------------------------------------------------------------------ // Get value for infinity //------------------------------------------------------------------ double CoinMpsIO::getInfinity() const { return infinity_; } //------------------------------------------------------------------ // Set value for infinity //------------------------------------------------------------------ void CoinMpsIO::setInfinity(double value) { if ( value >= 1.020 ) { infinity_ = value; } else { handler_->message(COIN_MPS_ILLEGAL,messages_)<<"infinity" <message(COIN_MPS_FILE,messages_)<<"NULL" <=0;i--) { char character = filename[i]; if (character=='/'||character=='\\') { break; } else if (character=='.') { foundDot=true; break; } } if (!foundDot) { strcat(newName,"."); strcat(newName,extension); } } else { // no extension strcpy(newName,filename); } } else { strcpy(newName,"stdin"); } // See if new name if (fileName_&&!strcmp(newName,fileName_)) { // old name return 0; } else { // new file free(fileName_); fileName_=strdup(newName); if (strcmp(fileName_,"stdin")) { // be clever with extensions here std::string fname = fileName_; bool readable = fileCoinReadable(fname); if (!readable) goodFile = -1; else { input = CoinFileInput::create (fname); goodFile = 1; } } else { // only plain file at present input = CoinFileInput::create ("stdin"); goodFile = 1; } } } else { // same as before // reset section ? goodFile=0; } if (goodFile<0) handler_->message(COIN_MPS_FILE,messages_)<= 1 && value <=MAX_INTEGER ) { defaultBound_ = value; } else { handler_->message(COIN_MPS_ILLEGAL,messages_)<<"default integer bound" <0) { delete cardReader_; cardReader_ = new CoinMpsCardReader ( input, this); } if (!extension||(strcmp(extension,"gms")&&!strstr(filename,".gms"))) { return readMps(); } else { int numberSets=0; CoinSet ** sets=NULL; int returnCode = readGms(numberSets,sets); for (int i=0;i0) { delete cardReader_; cardReader_ = new CoinMpsCardReader ( input, this); } return readMps(numberSets,sets); } int CoinMpsIO::readMps() { int numberSets=0; CoinSet ** sets=NULL; int returnCode = readMps(numberSets,sets); for (int i=0;ireadToNextSection(); if ( cardReader_->whichSection ( ) == COIN_NAME_SECTION ) { ifmps = true; // save name of section free(problemName_); problemName_=strdup(cardReader_->columnName()); } else if ( cardReader_->whichSection ( ) == COIN_UNKNOWN_SECTION ) { handler_->message(COIN_MPS_BADFILE1,messages_)<card() <<1 <fileInput()->getReadType()!="plain") handler_->message(COIN_MPS_BADFILE2,messages_) <fileInput()->getReadType() <whichSection ( ) != COIN_EOF_SECTION ) { // save name of section free(problemName_); problemName_=strdup(cardReader_->card()); ifmps = false; } else { handler_->message(COIN_MPS_EOF,messages_)<setStringsAllowed(); //get ROWS cardReader_->nextField ( ) ; // Fudge for what ever code has OBJSENSE if (!strncmp(cardReader_->card(),"OBJSENSE",8)) { cardReader_->nextField(); int i; const char * thisCard = cardReader_->card(); int direction = 0; for (i=0;i<20;i++) { if (thisCard[i]!=' ') { if (!strncmp(thisCard+i,"MAX",3)) direction=-1; else if (!strncmp(thisCard+i,"MIN",3)) direction=1; break; } } if (!direction) printf("No MAX/MIN found after OBJSENSE\n"); else printf("%s found after OBJSENSE - Coin ignores\n", (direction>0 ? "MIN" : "MAX")); cardReader_->nextField(); } if ( cardReader_->whichSection ( ) != COIN_ROW_SECTION ) { handler_->message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() <message(COIN_MPS_RETURNING,messages_)<nextField ( ) == COIN_ROW_SECTION ) { switch ( cardReader_->mpsType ( ) ) { case COIN_N_ROW: if ( !gotNrow ) { gotNrow = true; // save name of section free(objectiveName_); objectiveName_=strdup(cardReader_->columnName()); } else { // add to discard list if ( numberOtherFreeRows == maxFreeRows ) { maxFreeRows = ( 3 * maxFreeRows ) / 2 + 100; freeRowName = ( char ** ) realloc ( freeRowName, maxFreeRows * sizeof ( char * ) ); } freeRowName[numberOtherFreeRows] = strdup ( cardReader_->columnName ( ) ); numberOtherFreeRows++; } break; case COIN_E_ROW: case COIN_L_ROW: case COIN_G_ROW: if ( numberRows_ == maxRows ) { maxRows = ( 3 * maxRows ) / 2 + 1000; rowType = ( COINMpsType * ) realloc ( rowType, maxRows * sizeof ( COINMpsType ) ); rowName = ( char ** ) realloc ( rowName, maxRows * sizeof ( char * ) ); } rowType[numberRows_] = cardReader_->mpsType ( ); #ifndef NONAMES rowName[numberRows_] = strdup ( cardReader_->columnName ( ) ); #endif numberRows_++; break; default: numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<whichSection ( ) != COIN_COLUMN_SECTION ) { handler_->message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() <message(COIN_MPS_RETURNING,messages_)<nextField ( ) == COIN_COLUMN_SECTION ) { switch ( cardReader_->mpsType ( ) ) { case COIN_BLANK_COLUMN: if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) { // new column // reset old column and take out tiny if ( numberColumns_ ) { objUsed = false; CoinBigIndex i; CoinBigIndex k = start[column]; for ( i = k; i < numberElements_; i++ ) { COINRowIndex irow = row[i]; #if 0 if ( fabs ( element[i] ) > tinyElement ) { element[k++] = element[i]; } #endif rowUsed[irow] = -1; } //numberElements_ = k; } column = numberColumns_; if ( numberColumns_ == maxColumns ) { maxColumns = ( 3 * maxColumns ) / 2 + 1000; columnType = ( COINMpsType * ) realloc ( columnType, maxColumns * sizeof ( COINMpsType ) ); columnName = ( char ** ) realloc ( columnName, maxColumns * sizeof ( char * ) ); objective_ = ( double * ) realloc ( objective_, maxColumns * sizeof ( double ) ); start = ( CoinBigIndex * ) realloc ( start, ( maxColumns + 1 ) * sizeof ( CoinBigIndex ) ); } if ( !inIntegerSet ) { columnType[column] = COIN_UNSET_BOUND; } else { columnType[column] = COIN_INTORG; numberIntegers++; } #ifndef NONAMES columnName[column] = strdup ( cardReader_->columnName ( ) ); #else columnName[column]=NULL; #endif strcpy ( lastColumn, cardReader_->columnName ( ) ); objective_[column] = 0.0; start[column] = numberElements_; numberColumns_++; } if ( fabs ( cardReader_->value ( ) ) > tinyElement ) { if ( numberElements_ == maxElements ) { maxElements = ( 3 * maxElements ) / 2 + 1000; row = ( COINRowIndex * ) realloc ( row, maxElements * sizeof ( COINRowIndex ) ); element = ( double * ) realloc ( element, maxElements * sizeof ( double ) ); } // get row number COINRowIndex irow = findHash ( cardReader_->rowName ( ) , 0 ); if ( irow >= 0 ) { double value = cardReader_->value ( ); // check for duplicates if ( irow == numberRows_ ) { // objective if ( objUsed ) { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_DUPOBJ,messages_) <cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_) <= 0 ) { element[rowUsed[irow]] += value; numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_DUPROW,messages_) <rowName()<cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_) <message(COIN_MPS_NOMATCHROW,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<value () == STRING_VALUE ) { // tiny element - string const char * s = cardReader_->valueString(); assert (*s=='='); // get row number COINRowIndex irow = findHash ( cardReader_->rowName ( ) , 0 ); if ( irow >= 0 ) { addString(irow,column,s+1); } else { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_NOMATCHROW,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<whichSection ( ) != COIN_RHS_SECTION ) { handler_->message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() <message(COIN_MPS_RETURNING,messages_)<nextField ( ) == COIN_RHS_SECTION ) { COINRowIndex irow; switch ( cardReader_->mpsType ( ) ) { case COIN_BLANK_COLUMN: if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) { // skip rest if got a rhs if ( gotRhs ) { while ( cardReader_->nextField ( ) == COIN_RHS_SECTION ) { } break; } else { gotRhs = true; strcpy ( lastColumn, cardReader_->columnName ( ) ); // save name of section free(rhsName_); rhsName_=strdup(cardReader_->columnName()); } } // get row number irow = findHash ( cardReader_->rowName ( ) , 0 ); if ( irow >= 0 ) { double value = cardReader_->value ( ); // check for duplicates if ( irow == numberRows_ ) { // objective if ( objUsed ) { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_DUPOBJ,messages_) <cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<valueString(); assert (*s=='='); addString(irow,numberColumns_,s+1); } objectiveOffset_ += value; } else if ( irow < numberRows_ ) { if ( rowlower_[irow] != -infinity_ ) { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_DUPROW,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<valueString(); assert (*s=='='); addString(irow,numberColumns_,s+1); } rowlower_[irow] = value; } } } else { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_NOMATCHROW,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<whichSection ( ) == COIN_RANGES_SECTION ) { memset ( lastColumn, '\0', 200 ); bool gotRange = false; COINRowIndex irow; // need coding for blank range while ( cardReader_->nextField ( ) == COIN_RANGES_SECTION ) { switch ( cardReader_->mpsType ( ) ) { case COIN_BLANK_COLUMN: if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) { // skip rest if got a range if ( gotRange ) { while ( cardReader_->nextField ( ) == COIN_RANGES_SECTION ) { } break; } else { gotRange = true; strcpy ( lastColumn, cardReader_->columnName ( ) ); // save name of section free(rangeName_); rangeName_=strdup(cardReader_->columnName()); } } // get row number irow = findHash ( cardReader_->rowName ( ) , 0 ); if ( irow >= 0 ) { double value = cardReader_->value ( ); // check for duplicates if ( irow == numberRows_ ) { // objective numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_DUPOBJ,messages_) <cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_DUPROW,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_) <message(COIN_MPS_NOMATCHROW,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)< 0.0 ) { up += lo; } else { up = lo; lo += up2; } break; case COIN_L_ROW: if ( lo == -infinity_ ) { up = 0.0; } else { up = lo; lo = -infinity_; } if ( up2 != infinity_ ) { lo = up - fabs ( up2 ); } break; case COIN_G_ROW: if ( lo == -infinity_ ) { lo = 0.0; up = infinity_; } else { up = infinity_; } if ( up2 != infinity_ ) { up = lo + fabs ( up2 ); } break; default: abort(); } rowlower_[irow] = lo; rowupper_[irow] = up; } } free ( rowType ); // default bounds if (numberColumns_) { collower_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) ); colupper_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) ); } else { collower_ = ( double * ) malloc ( sizeof ( double ) ); colupper_ = ( double * ) malloc ( sizeof ( double ) ); } for (i=0;iwhichSection ( ) == COIN_BOUNDS_SECTION ) { memset ( lastColumn, '\0', 200 ); bool gotBound = false; while ( cardReader_->nextField ( ) == COIN_BOUNDS_SECTION ) { if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) { // skip rest if got a bound if ( gotBound ) { while ( cardReader_->nextField ( ) == COIN_BOUNDS_SECTION ) { } break; } else { gotBound = true;; strcpy ( lastColumn, cardReader_->columnName ( ) ); // save name of section free(boundName_); boundName_=strdup(cardReader_->columnName()); } } // get column number COINColumnIndex icolumn = findHash ( cardReader_->rowName ( ) , 1 ); if ( icolumn >= 0 ) { double value = cardReader_->value ( ); bool ifError = false; switch ( cardReader_->mpsType ( ) ) { case COIN_UP_BOUND: if ( value == -1.0e100 ) ifError = true; if (value==STRING_VALUE) { value=1.0e10; // tiny element - string const char * s = cardReader_->valueString(); assert (*s=='='); addString(numberRows_+2,icolumn,s+1); } if ( columnType[icolumn] == COIN_UNSET_BOUND ) { if ( value < 0.0 ) { collower_[icolumn] = -infinity_; } } else if ( columnType[icolumn] == COIN_LO_BOUND ) { if ( value < collower_[icolumn] ) { ifError = true; } else if ( value < collower_[icolumn] + tinyElement ) { value = collower_[icolumn]; } } else if ( columnType[icolumn] == COIN_MI_BOUND ) { } else { ifError = true; } if (value>1.0e25) value=infinity_; colupper_[icolumn] = value; columnType[icolumn] = COIN_UP_BOUND; break; case COIN_LO_BOUND: if ( value == -1.0e100 ) ifError = true; if (value==STRING_VALUE) { value=-1.0e10; // tiny element - string const char * s = cardReader_->valueString(); assert (*s=='='); addString(numberRows_+1,icolumn,s+1); } if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else if ( columnType[icolumn] == COIN_UP_BOUND || columnType[icolumn] == COIN_UI_BOUND ) { if ( value > colupper_[icolumn] ) { ifError = true; } else if ( value > colupper_[icolumn] - tinyElement ) { value = colupper_[icolumn]; } } else { ifError = true; } if (value<-1.0e25) value=-infinity_; collower_[icolumn] = value; columnType[icolumn] = COIN_LO_BOUND; break; case COIN_FX_BOUND: if ( value == -1.0e100 ) ifError = true; if (value==STRING_VALUE) { value=0.0; // tiny element - string const char * s = cardReader_->valueString(); assert (*s=='='); addString(numberRows_+1,icolumn,s+1); addString(numberRows_+2,icolumn,s+1); } if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else if ( columnType[icolumn] == COIN_UI_BOUND || columnType[icolumn] == COIN_BV_BOUND) { // Allow so people can easily put FX's at end double value2 = floor(value); if (fabs(value2-value)>1.0e-12|| value2colupper_[icolumn]) { ifError=true; } else { // take off integer list assert(integerType_[icolumn] ); numberIntegers--; integerType_[icolumn] = 0; } } else { ifError = true; } collower_[icolumn] = value; colupper_[icolumn] = value; columnType[icolumn] = COIN_FX_BOUND; break; case COIN_FR_BOUND: if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else { ifError = true; } collower_[icolumn] = -infinity_; colupper_[icolumn] = infinity_; columnType[icolumn] = COIN_FR_BOUND; break; case COIN_MI_BOUND: if ( columnType[icolumn] == COIN_UNSET_BOUND ) { colupper_[icolumn] = COIN_DBL_MAX; } else if ( columnType[icolumn] == COIN_UP_BOUND ) { } else { ifError = true; } collower_[icolumn] = -infinity_; columnType[icolumn] = COIN_MI_BOUND; break; case COIN_PL_BOUND: if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else { ifError = true; } columnType[icolumn] = COIN_PL_BOUND; break; case COIN_UI_BOUND: if (value==STRING_VALUE) { value=1.0e20; // tiny element - string const char * s = cardReader_->valueString(); assert (*s=='='); addString(numberRows_+2,icolumn,s+1); } #if 0 if ( value == -1.0e100 ) ifError = true; if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else if ( columnType[icolumn] == COIN_LO_BOUND ) { if ( value < collower_[icolumn] ) { ifError = true; } else if ( value < collower_[icolumn] + tinyElement ) { value = collower_[icolumn]; } } else { ifError = true; } #else if ( value == -1.0e100 ) { value = infinity_; if (columnType[icolumn] != COIN_UNSET_BOUND && columnType[icolumn] != COIN_LO_BOUND) { ifError = true; } } else { if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else if ( columnType[icolumn] == COIN_LO_BOUND || columnType[icolumn] == COIN_MI_BOUND ) { if ( value < collower_[icolumn] ) { ifError = true; } else if ( value < collower_[icolumn] + tinyElement ) { value = collower_[icolumn]; } } else { ifError = true; } } #endif if (value>1.0e25) value=infinity_; colupper_[icolumn] = value; columnType[icolumn] = COIN_UI_BOUND; if ( !integerType_[icolumn] ) { numberIntegers++; integerType_[icolumn] = 1; } break; case COIN_LI_BOUND: if ( value == -1.0e100 ) ifError = true; if (value==STRING_VALUE) { value=-1.0e20; // tiny element - string const char * s = cardReader_->valueString(); assert (*s=='='); addString(numberRows_+1,icolumn,s+1); } if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else if ( columnType[icolumn] == COIN_UP_BOUND || columnType[icolumn] == COIN_UI_BOUND ) { if ( value > colupper_[icolumn] ) { ifError = true; } else if ( value > colupper_[icolumn] - tinyElement ) { value = colupper_[icolumn]; } } else { ifError = true; } if (value<-1.0e25) value=-infinity_; collower_[icolumn] = value; columnType[icolumn] = COIN_LI_BOUND; if ( !integerType_[icolumn] ) { numberIntegers++; integerType_[icolumn] = 1; } break; case COIN_BV_BOUND: if ( columnType[icolumn] == COIN_UNSET_BOUND ) { } else { ifError = true; } collower_[icolumn] = 0.0; colupper_[icolumn] = 1.0; columnType[icolumn] = COIN_BV_BOUND; if ( !integerType_[icolumn] ) { numberIntegers++; integerType_[icolumn] = 1; } break; default: ifError = true; break; } if ( ifError ) { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_BADIMAGE,messages_) <cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_NOMATCHCOL,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<whichSection ( ) == COIN_SOS_SECTION ) { // Go to free format cardReader_->setFreeFormat(true); int numberInSet=0; int iType=-1; int * which = new int[numberColumns_]; double * weights = new double[numberColumns_]; CoinSet ** setsA = new CoinSet * [numberColumns_]; while ( cardReader_->nextField ( ) == COIN_SOS_SECTION ) { if (cardReader_->mpsType()==COIN_S1_BOUND|| cardReader_->mpsType()==COIN_S2_BOUND) { if (numberInSet) { CoinSosSet * newSet = new CoinSosSet(numberInSet,which,weights,iType); setsA[numberSets++]=newSet; } numberInSet=0; iType = cardReader_->mpsType()== COIN_S1_BOUND ? 1 : 2; // skip continue; } // get column number COINColumnIndex icolumn = findHash ( cardReader_->columnName ( ) , 1 ); if ( icolumn >= 0 ) { //integerType_[icolumn]=2; double value = cardReader_->value ( ); if (value==-1.0e100) value = atof(cardReader_->rowName()); // try from row name which[numberInSet]=icolumn; weights[numberInSet++]=value; } else { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_NOMATCHCOL,messages_) <columnName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)< MAX_INTEGER ) colupper_[icolumn] = MAX_INTEGER; // clean up to allow for bad reads on 1.0e2 etc if (colupper_[icolumn]<1.0e10) { double value = colupper_[icolumn]; double value2 = floor(value+0.5); if (value!=value2) { if (fabs(value-value2)<1.0e-5) colupper_[icolumn]=value2; } } if (collower_[icolumn]>-1.0e10) { double value = collower_[icolumn]; double value2 = floor(value+0.5); if (value!=value2) { if (fabs(value-value2)<1.0e-5) collower_[icolumn]=value2; } } } } } free ( columnType ); if ( cardReader_->whichSection ( ) != COIN_ENDATA_SECTION && cardReader_->whichSection ( ) != COIN_QUAD_SECTION ) { handler_->message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() <message(COIN_MPS_RETURNING,messages_)<filePointer(); fscanf ( fp, "%d %d %d\n", &numberRows_, &numberColumns_, &i); */ // new: char buffer[1000]; cardReader_->fileInput ()->gets (buffer, 1000); sscanf (buffer, "%d %d %d\n", &numberRows_, &numberColumns_, &i); numberElements_ = i; // done this way in case numberElements_ long rowlower_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) ); rowupper_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) ); for ( i = 0; i < numberRows_; i++ ) { int j; // old: fscanf ( fp, "%d %lg %lg\n", &j, &rowlower_[i], &rowupper_[i] ); // new: cardReader_->fileInput ()->gets (buffer, 1000); sscanf (buffer, "%d %lg %lg\n", &j, &rowlower_[i], &rowupper_[i] ); assert ( i == j ); } collower_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) ); colupper_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) ); objective_= ( double * ) malloc ( numberColumns_ * sizeof ( double ) ); start = ( CoinBigIndex *) malloc ((numberColumns_ + 1) * sizeof (CoinBigIndex) ); row = ( COINRowIndex * ) malloc (numberElements_ * sizeof (COINRowIndex)); element = ( double * ) malloc (numberElements_ * sizeof (double) ); start[0] = 0; numberElements_ = 0; for ( i = 0; i < numberColumns_; i++ ) { int j; int n; /* old: fscanf ( fp, "%d %d %lg %lg %lg\n", &j, &n, &collower_[i], &colupper_[i], &objective_[i] ); */ // new: cardReader_->fileInput ()->gets (buffer, 1000); sscanf (buffer, "%d %d %lg %lg %lg\n", &j, &n, &collower_[i], &colupper_[i], &objective_[i] ); assert ( i == j ); for ( j = 0; j < n; j++ ) { /* old: fscanf ( fp, " %d %lg\n", &row[numberElements_], &element[numberElements_] ); */ // new: cardReader_->fileInput ()->gets (buffer, 1000); sscanf (buffer, " %d %lg\n", &row[numberElements_], &element[numberElements_] ); numberElements_++; } start[i + 1] = numberElements_; } } // construct packed matrix matrixByColumn_ = new CoinPackedMatrix(true, numberRows_,numberColumns_,numberElements_, element,row,start,NULL); free ( row ); free ( start ); free ( element ); handler_->message(COIN_MPS_STATS,messages_)<reverseOrdering(); delete [] element; delete [] start; delete [] index; // Now do columns collower_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) ); colupper_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) ); integerType_ = (char *) malloc (numberColumns_*sizeof(char)); if (keepNames) { names = (char **) malloc(numberColumns_*sizeof(char *)); names_[1] = names; numberHash_[1] = numberColumns_; } int numberIntegers=0; for (iColumn=0; iColumn= -MAX_INTEGER ); if ( collower_[iColumn] < -MAX_INTEGER ) collower_[iColumn] = -MAX_INTEGER; if ( colupper_[iColumn] > MAX_INTEGER ) colupper_[iColumn] = MAX_INTEGER; } else if (columnType==MPL_BIN) { numberIntegers++; integerType_[iColumn]=1; collower_[iColumn]=0.0; colupper_[iColumn]=1.0; } else { integerType_[iColumn]=0; } if (keepNames) { strcpy(name,mpl_get_col_name(gmpl,iColumn+1)); // could look at name? names[iColumn]=strdup(name); } } mpl_terminate(gmpl); if ( !numberIntegers ) { free(integerType_); integerType_ = NULL; } handler_->message(COIN_MPS_STATS,messages_)<0) { delete cardReader_; cardReader_ = new CoinMpsCardReader ( input, this); } int numberSets=0; CoinSet ** sets=NULL; returnCode = readGms(numberSets,sets); for (int i=0;i0) { delete cardReader_; cardReader_ = new CoinMpsCardReader ( input, this); } return readGms(numberSets,sets); } int CoinMpsIO::readGms(int & numberSets,CoinSet ** &sets) { // First version expects comments giving size numberRows_ = 0; numberColumns_ = 0; numberElements_ = 0; bool gotName=false; bool minimize=false; char objName[COIN_MAX_FIELD_LENGTH]; int decodeType=-1; while(!gotName) { if (cardReader_->nextGmsField(0)<0) { handler_->message(COIN_MPS_EOF,messages_)<mutableCard(); if (card[0]!='*') { // finished preamble without finding name printf("bad gms file\n"); return -1; } else { // skip * and find next char * next = nextNonBlank(card+1); if (!next) continue; if (decodeType>=0) { // in middle of getting a total if (!strncmp(next,"Total",5)) { // next line wanted decodeType+=100; } else if (decodeType>=100) { decodeType -= 100; int number = atoi(next); assert (number>0); if (decodeType==0) numberRows_=number; else if (decodeType==1) numberColumns_=number; else numberElements_=number; decodeType=-1; } } else if (!strncmp(next,"Equation",8)) { decodeType=0; } else if (!strncmp(next,"Variable",8)) { decodeType=1; } else if (!strncmp(next,"Nonzero",7)) { decodeType=2; } else if (!strncmp(next,"Solve",5)) { decodeType=-1; gotName=true; assert (numberRows_>0&&numberColumns_>0&&numberElements_>0); next = cardReader_->nextBlankOr(next+5); char name[100]; char * put=name; next= nextNonBlank(next); while(*next!=' '&&*next!='\t') { *put = *next; put++; next++; } *put='\0'; assert (put-name<100); free(problemName_); problemName_=strdup(name); next = strchr(next,';'); assert (next); // backup while(*next!=' '&&*next!='\t') { next--; } cardReader_->setPosition(next); #ifdef NDEBUG cardReader_->nextGmsField(1); #else int returnCode = cardReader_->nextGmsField(1); assert (!returnCode); #endif next = strchr(next,';'); cardReader_->setPosition(next+1); strcpy(objName,cardReader_->columnName()); char * semi = strchr(objName,';'); if (semi) *semi='\0'; if (strstr(card,"minim")) { minimize=true; } else { assert (strstr(card,"maxim")); minimize=false; } } else { decodeType=-1; } } } } objectiveOffset_ = 0.0; 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 ) ); CoinBigIndex *start = ( CoinBigIndex *) malloc ((numberRows_ + 1) * sizeof (CoinBigIndex) ); COINColumnIndex * column = ( COINRowIndex * ) malloc (numberElements_ * sizeof (COINRowIndex)); double *element = ( double * ) malloc (numberElements_ * sizeof (double) ); COINMpsType *rowType = ( COINMpsType * ) malloc ( numberRows_ * sizeof ( COINMpsType ) ); char **rowName = ( char ** ) malloc ( numberRows_ * sizeof ( char * ) ); COINMpsType *columnType = ( COINMpsType * ) malloc ( numberColumns_ * sizeof ( COINMpsType ) ); char **columnName = ( char ** ) malloc ( numberColumns_ * sizeof ( char * ) ); start[0] = 0; numberElements_ = 0; int numberErrors = 0; int i; COINColumnIndex numberIntegers = 0; // expect Variables int returnCode; returnCode = cardReader_->nextGmsField(1); assert (!returnCode&&!strcmp(cardReader_->columnName(),"Variables")); for (i=0;inextGmsField(1); assert (!returnCode); char * next = cardReader_->getPosition(); if (*next=='\0') { // eol - expect , at beginning of next line returnCode = cardReader_->nextGmsField(0); assert (!returnCode); next = strchr(cardReader_->mutableCard(),','); assert (next); } assert (*next==','||*next==';'); cardReader_->setPosition(next+1); columnName[i]=strdup(cardReader_->columnName()); // Default is free? collower_[i]=-COIN_DBL_MAX; // Surely not - check collower_[i]=0.0; colupper_[i]=COIN_DBL_MAX; objective_[i]=0.0; columnType[i]=COIN_UNSET_BOUND; } startHash ( columnName, numberColumns_ , 1 ); integerType_ = (char *) malloc (numberColumns_*sizeof(char)); memset(integerType_,0,numberColumns_); // Lists come in various flavors - I don't know many now // 0 - Positive // 1 - Binary // -1 end int listType=10; while (listType>=0) { returnCode=cardReader_->nextGmsField(1); assert (!returnCode); listType=-1; if (!strcmp(cardReader_->columnName(),"Positive")) { listType=0; } else if (!strcmp(cardReader_->columnName(),"Binary")) { listType=1; } else if (!strcmp(cardReader_->columnName(),"Integer")) { listType=2; } else { break; } // skip Variables returnCode=cardReader_->nextGmsField(1); assert (!returnCode); assert (!strcmp(cardReader_->columnName(),"Variables")); // Go through lists bool inList=true; while (inList) { returnCode=cardReader_->nextGmsField(1); assert (!returnCode); char * next = cardReader_->getPosition(); if (*next=='\0') { // eol - expect , at beginning of next line returnCode = cardReader_->nextGmsField(0); assert (!returnCode); next = strchr(cardReader_->mutableCard(),','); assert (next); } assert (*next==','||*next==';'); cardReader_->setPosition(next+1); inList=(*next==','); int iColumn = findHash(cardReader_->columnName(),1); assert (iColumn>=0); if (listType==0) { collower_[iColumn]=0.0; } else if (listType==1) { collower_[iColumn]=0.0; colupper_[iColumn]=1.0; columnType[iColumn]=COIN_BV_BOUND; integerType_[iColumn] = 1; numberIntegers++; } else if (listType==2) { collower_[iColumn]=0.0; columnType[iColumn]=COIN_UI_BOUND; integerType_[iColumn] = 1; numberIntegers++; } } } // should be equations assert (!strcmp(cardReader_->columnName(),"Equations")); for (i=0;inextGmsField(1); assert (!returnCode); char * next = cardReader_->getPosition(); if (*next=='\0') { // eol - expect , at beginning of next line returnCode = cardReader_->nextGmsField(0); assert (!returnCode); next = strchr(cardReader_->mutableCard(),','); assert (next); } assert (*next==','||*next==';'); cardReader_->setPosition(next+1); rowName[i]=strdup(cardReader_->columnName()); // Default is free? rowlower_[i]=-COIN_DBL_MAX; rowupper_[i]=COIN_DBL_MAX; rowType[i]=COIN_N_ROW; } startHash ( rowName, numberRows_ , 0 ); const double tinyElement = 1.0e-14; const double largeElement = 1.0e14; int numberTiny=0; int numberLarge=0; // For now expect just equations so do loop for (i=0;inextGmsField(1); assert (!returnCode); char * next = cardReader_->getPosition(); assert (*next==' '); char rowName[COIN_MAX_FIELD_LENGTH]; strcpy(rowName,cardReader_->columnName()); char * dot = strchr(rowName,'.'); assert (dot); *dot='\0'; assert (*(dot+1)=='.'); #ifndef NDEBUG int iRow = findHash(rowName,0); assert (i==iRow); #endif returnCode=0; while(!returnCode) { returnCode = cardReader_->nextGmsField(3); assert (returnCode==0||returnCode==2); if (returnCode==2) break; int iColumn = findHash(cardReader_->columnName(),1); if (iColumn>=0) { column[numberElements_]=iColumn; double value = cardReader_->value(); if (fabs(value)largeElement) numberLarge++; element[numberElements_++]=value; } else { // may be string char temp[100]; strcpy(temp,cardReader_->columnName()); char * ast = strchr(temp,'*'); if (!ast) { assert (iColumn>=0); } else { assert (allowStringElements_); *ast='\0'; if (allowStringElements_==1) iColumn = findHash(temp,1); else iColumn = findHash(ast+1,1); assert (iColumn>=0); char temp2[100]; temp2[0]='\0'; double value = cardReader_->value(); if (value&&value!=1.0) sprintf(temp2,"%g*",value); if (allowStringElements_==1) strcat(temp2,ast+1); else strcat(temp2,temp); addString(i,iColumn,temp2); } } } start[i+1]=numberElements_; next=cardReader_->getPosition(); // what about ranges? COINMpsType type=COIN_N_ROW; if (!strncmp(next,"=E=",3)) type=COIN_E_ROW; else if (!strncmp(next,"=G=",3)) type=COIN_G_ROW; else if (!strncmp(next,"=L=",3)) type=COIN_L_ROW; assert (type!=COIN_N_ROW); cardReader_->setPosition(next+3); returnCode = cardReader_->nextGmsField(2); assert (!returnCode); if (type==COIN_E_ROW) { rowlower_[i]=cardReader_->value(); rowupper_[i]=cardReader_->value(); } else if (type==COIN_G_ROW) { rowlower_[i]=cardReader_->value(); } else if (type==COIN_L_ROW) { rowupper_[i]=cardReader_->value(); } rowType[i]=type; // and skip ; #ifdef NDEBUG cardReader_->nextGmsField(5); #else returnCode = cardReader_->nextGmsField(5); assert (!returnCode); #endif } // Now non default bounds while (true) { returnCode=cardReader_->nextGmsField(0); if (returnCode<0) break; // if there is a . see if valid name char * card = cardReader_->mutableCard(); char * dot = strchr(card,'.'); if (dot) { *dot='\0'; int iColumn = findHash(card,1); if (iColumn>=0) { // bound char * next = strchr(dot+1,'='); assert (next); double value =atof(next+1); if (!strncmp(dot+1,"fx",2)) { collower_[iColumn]=value; colupper_[iColumn]=value; } else if (!strncmp(dot+1,"up",2)) { colupper_[iColumn]=value; } else if (!strncmp(dot+1,"lo",2)) { collower_[iColumn]=value; } } // may be two per card char * semi = strchr(dot+1,';'); dot = NULL; if (semi) dot = strchr(semi+1,'.'); if (dot) { char * next= nextNonBlank(semi+1); dot = strchr(next,'.'); assert (dot); *dot='\0'; assert (iColumn==findHash(next,1)); // bound next = strchr(dot+1,'='); assert (next); double value =atof(next+1); if (!strncmp(dot+1,"fx",2)) { collower_[iColumn]=value; abort(); colupper_[iColumn]=value; } else if (!strncmp(dot+1,"up",2)) { colupper_[iColumn]=value; } else if (!strncmp(dot+1,"lo",2)) { collower_[iColumn]=value; } // may be two per card semi = strchr(dot+1,';'); assert (semi); } } } // Objective int iObjCol = findHash(objName,1); int iObjRow=-1; assert (iObjCol>=0); if (!convertObjective_) { objective_[iObjCol]=minimize ? 1.0 : -1.0; } else { // move column stuff COINColumnIndex iColumn; free(names_[1][iObjCol]); for ( iColumn = iObjCol+1; iColumn < numberColumns_; iColumn++ ) { integerType_[iColumn-1]=integerType_[iColumn]; collower_[iColumn-1]=collower_[iColumn]; colupper_[iColumn-1]=colupper_[iColumn]; names_[1][iColumn-1]=names_[1][iColumn]; } numberHash_[1]--; numberColumns_--; double multiplier = minimize ? 1.0 : -1.0; // but swap multiplier *= -1.0; int iRow; CoinBigIndex nel=0; CoinBigIndex last=0; int kRow=0; for (iRow=0;iRowiObjCol) iColumn --; objective_[iColumn]=multiplier * element[j]; } } nel=start[kRow]; last=start[iRow+1]; } } numberRows_=kRow; assert (iObjRow>=0); numberHash_[0]--; } stopHash(0); stopHash(1); // clean up integers if ( !numberIntegers ) { free(integerType_); integerType_ = NULL; } else { COINColumnIndex iColumn; for ( iColumn = 0; iColumn < numberColumns_; iColumn++ ) { if ( integerType_[iColumn] ) { //assert ( collower_[iColumn] >= -MAX_INTEGER ); if ( collower_[iColumn] < -MAX_INTEGER ) collower_[iColumn] = -MAX_INTEGER; if ( colupper_[iColumn] > MAX_INTEGER ) colupper_[iColumn] = MAX_INTEGER; } } } free ( columnType ); free ( rowType ); if (numberStringElements()&&convertObjective_) { int numberElements = numberStringElements(); for (int i=0;iiObjRow) { modify=true; iRow--; } if (iColumn>iObjCol) { modify=true; iColumn--; } if (modify) { char temp[500]; const char * pos = strchr(line,','); assert (pos); pos = strchr(pos+1,','); assert (pos); pos++; sprintf(temp,"%d,%d,%s",iRow,iColumn,pos); free(line); stringElements_[i]=strdup(temp); } } } // construct packed matrix and convert to column format CoinPackedMatrix matrixByRow(false, numberColumns_,numberRows_,numberElements_, element,column,start,NULL); free ( column ); free ( start ); free ( element ); matrixByColumn_= new CoinPackedMatrix(); matrixByColumn_->setExtraGap(0.0); matrixByColumn_->setExtraMajor(0.0); matrixByColumn_->reverseOrderedCopyOf(matrixByRow); if (!convertObjective_) assert (matrixByColumn_->getVectorLengths()[iObjCol]==1); handler_->message(COIN_MPS_STATS,messages_)< %g\n", numberTiny,tinyElement,numberLarge,largeElement); return numberErrors; } /* Read a basis in MPS format from the given filename. If VALUES on NAME card and solution not NULL fills in solution status values as for CoinWarmStartBasis (but one per char) Use "stdin" or "-" to read from stdin. */ int CoinMpsIO::readBasis(const char *filename, const char *extension , double * solution, unsigned char * rowStatus, unsigned char * columnStatus, const std::vector & colnames,int numberColumns, const std::vector & rownames, int numberRows) { // Deal with filename - +1 if new, 0 if same as before, -1 if error CoinFileInput *input = 0; int returnCode = dealWithFileName(filename,extension,input); if (returnCode<0) { return -1; } else if (returnCode>0) { delete cardReader_; cardReader_ = new CoinMpsCardReader ( input, this); } cardReader_->readToNextSection(); if ( cardReader_->whichSection ( ) == COIN_NAME_SECTION ) { // Get whether to use values (passed back by freeFormat) if (!cardReader_->freeFormat()) solution = NULL; } else if ( cardReader_->whichSection ( ) == COIN_UNKNOWN_SECTION ) { handler_->message(COIN_MPS_BADFILE1,messages_)<card() <<1 <fileInput()->getReadType()!="plain") handler_->message(COIN_MPS_BADFILE2,messages_) <fileInput()->getReadType() <whichSection ( ) != COIN_EOF_SECTION ) { return -4; } else { handler_->message(COIN_MPS_EOF,messages_)<(names_[0]); const char** columnNames = const_cast(names_[1]); int i; for (i = 0; i < numberRows_; ++i) { rowNames[i] = rownames[i].c_str(); } for (i = 0; i < numberColumns_; ++i) { columnNames[i] = colnames[i].c_str(); } startHash ( const_cast(rowNames), numberRows , 0 ); startHash ( const_cast(columnNames), numberColumns , 1 ); } cardReader_->setWhichSection(COIN_BASIS_SECTION); cardReader_->setFreeFormat(true); // below matches CoinWarmStartBasis, const unsigned char basic = 0x01; const unsigned char atLowerBound = 0x03; const unsigned char atUpperBound = 0x02; while ( cardReader_->nextField ( ) == COIN_BASIS_SECTION ) { // Get type and column number int iColumn; if (gotNames) { iColumn = findHash (cardReader_->columnName(),1); } else { // few checks char check; sscanf(cardReader_->columnName(),"%c%d",&check,&iColumn); assert (check=='C'&&iColumn>=0); if (iColumn>=numberColumns_) iColumn=-1; } if (iColumn>=0) { double value = cardReader_->value ( ); if (solution && value>-1.0e50) solution[iColumn]=value; int iRow=-1; switch ( cardReader_->mpsType ( ) ) { case COIN_BS_BASIS: columnStatus[iColumn]= basic; break; case COIN_XL_BASIS: columnStatus[iColumn]= basic; // get row number if (gotNames) { iRow = findHash (cardReader_->rowName(),0); } else { // few checks char check; sscanf(cardReader_->rowName(),"%c%d",&check,&iRow); assert (check=='R'&&iRow>=0); if (iRow>=numberRows_) iRow=-1; } if ( iRow >= 0 ) { rowStatus[iRow] = atLowerBound; } break; case COIN_XU_BASIS: columnStatus[iColumn]= basic; // get row number if (gotNames) { iRow = findHash (cardReader_->rowName(),0); } else { // few checks char check; sscanf(cardReader_->rowName(),"%c%d",&check,&iRow); assert (check=='R'&&iRow>=0); if (iRow>=numberRows_) iRow=-1; } if ( iRow >= 0 ) { rowStatus[iRow] = atUpperBound; } break; case COIN_LL_BASIS: columnStatus[iColumn]= atLowerBound; break; case COIN_UL_BASIS: columnStatus[iColumn]= atUpperBound; break; default: break; } } } if (gotNames) { stopHash ( 0 ); stopHash ( 1 ); free(names_[0]); names_[0]=NULL; numberHash_[0]=0; free(names_[1]); names_[1]=NULL; numberHash_[1]=0; delete[] hash_[0]; delete[] hash_[1]; hash_[0]=0; hash_[1]=0; } if ( cardReader_->whichSection ( ) != COIN_ENDATA_SECTION) { handler_->message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() <message(COIN_MPS_RETURNING,messages_)<1&&formatType<8) { int i; // pad out to 8 for (i=0;i<8;i++) { if (outputRow[i]=='\0') break; } for (;i<8;i++) outputRow[i]=' '; outputRow[8]='\0'; } } // Function to return number in most efficient way // Also creates row name field /* formatType is 0 - normal and 8 character names 1 - extra accuracy 2 - IEEE hex - INTEL 3 - IEEE hex - not INTEL */ static void convertDouble(int section,int formatType, double value, char outputValue[24], const char * name, char outputRow[100]) { convertRowName(formatType,name,outputRow); CoinConvertDouble(section,formatType&3,value,outputValue); } // Function to return number in most efficient way /* formatType is 0 - normal and 8 character names 1 - extra accuracy 2 - IEEE hex - INTEL 3 - IEEE hex - not INTEL */ void CoinConvertDouble(int section, int formatType, double value, char outputValue[24]) { if (formatType==0) { bool stripZeros=true; if (fabs(value)<1.0e40) { int power10, decimal; if (value>=0.0) { power10 =(int) log10(value); if (power10<9&&power10>-4) { decimal = CoinMin(10,10-power10); char format[8]; sprintf(format,"%%12.%df",decimal); sprintf(outputValue,format,value); } else { sprintf(outputValue,"%13.7g",value); stripZeros=false; } } else { power10 =(int) log10(-value)+1; if (power10<8&&power10>-3) { decimal = CoinMin(9,9-power10); char format[8]; sprintf(format,"%%12.%df",decimal); sprintf(outputValue,format,value); } else { sprintf(outputValue,"%13.6g",value); stripZeros=false; } } if (stripZeros) { // take off trailing 0 int j; for (j=11;j>=0;j--) { if (outputValue[j]=='0') outputValue[j]=' '; else break; } } else { // still need to make sure fits in 12 characters char * e = strchr(outputValue,'e'); if (!e) { // no e but better make sure fits in 12 if (outputValue[12]!=' '&&outputValue[12]!='\0') { assert (outputValue[0]==' '); int j; for (j=0;j<12;j++) outputValue[j]=outputValue[j+1]; } outputValue[12]='\0'; } else { // e take out 0s int j= (e-outputValue)+1; int put = j+1; assert(outputValue[j]=='-'||outputValue[j]=='+'); for ( j = put ; j < 14 ; j++) { if (outputValue[j]!='0') break; } if (j == put) { // we need to lose something // try taking out blanks if (outputValue[0]==' ') { // skip blank j=1; put=0; } else { // rounding will be wrong but .... put -= 3; // points to one before e j -= 2; // points to e } } // copy rest for ( ; j < 14 ; j++) { outputValue[put++] = outputValue[j]; } } } // overwrite if very very small if (fabs(value)<1.0e-20) strcpy(outputValue,"0.0"); } else { if (section==2) { outputValue[0]= '\0'; // needs no value } else { // probably error ... but .... sprintf(outputValue,"%12.6g",value); } } int i; // pad out to 12 for (i=0;i<12;i++) { if (outputValue[i]=='\0') break; } for (;i<12;i++) outputValue[i]=' '; outputValue[12]='\0'; } else if (formatType==1) { if (fabs(value)<1.0e40) { memset(outputValue,' ',24); sprintf(outputValue,"%.16g",value); // take out blanks int i=0; int j; for (j=0;j<23;j++) { if (outputValue[j]!=' ') outputValue[i++]=outputValue[j]; } outputValue[i]='\0'; } else { if (section==2) { outputValue[0]= '\0'; // needs no value } else { // probably error ... but .... sprintf(outputValue,"%12.6g",value); } } } else { // IEEE // ieee - 3 bytes go to 2 assert (sizeof(double)==8*sizeof(char)); assert (sizeof(unsigned short) == 2*sizeof(char)); unsigned short shortValue[4]; memcpy(shortValue,&value,sizeof(double)); outputValue[12]='\0'; if (formatType==2) { // INTEL char * thisChar = outputValue; for (int i=3;i>=0;i--) { unsigned short thisValue=shortValue[i]; // encode 6 bits at a time for (int j=0;j<3;j++) { unsigned short thisPart = thisValue &63; thisValue = thisValue>>6; if (thisPart < 10) { *thisChar = (char) (thisPart+'0'); } else if (thisPart < 36) { *thisChar = (char) (thisPart-10+'a'); } else if (thisPart < 62) { *thisChar = (char) (thisPart-36+'A'); } else { *thisChar = (char) (thisPart-62+'*'); } thisChar++; } } } else { // not INTEL char * thisChar = outputValue; for (int i=0;i<4;i++) { unsigned short thisValue=shortValue[i]; // encode 6 bits at a time for (int j=0;j<3;j++) { unsigned short thisPart = thisValue &63; thisValue = thisValue>>6; if (thisPart < 10) { *thisChar = (char) (thisPart+'0'); } else if (thisPart < 36) { *thisChar = (char) (thisPart-10+'a'); } else if (thisPart < 62) { *thisChar = (char) (thisPart-36+'A'); } else { *thisChar = (char) (thisPart-62+'*'); } thisChar++; } } } } } static void writeString(CoinFileOutput *output, const char* str) { if (output != 0) { output->puts (str); } } // Put out card image static void outputCard(int formatType,int numberFields, CoinFileOutput *output, std::string head, const char * name, const char outputValue[2][24], const char outputRow[2][100]) { // fprintf(fp,"%s",head.c_str()); std::string line = head; int i; if (formatType==0||(formatType>=2&&formatType<8)) { char outputColumn[9]; strcpy(outputColumn,name); for (i=0;i<8;i++) { if (outputColumn[i]=='\0') break; } for (;i<8;i++) outputColumn[i]=' '; outputColumn[8]='\0'; // fprintf(fp,"%s ",outputColumn); line += outputColumn; line += " "; for (i=0;i='0'&&num<='9') { n *= 10; n += num-'0'; } else { n=-1; break; } } if (n>=0) largest = CoinMax(largest,n); } } largest ++; if (largest>0) { // check char * used = new char[largest]; memset(used,0,largest); int nDup=0; for (i=0;i='0'&&num<='9') { n *= 10; n += num-'0'; } else { n=-1; break; } } if (n>=0) { if (!used[n]) { used[n]=1; } else { // duplicate nDup++; free(names[i]); char newName[9]; sprintf(newName,"%c%7.7d",first,largest); names[i] = strdup(newName); largest++; } } } } delete []used; return nDup; } else { return 0; } } static void strcpyeq(char * output, const char * input) { output[0]='='; strcpy(output+1,input); } int CoinMpsIO::writeMps(const char *filename, int compression, int formatType, int numberAcross, CoinPackedMatrix * quadratic, int numberSOS, const CoinSet * setInfo) const { // Clean up format and numberacross numberAcross=CoinMax(1,numberAcross); numberAcross=CoinMin(2,numberAcross); formatType=CoinMax(0,formatType); formatType=CoinMin(2,formatType); int possibleCompression=0; #ifdef COIN_HAS_ZLIB possibleCompression =1; #endif #ifdef COIN_HAS_BZLIB possibleCompression += 2; #endif if ((compression&possibleCompression)==0) { // switch to other if possible if (compression&&possibleCompression) compression = 3-compression; else compression=0; } std::string line = filename; CoinFileOutput *output = 0; switch (compression) { case 1: if (strcmp(line.c_str() +(line.size()-3), ".gz") != 0) { line += ".gz"; } output = CoinFileOutput::create (line, CoinFileOutput::COMPRESS_GZIP); break; case 2: if (strcmp(line.c_str() +(line.size()-4), ".bz2") != 0) { line += ".bz2"; } output = CoinFileOutput::create (line, CoinFileOutput::COMPRESS_BZIP2); break; case 0: default: output = CoinFileOutput::create (line, CoinFileOutput::COMPRESS_NONE); break; } const char * const * const rowNames = names_[0]; const char * const * const columnNames = names_[1]; int i; unsigned int length = 8; bool freeFormat = (formatType==1); // Check names for uniqueness if default int nChanged; nChanged=makeUniqueNames(names_[0],numberRows_,'R'); if (nChanged) handler_->message(COIN_MPS_CHANGED,messages_)<<"row"<message(COIN_MPS_CHANGED,messages_)<<"column"< length) { length = strlen(rowNames[i]); break; } } if (length <= 8) { for (i = 0 ; i < numberColumns_; ++i) { if (strlen(columnNames[i]) > length) { length = strlen(columnNames[i]); break; } } } if (length > 8 && freeFormat!=1) { freeFormat = true; formatType += 8; } if (numberStringElements_) { freeFormat=true; numberAcross=1; } // NAME card line = "NAME "; if (strcmp(problemName_,"")==0) { line.append("BLANK "); } else { if (strlen(problemName_) >= 8) { line.append(problemName_, 8); } else { line.append(problemName_); line.append(8-strlen(problemName_), ' '); } } if (freeFormat&&(formatType&7)!=2) line.append(" FREE"); else if (freeFormat) line.append(" FREEIEEE"); else if ((formatType&7)==2) line.append(" IEEE"); // See if INTEL if IEEE if ((formatType&7)==2) { // test intel here and add 1 if not intel double value=1.0; char x[8]; memcpy(x,&value,8); if (x[0]==63) { formatType ++; // not intel } else { assert (x[0]==0); } } // finish off name and do ROWS card and objective line.append("\nROWS\n N OBJROW\n"); writeString(output, line.c_str()); // Rows section // Sense array // But massage if looks odd char * sense = new char [numberRows_]; memcpy( sense , getRowSense(), numberRows_); const double * rowLower = getRowLower(); const double * rowUpper = getRowUpper(); for (i=0;i-1.0e30) { if(rowUpper[i]<1.0e30) { line.append("L"); } else { sense[i]='G'; line.append(1,sense[i]); } } else { sense[i]='L'; line.append(1,sense[i]); } } line.append(" "); line.append(rowNames[i]); line.append("\n"); writeString(output, line.c_str()); } // COLUMNS card writeString(output, "COLUMNS\n"); bool ifBounds=false; double largeValue = infinity_; largeValue = 1.0e30; // safer const double * columnLower = getColLower(); const double * columnUpper = getColUpper(); const double * objective = getObjCoefficients(); const CoinPackedMatrix * matrix = getMatrixByCol(); const double * elements = matrix->getElements(); const int * rows = matrix->getIndices(); const CoinBigIndex * starts = matrix->getVectorStarts(); const int * lengths = matrix->getVectorLengths(); char outputValue[2][24]; char outputRow[2][100]; // strings int nextRowString=numberRows_+10; int nextColumnString=numberColumns_+10; int whichString=0; const char * nextString=NULL; // mark string rows char * stringRow = new char[numberRows_+1]; memset(stringRow,0,numberRows_+1); if (numberStringElements_) { decodeString(whichString,nextRowString,nextColumnString,nextString); } // Through columns (only put out if elements or objective value) for (i=0;i=numberColumns_) { strcpyeq(outputValue[0],nextString); decodeString(++whichString,nextRowString,nextColumnString,nextString); } numberFields++; if (numberFields==numberAcross) { // put out card outputCard(formatType, numberFields, output, " ", "RHS", outputValue, outputRow); numberFields=0; } } } if (numberFields) { // put out card outputCard(formatType, numberFields, output, " ", "RHS", outputValue, outputRow); } if (ifRange) { // RANGES writeString(output, "RANGES\n"); numberFields = 0; for (i=0;i=largeValue&&!isInteger(i)) { header[0]=" FR "; value[0] = largeValue; } else { header[0]=" MI "; value[0] = -largeValue; if (!isInteger(i)) header[1]=" UP "; else header[1]=" UI "; if (upperValuegetIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); const double * quadraticElement = quadratic->getElements(); for (int iColumn=0;iColumn -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; } } } //----------------------------------------------------------------------------- /** A quick inlined function to convert from sense/rhs/range stryle constraint definition to lb/ub style */ inline void CoinMpsIO::convertSenseToBound(const char sense, const double right, const double range, double& lower, double& upper) const { switch (sense) { case 'E': lower = upper = right; break; case 'L': lower = -infinity_; upper = right; break; case 'G': lower = right; upper = infinity_; break; case 'R': lower = right - range; upper = right; break; case 'N': lower = -infinity_; upper = infinity_; break; } } //------------------------------------------------------------------ // Get sense of row constraints. //------------------------------------------------------------------ const char * CoinMpsIO::getRowSense() const { if ( rowsense_==NULL ) { int nr=numberRows_; rowsense_ = (char *) malloc(nr*sizeof(char)); double dum1,dum2; int i; for ( i=0; ireverseOrdering(); } return matrixByRow_; } //------------------------------------------------------------------ // Create a column copy of the matrix ... //------------------------------------------------------------------ const CoinPackedMatrix * CoinMpsIO::getMatrixByCol() const { return matrixByColumn_; } //------------------------------------------------------------------ // Save the data ... //------------------------------------------------------------------ void CoinMpsIO::setMpsDataWithoutRowAndColNames( const CoinPackedMatrix& m, const double infinity, const double* collb, const double* colub, const double* obj, const char* integrality, const double* rowlb, const double* rowub) { freeAll(); if (m.isColOrdered()) { matrixByColumn_ = new CoinPackedMatrix(m); } else { matrixByColumn_ = new CoinPackedMatrix; matrixByColumn_->reverseOrderedCopyOf(m); } numberColumns_ = matrixByColumn_->getNumCols(); numberRows_ = matrixByColumn_->getNumRows(); numberElements_ = matrixByColumn_->getNumElements(); defaultBound_ = 1; infinity_ = infinity; objectiveOffset_ = 0; 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, obj + numberColumns_, objective_); if (integrality) { integerType_ = (char *) malloc (numberColumns_ * sizeof(char)); std::copy(integrality, integrality + numberColumns_, integerType_); } else { integerType_ = NULL; } problemName_ = strdup(""); objectiveName_ = strdup(""); rhsName_ = strdup(""); rangeName_ = strdup(""); boundName_ = strdup(""); } void CoinMpsIO::setMpsDataColAndRowNames( char const * const * const colnames, char const * const * const rownames) { releaseRowNames(); releaseColumnNames(); // If long names free format names_[0] = (char **) malloc(numberRows_ * sizeof(char *)); names_[1] = (char **) malloc (numberColumns_ * sizeof(char *)); numberHash_[0]=numberRows_; numberHash_[1]=numberColumns_; char** rowNames = names_[0]; char** columnNames = names_[1]; int i; if (rownames) { for (i = 0 ; i < numberRows_; ++i) { if (rownames[i]) { rowNames[i] = strdup(rownames[i]); } else { rowNames[i] = (char *) malloc (9 * sizeof(char)); sprintf(rowNames[i],"R%7.7d",i); } } } else { for (i = 0; i < numberRows_; ++i) { rowNames[i] = (char *) malloc (9 * sizeof(char)); sprintf(rowNames[i],"R%7.7d",i); } } #ifndef NONAMES if (colnames) { for (i = 0 ; i < numberColumns_; ++i) { if (colnames[i]) { columnNames[i] = strdup(colnames[i]); } else { columnNames[i] = (char *) malloc (9 * sizeof(char)); sprintf(columnNames[i],"C%7.7d",i); } } } else { for (i = 0; i < numberColumns_; ++i) { columnNames[i] = (char *) malloc (9 * sizeof(char)); sprintf(columnNames[i],"C%7.7d",i); } } #else const double * objective = getObjCoefficients(); const CoinPackedMatrix * matrix = getMatrixByCol(); const int * lengths = matrix->getVectorLengths(); int k=0; for (i = 0 ; i < numberColumns_; ++i) { columnNames[i] = (char *) malloc (9 * sizeof(char)); sprintf(columnNames[i],"C%7.7d",k); if (objective[i]||lengths[i]) k++; } #endif } void CoinMpsIO::setMpsDataColAndRowNames( const std::vector & colnames, const std::vector & rownames) { // If long names free format names_[0] = (char **) malloc(numberRows_ * sizeof(char *)); names_[1] = (char **) malloc (numberColumns_ * sizeof(char *)); char** rowNames = names_[0]; char** columnNames = names_[1]; int i; if (rownames.size()!=0) { for (i = 0 ; i < numberRows_; ++i) { rowNames[i] = strdup(rownames[i].c_str()); } } else { for (i = 0; i < numberRows_; ++i) { rowNames[i] = (char *) malloc (9 * sizeof(char)); sprintf(rowNames[i],"R%7.7d",i); } } if (colnames.size()!=0) { for (i = 0 ; i < numberColumns_; ++i) { columnNames[i] = strdup(colnames[i].c_str()); } } else { for (i = 0; i < numberColumns_; ++i) { columnNames[i] = (char *) malloc (9 * sizeof(char)); sprintf(columnNames[i],"C%7.7d",i); } } } void CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity, const double* collb, const double* colub, const double* obj, const char* integrality, const double* rowlb, const double* rowub, char const * const * const colnames, char const * const * const rownames) { setMpsDataWithoutRowAndColNames(m,infinity,collb,colub,obj,integrality,rowlb,rowub); setMpsDataColAndRowNames(colnames,rownames); } void CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity, const double* collb, const double* colub, const double* obj, const char* integrality, const double* rowlb, const double* rowub, const std::vector & colnames, const std::vector & rownames) { setMpsDataWithoutRowAndColNames(m,infinity,collb,colub,obj,integrality,rowlb,rowub); setMpsDataColAndRowNames(colnames,rownames); } void CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity, const double* collb, const double* colub, const double* obj, const char* integrality, const char* rowsen, const double* rowrhs, const double* rowrng, char const * const * const colnames, char const * const * const rownames) { const int numrows = m.getNumRows(); double * rlb = numrows ? new double[numrows] : 0; double * rub = numrows ? new double[numrows] : 0; for (int i = 0; i < numrows; ++i) { convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]); } setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub, colnames, rownames); delete [] rlb; delete [] rub; } void CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity, const double* collb, const double* colub, const double* obj, const char* integrality, const char* rowsen, const double* rowrhs, const double* rowrng, const std::vector & colnames, const std::vector & rownames) { const int numrows = m.getNumRows(); double * rlb = numrows ? new double[numrows] : 0; double * rub = numrows ? new double[numrows] : 0; for (int i = 0; i < numrows; ++i) { convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]); } setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub, colnames, rownames); delete [] rlb; delete [] rub; } void CoinMpsIO::setProblemName (const char *name) { free(problemName_) ; problemName_ = strdup(name) ; } //------------------------------------------------------------------ // Return true if column is a continuous, binary, ... //------------------------------------------------------------------ bool CoinMpsIO::isContinuous(int columnNumber) const { const char * intType = integerType_; if ( intType==NULL ) return true; assert (columnNumber>=0 && columnNumber < numberColumns_); if ( intType[columnNumber]==0 ) return true; return false; } /* Return true if column is integer. Note: This function returns true if the the column is binary or a general integer. */ bool CoinMpsIO::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; } // if integer const char * CoinMpsIO::integerColumns() const { return integerType_; } // Pass in array saying if each variable integer void CoinMpsIO::copyInIntegerInformation(const char * integerType) { if (integerType) { if (!integerType_) integerType_ = (char *) malloc (numberColumns_ * sizeof(char)); memcpy(integerType_,integerType,numberColumns_); } else { free(integerType_); integerType_=NULL; } } // names - returns NULL if out of range const char * CoinMpsIO::rowName(int index) const { if (index>=0&&index=0&&index0) { delete cardReader_; cardReader_ = new CoinMpsCardReader ( input, this); } // See if QUADOBJ just found if (!filename&&cardReader_->whichSection ( ) == COIN_QUAD_SECTION ) { cardReader_->setWhichSection(COIN_QUADRATIC_SECTION); } else { cardReader_->readToNextSection(); // Skip NAME if ( cardReader_->whichSection ( ) == COIN_NAME_SECTION ) cardReader_->readToNextSection(); if ( cardReader_->whichSection ( ) == COIN_QUADRATIC_SECTION ) { // save name of section free(problemName_); problemName_=strdup(cardReader_->columnName()); } else if ( cardReader_->whichSection ( ) == COIN_EOF_SECTION ) { handler_->message(COIN_MPS_EOF,messages_)<message(COIN_MPS_BADFILE1,messages_)<card() <cardNumber() <nextField ( ) == COIN_QUADRATIC_SECTION ) { switch ( cardReader_->mpsType ( ) ) { case COIN_BLANK_COLUMN: if ( fabs ( cardReader_->value ( ) ) > tinyElement ) { if ( numberElements == maximumNonZeros ) { maximumNonZeros = ( 3 * maximumNonZeros ) / 2 + 1000; column = ( COINColumnIndex * ) realloc ( column, maximumNonZeros * sizeof ( COINColumnIndex ) ); column2Temp = ( COINColumnIndex * ) realloc ( column2Temp, maximumNonZeros * sizeof ( COINColumnIndex ) ); elementTemp = ( double * ) realloc ( elementTemp, maximumNonZeros * sizeof ( double ) ); } // get indices COINColumnIndex iColumn1 = findHash ( cardReader_->columnName ( ) , 1 ); COINColumnIndex iColumn2 = findHash ( cardReader_->rowName ( ) , 1 ); if ( iColumn1 >= 0 ) { if (iColumn2 >=0) { double value = cardReader_->value ( ); column[numberElements]=iColumn1; column2Temp[numberElements]=iColumn2; elementTemp[numberElements++]=value; } else { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_NOMATCHROW,messages_) <rowName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_NOMATCHCOL,messages_) <columnName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<0) { delete cardReader_; cardReader_ = new CoinMpsCardReader ( input, this); } cardReader_->readToNextSection(); // Skip NAME if ( cardReader_->whichSection ( ) == COIN_NAME_SECTION ) cardReader_->readToNextSection(); numberCones=0; // Get arrays columnStart = new int [numberColumns_+1]; column = new int [numberColumns_]; int numberErrors = 0; columnStart[0]=0; int numberElements=0; startHash(1); //if (cardReader_->whichSection()==COIN_CONIC_SECTION) //cardReader_->cleanCard(); // skip doing last while ( cardReader_->nextField ( ) == COIN_CONIC_SECTION ) { // should check QUAD // Have to check by hand if (!strncmp(cardReader_->card(),"CSECTION",8)) { if (numberElements==columnStart[numberCones]) { printf("Cone must have at least one column\n"); abort(); } columnStart[++numberCones]=numberElements; continue; } COINColumnIndex iColumn1; switch ( cardReader_->mpsType ( ) ) { case COIN_BLANK_COLUMN: // get index iColumn1 = findHash ( cardReader_->columnName ( ) , 1 ); if ( iColumn1 >= 0 ) { column[numberElements++]=iColumn1; } else { numberErrors++; if ( numberErrors < 100 ) { handler_->message(COIN_MPS_NOMATCHCOL,messages_) <columnName()<cardNumber()<card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<message(COIN_MPS_BADIMAGE,messages_)<cardNumber() <card() < 100000) { handler_->message(COIN_MPS_RETURNING,messages_)<whichSection ( ) == COIN_ENDATA_SECTION ) { // Error if no cones if (!numberElements) { handler_->message(COIN_MPS_EOF,messages_)<message(COIN_MPS_BADFILE1,messages_)<card() <cardNumber() <=0&&iStringstringsExist()) return 0; // no strings assert (!numberStringElements_); /* First columns (including objective==numberRows) then RHS(==numberColumns (+1)) (with rowLower and rowUpper marked) then bounds LO==numberRows+1, UP==numberRows+2 */ int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); int iColumn; for (iColumn=0;iColumngetColumnObjectiveAsString(iColumn); if (strcmp(expr,"Numeric")) { addString(numberRows,iColumn,expr); } CoinModelLink triple=model->firstInColumn(iColumn); while (triple.row()>=0) { int iRow = triple.row(); const char * expr = model->getElementAsString(iRow,iColumn); if (strcmp(expr,"Numeric")) { addString(iRow,iColumn,expr); } triple=model->next(triple); } } int iRow; for (iRow=0;iRowgetRowLowerAsString(iRow); const char * expr2 = model->getRowUpperAsString(iRow); if (strcmp(expr1,"Numeric")) { if (rowupper_[iRow]>1.0e20&&!strcmp(expr2,"Numeric")) { // G row addString(iRow,numberColumns,expr1); rowlower_[iRow]=STRING_VALUE; } else if (!strcmp(expr1,expr2)) { // E row addString(iRow,numberColumns,expr1); rowlower_[iRow]=STRING_VALUE; addString(iRow,numberColumns+1,expr1); rowupper_[iRow]=STRING_VALUE; } else if (rowlower_[iRow]<-1.0e20&&!strcmp(expr1,"Numeric")) { // L row addString(iRow,numberColumns+1,expr2); rowupper_[iRow]=STRING_VALUE; } else { // Range printf("Unaable to handle string ranges row %d %s %s\n", iRow,expr1,expr2); abort(); } } } // Bounds for (iColumn=0;iColumngetColumnLowerAsString(iColumn); if (strcmp(expr,"Numeric")) { addString(numberRows+1,iColumn,expr); collower_[iColumn]=STRING_VALUE; } expr = model->getColumnUpperAsString(iColumn); if (strcmp(expr,"Numeric")) { addString(numberRows+2,iColumn,expr); colupper_[iColumn]=STRING_VALUE; } } return numberStringElements_; } // Constructor CoinSet::CoinSet ( int numberEntries, const int * which) { numberEntries_ = numberEntries; which_ = new int [numberEntries_]; weights_ = NULL; memcpy(which_,which,numberEntries_*sizeof(int)); setType_=1; } // Default constructor CoinSet::CoinSet () { numberEntries_ = 0; which_ = NULL; weights_ = NULL; setType_=1; } // Copy constructor CoinSet::CoinSet (const CoinSet & rhs) { numberEntries_ = rhs.numberEntries_; setType_=rhs.setType_; which_ = CoinCopyOfArray(rhs.which_,numberEntries_); weights_ = CoinCopyOfArray(rhs.weights_,numberEntries_); } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CoinSet & CoinSet::operator=(const CoinSet& rhs) { if (this != &rhs) { delete [] which_; delete [] weights_; numberEntries_ = rhs.numberEntries_; setType_=rhs.setType_; which_ = CoinCopyOfArray(rhs.which_,numberEntries_); weights_ = CoinCopyOfArray(rhs.weights_,numberEntries_); } return *this; } // Destructor CoinSet::~CoinSet ( ) { delete [] which_; delete [] weights_; } // Constructor CoinSosSet::CoinSosSet ( int numberEntries, const int * which, const double * weights, int type) : CoinSet(numberEntries,which) { weights_= new double [numberEntries_]; memcpy(weights_,weights,numberEntries_*sizeof(double)); setType_ = type; double last = weights_[0]; int i; bool allSame=true; for (i=1;i